mirror of
https://github.com/moparisthebest/Conversations
synced 2024-11-28 03:32:15 -05:00
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;
|
return this.mLastseen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastPresence(String presence) {
|
public void setLastResource(String resource) {
|
||||||
this.mLastPresence = presence;
|
this.mLastPresence = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLastPresence() {
|
public String getLastResource() {
|
||||||
return this.mLastPresence;
|
return this.mLastPresence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@ import android.database.Cursor;
|
|||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||||
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.MimeUtils;
|
import eu.siacs.conversations.utils.MimeUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
@ -396,7 +396,7 @@ public class Message extends AbstractEntity {
|
|||||||
&& this.counterpart.equals(message.getCounterpart())
|
&& this.counterpart.equals(message.getCounterpart())
|
||||||
&& (body.equals(otherBody)
|
&& (body.equals(otherBody)
|
||||||
||(message.getEncryption() == Message.ENCRYPTION_PGP
|
||(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 {
|
} else {
|
||||||
return this.remoteMsgId == null
|
return this.remoteMsgId == null
|
||||||
&& this.counterpart.equals(message.getCounterpart())
|
&& this.counterpart.equals(message.getCounterpart())
|
||||||
@ -550,7 +550,7 @@ public class Message extends AbstractEntity {
|
|||||||
try {
|
try {
|
||||||
counterpart = Jid.fromParts(conversation.getJid().getLocalpart(),
|
counterpart = Jid.fromParts(conversation.getJid().getLocalpart(),
|
||||||
conversation.getJid().getDomainpart(),
|
conversation.getJid().getDomainpart(),
|
||||||
presences.asStringArray()[0]);
|
presences.toResourceArray()[0]);
|
||||||
return true;
|
return true;
|
||||||
} catch (InvalidJidException e) {
|
} catch (InvalidJidException e) {
|
||||||
counterpart = null;
|
counterpart = null;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package eu.siacs.conversations.entities;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -54,7 +57,7 @@ public class Presences {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] asStringArray() {
|
public String[] toResourceArray() {
|
||||||
synchronized (this.presences) {
|
synchronized (this.presences) {
|
||||||
final String[] presencesArray = new String[presences.size()];
|
final String[] presencesArray = new String[presences.size()];
|
||||||
presences.keySet().toArray(presencesArray);
|
presences.keySet().toArray(presencesArray);
|
||||||
@ -104,4 +107,28 @@ public class Presences {
|
|||||||
}
|
}
|
||||||
return true;
|
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) {
|
protected void updateLastseen(final Account account, final Jid from) {
|
||||||
final Contact contact = account.getRoster().getContact(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) {
|
protected String avatarData(Element items) {
|
||||||
|
@ -401,7 +401,12 @@ public class FileBackend {
|
|||||||
private Bitmap getFullsizeImagePreview(File file, int size) {
|
private Bitmap getFullsizeImagePreview(File file, int size) {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inSampleSize = calcSampleSize(file, size);
|
options.inSampleSize = calcSampleSize(file, size);
|
||||||
|
try {
|
||||||
return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
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) {
|
private Bitmap getVideoPreview(File file, int size) {
|
||||||
|
@ -196,7 +196,7 @@ public class XmppConnectionService extends Service {
|
|||||||
if (contact.getPresences().size() >= 1) {
|
if (contact.getPresences().size() >= 1) {
|
||||||
if (conversation.hasValidOtrSession()) {
|
if (conversation.hasValidOtrSession()) {
|
||||||
String otrResource = conversation.getOtrSession().getSessionID().getUserID();
|
String otrResource = conversation.getOtrSession().getSessionID().getUserID();
|
||||||
if (!(Arrays.asList(contact.getPresences().asStringArray()).contains(otrResource))) {
|
if (!(Arrays.asList(contact.getPresences().toResourceArray()).contains(otrResource))) {
|
||||||
conversation.endOtrIfNeeded();
|
conversation.endOtrIfNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ import android.preference.PreferenceManager;
|
|||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
@ -66,9 +67,13 @@ import net.java.otr4j.session.SessionID;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
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.Conversation;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.MucOptions;
|
import eu.siacs.conversations.entities.MucOptions;
|
||||||
|
import eu.siacs.conversations.entities.Presence;
|
||||||
import eu.siacs.conversations.entities.Presences;
|
import eu.siacs.conversations.entities.Presences;
|
||||||
|
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
||||||
import eu.siacs.conversations.services.AvatarService;
|
import eu.siacs.conversations.services.AvatarService;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
|
import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
|
||||||
import eu.siacs.conversations.ui.widget.Switch;
|
import eu.siacs.conversations.ui.widget.Switch;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.ExceptionHelper;
|
import eu.siacs.conversations.utils.ExceptionHelper;
|
||||||
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||||
@ -940,7 +948,7 @@ public abstract class XmppActivity extends Activity {
|
|||||||
} else if (!contact.showInRoster()) {
|
} else if (!contact.showInRoster()) {
|
||||||
showAddToRosterDialog(conversation);
|
showAddToRosterDialog(conversation);
|
||||||
} else {
|
} else {
|
||||||
Presences presences = contact.getPresences();
|
final Presences presences = contact.getPresences();
|
||||||
if (presences.size() == 0) {
|
if (presences.size() == 0) {
|
||||||
if (!contact.getOption(Contact.Options.TO)
|
if (!contact.getOption(Contact.Options.TO)
|
||||||
&& !contact.getOption(Contact.Options.ASKING)
|
&& !contact.getOption(Contact.Options.ASKING)
|
||||||
@ -954,7 +962,7 @@ public abstract class XmppActivity extends Activity {
|
|||||||
listener.onPresenceSelected();
|
listener.onPresenceSelected();
|
||||||
}
|
}
|
||||||
} else if (presences.size() == 1) {
|
} else if (presences.size() == 1) {
|
||||||
String presence = presences.asStringArray()[0];
|
String presence = presences.toResourceArray()[0];
|
||||||
try {
|
try {
|
||||||
conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence));
|
conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence));
|
||||||
} catch (InvalidJidException e) {
|
} catch (InvalidJidException e) {
|
||||||
@ -962,27 +970,52 @@ public abstract class XmppActivity extends Activity {
|
|||||||
}
|
}
|
||||||
listener.onPresenceSelected();
|
listener.onPresenceSelected();
|
||||||
} else {
|
} 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);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
builder.setTitle(getString(R.string.choose_presence));
|
builder.setTitle(getString(R.string.choose_presence));
|
||||||
final String[] presencesArray = presences.asStringArray();
|
final String[] resourceArray = presences.toResourceArray();
|
||||||
int preselectedPresence = 0;
|
Pair<Map<String, String>, Map<String, String>> typeAndName = presences.toTypeAndNameMap();
|
||||||
for (int i = 0; i < presencesArray.length; ++i) {
|
final Map<String,String> resourceTypeMap = typeAndName.first;
|
||||||
if (presencesArray[i].equals(contact.getLastPresence())) {
|
final Map<String,String> resourceNameMap = typeAndName.second;
|
||||||
preselectedPresence = i;
|
final String[] readableIdentities = new String[resourceArray.length];
|
||||||
break;
|
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(readableIdentities,
|
||||||
builder.setSingleChoiceItems(presencesArray,
|
selectedResource.get(),
|
||||||
preselectedPresence,
|
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog,
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
int which) {
|
selectedResource.set(which);
|
||||||
presence.delete(0, presence.length());
|
|
||||||
presence.append(presencesArray[which]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(R.string.cancel, null);
|
builder.setNegativeButton(R.string.cancel, null);
|
||||||
@ -991,7 +1024,8 @@ public abstract class XmppActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
try {
|
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) {
|
} catch (InvalidJidException e) {
|
||||||
conversation.setNextCounterpart(null);
|
conversation.setNextCounterpart(null);
|
||||||
}
|
}
|
||||||
@ -1000,11 +1034,8 @@ public abstract class XmppActivity extends Activity {
|
|||||||
});
|
});
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode,
|
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
||||||
final Intent data) {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) {
|
if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) {
|
||||||
mPendingConferenceInvite = ConferenceInvite.parse(data);
|
mPendingConferenceInvite = ConferenceInvite.parse(data);
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
@ -31,6 +32,8 @@ import eu.siacs.conversations.xmpp.jid.Jid;
|
|||||||
public final class CryptoHelper {
|
public final class CryptoHelper {
|
||||||
public static final String FILETRANSFER = "?FILETRANSFERv1:";
|
public static final String FILETRANSFER = "?FILETRANSFERv1:";
|
||||||
private final static char[] hexArray = "0123456789abcdef".toCharArray();
|
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 };
|
final public static byte[] ONE = new byte[] { 0, 0, 0, 1 };
|
||||||
|
|
||||||
public static String bytesToHex(byte[] bytes) {
|
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.Message;
|
||||||
import eu.siacs.conversations.entities.Presence;
|
import eu.siacs.conversations.entities.Presence;
|
||||||
import eu.siacs.conversations.entities.Transferable;
|
import eu.siacs.conversations.entities.Transferable;
|
||||||
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
|
|
||||||
public class UIHelper {
|
public class UIHelper {
|
||||||
@ -286,4 +287,21 @@ public class UIHelper {
|
|||||||
return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24);
|
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="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="delete_messages">Delete messages</string>
|
||||||
<string name="also_end_conversation">End this conversation afterwards</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_unencrypted_message">Send unencrypted message</string>
|
||||||
<string name="send_message_to_x">Send message to %s</string>
|
<string name="send_message_to_x">Send message to %s</string>
|
||||||
<string name="send_otr_message">Send OTR encrypted message</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="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="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="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>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user