show identity type for device selection
This commit is contained in:
		
							parent
							
								
									c06aceaae9
								
							
						
					
					
						commit
						0e96e0a796
					
				| @ -526,11 +526,11 @@ public class Contact implements ListItem, Blockable { | ||||
| 		return this.mLastseen; | ||||
| 	} | ||||
| 
 | ||||
| 	public void setLastPresence(String presence) { | ||||
| 		this.mLastPresence = presence; | ||||
| 	public void setLastResource(String resource) { | ||||
| 		this.mLastPresence = resource; | ||||
| 	} | ||||
| 
 | ||||
| 	public String getLastPresence() { | ||||
| 	public String getLastResource() { | ||||
| 		return this.mLastPresence; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -5,10 +5,10 @@ import android.database.Cursor; | ||||
| 
 | ||||
| import java.net.MalformedURLException; | ||||
| import java.net.URL; | ||||
| import java.util.Arrays; | ||||
| 
 | ||||
| import eu.siacs.conversations.Config; | ||||
| import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; | ||||
| import eu.siacs.conversations.utils.CryptoHelper; | ||||
| import eu.siacs.conversations.utils.GeoHelper; | ||||
| import eu.siacs.conversations.utils.MimeUtils; | ||||
| import eu.siacs.conversations.utils.UIHelper; | ||||
| @ -396,7 +396,7 @@ public class Message extends AbstractEntity { | ||||
| 						&& this.counterpart.equals(message.getCounterpart()) | ||||
| 						&& (body.equals(otherBody) | ||||
| 						||(message.getEncryption() == Message.ENCRYPTION_PGP | ||||
| 						&&  message.getRemoteMsgId().matches("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))) ; | ||||
| 						&& CryptoHelper.UUID_PATTERN.matcher(message.getRemoteMsgId()).matches())); | ||||
| 			} else { | ||||
| 				return this.remoteMsgId == null | ||||
| 						&& this.counterpart.equals(message.getCounterpart()) | ||||
| @ -550,7 +550,7 @@ public class Message extends AbstractEntity { | ||||
| 			try { | ||||
| 				counterpart = Jid.fromParts(conversation.getJid().getLocalpart(), | ||||
| 						conversation.getJid().getDomainpart(), | ||||
| 						presences.asStringArray()[0]); | ||||
| 						presences.toResourceArray()[0]); | ||||
| 				return true; | ||||
| 			} catch (InvalidJidException e) { | ||||
| 				counterpart = null; | ||||
|  | ||||
| @ -1,7 +1,10 @@ | ||||
| package eu.siacs.conversations.entities; | ||||
| 
 | ||||
| import android.util.Pair; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Hashtable; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| @ -54,7 +57,7 @@ public class Presences { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public String[] asStringArray() { | ||||
| 	public String[] toResourceArray() { | ||||
| 		synchronized (this.presences) { | ||||
| 			final String[] presencesArray = new String[presences.size()]; | ||||
| 			presences.keySet().toArray(presencesArray); | ||||
| @ -104,4 +107,28 @@ public class Presences { | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	public Pair<Map<String, String>,Map<String,String>> toTypeAndNameMap() { | ||||
| 		Map<String,String> typeMap = new HashMap<>(); | ||||
| 		Map<String,String> nameMap = new HashMap<>(); | ||||
| 		synchronized (this.presences) { | ||||
| 			for(Map.Entry<String,Presence> presenceEntry : this.presences.entrySet()) { | ||||
| 				String resource = presenceEntry.getKey(); | ||||
| 				Presence presence = presenceEntry.getValue(); | ||||
| 				ServiceDiscoveryResult serviceDiscoveryResult = presence == null ? null : presence.getServiceDiscoveryResult(); | ||||
| 				if (serviceDiscoveryResult != null && serviceDiscoveryResult.getIdentities().size() > 0) { | ||||
| 					ServiceDiscoveryResult.Identity identity = serviceDiscoveryResult.getIdentities().get(0); | ||||
| 					String type = identity.getType(); | ||||
| 					String name = identity.getName(); | ||||
| 					if (type != null) { | ||||
| 						typeMap.put(resource,type); | ||||
| 					} | ||||
| 					if (name != null) { | ||||
| 						nameMap.put(resource, name); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return new Pair(typeMap,nameMap); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -62,7 +62,7 @@ public abstract class AbstractParser { | ||||
| 
 | ||||
| 	protected void updateLastseen(final Account account, final Jid from) { | ||||
| 		final Contact contact = account.getRoster().getContact(from); | ||||
| 		contact.setLastPresence(from.isBareJid() ? "" : from.getResourcepart()); | ||||
| 		contact.setLastResource(from.isBareJid() ? "" : from.getResourcepart()); | ||||
| 	} | ||||
| 
 | ||||
| 	protected String avatarData(Element items) { | ||||
|  | ||||
| @ -401,7 +401,12 @@ public class FileBackend { | ||||
| 	private Bitmap getFullsizeImagePreview(File file, int size) { | ||||
| 		BitmapFactory.Options options = new BitmapFactory.Options(); | ||||
| 		options.inSampleSize = calcSampleSize(file, size); | ||||
| 		return BitmapFactory.decodeFile(file.getAbsolutePath(), options); | ||||
| 		try { | ||||
| 			return BitmapFactory.decodeFile(file.getAbsolutePath(), options); | ||||
| 		} catch (OutOfMemoryError e) { | ||||
| 			options.inSampleSize *= 2; | ||||
| 			return BitmapFactory.decodeFile(file.getAbsolutePath(), options); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private Bitmap getVideoPreview(File file, int size) { | ||||
|  | ||||
| @ -196,7 +196,7 @@ public class XmppConnectionService extends Service { | ||||
| 					if (contact.getPresences().size() >= 1) { | ||||
| 						if (conversation.hasValidOtrSession()) { | ||||
| 							String otrResource = conversation.getOtrSession().getSessionID().getUserID(); | ||||
| 							if (!(Arrays.asList(contact.getPresences().asStringArray()).contains(otrResource))) { | ||||
| 							if (!(Arrays.asList(contact.getPresences().toResourceArray()).contains(otrResource))) { | ||||
| 								conversation.endOtrIfNeeded(); | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| @ -44,6 +44,7 @@ import android.preference.PreferenceManager; | ||||
| import android.text.InputType; | ||||
| import android.util.DisplayMetrics; | ||||
| import android.util.Log; | ||||
| import android.util.Pair; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.view.inputmethod.InputMethodManager; | ||||
| @ -66,9 +67,13 @@ import net.java.otr4j.session.SessionID; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Hashtable; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.RejectedExecutionException; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
| 
 | ||||
| import eu.siacs.conversations.Config; | ||||
| import eu.siacs.conversations.R; | ||||
| @ -78,13 +83,16 @@ import eu.siacs.conversations.entities.Contact; | ||||
| import eu.siacs.conversations.entities.Conversation; | ||||
| import eu.siacs.conversations.entities.Message; | ||||
| import eu.siacs.conversations.entities.MucOptions; | ||||
| import eu.siacs.conversations.entities.Presence; | ||||
| import eu.siacs.conversations.entities.Presences; | ||||
| import eu.siacs.conversations.entities.ServiceDiscoveryResult; | ||||
| import eu.siacs.conversations.services.AvatarService; | ||||
| import eu.siacs.conversations.services.XmppConnectionService; | ||||
| import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; | ||||
| import eu.siacs.conversations.ui.widget.Switch; | ||||
| import eu.siacs.conversations.utils.CryptoHelper; | ||||
| import eu.siacs.conversations.utils.ExceptionHelper; | ||||
| import eu.siacs.conversations.utils.UIHelper; | ||||
| import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; | ||||
| import eu.siacs.conversations.xmpp.OnUpdateBlocklist; | ||||
| import eu.siacs.conversations.xmpp.jid.InvalidJidException; | ||||
| @ -940,7 +948,7 @@ public abstract class XmppActivity extends Activity { | ||||
| 		} else 	if (!contact.showInRoster()) { | ||||
| 			showAddToRosterDialog(conversation); | ||||
| 		} else { | ||||
| 			Presences presences = contact.getPresences(); | ||||
| 			final Presences presences = contact.getPresences(); | ||||
| 			if (presences.size() == 0) { | ||||
| 				if (!contact.getOption(Contact.Options.TO) | ||||
| 						&& !contact.getOption(Contact.Options.ASKING) | ||||
| @ -954,7 +962,7 @@ public abstract class XmppActivity extends Activity { | ||||
| 					listener.onPresenceSelected(); | ||||
| 				} | ||||
| 			} else if (presences.size() == 1) { | ||||
| 				String presence = presences.asStringArray()[0]; | ||||
| 				String presence = presences.toResourceArray()[0]; | ||||
| 				try { | ||||
| 					conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence)); | ||||
| 				} catch (InvalidJidException e) { | ||||
| @ -962,49 +970,72 @@ public abstract class XmppActivity extends Activity { | ||||
| 				} | ||||
| 				listener.onPresenceSelected(); | ||||
| 			} else { | ||||
| 				final StringBuilder presence = new StringBuilder(); | ||||
| 				AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
| 				builder.setTitle(getString(R.string.choose_presence)); | ||||
| 				final String[] presencesArray = presences.asStringArray(); | ||||
| 				int preselectedPresence = 0; | ||||
| 				for (int i = 0; i < presencesArray.length; ++i) { | ||||
| 					if (presencesArray[i].equals(contact.getLastPresence())) { | ||||
| 						preselectedPresence = i; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 				presence.append(presencesArray[preselectedPresence]); | ||||
| 				builder.setSingleChoiceItems(presencesArray, | ||||
| 						preselectedPresence, | ||||
| 						new DialogInterface.OnClickListener() { | ||||
| 
 | ||||
| 							@Override | ||||
| 							public void onClick(DialogInterface dialog, | ||||
| 									int which) { | ||||
| 								presence.delete(0, presence.length()); | ||||
| 								presence.append(presencesArray[which]); | ||||
| 							} | ||||
| 						}); | ||||
| 				builder.setNegativeButton(R.string.cancel, null); | ||||
| 				builder.setPositiveButton(R.string.ok, new OnClickListener() { | ||||
| 
 | ||||
| 					@Override | ||||
| 					public void onClick(DialogInterface dialog, int which) { | ||||
| 						try { | ||||
| 							conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence.toString())); | ||||
| 						} catch (InvalidJidException e) { | ||||
| 							conversation.setNextCounterpart(null); | ||||
| 						} | ||||
| 						listener.onPresenceSelected(); | ||||
| 					} | ||||
| 				}); | ||||
| 				builder.create().show(); | ||||
| 				showPresenceSelectionDialog(presences,conversation,listener); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	protected void onActivityResult(int requestCode, int resultCode, | ||||
| 			final Intent data) { | ||||
| 	private void showPresenceSelectionDialog(Presences presences, final Conversation conversation, final OnPresenceSelected listener) { | ||||
| 		final Contact contact = conversation.getContact(); | ||||
| 		AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
| 		builder.setTitle(getString(R.string.choose_presence)); | ||||
| 		final String[] resourceArray = presences.toResourceArray(); | ||||
| 		Pair<Map<String, String>, Map<String, String>> typeAndName = presences.toTypeAndNameMap(); | ||||
| 		final Map<String,String> resourceTypeMap = typeAndName.first; | ||||
| 		final Map<String,String> resourceNameMap = typeAndName.second; | ||||
| 		final String[] readableIdentities = new String[resourceArray.length]; | ||||
| 		final AtomicInteger selectedResource = new AtomicInteger(0); | ||||
| 		for (int i = 0; i < resourceArray.length; ++i) { | ||||
| 			String resource = resourceArray[i]; | ||||
| 			if (resource.equals(contact.getLastResource())) { | ||||
| 				selectedResource.set(i); | ||||
| 			} | ||||
| 			String type = resourceTypeMap.get(resource); | ||||
| 			String name = resourceNameMap.get(resource); | ||||
| 			if (type != null) { | ||||
| 				if (Collections.frequency(resourceTypeMap.values(),type) == 1) { | ||||
| 					readableIdentities[i] = UIHelper.tranlasteType(this,type); | ||||
| 				} else if (name != null) { | ||||
| 					if (Collections.frequency(resourceNameMap.values(), name) == 1 | ||||
| 							|| CryptoHelper.UUID_PATTERN.matcher(resource).matches()) { | ||||
| 						readableIdentities[i] = UIHelper.tranlasteType(this,type) + "  (" + name+")"; | ||||
| 					} else { | ||||
| 						readableIdentities[i] = UIHelper.tranlasteType(this,type) + " (" + name +" / " + resource+")"; | ||||
| 					} | ||||
| 				} else { | ||||
| 					readableIdentities[i] = UIHelper.tranlasteType(this,type) + " (" + resource+")"; | ||||
| 				} | ||||
| 			} else { | ||||
| 				readableIdentities[i] = resource; | ||||
| 			} | ||||
| 		} | ||||
| 		builder.setSingleChoiceItems(readableIdentities, | ||||
| 				selectedResource.get(), | ||||
| 				new DialogInterface.OnClickListener() { | ||||
| 
 | ||||
| 					@Override | ||||
| 					public void onClick(DialogInterface dialog, int which) { | ||||
| 						selectedResource.set(which); | ||||
| 					} | ||||
| 				}); | ||||
| 		builder.setNegativeButton(R.string.cancel, null); | ||||
| 		builder.setPositiveButton(R.string.ok, new OnClickListener() { | ||||
| 
 | ||||
| 			@Override | ||||
| 			public void onClick(DialogInterface dialog, int which) { | ||||
| 				try { | ||||
| 					Jid next = Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),resourceArray[selectedResource.get()]); | ||||
| 					conversation.setNextCounterpart(next); | ||||
| 				} catch (InvalidJidException e) { | ||||
| 					conversation.setNextCounterpart(null); | ||||
| 				} | ||||
| 				listener.onPresenceSelected(); | ||||
| 			} | ||||
| 		}); | ||||
| 		builder.create().show(); | ||||
| 	} | ||||
| 
 | ||||
| 	protected void onActivityResult(int requestCode, int resultCode, final Intent data) { | ||||
| 		super.onActivityResult(requestCode, resultCode, data); | ||||
| 		if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) { | ||||
| 			mPendingConferenceInvite = ConferenceInvite.parse(data); | ||||
|  | ||||
| @ -21,6 +21,7 @@ import java.util.Iterator; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| import java.util.regex.Pattern; | ||||
| 
 | ||||
| import eu.siacs.conversations.Config; | ||||
| import eu.siacs.conversations.R; | ||||
| @ -31,6 +32,8 @@ import eu.siacs.conversations.xmpp.jid.Jid; | ||||
| public final class CryptoHelper { | ||||
| 	public static final String FILETRANSFER = "?FILETRANSFERv1:"; | ||||
| 	private final static char[] hexArray = "0123456789abcdef".toCharArray(); | ||||
| 
 | ||||
| 	public static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"); | ||||
| 	final public static byte[] ONE = new byte[] { 0, 0, 0, 1 }; | ||||
| 
 | ||||
| 	public static String bytesToHex(byte[] bytes) { | ||||
|  | ||||
| @ -18,6 +18,7 @@ import eu.siacs.conversations.entities.ListItem; | ||||
| import eu.siacs.conversations.entities.Message; | ||||
| import eu.siacs.conversations.entities.Presence; | ||||
| import eu.siacs.conversations.entities.Transferable; | ||||
| import eu.siacs.conversations.ui.XmppActivity; | ||||
| import eu.siacs.conversations.xmpp.jid.Jid; | ||||
| 
 | ||||
| public class UIHelper { | ||||
| @ -286,4 +287,21 @@ public class UIHelper { | ||||
| 				return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public static String tranlasteType(Context context, String type) { | ||||
| 		switch (type.toLowerCase()) { | ||||
| 			case "pc": | ||||
| 				return context.getString(R.string.type_pc); | ||||
| 			case "phone": | ||||
| 				return context.getString(R.string.type_phone); | ||||
| 			case "tablet": | ||||
| 				return context.getString(R.string.type_tablet); | ||||
| 			case "web": | ||||
| 				return context.getString(R.string.type_web); | ||||
| 			case "console": | ||||
| 				return context.getString(R.string.type_console); | ||||
| 			default: | ||||
| 				return type; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -79,7 +79,7 @@ | ||||
| 	<string name="clear_histor_msg">Do you want to delete all messages within this Conversation?\n\n<b>Warning:</b> This will not influence messages stored on other devices or servers.</string> | ||||
| 	<string name="delete_messages">Delete messages</string> | ||||
| 	<string name="also_end_conversation">End this conversation afterwards</string> | ||||
| 	<string name="choose_presence">Choose presence to contact</string> | ||||
| 	<string name="choose_presence">Choose device</string> | ||||
| 	<string name="send_unencrypted_message">Send unencrypted message</string> | ||||
| 	<string name="send_message_to_x">Send message to %s</string> | ||||
| 	<string name="send_otr_message">Send OTR encrypted message</string> | ||||
| @ -669,4 +669,9 @@ | ||||
| 	<string name="pref_use_green_background_summary">Use green background for received messages</string> | ||||
| 	<string name="unable_to_connect_to_keychain">Unable to connect to OpenKeychain</string> | ||||
| 	<string name="this_device_is_no_longer_in_use">This device is no longer in use</string> | ||||
| 	<string name="type_pc">Computer</string> | ||||
| 	<string name="type_phone">Mobile phone</string> | ||||
| 	<string name="type_tablet">Tablet</string> | ||||
| 	<string name="type_web">Web browser</string> | ||||
| 	<string name="type_console">Console</string> | ||||
| </resources> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch