show identity type for device selection

This commit is contained in:
Daniel Gultsch 2016-07-28 22:58:37 +02:00
parent c06aceaae9
commit 0e96e0a796
10 changed files with 141 additions and 52 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
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) {

View File

@ -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();
}
}

View File

@ -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,27 +970,52 @@ public abstract class XmppActivity extends Activity {
}
listener.onPresenceSelected();
} else {
final StringBuilder presence = new StringBuilder();
showPresenceSelectionDialog(presences,conversation,listener);
}
}
}
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[] presencesArray = presences.asStringArray();
int preselectedPresence = 0;
for (int i = 0; i < presencesArray.length; ++i) {
if (presencesArray[i].equals(contact.getLastPresence())) {
preselectedPresence = i;
break;
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;
}
}
presence.append(presencesArray[preselectedPresence]);
builder.setSingleChoiceItems(presencesArray,
preselectedPresence,
builder.setSingleChoiceItems(readableIdentities,
selectedResource.get(),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
presence.delete(0, presence.length());
presence.append(presencesArray[which]);
public void onClick(DialogInterface dialog, int which) {
selectedResource.set(which);
}
});
builder.setNegativeButton(R.string.cancel, null);
@ -991,7 +1024,8 @@ public abstract class XmppActivity extends Activity {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence.toString()));
Jid next = Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),resourceArray[selectedResource.get()]);
conversation.setNextCounterpart(next);
} catch (InvalidJidException e) {
conversation.setNextCounterpart(null);
}
@ -1000,11 +1034,8 @@ public abstract class XmppActivity extends Activity {
});
builder.create().show();
}
}
}
protected void onActivityResult(int requestCode, int resultCode,
final Intent data) {
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);

View File

@ -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) {

View File

@ -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;
}
}
}

View File

@ -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>