Merge commit 'v2.9.0' into develop
|  | @ -11,7 +11,7 @@ android: | ||||||
|     - '.+' |     - '.+' | ||||||
| before_script: | before_script: | ||||||
|     - mkdir libs |     - mkdir libs | ||||||
|     - wget -O libs/libwebrtc-m84.aar http://gultsch.de/files/libwebrtc-m84.aar |     - wget -O libs/libwebrtc-m85.aar https://gultsch.de/files/libwebrtc-m85.aar | ||||||
| script: | script: | ||||||
|     - ./gradlew assembleConversationsFreeSystemRelease |     - ./gradlew assembleConversationsFreeSystemRelease | ||||||
|     - ./gradlew assembleQuicksyFreeCompatRelease |     - ./gradlew assembleQuicksyFreeCompatRelease | ||||||
|  |  | ||||||
|  | @ -1,5 +1,12 @@ | ||||||
| # Changelog | # Changelog | ||||||
| 
 | 
 | ||||||
|  | ### Version 2.9.0 | ||||||
|  | 
 | ||||||
|  | * Search individual conversations | ||||||
|  | * Notify user if message delivery fails | ||||||
|  | * Remember display names (nicks) from Quicksy users across restarts | ||||||
|  | * Add button to start Orbot (Tor) from notification if necessary | ||||||
|  | 
 | ||||||
| ### Version 2.8.10 | ### Version 2.8.10 | ||||||
| 
 | 
 | ||||||
| * Handle GPX files | * Handle GPX files | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ dependencies { | ||||||
|     implementation 'com.squareup.okhttp3:okhttp:3.12.12' |     implementation 'com.squareup.okhttp3:okhttp:3.12.12' | ||||||
|     implementation 'com.google.guava:guava:27.1-android' |     implementation 'com.google.guava:guava:27.1-android' | ||||||
|     quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.11.1' |     quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.11.1' | ||||||
|     //implementation fileTree(include: ['libwebrtc-m83.aar'], dir: 'libs') |     //implementation fileTree(include: ['libwebrtc-m85.aar'], dir: 'libs') | ||||||
|     implementation 'org.webrtc:google-webrtc:1.0.32006' |     implementation 'org.webrtc:google-webrtc:1.0.32006' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -96,8 +96,8 @@ android { | ||||||
|     defaultConfig { |     defaultConfig { | ||||||
|         minSdkVersion 21 |         minSdkVersion 21 | ||||||
|         targetSdkVersion 28 |         targetSdkVersion 28 | ||||||
|         versionCode 398 |         versionCode 399 | ||||||
|         versionName "2.8.10.1" |         versionName "2.9.0" | ||||||
|         archivesBaseName += "-$versionName" |         archivesBaseName += "-$versionName" | ||||||
|         applicationId "eu.sum7.conversations" |         applicationId "eu.sum7.conversations" | ||||||
|         resValue "string", "applicationId", applicationId |         resValue "string", "applicationId", applicationId | ||||||
|  |  | ||||||
|  | @ -8,4 +8,5 @@ | ||||||
|     <string name="magic_create_text_on_x">Zostałeś zaproszony do %1$s. Poprowadzimy ciebie przez proces tworzenia konta.\nWybierając %1$s jako dostawcę będziesz mógł komunikować się z innymi użytkownikami podając swój pełny adres XMPP.</string> |     <string name="magic_create_text_on_x">Zostałeś zaproszony do %1$s. Poprowadzimy ciebie przez proces tworzenia konta.\nWybierając %1$s jako dostawcę będziesz mógł komunikować się z innymi użytkownikami podając swój pełny adres XMPP.</string> | ||||||
|     <string name="magic_create_text_fixed">Zostałeś zaproszony do %1$s. Nazwa użytkownika została już dla ciebie wybrana. Poprowadzimy ciebie przez proces tworzenia konta.\nBęziesz mógł komunikować się z innymi użytkownikami podając swój adres XMPP.</string> |     <string name="magic_create_text_fixed">Zostałeś zaproszony do %1$s. Nazwa użytkownika została już dla ciebie wybrana. Poprowadzimy ciebie przez proces tworzenia konta.\nBęziesz mógł komunikować się z innymi użytkownikami podając swój adres XMPP.</string> | ||||||
|     <string name="your_server_invitation">Zaproszenie twojego serwera</string> |     <string name="your_server_invitation">Zaproszenie twojego serwera</string> | ||||||
|  |     <string name="improperly_formatted_provisioning">Niepoprawnie sformatowany kod zaopatrywania</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
|     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||||||
|     <uses-permission android:name="android.permission.READ_CONTACTS" /> |     <uses-permission android:name="android.permission.READ_CONTACTS" /> | ||||||
|     <uses-permission android:name="android.permission.READ_PROFILE" /> |     <uses-permission android:name="android.permission.READ_PROFILE" /> | ||||||
|  |     <uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="22" /> | ||||||
|     <uses-permission android:name="android.permission.INTERNET" /> |     <uses-permission android:name="android.permission.INTERNET" /> | ||||||
|     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||||||
|     <uses-permission android:name="android.permission.WAKE_LOCK" /> |     <uses-permission android:name="android.permission.WAKE_LOCK" /> | ||||||
|  | @ -36,10 +37,6 @@ | ||||||
|     <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> |     <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> | ||||||
|     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> |     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> | ||||||
| 
 | 
 | ||||||
|     <uses-permission |  | ||||||
|         android:name="android.permission.READ_PHONE_STATE" |  | ||||||
|         tools:node="remove" /> |  | ||||||
| 
 |  | ||||||
|     <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" /> |     <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" /> | ||||||
| 
 | 
 | ||||||
|     <uses-feature |     <uses-feature | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ public final class Config { | ||||||
|     public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments |     public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments | ||||||
| 
 | 
 | ||||||
|     public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; |     public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; | ||||||
|     public static final boolean MUC_LEAVE_BEFORE_JOIN = true; |     public static final boolean MUC_LEAVE_BEFORE_JOIN = false; | ||||||
| 
 | 
 | ||||||
|     public static final boolean USE_LMC_VERSION_1_1 = true; |     public static final boolean USE_LMC_VERSION_1_1 = true; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -615,6 +615,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable | ||||||
|         return UIHelper.getColorForName(jid.asBareJid().toString()); |         return UIHelper.getColorForName(jid.asBareJid().toString()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getAvatarName() { | ||||||
|  |         throw new IllegalStateException("This method should not be called"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public enum State { |     public enum State { | ||||||
|         DISABLED(false, false), |         DISABLED(false, false), | ||||||
|         OFFLINE(false), |         OFFLINE(false), | ||||||
|  |  | ||||||
|  | @ -248,4 +248,9 @@ public class Bookmark extends Element implements ListItem { | ||||||
| 	public int getAvatarBackgroundColor() { | 	public int getAvatarBackgroundColor() { | ||||||
| 		return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName()); | 		return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName()); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getAvatarName() { | ||||||
|  | 		return getDisplayName(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ public class Contact implements ListItem, Blockable { | ||||||
| 
 | 
 | ||||||
| 	public static final String SYSTEMNAME = "systemname"; | 	public static final String SYSTEMNAME = "systemname"; | ||||||
| 	public static final String SERVERNAME = "servername"; | 	public static final String SERVERNAME = "servername"; | ||||||
|  | 	public static final String PRESENCE_NAME = "presence_name"; | ||||||
| 	public static final String JID = "jid"; | 	public static final String JID = "jid"; | ||||||
| 	public static final String OPTIONS = "options"; | 	public static final String OPTIONS = "options"; | ||||||
| 	public static final String SYSTEMACCOUNT = "systemaccount"; | 	public static final String SYSTEMACCOUNT = "systemaccount"; | ||||||
|  | @ -62,13 +63,14 @@ public class Contact implements ListItem, Blockable { | ||||||
| 	private long mLastseen = 0; | 	private long mLastseen = 0; | ||||||
| 	private String mLastPresence = null; | 	private String mLastPresence = null; | ||||||
| 
 | 
 | ||||||
| 	public Contact(final String account, final String systemName, final String serverName, | 	public Contact(final String account, final String systemName, final String serverName, final String presenceName, | ||||||
| 	               final Jid jid, final int subscription, final String photoUri, | 	               final Jid jid, final int subscription, final String photoUri, | ||||||
| 	               final Uri systemAccount, final String keys, final String avatar, final long lastseen, | 	               final Uri systemAccount, final String keys, final String avatar, final long lastseen, | ||||||
| 	               final String presence, final String groups) { | 	               final String presence, final String groups) { | ||||||
| 		this.accountUuid = account; | 		this.accountUuid = account; | ||||||
| 		this.systemName = systemName; | 		this.systemName = systemName; | ||||||
| 		this.serverName = serverName; | 		this.serverName = serverName; | ||||||
|  | 		this.presenceName = presenceName; | ||||||
| 		this.jid = jid; | 		this.jid = jid; | ||||||
| 		this.subscription = subscription; | 		this.subscription = subscription; | ||||||
| 		this.photoUri = photoUri; | 		this.photoUri = photoUri; | ||||||
|  | @ -116,6 +118,7 @@ public class Contact implements ListItem, Blockable { | ||||||
| 		return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)), | 		return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)), | ||||||
| 				cursor.getString(cursor.getColumnIndex(SYSTEMNAME)), | 				cursor.getString(cursor.getColumnIndex(SYSTEMNAME)), | ||||||
| 				cursor.getString(cursor.getColumnIndex(SERVERNAME)), | 				cursor.getString(cursor.getColumnIndex(SERVERNAME)), | ||||||
|  | 				cursor.getString(cursor.getColumnIndex(PRESENCE_NAME)), | ||||||
| 				jid, | 				jid, | ||||||
| 				cursor.getInt(cursor.getColumnIndex(OPTIONS)), | 				cursor.getInt(cursor.getColumnIndex(OPTIONS)), | ||||||
| 				cursor.getString(cursor.getColumnIndex(PHOTOURI)), | 				cursor.getString(cursor.getColumnIndex(PHOTOURI)), | ||||||
|  | @ -213,6 +216,7 @@ public class Contact implements ListItem, Blockable { | ||||||
| 			values.put(ACCOUNT, accountUuid); | 			values.put(ACCOUNT, accountUuid); | ||||||
| 			values.put(SYSTEMNAME, systemName); | 			values.put(SYSTEMNAME, systemName); | ||||||
| 			values.put(SERVERNAME, serverName); | 			values.put(SERVERNAME, serverName); | ||||||
|  | 			values.put(PRESENCE_NAME, presenceName); | ||||||
| 			values.put(JID, jid.toString()); | 			values.put(JID, jid.toString()); | ||||||
| 			values.put(OPTIONS, subscription); | 			values.put(OPTIONS, subscription); | ||||||
| 			values.put(SYSTEMACCOUNT, systemAccount != null ? systemAccount.toString() : null); | 			values.put(SYSTEMACCOUNT, systemAccount != null ? systemAccount.toString() : null); | ||||||
|  | @ -554,6 +558,15 @@ public class Contact implements ListItem, Blockable { | ||||||
| 		return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName()); | 		return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getAvatarName() { | ||||||
|  | 		return getDisplayName(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean hasAvatarOrPresenceName() { | ||||||
|  | 		return (avatar != null && avatar.getFilename() != null) || presenceName != null; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public final class Options { | 	public final class Options { | ||||||
| 		public static final int TO = 0; | 		public static final int TO = 0; | ||||||
| 		public static final int FROM = 1; | 		public static final int FROM = 1; | ||||||
|  |  | ||||||
|  | @ -186,6 +186,18 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public int countFailedDeliveries() { | ||||||
|  |         int count = 0; | ||||||
|  |         synchronized (this.messages) { | ||||||
|  |             for(final Message message : this.messages) { | ||||||
|  |                 if (message.getStatus() == Message.STATUS_SEND_FAILED) { | ||||||
|  |                     ++count; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public Message getLastEditableMessage() { |     public Message getLastEditableMessage() { | ||||||
|         synchronized (this.messages) { |         synchronized (this.messages) { | ||||||
|             for (final Message message : Lists.reverse(this.messages)) { |             for (final Message message : Lists.reverse(this.messages)) { | ||||||
|  | @ -1066,6 +1078,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         return UIHelper.getColorForName(getName().toString()); |         return UIHelper.getColorForName(getName().toString()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getAvatarName() { | ||||||
|  |         return getName().toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public interface OnMessageFound { |     public interface OnMessageFound { | ||||||
|         void onMessageFound(final Message message); |         void onMessageFound(final Message message); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -684,6 +684,11 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getAvatarName() { | ||||||
|  | 		return UIHelper.getMessageDisplayName(this); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public boolean isOOb() { | 	public boolean isOOb() { | ||||||
| 		return oob; | 		return oob; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -900,5 +900,10 @@ public class MucOptions { | ||||||
|             final String seed = realJid != null ? realJid.asBareJid().toString() : null; |             final String seed = realJid != null ? realJid.asBareJid().toString() : null; | ||||||
|             return UIHelper.getColorForName(seed == null ? getName() : seed); |             return UIHelper.getColorForName(seed == null ? getName() : seed); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public String getAvatarName() { | ||||||
|  |             return getConversation().getName().toString(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -79,6 +79,11 @@ public class RawBlockable implements ListItem, Blockable { | ||||||
|         return  UIHelper.getColorForName(jid.toEscapedString()); |         return  UIHelper.getColorForName(jid.toEscapedString()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getAvatarName() { | ||||||
|  |         return getDisplayName(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public int compareTo(ListItem o) { |     public int compareTo(ListItem o) { | ||||||
|         return this.getDisplayName().compareToIgnoreCase( |         return this.getDisplayName().compareToIgnoreCase( | ||||||
|  |  | ||||||
|  | @ -55,6 +55,11 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> { | ||||||
|         return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name); |         return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getAvatarName() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean equals(Object o) { |     public boolean equals(Object o) { | ||||||
|         if (this == o) return true; |         if (this == o) return true; | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ public class PresenceGenerator extends AbstractGenerator { | ||||||
|             Element cap = packet.addChild("c", |             Element cap = packet.addChild("c", | ||||||
|                     "http://jabber.org/protocol/caps"); |                     "http://jabber.org/protocol/caps"); | ||||||
|             cap.setAttribute("hash", "sha-1"); |             cap.setAttribute("hash", "sha-1"); | ||||||
| 			cap.setAttribute("node", "https://sum7.eu"); |             cap.setAttribute("node", "http://conversations.im"); | ||||||
|             cap.setAttribute("ver", capHash); |             cap.setAttribute("ver", capHash); | ||||||
|         } |         } | ||||||
|         return packet; |         return packet; | ||||||
|  |  | ||||||
|  | @ -300,6 +300,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|         } else { |         } else { | ||||||
|             Contact contact = account.getRoster().getContact(user); |             Contact contact = account.getRoster().getContact(user); | ||||||
|             if (contact.setPresenceName(nick)) { |             if (contact.setPresenceName(nick)) { | ||||||
|  |                 mXmppConnectionService.syncRoster(account); | ||||||
|                 mXmppConnectionService.getAvatarService().clear(contact); |                 mXmppConnectionService.getAvatarService().clear(contact); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -307,8 +308,14 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|         mXmppConnectionService.updateAccountUi(); |         mXmppConnectionService.updateAccountUi(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean handleErrorMessage(Account account, MessagePacket packet) { |     private boolean handleErrorMessage(final Account account, final MessagePacket packet) { | ||||||
|         if (packet.getType() == MessagePacket.TYPE_ERROR) { |         if (packet.getType() == MessagePacket.TYPE_ERROR) { | ||||||
|  |             if (packet.fromServer(account)) { | ||||||
|  |                 final Pair<MessagePacket, Long> forwarded = packet.getForwardedMessagePacket("received", "urn:xmpp:carbons:2"); | ||||||
|  |                 if (forwarded != null) { | ||||||
|  |                     return handleErrorMessage(account, forwarded.first); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             final Jid from = packet.getFrom(); |             final Jid from = packet.getFrom(); | ||||||
|             final String id = packet.getId(); |             final String id = packet.getId(); | ||||||
|             if (from != null && id != null) { |             if (from != null && id != null) { | ||||||
|  | @ -362,7 +369,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|         final Element result = MessageArchiveService.Version.findResult(original); |         final Element result = MessageArchiveService.Version.findResult(original); | ||||||
|         final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid")); |         final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid")); | ||||||
|         if (query != null && query.validFrom(original.getFrom())) { |         if (query != null && query.validFrom(original.getFrom())) { | ||||||
|             Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", query.version.namespace); |             final Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", query.version.namespace); | ||||||
|             if (f == null) { |             if (f == null) { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  | @ -370,6 +377,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|             packet = f.first; |             packet = f.first; | ||||||
|             serverMsgId = result.getAttribute("id"); |             serverMsgId = result.getAttribute("id"); | ||||||
|             query.incrementMessageCount(); |             query.incrementMessageCount(); | ||||||
|  |             if (handleErrorMessage(account, packet)) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|         } else if (query != null) { |         } else if (query != null) { | ||||||
|             Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received mam result from invalid sender"); |             Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received mam result from invalid sender"); | ||||||
|             return; |             return; | ||||||
|  | @ -1011,8 +1021,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
| 
 | 
 | ||||||
|         final String nick = packet.findChildContent("nick", Namespace.NICK); |         final String nick = packet.findChildContent("nick", Namespace.NICK); | ||||||
|         if (nick != null && InvalidJid.hasValidFrom(original)) { |         if (nick != null && InvalidJid.hasValidFrom(original)) { | ||||||
|             Contact contact = account.getRoster().getContact(from); |             final Contact contact = account.getRoster().getContact(from); | ||||||
|             if (contact.setPresenceName(nick)) { |             if (contact.setPresenceName(nick)) { | ||||||
|  |                 mXmppConnectionService.syncRoster(account); | ||||||
|                 mXmppConnectionService.getAvatarService().clear(contact); |                 mXmppConnectionService.getAvatarService().clear(contact); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -337,6 +337,7 @@ public class PresenceParser extends AbstractParser implements | ||||||
| 			mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false); | 			mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false); | ||||||
| 		} else if (type.equals("subscribe")) { | 		} else if (type.equals("subscribe")) { | ||||||
| 			if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) { | 			if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) { | ||||||
|  | 				mXmppConnectionService.syncRoster(account); | ||||||
| 				mXmppConnectionService.getAvatarService().clear(contact); | 				mXmppConnectionService.getAvatarService().clear(contact); | ||||||
| 			} | 			} | ||||||
| 			if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) { | 			if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) { | ||||||
|  |  | ||||||
|  | @ -63,11 +63,12 @@ import eu.siacs.conversations.xmpp.Jid; | ||||||
| public class DatabaseBackend extends SQLiteOpenHelper { | public class DatabaseBackend extends SQLiteOpenHelper { | ||||||
| 
 | 
 | ||||||
|     private static final String DATABASE_NAME = "history"; |     private static final String DATABASE_NAME = "history"; | ||||||
|     private static final int DATABASE_VERSION = 47; |     private static final int DATABASE_VERSION = 48; | ||||||
|     private static DatabaseBackend instance = null; |     private static DatabaseBackend instance = null; | ||||||
|     private static String CREATE_CONTATCS_STATEMENT = "create table " |     private static String CREATE_CONTATCS_STATEMENT = "create table " | ||||||
|             + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " |             + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " | ||||||
|             + Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT," |             + Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT," | ||||||
|  |             + Contact.PRESENCE_NAME + " TEXT," | ||||||
|             + Contact.JID + " TEXT," + Contact.KEYS + " TEXT," |             + Contact.JID + " TEXT," + Contact.KEYS + " TEXT," | ||||||
|             + Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER," |             + Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER," | ||||||
|             + Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, " |             + Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, " | ||||||
|  | @ -559,6 +560,9 @@ public class DatabaseBackend extends SQLiteOpenHelper { | ||||||
|           db.execSQL(CREATE_RESOLVER_RESULTS_TABLE); |           db.execSQL(CREATE_RESOLVER_RESULTS_TABLE); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if (oldVersion < 48 && newVersion >= 48) { | ||||||
|  |             db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " + Contact.PRESENCE_NAME + " TEXT"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void canonicalizeJids(SQLiteDatabase db) { |     private void canonicalizeJids(SQLiteDatabase db) { | ||||||
|  | @ -577,7 +581,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             String updateArgs[] = { |             final String[] updateArgs = { | ||||||
|                     newJid, |                     newJid, | ||||||
|                     cursor.getString(cursor.getColumnIndex(Conversation.UUID)), |                     cursor.getString(cursor.getColumnIndex(Conversation.UUID)), | ||||||
|             }; |             }; | ||||||
|  | @ -780,11 +784,20 @@ public class DatabaseBackend extends SQLiteOpenHelper { | ||||||
|         return list; |         return list; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Cursor getMessageSearchCursor(List<String> term) { |     public Cursor getMessageSearchCursor(final List<String> term, final String uuid) { | ||||||
|         SQLiteDatabase db = this.getReadableDatabase(); |         final SQLiteDatabase db = this.getReadableDatabase(); | ||||||
|         String SQL = "SELECT " + Message.TABLENAME + ".*," + Conversation.TABLENAME + '.' + Conversation.CONTACTJID + ',' + Conversation.TABLENAME + '.' + Conversation.ACCOUNT + ',' + Conversation.TABLENAME + '.' + Conversation.MODE + " FROM " + Message.TABLENAME + " join " + Conversation.TABLENAME + " on " + Message.TABLENAME + '.' + Message.CONVERSATION + '=' + Conversation.TABLENAME + '.' + Conversation.UUID + " join messages_index ON messages_index.uuid=messages.uuid where " + Message.ENCRYPTION + " NOT IN(" + Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE + ',' + Message.ENCRYPTION_PGP + ',' + Message.ENCRYPTION_DECRYPTION_FAILED + ',' + Message.ENCRYPTION_AXOLOTL_FAILED + ") AND " + Message.TYPE + " IN(" + Message.TYPE_TEXT + ',' + Message.TYPE_PRIVATE + ") AND messages_index.body MATCH ? ORDER BY " + Message.TIME_SENT + " DESC limit " + Config.MAX_SEARCH_RESULTS; |         final StringBuilder SQL = new StringBuilder(); | ||||||
|  |         final String[] selectionArgs; | ||||||
|  |         SQL.append("SELECT " + Message.TABLENAME + ".*," + Conversation.TABLENAME + '.' + Conversation.CONTACTJID + ',' + Conversation.TABLENAME + '.' + Conversation.ACCOUNT + ',' + Conversation.TABLENAME + '.' + Conversation.MODE + " FROM " + Message.TABLENAME + " join " + Conversation.TABLENAME + " on " + Message.TABLENAME + '.' + Message.CONVERSATION + '=' + Conversation.TABLENAME + '.' + Conversation.UUID + " join messages_index ON messages_index.uuid=messages.uuid where " + Message.ENCRYPTION + " NOT IN(" + Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE + ',' + Message.ENCRYPTION_PGP + ',' + Message.ENCRYPTION_DECRYPTION_FAILED + ',' + Message.ENCRYPTION_AXOLOTL_FAILED + ") AND " + Message.TYPE + " IN(" + Message.TYPE_TEXT + ',' + Message.TYPE_PRIVATE + ") AND messages_index.body MATCH ?"); | ||||||
|  |         if (uuid == null) { | ||||||
|  |             selectionArgs = new String[]{FtsUtils.toMatchString(term)}; | ||||||
|  |         } else { | ||||||
|  |             selectionArgs = new String[]{FtsUtils.toMatchString(term), uuid}; | ||||||
|  |             SQL.append(" AND "+Conversation.TABLENAME+'.'+Conversation.UUID+"=?"); | ||||||
|  |         } | ||||||
|  |         SQL.append(" ORDER BY " + Message.TIME_SENT + " DESC limit " + Config.MAX_SEARCH_RESULTS); | ||||||
|         Log.d(Config.LOGTAG, "search term: " + FtsUtils.toMatchString(term)); |         Log.d(Config.LOGTAG, "search term: " + FtsUtils.toMatchString(term)); | ||||||
|         return db.rawQuery(SQL, new String[]{FtsUtils.toMatchString(term)}); |         return db.rawQuery(SQL.toString(), selectionArgs); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public List<String> markFileAsDeleted(final File file, final boolean internal) { |     public List<String> markFileAsDeleted(final File file, final boolean internal) { | ||||||
|  | @ -1006,7 +1019,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { | ||||||
|         final SQLiteDatabase db = this.getWritableDatabase(); |         final SQLiteDatabase db = this.getWritableDatabase(); | ||||||
|         db.beginTransaction(); |         db.beginTransaction(); | ||||||
|         for (Contact contact : roster.getContacts()) { |         for (Contact contact : roster.getContacts()) { | ||||||
|             if (contact.getOption(Contact.Options.IN_ROSTER) || contact.getAvatarFilename() != null || contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) { |             if (contact.getOption(Contact.Options.IN_ROSTER) || contact.hasAvatarOrPresenceName() || contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) { | ||||||
|                 db.insert(Contact.TABLENAME, null, contact.getContentValues()); |                 db.insert(Contact.TABLENAME, null, contact.getContentValues()); | ||||||
|             } else { |             } else { | ||||||
|                 String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?"; |                 String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?"; | ||||||
|  |  | ||||||
|  | @ -685,5 +685,6 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { | ||||||
| 
 | 
 | ||||||
| 	public interface Avatarable { | 	public interface Avatarable { | ||||||
| 		@ColorInt int getAvatarBackgroundColor(); | 		@ColorInt int getAvatarBackgroundColor(); | ||||||
|  | 		String getAvatarName(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ import android.preference.PreferenceManager; | ||||||
| import android.support.v4.content.ContextCompat; | import android.support.v4.content.ContextCompat; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| 
 | 
 | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | 
 | ||||||
| import eu.siacs.conversations.Config; | import eu.siacs.conversations.Config; | ||||||
| import eu.siacs.conversations.utils.Compatibility; | import eu.siacs.conversations.utils.Compatibility; | ||||||
| 
 | 
 | ||||||
|  | @ -19,17 +21,13 @@ public class EventReceiver extends BroadcastReceiver { | ||||||
|     @Override |     @Override | ||||||
|     public void onReceive(final Context context, final Intent originalIntent) { |     public void onReceive(final Context context, final Intent originalIntent) { | ||||||
|         final Intent intentForService = new Intent(context, XmppConnectionService.class); |         final Intent intentForService = new Intent(context, XmppConnectionService.class); | ||||||
|         if (originalIntent.getAction() != null) { |         final String action = originalIntent.getAction(); | ||||||
|             intentForService.setAction(originalIntent.getAction()); |         intentForService.setAction(Strings.isNullOrEmpty(action) ? "other" : action); | ||||||
|         final Bundle extras = originalIntent.getExtras(); |         final Bundle extras = originalIntent.getExtras(); | ||||||
|         if (extras != null) { |         if (extras != null) { | ||||||
|             intentForService.putExtras(extras); |             intentForService.putExtras(extras); | ||||||
|         } |         } | ||||||
|         } else { |         if ("ui".equals(action) || hasEnabledAccounts(context)) { | ||||||
|             intentForService.setAction("other"); |  | ||||||
|         } |  | ||||||
|         final String action = originalIntent.getAction(); |  | ||||||
|         if (action.equals("ui") || hasEnabledAccounts(context)) { |  | ||||||
|             Compatibility.startService(context, intentForService); |             Compatibility.startService(context, intentForService); | ||||||
|         } else { |         } else { | ||||||
|             Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction()); |             Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction()); | ||||||
|  |  | ||||||
|  | @ -56,18 +56,20 @@ public class MessageSearchTask implements Runnable, Cancellable { | ||||||
| 
 | 
 | ||||||
| 	private final XmppConnectionService xmppConnectionService; | 	private final XmppConnectionService xmppConnectionService; | ||||||
| 	private final List<String> term; | 	private final List<String> term; | ||||||
|  | 	private final String uuid; | ||||||
| 	private final OnSearchResultsAvailable onSearchResultsAvailable; | 	private final OnSearchResultsAvailable onSearchResultsAvailable; | ||||||
| 
 | 
 | ||||||
| 	private boolean isCancelled = false; | 	private boolean isCancelled = false; | ||||||
| 
 | 
 | ||||||
| 	private MessageSearchTask(XmppConnectionService xmppConnectionService, List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) { | 	private MessageSearchTask(XmppConnectionService xmppConnectionService, List<String> term, final String uuid, OnSearchResultsAvailable onSearchResultsAvailable) { | ||||||
| 		this.xmppConnectionService = xmppConnectionService; | 		this.xmppConnectionService = xmppConnectionService; | ||||||
| 		this.term = term; | 		this.term = term; | ||||||
|  | 		this.uuid = uuid; | ||||||
| 		this.onSearchResultsAvailable = onSearchResultsAvailable; | 		this.onSearchResultsAvailable = onSearchResultsAvailable; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static void search(XmppConnectionService xmppConnectionService, List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) { | 	public static void search(XmppConnectionService xmppConnectionService, List<String> term, final String uuid, OnSearchResultsAvailable onSearchResultsAvailable) { | ||||||
| 		new MessageSearchTask(xmppConnectionService, term, onSearchResultsAvailable).executeInBackground(); | 		new MessageSearchTask(xmppConnectionService, term, uuid, onSearchResultsAvailable).executeInBackground(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static void cancelRunningTasks() { | 	public static void cancelRunningTasks() { | ||||||
|  | @ -86,7 +88,7 @@ public class MessageSearchTask implements Runnable, Cancellable { | ||||||
| 		try { | 		try { | ||||||
| 			final HashMap<String, Conversational> conversationCache = new HashMap<>(); | 			final HashMap<String, Conversational> conversationCache = new HashMap<>(); | ||||||
| 			final List<Message> result = new ArrayList<>(); | 			final List<Message> result = new ArrayList<>(); | ||||||
| 			cursor = xmppConnectionService.databaseBackend.getMessageSearchCursor(term); | 			cursor = xmppConnectionService.databaseBackend.getMessageSearchCursor(term, uuid); | ||||||
| 			long dbTimer = SystemClock.elapsedRealtime(); | 			long dbTimer = SystemClock.elapsedRealtime(); | ||||||
| 			if (isCancelled) { | 			if (isCancelled) { | ||||||
| 				Log.d(Config.LOGTAG, "canceled search task"); | 				Log.d(Config.LOGTAG, "canceled search task"); | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ import eu.siacs.conversations.ui.TimePreference; | ||||||
| import eu.siacs.conversations.utils.AccountUtils; | import eu.siacs.conversations.utils.AccountUtils; | ||||||
| import eu.siacs.conversations.utils.Compatibility; | import eu.siacs.conversations.utils.Compatibility; | ||||||
| import eu.siacs.conversations.utils.GeoHelper; | import eu.siacs.conversations.utils.GeoHelper; | ||||||
|  | import eu.siacs.conversations.utils.TorServiceUtils; | ||||||
| import eu.siacs.conversations.utils.UIHelper; | import eu.siacs.conversations.utils.UIHelper; | ||||||
| import eu.siacs.conversations.xmpp.XmppConnection; | import eu.siacs.conversations.xmpp.XmppConnection; | ||||||
| import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; | import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; | ||||||
|  | @ -82,6 +83,7 @@ public class NotificationService { | ||||||
|     private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; |     private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; | ||||||
|     private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; |     private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; | ||||||
|     public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; |     public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; | ||||||
|  |     private static final int DELIVERY_FAILED_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 12; | ||||||
|     private final XmppConnectionService mXmppConnectionService; |     private final XmppConnectionService mXmppConnectionService; | ||||||
|     private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>(); |     private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>(); | ||||||
|     private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>(); |     private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>(); | ||||||
|  | @ -220,9 +222,20 @@ public class NotificationService { | ||||||
|         quietHoursChannel.setSound(null, null); |         quietHoursChannel.setSound(null, null); | ||||||
| 
 | 
 | ||||||
|         notificationManager.createNotificationChannel(quietHoursChannel); |         notificationManager.createNotificationChannel(quietHoursChannel); | ||||||
|  | 
 | ||||||
|  |         final NotificationChannel deliveryFailedChannel = new NotificationChannel("delivery_failed", | ||||||
|  |                 c.getString(R.string.delivery_failed_channel_name), | ||||||
|  |                 NotificationManager.IMPORTANCE_DEFAULT); | ||||||
|  |         deliveryFailedChannel.setShowBadge(false); | ||||||
|  |         deliveryFailedChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), new AudioAttributes.Builder() | ||||||
|  |                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) | ||||||
|  |                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) | ||||||
|  |                 .build()); | ||||||
|  |         deliveryFailedChannel.setGroup("chats"); | ||||||
|  |         notificationManager.createNotificationChannel(deliveryFailedChannel); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean notify(final Message message) { |     private boolean notify(final Message message) { | ||||||
|         final Conversation conversation = (Conversation) message.getConversation(); |         final Conversation conversation = (Conversation) message.getConversation(); | ||||||
|         return message.getStatus() == Message.STATUS_RECEIVED |         return message.getStatus() == Message.STATUS_RECEIVED | ||||||
|                 && !conversation.isMuted() |                 && !conversation.isMuted() | ||||||
|  | @ -342,6 +355,37 @@ public class NotificationService { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void pushFailedDelivery(final Message message) { | ||||||
|  |         final Conversation conversation = (Conversation) message.getConversation(); | ||||||
|  |         final boolean isScreenOn = mXmppConnectionService.isInteractive(); | ||||||
|  |         if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { | ||||||
|  |             Log.d(Config.LOGTAG, message.getConversation().getAccount().getJid().asBareJid() + ": suppressing failed delivery notification because conversation is open"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         final PendingIntent pendingIntent = createContentIntent(conversation); | ||||||
|  |         final int notificationId = generateRequestCode(conversation, 0) + DELIVERY_FAILED_NOTIFICATION_ID; | ||||||
|  |         final int failedDeliveries = conversation.countFailedDeliveries(); | ||||||
|  |         final Notification notification = | ||||||
|  |                 new Builder(mXmppConnectionService, "delivery_failed") | ||||||
|  |                         .setContentTitle(conversation.getName()) | ||||||
|  |                         .setAutoCancel(true) | ||||||
|  |                         .setSmallIcon(R.drawable.ic_error_white_24dp) | ||||||
|  |                         .setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, failedDeliveries)) | ||||||
|  |                         .setGroup("delivery_failed") | ||||||
|  |                         .setContentIntent(pendingIntent).build(); | ||||||
|  |         final Notification summaryNotification = | ||||||
|  |                 new Builder(mXmppConnectionService, "delivery_failed") | ||||||
|  |                         .setContentTitle(mXmppConnectionService.getString(R.string.failed_deliveries)) | ||||||
|  |                         .setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, 1024)) | ||||||
|  |                         .setSmallIcon(R.drawable.ic_error_white_24dp) | ||||||
|  |                         .setGroup("delivery_failed") | ||||||
|  |                         .setGroupSummary(true) | ||||||
|  |                         .setAutoCancel(true) | ||||||
|  |                         .build(); | ||||||
|  |         notify(notificationId, notification); | ||||||
|  |         notify(DELIVERY_FAILED_NOTIFICATION_ID, summaryNotification); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public void showIncomingCallNotification(final AbstractJingleConnection.Id id, final Set<Media> media) { |     public void showIncomingCallNotification(final AbstractJingleConnection.Id id, final Set<Media> media) { | ||||||
|         final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class); |         final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class); | ||||||
|         fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toEscapedString()); |         fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toEscapedString()); | ||||||
|  | @ -1092,9 +1136,11 @@ public class NotificationService { | ||||||
|         } |         } | ||||||
|         final boolean showAllErrors = QuickConversationsService.isConversations(); |         final boolean showAllErrors = QuickConversationsService.isConversations(); | ||||||
|         final List<Account> errors = new ArrayList<>(); |         final List<Account> errors = new ArrayList<>(); | ||||||
|  |         boolean torNotAvailable = false; | ||||||
|         for (final Account account : mXmppConnectionService.getAccounts()) { |         for (final Account account : mXmppConnectionService.getAccounts()) { | ||||||
|             if (account.hasErrorStatus() && account.showErrorNotification() && (showAllErrors || account.getLastErrorStatus() == Account.State.UNAUTHORIZED)) { |             if (account.hasErrorStatus() && account.showErrorNotification() && (showAllErrors || account.getLastErrorStatus() == Account.State.UNAUTHORIZED)) { | ||||||
|                 errors.add(account); |                 errors.add(account); | ||||||
|  |                 torNotAvailable |= account.getStatus() == Account.State.TOR_NOT_AVAILABLE; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (mXmppConnectionService.foregroundNotificationNeedsUpdatingWhenErrorStateChanges()) { |         if (mXmppConnectionService.foregroundNotificationNeedsUpdatingWhenErrorStateChanges()) { | ||||||
|  | @ -1113,7 +1159,23 @@ public class NotificationService { | ||||||
|         } |         } | ||||||
|         mBuilder.addAction(R.drawable.ic_autorenew_white_24dp, |         mBuilder.addAction(R.drawable.ic_autorenew_white_24dp, | ||||||
|                 mXmppConnectionService.getString(R.string.try_again), |                 mXmppConnectionService.getString(R.string.try_again), | ||||||
|                 createTryAgainIntent()); |                 createTryAgainIntent() | ||||||
|  |         ); | ||||||
|  |         if (torNotAvailable) { | ||||||
|  |             if (TorServiceUtils.isOrbotInstalled(mXmppConnectionService)) { | ||||||
|  |                 mBuilder.addAction( | ||||||
|  |                         R.drawable.ic_play_circle_filled_white_48dp, | ||||||
|  |                         mXmppConnectionService.getString(R.string.start_orbot), | ||||||
|  |                         PendingIntent.getActivity(mXmppConnectionService, 147, TorServiceUtils.LAUNCH_INTENT, 0) | ||||||
|  |                 ); | ||||||
|  |             } else { | ||||||
|  |                 mBuilder.addAction( | ||||||
|  |                         R.drawable.ic_file_download_white_24dp, | ||||||
|  |                         mXmppConnectionService.getString(R.string.install_orbot), | ||||||
|  |                         PendingIntent.getActivity(mXmppConnectionService, 146, TorServiceUtils.INSTALL_INTENT, 0) | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         mBuilder.setDeleteIntent(createDismissErrorIntent()); |         mBuilder.setDeleteIntent(createDismissErrorIntent()); | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||||||
|             mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); |             mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ import android.support.annotation.BoolRes; | ||||||
| import android.support.annotation.IntegerRes; | import android.support.annotation.IntegerRes; | ||||||
| import android.support.v4.app.RemoteInput; | import android.support.v4.app.RemoteInput; | ||||||
| import android.support.v4.content.ContextCompat; | import android.support.v4.content.ContextCompat; | ||||||
|  | import android.telephony.PhoneStateListener; | ||||||
|  | import android.telephony.TelephonyManager; | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
| import android.util.DisplayMetrics; | import android.util.DisplayMetrics; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  | @ -127,6 +129,7 @@ import eu.siacs.conversations.utils.ReplacingTaskManager; | ||||||
| import eu.siacs.conversations.utils.Resolver; | import eu.siacs.conversations.utils.Resolver; | ||||||
| import eu.siacs.conversations.utils.SerialSingleThreadExecutor; | import eu.siacs.conversations.utils.SerialSingleThreadExecutor; | ||||||
| import eu.siacs.conversations.utils.StringUtils; | import eu.siacs.conversations.utils.StringUtils; | ||||||
|  | import eu.siacs.conversations.utils.TorServiceUtils; | ||||||
| import eu.siacs.conversations.utils.WakeLockHelper; | import eu.siacs.conversations.utils.WakeLockHelper; | ||||||
| import eu.siacs.conversations.utils.XmppUri; | import eu.siacs.conversations.utils.XmppUri; | ||||||
| import eu.siacs.conversations.xml.Element; | import eu.siacs.conversations.xml.Element; | ||||||
|  | @ -261,6 +264,16 @@ public class XmppConnectionService extends Service { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |     private final AtomicBoolean isPhoneInCall = new AtomicBoolean(false); | ||||||
|  |     private final PhoneStateListener phoneStateListener = new PhoneStateListener() { | ||||||
|  |         @Override | ||||||
|  |         public void onCallStateChanged(final int state, final String phoneNumber) { | ||||||
|  |             isPhoneInCall.set(state != TelephonyManager.CALL_STATE_IDLE); | ||||||
|  |             if (state == TelephonyManager.CALL_STATE_OFFHOOK) { | ||||||
|  |                 mJingleConnectionManager.notifyPhoneCallStarted(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     private boolean destroyed = false; |     private boolean destroyed = false; | ||||||
| 
 | 
 | ||||||
|  | @ -602,8 +615,8 @@ public class XmppConnectionService extends Service { | ||||||
|         return c != null && c.getMode() == Conversational.MODE_MULTI; |         return c != null && c.getMode() == Conversational.MODE_MULTI; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void search(List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) { |     public void search(final List<String> term, final String uuid, final OnSearchResultsAvailable onSearchResultsAvailable) { | ||||||
|         MessageSearchTask.search(this, term, onSearchResultsAvailable); |         MessageSearchTask.search(this, term, uuid, onSearchResultsAvailable); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -652,6 +665,13 @@ public class XmppConnectionService extends Service { | ||||||
|                     final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); |                     final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); | ||||||
|                     Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId); |                     Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId); | ||||||
|                     mJingleConnectionManager.rejectRtpSession(sessionId); |                     mJingleConnectionManager.rejectRtpSession(sessionId); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 case TorServiceUtils.ACTION_STATUS: | ||||||
|  |                     final String status = intent.getStringExtra(TorServiceUtils.EXTRA_STATUS); | ||||||
|  |                     if ("ON".equals(status)) { | ||||||
|  |                         handleOrbotStartedEvent(); | ||||||
|  |                         return START_STICKY; | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
|                 case ACTION_END_CALL: { |                 case ACTION_END_CALL: { | ||||||
|  | @ -787,6 +807,14 @@ public class XmppConnectionService extends Service { | ||||||
|         return START_STICKY; |         return START_STICKY; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void handleOrbotStartedEvent() { | ||||||
|  |         for (final Account account : accounts) { | ||||||
|  |             if (account.getStatus() == Account.State.TOR_NOT_AVAILABLE) { | ||||||
|  |                 reconnectAccount(account, true, false); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet<Account> pingCandidates) { |     private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet<Account> pingCandidates) { | ||||||
|         boolean pingNow = false; |         boolean pingNow = false; | ||||||
|         if (account.getStatus().isAttemptReconnect()) { |         if (account.getStatus().isAttemptReconnect()) { | ||||||
|  | @ -1128,17 +1156,31 @@ public class XmppConnectionService extends Service { | ||||||
|         toggleForegroundService(); |         toggleForegroundService(); | ||||||
|         updateUnreadCountBadge(); |         updateUnreadCountBadge(); | ||||||
|         toggleScreenEventReceiver(); |         toggleScreenEventReceiver(); | ||||||
|  |         final IntentFilter intentFilter = new IntentFilter(); | ||||||
|  |         intentFilter.addAction(TorServiceUtils.ACTION_STATUS); | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||||
|             scheduleNextIdlePing(); |             scheduleNextIdlePing(); | ||||||
|             IntentFilter intentFilter = new IntentFilter(); |  | ||||||
|             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||||
|                 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); |                 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); | ||||||
|             } |             } | ||||||
|             intentFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); |             intentFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); | ||||||
|             registerReceiver(this.mInternalEventReceiver, intentFilter); |  | ||||||
|         } |         } | ||||||
|  |         registerReceiver(this.mInternalEventReceiver, intentFilter); | ||||||
|         mForceDuringOnCreate.set(false); |         mForceDuringOnCreate.set(false); | ||||||
|         toggleForegroundService(); |         toggleForegroundService(); | ||||||
|  |         setupPhoneStateListener(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     private void setupPhoneStateListener() { | ||||||
|  |         final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); | ||||||
|  |         if (telephonyManager != null) { | ||||||
|  |             telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean isPhoneInCall() { | ||||||
|  |         return isPhoneInCall.get(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void checkForDeletedFiles() { |     private void checkForDeletedFiles() { | ||||||
|  | @ -1192,7 +1234,7 @@ public class XmppConnectionService extends Service { | ||||||
|     public void onDestroy() { |     public void onDestroy() { | ||||||
|         try { |         try { | ||||||
|             unregisterReceiver(this.mInternalEventReceiver); |             unregisterReceiver(this.mInternalEventReceiver); | ||||||
|         } catch (IllegalArgumentException e) { |         } catch (final IllegalArgumentException e) { | ||||||
|             //ignored |             //ignored | ||||||
|         } |         } | ||||||
|         destroyed = false; |         destroyed = false; | ||||||
|  | @ -3880,7 +3922,7 @@ public class XmppConnectionService extends Service { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     public void markMessage(Message message, int status, String errorMessage) { |     public void markMessage(final Message message, final int status, final String errorMessage) { | ||||||
|         final int oldStatus = message.getStatus(); |         final int oldStatus = message.getStatus(); | ||||||
|         if (status == Message.STATUS_SEND_FAILED && (oldStatus == Message.STATUS_SEND_RECEIVED || oldStatus == Message.STATUS_SEND_DISPLAYED)) { |         if (status == Message.STATUS_SEND_FAILED && (oldStatus == Message.STATUS_SEND_RECEIVED || oldStatus == Message.STATUS_SEND_DISPLAYED)) { | ||||||
|             return; |             return; | ||||||
|  | @ -3892,6 +3934,9 @@ public class XmppConnectionService extends Service { | ||||||
|         message.setStatus(status); |         message.setStatus(status); | ||||||
|         databaseBackend.updateMessage(message, false); |         databaseBackend.updateMessage(message, false); | ||||||
|         updateConversationUi(); |         updateConversationUi(); | ||||||
|  |         if (oldStatus != status && status == Message.STATUS_SEND_FAILED) { | ||||||
|  |             mNotificationService.pushFailedDelivery(message); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private SharedPreferences getPreferences() { |     private SharedPreferences getPreferences() { | ||||||
|  |  | ||||||
|  | @ -1240,6 +1240,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke | ||||||
|             case R.id.attach_location: |             case R.id.attach_location: | ||||||
|                 handleAttachmentSelection(item); |                 handleAttachmentSelection(item); | ||||||
|                 break; |                 break; | ||||||
|  |             case R.id.action_search: | ||||||
|  |                 startSearch(); | ||||||
|  |                 break; | ||||||
|             case R.id.action_archive: |             case R.id.action_archive: | ||||||
|                 activity.xmppConnectionService.archiveConversation(conversation); |                 activity.xmppConnectionService.archiveConversation(conversation); | ||||||
|                 break; |                 break; | ||||||
|  | @ -1289,6 +1292,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke | ||||||
|         return super.onOptionsItemSelected(item); |         return super.onOptionsItemSelected(item); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void startSearch() { | ||||||
|  |         final Intent intent = new Intent(getActivity(), SearchActivity.class); | ||||||
|  |         intent.putExtra(SearchActivity.EXTRA_CONVERSATION_UUID, conversation.getUuid()); | ||||||
|  |         startActivity(intent); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private void returnToOngoingCall() { |     private void returnToOngoingCall() { | ||||||
|         final Optional<OngoingRtpSession> ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact()); |         final Optional<OngoingRtpSession> ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact()); | ||||||
|         if (ongoingRtpSession.isPresent()) { |         if (ongoingRtpSession.isPresent()) { | ||||||
|  | @ -2034,9 +2043,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke | ||||||
|         toggleInputMethod(); |         toggleInputMethod(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void reInit(Conversation conversation, Bundle extras) { |     public void reInit(final Conversation conversation, final Bundle extras) { | ||||||
|         QuickLoader.set(conversation.getUuid()); |         QuickLoader.set(conversation.getUuid()); | ||||||
|  |         final boolean changedConversation = this.conversation != conversation; | ||||||
|  |         if (changedConversation) { | ||||||
|             this.saveMessageDraftStopAudioPlayer(); |             this.saveMessageDraftStopAudioPlayer(); | ||||||
|  |         } | ||||||
|         this.clearPending(); |         this.clearPending(); | ||||||
|         if (this.reInit(conversation, extras != null)) { |         if (this.reInit(conversation, extras != null)) { | ||||||
|             if (extras != null) { |             if (extras != null) { | ||||||
|  |  | ||||||
|  | @ -266,8 +266,8 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean processViewIntent(Intent intent) { |     private boolean processViewIntent(Intent intent) { | ||||||
|         String uuid = intent.getStringExtra(EXTRA_CONVERSATION); |         final String uuid = intent.getStringExtra(EXTRA_CONVERSATION); | ||||||
|         Conversation conversation = uuid != null ? xmppConnectionService.findConversationByUuid(uuid) : null; |         final Conversation conversation = uuid != null ? xmppConnectionService.findConversationByUuid(uuid) : null; | ||||||
|         if (conversation == null) { |         if (conversation == null) { | ||||||
|             Log.d(Config.LOGTAG, "unable to view conversation with uuid:" + uuid); |             Log.d(Config.LOGTAG, "unable to view conversation with uuid:" + uuid); | ||||||
|             return false; |             return false; | ||||||
|  | @ -380,8 +380,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio | ||||||
|     @Override |     @Override | ||||||
|     public boolean onCreateOptionsMenu(Menu menu) { |     public boolean onCreateOptionsMenu(Menu menu) { | ||||||
|         getMenuInflater().inflate(R.menu.activity_conversations, menu); |         getMenuInflater().inflate(R.menu.activity_conversations, menu); | ||||||
|         AccountUtils.showHideMenuItems(menu); |         final MenuItem qrCodeScanMenuItem = menu.findItem(R.id.action_scan_qr_code); | ||||||
|         MenuItem qrCodeScanMenuItem = menu.findItem(R.id.action_scan_qr_code); |  | ||||||
|         if (qrCodeScanMenuItem != null) { |         if (qrCodeScanMenuItem != null) { | ||||||
|             if (isCameraFeatureAvailable()) { |             if (isCameraFeatureAvailable()) { | ||||||
|                 Fragment fragment = getFragmentManager().findFragmentById(R.id.main_fragment); |                 Fragment fragment = getFragmentManager().findFragmentById(R.id.main_fragment); | ||||||
|  | @ -489,6 +488,18 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio | ||||||
|             case R.id.action_scan_qr_code: |             case R.id.action_scan_qr_code: | ||||||
|                 UriHandlerActivity.scan(this); |                 UriHandlerActivity.scan(this); | ||||||
|                 return true; |                 return true; | ||||||
|  |             case R.id.action_search_all_conversations: | ||||||
|  |                 startActivity(new Intent(this, SearchActivity.class)); | ||||||
|  |                 return true; | ||||||
|  |             case R.id.action_search_this_conversation: | ||||||
|  |                 final Conversation conversation = ConversationFragment.getConversation(this); | ||||||
|  |                 if (conversation == null) { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |                 final Intent intent = new Intent(this, SearchActivity.class); | ||||||
|  |                 intent.putExtra(SearchActivity.EXTRA_CONVERSATION_UUID, conversation.getUuid()); | ||||||
|  |                 startActivity(intent); | ||||||
|  |                 return true; | ||||||
|         } |         } | ||||||
|         return super.onOptionsItemSelected(item); |         return super.onOptionsItemSelected(item); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -64,6 +64,7 @@ import eu.siacs.conversations.ui.util.PendingActionHelper; | ||||||
| import eu.siacs.conversations.ui.util.PendingItem; | import eu.siacs.conversations.ui.util.PendingItem; | ||||||
| import eu.siacs.conversations.ui.util.ScrollState; | import eu.siacs.conversations.ui.util.ScrollState; | ||||||
| import eu.siacs.conversations.ui.util.StyledAttributes; | import eu.siacs.conversations.ui.util.StyledAttributes; | ||||||
|  | import eu.siacs.conversations.utils.AccountUtils; | ||||||
| import eu.siacs.conversations.utils.ThemeHelper; | import eu.siacs.conversations.utils.ThemeHelper; | ||||||
| 
 | 
 | ||||||
| import static android.support.v7.widget.helper.ItemTouchHelper.LEFT; | import static android.support.v7.widget.helper.ItemTouchHelper.LEFT; | ||||||
|  | @ -284,6 +285,7 @@ public class ConversationsOverviewFragment extends XmppFragment { | ||||||
| 	@Override | 	@Override | ||||||
| 	public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { | 	public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { | ||||||
| 		menuInflater.inflate(R.menu.fragment_conversations_overview, menu); | 		menuInflater.inflate(R.menu.fragment_conversations_overview, menu); | ||||||
|  | 		AccountUtils.showHideMenuItems(menu); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  |  | ||||||
|  | @ -89,7 +89,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat | ||||||
|     private static final int REQUEST_CHANGE_STATUS = 0xee11; |     private static final int REQUEST_CHANGE_STATUS = 0xee11; | ||||||
|     private static final int REQUEST_ORBOT = 0xff22; |     private static final int REQUEST_ORBOT = 0xff22; | ||||||
|     private final PendingItem<PresenceTemplate> mPendingPresenceTemplate = new PendingItem<>(); |     private final PendingItem<PresenceTemplate> mPendingPresenceTemplate = new PendingItem<>(); | ||||||
|     private final AtomicBoolean mPendingReconnect = new AtomicBoolean(false); |  | ||||||
|     private AlertDialog mCaptchaDialog = null; |     private AlertDialog mCaptchaDialog = null; | ||||||
|     private Jid jidToEdit; |     private Jid jidToEdit; | ||||||
|     private boolean mInitMode = false; |     private boolean mInitMode = false; | ||||||
|  | @ -475,13 +474,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat | ||||||
|                 Log.d(Config.LOGTAG, "pgp result not ok"); |                 Log.d(Config.LOGTAG, "pgp result not ok"); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (requestCode == REQUEST_ORBOT) { |  | ||||||
|             if (xmppConnectionService != null && mAccount != null) { |  | ||||||
|                 xmppConnectionService.reconnectAccountInBackground(mAccount); |  | ||||||
|             } else { |  | ||||||
|                 mPendingReconnect.set(true); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -781,11 +773,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (mAccount != null) { |         if (mAccount != null) { | ||||||
| 
 |  | ||||||
|             if (mPendingReconnect.compareAndSet(true, false)) { |  | ||||||
|                 xmppConnectionService.reconnectAccountInBackground(mAccount); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); |             this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); | ||||||
|             this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER); |             this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER); | ||||||
|             if (mPendingFingerprintVerificationUri != null) { |             if (mPendingFingerprintVerificationUri != null) { | ||||||
|  |  | ||||||
|  | @ -677,18 +677,22 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe | ||||||
|             this.binding.endCall.setVisibility(View.INVISIBLE); |             this.binding.endCall.setVisibility(View.INVISIBLE); | ||||||
|             this.binding.acceptCall.setVisibility(View.INVISIBLE); |             this.binding.acceptCall.setVisibility(View.INVISIBLE); | ||||||
|         } else if (state == RtpEndUserState.INCOMING_CALL) { |         } else if (state == RtpEndUserState.INCOMING_CALL) { | ||||||
|  |             this.binding.rejectCall.setContentDescription(getString(R.string.dismiss_call)); | ||||||
|             this.binding.rejectCall.setOnClickListener(this::rejectCall); |             this.binding.rejectCall.setOnClickListener(this::rejectCall); | ||||||
|             this.binding.rejectCall.setImageResource(R.drawable.ic_call_end_white_48dp); |             this.binding.rejectCall.setImageResource(R.drawable.ic_call_end_white_48dp); | ||||||
|             this.binding.rejectCall.setVisibility(View.VISIBLE); |             this.binding.rejectCall.setVisibility(View.VISIBLE); | ||||||
|             this.binding.endCall.setVisibility(View.INVISIBLE); |             this.binding.endCall.setVisibility(View.INVISIBLE); | ||||||
|  |             this.binding.acceptCall.setContentDescription(getString(R.string.answer_call)); | ||||||
|             this.binding.acceptCall.setOnClickListener(this::acceptCall); |             this.binding.acceptCall.setOnClickListener(this::acceptCall); | ||||||
|             this.binding.acceptCall.setImageResource(R.drawable.ic_call_white_48dp); |             this.binding.acceptCall.setImageResource(R.drawable.ic_call_white_48dp); | ||||||
|             this.binding.acceptCall.setVisibility(View.VISIBLE); |             this.binding.acceptCall.setVisibility(View.VISIBLE); | ||||||
|         } else if (state == RtpEndUserState.DECLINED_OR_BUSY) { |         } else if (state == RtpEndUserState.DECLINED_OR_BUSY) { | ||||||
|  |             this.binding.rejectCall.setContentDescription(getString(R.string.exit)); | ||||||
|             this.binding.rejectCall.setOnClickListener(this::exit); |             this.binding.rejectCall.setOnClickListener(this::exit); | ||||||
|             this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp); |             this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp); | ||||||
|             this.binding.rejectCall.setVisibility(View.VISIBLE); |             this.binding.rejectCall.setVisibility(View.VISIBLE); | ||||||
|             this.binding.endCall.setVisibility(View.INVISIBLE); |             this.binding.endCall.setVisibility(View.INVISIBLE); | ||||||
|  |             this.binding.acceptCall.setContentDescription(getString(R.string.record_voice_mail)); | ||||||
|             this.binding.acceptCall.setOnClickListener(this::recordVoiceMail); |             this.binding.acceptCall.setOnClickListener(this::recordVoiceMail); | ||||||
|             this.binding.acceptCall.setImageResource(R.drawable.ic_voicemail_white_24dp); |             this.binding.acceptCall.setImageResource(R.drawable.ic_voicemail_white_24dp); | ||||||
|             this.binding.acceptCall.setVisibility(View.VISIBLE); |             this.binding.acceptCall.setVisibility(View.VISIBLE); | ||||||
|  | @ -698,15 +702,18 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe | ||||||
|                 RtpEndUserState.APPLICATION_ERROR, |                 RtpEndUserState.APPLICATION_ERROR, | ||||||
|                 RtpEndUserState.RETRACTED |                 RtpEndUserState.RETRACTED | ||||||
|         ).contains(state)) { |         ).contains(state)) { | ||||||
|  |             this.binding.rejectCall.setContentDescription(getString(R.string.exit)); | ||||||
|             this.binding.rejectCall.setOnClickListener(this::exit); |             this.binding.rejectCall.setOnClickListener(this::exit); | ||||||
|             this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp); |             this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp); | ||||||
|             this.binding.rejectCall.setVisibility(View.VISIBLE); |             this.binding.rejectCall.setVisibility(View.VISIBLE); | ||||||
|             this.binding.endCall.setVisibility(View.INVISIBLE); |             this.binding.endCall.setVisibility(View.INVISIBLE); | ||||||
|  |             this.binding.acceptCall.setContentDescription(getString(R.string.try_again)); | ||||||
|             this.binding.acceptCall.setOnClickListener(this::retry); |             this.binding.acceptCall.setOnClickListener(this::retry); | ||||||
|             this.binding.acceptCall.setImageResource(R.drawable.ic_replay_white_48dp); |             this.binding.acceptCall.setImageResource(R.drawable.ic_replay_white_48dp); | ||||||
|             this.binding.acceptCall.setVisibility(View.VISIBLE); |             this.binding.acceptCall.setVisibility(View.VISIBLE); | ||||||
|         } else { |         } else { | ||||||
|             this.binding.rejectCall.setVisibility(View.INVISIBLE); |             this.binding.rejectCall.setVisibility(View.INVISIBLE); | ||||||
|  |             this.binding.endCall.setContentDescription(getString(R.string.hang_up)); | ||||||
|             this.binding.endCall.setOnClickListener(this::endCall); |             this.binding.endCall.setOnClickListener(this::endCall); | ||||||
|             this.binding.endCall.setImageResource(R.drawable.ic_call_end_white_48dp); |             this.binding.endCall.setImageResource(R.drawable.ic_call_end_white_48dp); | ||||||
|             this.binding.endCall.setVisibility(View.VISIBLE); |             this.binding.endCall.setVisibility(View.VISIBLE); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
| 
 | 
 | ||||||
| package eu.siacs.conversations.ui; | package eu.siacs.conversations.ui; | ||||||
| 
 | 
 | ||||||
|  | import android.content.Intent; | ||||||
| import android.databinding.DataBindingUtil; | import android.databinding.DataBindingUtil; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.support.v7.widget.Toolbar; | import android.support.v7.widget.Toolbar; | ||||||
|  | @ -42,6 +43,8 @@ import android.view.View; | ||||||
| import android.widget.AdapterView; | import android.widget.AdapterView; | ||||||
| import android.widget.EditText; | import android.widget.EditText; | ||||||
| 
 | 
 | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | 
 | ||||||
| import java.lang.ref.WeakReference; | import java.lang.ref.WeakReference; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | @ -70,17 +73,21 @@ import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.showKeyboard; | ||||||
| public class SearchActivity extends XmppActivity implements TextWatcher, OnSearchResultsAvailable, MessageAdapter.OnContactPictureClicked { | public class SearchActivity extends XmppActivity implements TextWatcher, OnSearchResultsAvailable, MessageAdapter.OnContactPictureClicked { | ||||||
| 
 | 
 | ||||||
| 	private static final String EXTRA_SEARCH_TERM = "search-term"; | 	private static final String EXTRA_SEARCH_TERM = "search-term"; | ||||||
|  | 	public static final String EXTRA_CONVERSATION_UUID = "uuid"; | ||||||
| 
 | 
 | ||||||
| 	private ActivitySearchBinding binding; | 	private ActivitySearchBinding binding; | ||||||
| 	private MessageAdapter messageListAdapter; | 	private MessageAdapter messageListAdapter; | ||||||
| 	private final List<Message> messages = new ArrayList<>(); | 	private final List<Message> messages = new ArrayList<>(); | ||||||
| 	private WeakReference<Message> selectedMessageReference = new WeakReference<>(null); | 	private WeakReference<Message> selectedMessageReference = new WeakReference<>(null); | ||||||
|  | 	private String uuid; | ||||||
| 	private final ChangeWatcher<List<String>> currentSearch = new ChangeWatcher<>(); | 	private final ChangeWatcher<List<String>> currentSearch = new ChangeWatcher<>(); | ||||||
| 	private final PendingItem<String> pendingSearchTerm = new PendingItem<>(); | 	private final PendingItem<String> pendingSearchTerm = new PendingItem<>(); | ||||||
| 	private final PendingItem<List<String>> pendingSearch = new PendingItem<>(); | 	private final PendingItem<List<String>> pendingSearch = new PendingItem<>(); | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void onCreate(final Bundle bundle) { | 	public void onCreate(final Bundle bundle) { | ||||||
|  | 		final Intent intent = getIntent(); | ||||||
|  | 		this.uuid = intent == null ? null : Strings.emptyToNull(intent.getStringExtra(EXTRA_CONVERSATION_UUID)); | ||||||
| 		final String searchTerm = bundle == null ? null : bundle.getString(EXTRA_SEARCH_TERM); | 		final String searchTerm = bundle == null ? null : bundle.getString(EXTRA_SEARCH_TERM); | ||||||
| 		if (searchTerm != null) { | 		if (searchTerm != null) { | ||||||
| 			pendingSearchTerm.push(searchTerm); | 			pendingSearchTerm.push(searchTerm); | ||||||
|  | @ -103,10 +110,10 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc | ||||||
| 		final String term = pendingSearchTerm.pop(); | 		final String term = pendingSearchTerm.pop(); | ||||||
| 		if (term != null) { | 		if (term != null) { | ||||||
| 			searchField.append(term); | 			searchField.append(term); | ||||||
| 			List<String> searchTerm = FtsUtils.parse(term); | 			final List<String> searchTerm = FtsUtils.parse(term); | ||||||
| 			if (xmppConnectionService != null) { | 			if (xmppConnectionService != null) { | ||||||
| 				if (currentSearch.watch(searchTerm)) { | 				if (currentSearch.watch(searchTerm)) { | ||||||
| 					xmppConnectionService.search(searchTerm, this); | 					xmppConnectionService.search(searchTerm, uuid, this); | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				pendingSearch.push(searchTerm); | 				pendingSearch.push(searchTerm); | ||||||
|  | @ -114,6 +121,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc | ||||||
| 		} | 		} | ||||||
| 		searchField.addTextChangedListener(this); | 		searchField.addTextChangedListener(this); | ||||||
| 		searchField.setHint(R.string.search_messages); | 		searchField.setHint(R.string.search_messages); | ||||||
|  | 		searchField.setContentDescription(getString(R.string.search_messages)); | ||||||
| 		searchField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); | 		searchField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); | ||||||
| 		if (term == null) { | 		if (term == null) { | ||||||
| 			showKeyboard(searchField); | 			showKeyboard(searchField); | ||||||
|  | @ -206,7 +214,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc | ||||||
| 	void onBackendConnected() { | 	void onBackendConnected() { | ||||||
| 		final List<String> searchTerm = pendingSearch.pop(); | 		final List<String> searchTerm = pendingSearch.pop(); | ||||||
| 		if (searchTerm != null && currentSearch.watch(searchTerm)) { | 		if (searchTerm != null && currentSearch.watch(searchTerm)) { | ||||||
| 			xmppConnectionService.search(searchTerm, this); | 			xmppConnectionService.search(searchTerm, uuid,this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -239,7 +247,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		if (term.size() > 0) { | 		if (term.size() > 0) { | ||||||
| 			xmppConnectionService.search(term, this); | 			xmppConnectionService.search(term, uuid,this); | ||||||
| 		} else { | 		} else { | ||||||
| 			MessageSearchTask.cancelRunningTasks(); | 			MessageSearchTask.cancelRunningTasks(); | ||||||
| 			this.messages.clear(); | 			this.messages.clear(); | ||||||
|  |  | ||||||
|  | @ -621,8 +621,10 @@ public class StartConversationActivity extends XmppActivity implements XmppConne | ||||||
| 		} | 		} | ||||||
| 		if (binding.startConversationViewPager.getCurrentItem() == 0) { | 		if (binding.startConversationViewPager.getCurrentItem() == 0) { | ||||||
| 			mSearchEditText.setHint(R.string.search_contacts); | 			mSearchEditText.setHint(R.string.search_contacts); | ||||||
|  | 			mSearchEditText.setContentDescription(getString(R.string.search_contacts)); | ||||||
| 		} else { | 		} else { | ||||||
| 			mSearchEditText.setHint(R.string.search_bookmarks); | 			mSearchEditText.setHint(R.string.search_bookmarks); | ||||||
|  | 			mSearchEditText.setContentDescription(getString(R.string.search_bookmarks)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -112,17 +112,21 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|         } |         } | ||||||
|         viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); |         viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); | ||||||
|         viewHolder.playPause.setOnClickListener(this); |         viewHolder.playPause.setOnClickListener(this); | ||||||
|  |         final Context context = viewHolder.playPause.getContext(); | ||||||
|         if (message == currentlyPlayingMessage) { |         if (message == currentlyPlayingMessage) { | ||||||
|             if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) { |             if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) { | ||||||
|                 viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); |                 viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); | ||||||
|  |                 viewHolder.playPause.setContentDescription(context.getString(R.string.pause_audio)); | ||||||
|                 viewHolder.progress.setEnabled(true); |                 viewHolder.progress.setEnabled(true); | ||||||
|             } else { |             } else { | ||||||
|  |                 viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio)); | ||||||
|                 viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); |                 viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); | ||||||
|                 viewHolder.progress.setEnabled(false); |                 viewHolder.progress.setEnabled(false); | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } else { |         } else { | ||||||
|             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); |             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); | ||||||
|  |             viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio)); | ||||||
|             viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); |             viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); | ||||||
|             viewHolder.progress.setProgress(0); |             viewHolder.progress.setProgress(0); | ||||||
|             viewHolder.progress.setEnabled(false); |             viewHolder.progress.setEnabled(false); | ||||||
|  | @ -156,7 +160,8 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean playPauseCurrent(ViewHolder viewHolder) { |     private boolean playPauseCurrent(final ViewHolder viewHolder) { | ||||||
|  |         final Context context = viewHolder.playPause.getContext(); | ||||||
|         viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); |         viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); | ||||||
|         if (player.isPlaying()) { |         if (player.isPlaying()) { | ||||||
|             viewHolder.progress.setEnabled(false); |             viewHolder.progress.setEnabled(false); | ||||||
|  | @ -164,6 +169,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|             messageAdapter.flagScreenOff(); |             messageAdapter.flagScreenOff(); | ||||||
|             releaseProximityWakeLock(); |             releaseProximityWakeLock(); | ||||||
|             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); |             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); | ||||||
|  |             viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio)); | ||||||
|         } else { |         } else { | ||||||
|             viewHolder.progress.setEnabled(true); |             viewHolder.progress.setEnabled(true); | ||||||
|             player.start(); |             player.start(); | ||||||
|  | @ -171,6 +177,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|             acquireProximityWakeLock(); |             acquireProximityWakeLock(); | ||||||
|             this.stopRefresher(true); |             this.stopRefresher(true); | ||||||
|             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); |             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); | ||||||
|  |             viewHolder.playPause.setContentDescription(context.getString(R.string.pause_audio)); | ||||||
|         } |         } | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | @ -194,6 +201,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|             acquireProximityWakeLock(); |             acquireProximityWakeLock(); | ||||||
|             viewHolder.progress.setEnabled(true); |             viewHolder.progress.setEnabled(true); | ||||||
|             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); |             viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); | ||||||
|  |             viewHolder.playPause.setContentDescription(viewHolder.playPause.getContext().getString(R.string.pause_audio)); | ||||||
|             sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); |             sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); | ||||||
|             return true; |             return true; | ||||||
|         } catch (Exception e) { |         } catch (Exception e) { | ||||||
|  | @ -248,6 +256,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti | ||||||
|         } |         } | ||||||
|         final ViewHolder viewHolder = ViewHolder.get(audioPlayer); |         final ViewHolder viewHolder = ViewHolder.get(audioPlayer); | ||||||
|         final Message message = (Message) audioPlayer.getTag(); |         final Message message = (Message) audioPlayer.getTag(); | ||||||
|  |         viewHolder.playPause.setContentDescription(viewHolder.playPause.getContext().getString(R.string.play_audio)); | ||||||
|         viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); |         viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); | ||||||
|         if (message != null) { |         if (message != null) { | ||||||
|             viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); |             viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package eu.siacs.conversations.ui.util; | package eu.siacs.conversations.ui.util; | ||||||
| 
 | 
 | ||||||
|  | import android.content.Context; | ||||||
| import android.content.res.Resources; | import android.content.res.Resources; | ||||||
| import android.graphics.Bitmap; | import android.graphics.Bitmap; | ||||||
| import android.graphics.drawable.BitmapDrawable; | import android.graphics.drawable.BitmapDrawable; | ||||||
|  | @ -11,11 +12,10 @@ import android.widget.ImageView; | ||||||
| import java.lang.ref.WeakReference; | import java.lang.ref.WeakReference; | ||||||
| import java.util.concurrent.RejectedExecutionException; | import java.util.concurrent.RejectedExecutionException; | ||||||
| 
 | 
 | ||||||
|  | import eu.siacs.conversations.R; | ||||||
| import eu.siacs.conversations.entities.Account; | import eu.siacs.conversations.entities.Account; | ||||||
| import eu.siacs.conversations.services.AvatarService; | import eu.siacs.conversations.services.AvatarService; | ||||||
| import eu.siacs.conversations.ui.XmppActivity; | import eu.siacs.conversations.ui.XmppActivity; | ||||||
| import eu.siacs.conversations.ui.adapter.AccountAdapter; |  | ||||||
| import eu.siacs.conversations.utils.UIHelper; |  | ||||||
| 
 | 
 | ||||||
| public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> { | public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> { | ||||||
|     private final WeakReference<ImageView> imageViewReference; |     private final WeakReference<ImageView> imageViewReference; | ||||||
|  | @ -80,6 +80,7 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true); |             final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true); | ||||||
|  |             setContentDescription(avatarable, imageView); | ||||||
|             if (bm != null) { |             if (bm != null) { | ||||||
|                 cancelPotentialWork(avatarable, imageView); |                 cancelPotentialWork(avatarable, imageView); | ||||||
|                 imageView.setImageBitmap(bm); |                 imageView.setImageBitmap(bm); | ||||||
|  | @ -98,6 +99,15 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private static void setContentDescription(final AvatarService.Avatarable avatarable, final ImageView imageView) { | ||||||
|  |         final Context context = imageView.getContext(); | ||||||
|  |         if (avatarable instanceof Account) { | ||||||
|  |             imageView.setContentDescription(context.getString(R.string.your_avatar)); | ||||||
|  |         } else { | ||||||
|  |             imageView.setContentDescription(context.getString(R.string.avatar_for_x, avatarable.getAvatarName())); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     static class AsyncDrawable extends BitmapDrawable { |     static class AsyncDrawable extends BitmapDrawable { | ||||||
|         private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference; |         private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -112,16 +112,16 @@ public class ConversationMenuConfigurator { | ||||||
| 		none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI); | 		none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI); | ||||||
| 		axolotl.setVisible(Config.supportOmemo()); | 		axolotl.setVisible(Config.supportOmemo()); | ||||||
| 		switch (conversation.getNextEncryption()) { | 		switch (conversation.getNextEncryption()) { | ||||||
| 			case Message.ENCRYPTION_NONE: |  | ||||||
| 				none.setChecked(true); |  | ||||||
| 				break; |  | ||||||
| 			case Message.ENCRYPTION_PGP: | 			case Message.ENCRYPTION_PGP: | ||||||
|  | 				menuSecure.setTitle(R.string.encrypted_with_openpgp); | ||||||
| 				pgp.setChecked(true); | 				pgp.setChecked(true); | ||||||
| 				break; | 				break; | ||||||
| 			case Message.ENCRYPTION_AXOLOTL: | 			case Message.ENCRYPTION_AXOLOTL: | ||||||
|  | 				menuSecure.setTitle(R.string.encrypted_with_omemo); | ||||||
| 				axolotl.setChecked(true); | 				axolotl.setChecked(true); | ||||||
| 				break; | 				break; | ||||||
| 			default: | 			default: | ||||||
|  | 				menuSecure.setTitle(R.string.not_encrypted); | ||||||
| 				none.setChecked(true); | 				none.setChecked(true); | ||||||
| 				break; | 				break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -129,7 +129,7 @@ public class StylingHelper { | ||||||
| 		int start = indexOfIgnoreCase(string, needle, 0); | 		int start = indexOfIgnoreCase(string, needle, 0); | ||||||
| 		while (start != -1) { | 		while (start != -1) { | ||||||
| 			int end = start + length; | 			int end = start + length; | ||||||
| 			editable.setSpan(new BackgroundColorSpan(ContextCompat.getColor(context, dark ? R.color.blue_a100 : R.color.blue_a200)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); | 			editable.setSpan(new BackgroundColorSpan(ContextCompat.getColor(context, dark ? R.color.blue_a100 : R.color.blue_a400)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 			editable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, dark ? R.color.black87 : R.color.white)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); | 			editable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, dark ? R.color.black87 : R.color.white)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 			start = indexOfIgnoreCase(string, needle, start + length); | 			start = indexOfIgnoreCase(string, needle, start + length); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -16,6 +16,12 @@ public class TorServiceUtils { | ||||||
|     private static final Uri ORBOT_PLAYSTORE_URI = Uri.parse("market://details?id=" + URI_ORBOT); |     private static final Uri ORBOT_PLAYSTORE_URI = Uri.parse("market://details?id=" + URI_ORBOT); | ||||||
|     private final static String ACTION_START_TOR = "org.torproject.android.START_TOR"; |     private final static String ACTION_START_TOR = "org.torproject.android.START_TOR"; | ||||||
| 
 | 
 | ||||||
|  |     public static final Intent INSTALL_INTENT = new Intent(Intent.ACTION_VIEW, ORBOT_PLAYSTORE_URI); | ||||||
|  |     public static final Intent LAUNCH_INTENT = new Intent(ACTION_START_TOR); | ||||||
|  | 
 | ||||||
|  |     public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; | ||||||
|  |     public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; | ||||||
|  | 
 | ||||||
|     public static boolean isOrbotInstalled(Context context) { |     public static boolean isOrbotInstalled(Context context) { | ||||||
|         try { |         try { | ||||||
|             context.getPackageManager().getPackageInfo(URI_ORBOT, PackageManager.GET_ACTIVITIES); |             context.getPackageManager().getPackageInfo(URI_ORBOT, PackageManager.GET_ACTIVITIES); | ||||||
|  | @ -27,17 +33,14 @@ public class TorServiceUtils { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     public static void downloadOrbot(Activity activity, int requestCode) { |     public static void downloadOrbot(Activity activity, int requestCode) { | ||||||
|         final Intent intent = new Intent(Intent.ACTION_VIEW, ORBOT_PLAYSTORE_URI); |  | ||||||
|         try { |         try { | ||||||
|             activity.startActivityForResult(intent, requestCode); |             activity.startActivityForResult(INSTALL_INTENT, requestCode); | ||||||
|         } catch (ActivityNotFoundException e) { |         } catch (ActivityNotFoundException e) { | ||||||
|             ToastCompat.makeText(activity, R.string.no_market_app_installed, ToastCompat.LENGTH_SHORT).show(); |             ToastCompat.makeText(activity, R.string.no_market_app_installed, ToastCompat.LENGTH_SHORT).show(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void startOrbot(Activity activity, int requestCode) { |     public static void startOrbot(Activity activity, int requestCode) { | ||||||
|         final Intent launchIntent = new Intent(URI_ORBOT); |         activity.startActivityForResult(LAUNCH_INTENT, requestCode); | ||||||
|         launchIntent.setAction(ACTION_START_TOR); |  | ||||||
|         activity.startActivityForResult(launchIntent, requestCode); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ import com.google.common.collect.ImmutableSet; | ||||||
| 
 | 
 | ||||||
| import java.lang.ref.WeakReference; | import java.lang.ref.WeakReference; | ||||||
| import java.security.SecureRandom; | import java.security.SecureRandom; | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
|  | @ -90,7 +91,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { | ||||||
|             final AbstractJingleConnection connection; |             final AbstractJingleConnection connection; | ||||||
|             if (FileTransferDescription.NAMESPACES.contains(descriptionNamespace)) { |             if (FileTransferDescription.NAMESPACES.contains(descriptionNamespace)) { | ||||||
|                 connection = new JingleFileTransferConnection(this, id, from); |                 connection = new JingleFileTransferConnection(this, id, from); | ||||||
|             } else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace) && !usesTor(account)) { |             } else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace) && isUsingClearNet(account)) { | ||||||
|                 final boolean sessionEnded = this.terminatedSessions.asMap().containsKey(PersistableSessionId.of(id)); |                 final boolean sessionEnded = this.terminatedSessions.asMap().containsKey(PersistableSessionId.of(id)); | ||||||
|                 final boolean stranger = isWithStrangerAndStrangerNotificationsAreOff(account, id.with); |                 final boolean stranger = isWithStrangerAndStrangerNotificationsAreOff(account, id.with); | ||||||
|                 if (isBusy() || sessionEnded || stranger) { |                 if (isBusy() || sessionEnded || stranger) { | ||||||
|  | @ -116,11 +117,14 @@ public class JingleConnectionManager extends AbstractConnectionManager { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean usesTor(final Account account) { |     private boolean isUsingClearNet(final Account account) { | ||||||
|         return account.isOnion() || mXmppConnectionService.useTorToConnect(); |         return !account.isOnion() && !mXmppConnectionService.useTorToConnect(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean isBusy() { |     public boolean isBusy() { | ||||||
|  |         if (mXmppConnectionService.isPhoneInCall()) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|         for (AbstractJingleConnection connection : this.connections.values()) { |         for (AbstractJingleConnection connection : this.connections.values()) { | ||||||
|             if (connection instanceof JingleRtpConnection) { |             if (connection instanceof JingleRtpConnection) { | ||||||
|                 if (((JingleRtpConnection) connection).isTerminated()) { |                 if (((JingleRtpConnection) connection).isTerminated()) { | ||||||
|  | @ -134,6 +138,18 @@ public class JingleConnectionManager extends AbstractConnectionManager { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void notifyPhoneCallStarted() { | ||||||
|  |         for (AbstractJingleConnection connection : connections.values()) { | ||||||
|  |             if (connection instanceof JingleRtpConnection) { | ||||||
|  |                 final JingleRtpConnection rtpConnection = (JingleRtpConnection) connection; | ||||||
|  |                 if (rtpConnection.isTerminated()) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 rtpConnection.notifyPhoneCall(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private Optional<RtpSessionProposal> findMatchingSessionProposal(final Account account, final Jid with, final Set<Media> media) { |     private Optional<RtpSessionProposal> findMatchingSessionProposal(final Account account, final Jid with, final Set<Media> media) { | ||||||
|         synchronized (this.rtpSessionProposals) { |         synchronized (this.rtpSessionProposals) { | ||||||
|             for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) { |             for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) { | ||||||
|  | @ -257,7 +273,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { | ||||||
|                     Collections2.filter(descriptions, d -> d instanceof RtpDescription), |                     Collections2.filter(descriptions, d -> d instanceof RtpDescription), | ||||||
|                     input -> (RtpDescription) input |                     input -> (RtpDescription) input | ||||||
|             ); |             ); | ||||||
|             if (rtpDescriptions.size() > 0 && rtpDescriptions.size() == descriptions.size() && !usesTor(account)) { |             if (rtpDescriptions.size() > 0 && rtpDescriptions.size() == descriptions.size() && isUsingClearNet(account)) { | ||||||
|                 final Collection<Media> media = Collections2.transform(rtpDescriptions, RtpDescription::getMedia); |                 final Collection<Media> media = Collections2.transform(rtpDescriptions, RtpDescription::getMedia); | ||||||
|                 if (media.contains(Media.UNKNOWN)) { |                 if (media.contains(Media.UNKNOWN)) { | ||||||
|                     Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": encountered unknown media in session proposal. " + propose); |                     Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": encountered unknown media in session proposal. " + propose); | ||||||
|  |  | ||||||
|  | @ -371,8 +371,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web | ||||||
|         if (transition(State.SESSION_ACCEPTED)) { |         if (transition(State.SESSION_ACCEPTED)) { | ||||||
|             respondOk(jinglePacket); |             respondOk(jinglePacket); | ||||||
|             receiveSessionAccept(contentMap); |             receiveSessionAccept(contentMap); | ||||||
|             final List<String> identificationTags = contentMap.group == null ? contentMap.getNames() : contentMap.group.getIdentificationTags(); |  | ||||||
|             processCandidates(identificationTags, contentMap.contents.entrySet()); |  | ||||||
|         } else { |         } else { | ||||||
|             Log.d(Config.LOGTAG, String.format("%s: received session-accept while in state %s", id.account.getJid().asBareJid(), state)); |             Log.d(Config.LOGTAG, String.format("%s: received session-accept while in state %s", id.account.getJid().asBareJid(), state)); | ||||||
|             respondOk(jinglePacket); |             respondOk(jinglePacket); | ||||||
|  | @ -390,7 +388,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web | ||||||
|             sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage()); |             sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage()); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         org.webrtc.SessionDescription answer = new org.webrtc.SessionDescription( |         final org.webrtc.SessionDescription answer = new org.webrtc.SessionDescription( | ||||||
|                 org.webrtc.SessionDescription.Type.ANSWER, |                 org.webrtc.SessionDescription.Type.ANSWER, | ||||||
|                 sessionDescription.toString() |                 sessionDescription.toString() | ||||||
|         ); |         ); | ||||||
|  | @ -400,7 +398,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web | ||||||
|             Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to set remote description after receiving session-accept", Throwables.getRootCause(e)); |             Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to set remote description after receiving session-accept", Throwables.getRootCause(e)); | ||||||
|             webRTCWrapper.close(); |             webRTCWrapper.close(); | ||||||
|             sendSessionTerminate(Reason.FAILED_APPLICATION); |             sendSessionTerminate(Reason.FAILED_APPLICATION); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|  |         final List<String> identificationTags = contentMap.group == null ? contentMap.getNames() : contentMap.group.getIdentificationTags(); | ||||||
|  |         processCandidates(identificationTags, contentMap.contents.entrySet()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void sendSessionAccept() { |     private void sendSessionAccept() { | ||||||
|  | @ -900,6 +901,16 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     public void notifyPhoneCall() { | ||||||
|  |         Log.d(Config.LOGTAG, "a phone call has just been started. killing jingle rtp connections"); | ||||||
|  |         if (Arrays.asList(State.PROPOSED, State.SESSION_INITIALIZED).contains(this.state)) { | ||||||
|  |             rejectCall(); | ||||||
|  |         } else { | ||||||
|  |             endCall(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public synchronized void rejectCall() { |     public synchronized void rejectCall() { | ||||||
|         if (isTerminated()) { |         if (isTerminated()) { | ||||||
|             Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": received rejectCall() when session has already been terminated. nothing to do"); |             Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": received rejectCall() when session has already been terminated. nothing to do"); | ||||||
|  |  | ||||||
| After Width: | Height: | Size: 324 B | 
| After Width: | Height: | Size: 666 B | 
| After Width: | Height: | Size: 232 B | 
| After Width: | Height: | Size: 464 B | 
| After Width: | Height: | Size: 431 B | 
| After Width: | Height: | Size: 883 B | 
| After Width: | Height: | Size: 614 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 814 B | 
| After Width: | Height: | Size: 1.8 KiB | 
|  | @ -50,6 +50,7 @@ | ||||||
|             app:sdMainFabClosedBackgroundColor="?colorPrimary" |             app:sdMainFabClosedBackgroundColor="?colorPrimary" | ||||||
|             app:sdMainFabOpenedBackgroundColor="?colorPrimaryDark" |             app:sdMainFabOpenedBackgroundColor="?colorPrimaryDark" | ||||||
|             app:sdUseReverseAnimationOnClose="true" |             app:sdUseReverseAnimationOnClose="true" | ||||||
|  |             android:contentDescription="@string/add_contact_or_create_or_join_group_chat" | ||||||
|             app:sdOverlayLayout="@id/overlay"/> |             app:sdOverlayLayout="@id/overlay"/> | ||||||
|     </RelativeLayout> |     </RelativeLayout> | ||||||
| </layout> | </layout> | ||||||
|  |  | ||||||
|  | @ -37,7 +37,9 @@ | ||||||
|             android:orientation="vertical" |             android:orientation="vertical" | ||||||
|             android:padding="2dp"> |             android:padding="2dp"> | ||||||
| 
 | 
 | ||||||
|             <include layout="@layout/message_content"/> |             <include | ||||||
|  |                 android:id="@+id/message_content" | ||||||
|  |                 layout="@layout/message_content"/> | ||||||
| 
 | 
 | ||||||
|             <LinearLayout |             <LinearLayout | ||||||
|                 android:layout_width="wrap_content" |                 android:layout_width="wrap_content" | ||||||
|  | @ -82,6 +84,8 @@ | ||||||
|                     android:layout_gravity="center_vertical" |                     android:layout_gravity="center_vertical" | ||||||
|                     android:gravity="center_vertical" |                     android:gravity="center_vertical" | ||||||
|                     android:text="@string/sending" |                     android:text="@string/sending" | ||||||
|  |                     android:accessibilityTraversalAfter="@id/message_photo" | ||||||
|  |                     android:accessibilityTraversalBefore="@id/message_content" | ||||||
|                     android:textAppearance="@style/TextAppearance.Conversations.Caption"/> |                     android:textAppearance="@style/TextAppearance.Conversations.Caption"/> | ||||||
|             </LinearLayout> |             </LinearLayout> | ||||||
|         </LinearLayout> |         </LinearLayout> | ||||||
|  |  | ||||||
|  | @ -51,7 +51,9 @@ | ||||||
|             android:orientation="vertical" |             android:orientation="vertical" | ||||||
|             android:padding="2dp"> |             android:padding="2dp"> | ||||||
| 
 | 
 | ||||||
|             <include layout="@layout/message_content" /> |             <include | ||||||
|  |                 android:id="@+id/message_content" | ||||||
|  |                 layout="@layout/message_content" /> | ||||||
| 
 | 
 | ||||||
|             <LinearLayout |             <LinearLayout | ||||||
|                 android:layout_width="wrap_content" |                 android:layout_width="wrap_content" | ||||||
|  | @ -67,6 +69,8 @@ | ||||||
|                     android:layout_gravity="center_vertical" |                     android:layout_gravity="center_vertical" | ||||||
|                     android:layout_marginEnd="4sp" |                     android:layout_marginEnd="4sp" | ||||||
|                     android:layout_marginRight="4sp" |                     android:layout_marginRight="4sp" | ||||||
|  |                     android:accessibilityTraversalAfter="@id/message_photo" | ||||||
|  |                     android:accessibilityTraversalBefore="@id/message_content" | ||||||
|                     android:gravity="center_vertical" |                     android:gravity="center_vertical" | ||||||
|                     android:text="@string/sending" |                     android:text="@string/sending" | ||||||
|                     android:textAppearance="@style/TextAppearance.Conversations.Caption" /> |                     android:textAppearance="@style/TextAppearance.Conversations.Caption" /> | ||||||
|  |  | ||||||
|  | @ -1,26 +1,25 @@ | ||||||
| <menu xmlns:android="http://schemas.android.com/apk/res/android" | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     xmlns:app="http://schemas.android.com/apk/res-auto"> |     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|     <item |     <item | ||||||
|         android:id="@+id/action_scan_qr_code" |         android:icon="?attr/icon_search" | ||||||
|         android:title="@string/scan_qr_code" |         android:orderInCategory="5" | ||||||
|         app:showAsAction="always" |         android:title="@string/search_messages" | ||||||
|         android:orderInCategory="10" |         android:visible="@bool/show_combined_search_options" | ||||||
|         android:visible="@bool/show_qr_code_scan" |         app:showAsAction="always"> | ||||||
|         android:icon="?attr/icon_scan_qr_code"/> |         <menu> | ||||||
|             <item |             <item | ||||||
|         android:id="@+id/action_accounts" |                 android:id="@+id/action_search_all_conversations" | ||||||
|         android:orderInCategory="90" |                 android:title="@string/search_all_conversations" /> | ||||||
|         android:title="@string/action_accounts" |  | ||||||
|         app:showAsAction="never"/> |  | ||||||
|             <item |             <item | ||||||
|         android:id="@+id/action_account" |                 android:id="@+id/action_search_this_conversation" | ||||||
|         android:orderInCategory="90" |                 android:title="@string/search_this_conversation" /> | ||||||
|         android:title="@string/action_account" |         </menu> | ||||||
|         app:showAsAction="never"/> |     </item> | ||||||
|     <item |     <item | ||||||
|         android:id="@+id/action_settings" |         android:id="@+id/action_scan_qr_code" | ||||||
|         android:orderInCategory="100" |         android:icon="?attr/icon_scan_qr_code" | ||||||
|         android:title="@string/action_settings" |         android:orderInCategory="10" | ||||||
|         app:showAsAction="never"/> |         android:title="@string/scan_qr_code" | ||||||
| 
 |         android:visible="@bool/show_qr_code_scan" | ||||||
|  |         app:showAsAction="always" /> | ||||||
| </menu> | </menu> | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
|         android:id="@+id/action_security" |         android:id="@+id/action_security" | ||||||
|         android:icon="?attr/icon_not_secure" |         android:icon="?attr/icon_not_secure" | ||||||
|         android:orderInCategory="20" |         android:orderInCategory="20" | ||||||
|         android:title="@string/action_secure" |         android:title="@string/encrypted_with_omemo" | ||||||
|         app:showAsAction="always"> |         app:showAsAction="always"> | ||||||
|         <menu> |         <menu> | ||||||
|             <group android:checkableBehavior="single"> |             <group android:checkableBehavior="single"> | ||||||
|  | @ -99,6 +99,12 @@ | ||||||
|         android:orderInCategory="45" |         android:orderInCategory="45" | ||||||
|         android:title="@string/invite_contact" |         android:title="@string/invite_contact" | ||||||
|         app:showAsAction="never" /> |         app:showAsAction="never" /> | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/action_search" | ||||||
|  |         android:orderInCategory="48" | ||||||
|  |         android:title="@string/search_messages" | ||||||
|  |         android:visible="@bool/show_individual_search_options" | ||||||
|  |         app:showAsAction="never" /> | ||||||
|     <item |     <item | ||||||
|         android:id="@+id/action_clear_history" |         android:id="@+id/action_clear_history" | ||||||
|         android:orderInCategory="50" |         android:orderInCategory="50" | ||||||
|  | @ -110,20 +116,27 @@ | ||||||
|         android:title="@string/action_end_conversation" |         android:title="@string/action_end_conversation" | ||||||
|         app:showAsAction="never" /> |         app:showAsAction="never" /> | ||||||
|     <item |     <item | ||||||
|         android:id="@+id/action_mute" |  | ||||||
|         android:orderInCategory="70" |         android:orderInCategory="70" | ||||||
|  |         android:title="@string/more_options"> | ||||||
|  |         <menu> | ||||||
|  |             <item | ||||||
|  |                 android:id="@+id/action_mute" | ||||||
|  |                 android:orderInCategory="71" | ||||||
|                 android:title="@string/disable_notifications" |                 android:title="@string/disable_notifications" | ||||||
|                 app:showAsAction="never" /> |                 app:showAsAction="never" /> | ||||||
| 
 |  | ||||||
|             <item |             <item | ||||||
|                 android:id="@+id/action_unmute" |                 android:id="@+id/action_unmute" | ||||||
|         android:orderInCategory="71" |                 android:orderInCategory="72" | ||||||
|                 android:title="@string/enable_notifications" |                 android:title="@string/enable_notifications" | ||||||
|                 app:showAsAction="never" /> |                 app:showAsAction="never" /> | ||||||
| 
 | 
 | ||||||
|             <item |             <item | ||||||
|                 android:id="@+id/action_toggle_pinned" |                 android:id="@+id/action_toggle_pinned" | ||||||
|         android:orderInCategory="72" |                 android:orderInCategory="73" | ||||||
|                 android:title="@string/add_to_favorites" |                 android:title="@string/add_to_favorites" | ||||||
|                 app:showAsAction="never" /> |                 app:showAsAction="never" /> | ||||||
|         </menu> |         </menu> | ||||||
|  |     </item> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | </menu> | ||||||
|  | @ -31,7 +31,23 @@ | ||||||
|     xmlns:app="http://schemas.android.com/apk/res-auto"> |     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|     <item |     <item | ||||||
|         android:id="@+id/action_search" |         android:id="@+id/action_search" | ||||||
|  |         android:orderInCategory="10" | ||||||
|         android:title="@string/search_messages" |         android:title="@string/search_messages" | ||||||
|         android:orderInCategory="50" |         android:visible="@bool/show_individual_search_options" | ||||||
|  |         app:showAsAction="never" /> | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/action_accounts" | ||||||
|  |         android:orderInCategory="90" | ||||||
|  |         android:title="@string/action_accounts" | ||||||
|  |         app:showAsAction="never" /> | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/action_account" | ||||||
|  |         android:orderInCategory="90" | ||||||
|  |         android:title="@string/action_account" | ||||||
|  |         app:showAsAction="never" /> | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/action_settings" | ||||||
|  |         android:orderInCategory="100" | ||||||
|  |         android:title="@string/action_settings" | ||||||
|         app:showAsAction="never" /> |         app:showAsAction="never" /> | ||||||
| </menu> | </menu> | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">محادثة جديدة</string> |   <string name="action_add">محادثة جديدة</string> | ||||||
|   <string name="action_accounts">إدارة الحسابات</string> |   <string name="action_accounts">إدارة الحسابات</string> | ||||||
|   <string name="action_account">إدارة الحساب</string> |   <string name="action_account">إدارة الحساب</string> | ||||||
|   <string name="action_end_conversation">أغلق هذه المحادثة</string> |  | ||||||
|   <string name="action_contact_details">بيانات جهة الإتصال</string> |   <string name="action_contact_details">بيانات جهة الإتصال</string> | ||||||
|   <string name="action_muc_details">تفاصيل مجموعة المحادثة</string> |   <string name="action_muc_details">تفاصيل مجموعة المحادثة</string> | ||||||
|   <string name="channel_details">تفاصيل القناة</string> |   <string name="channel_details">تفاصيل القناة</string> | ||||||
|   <string name="action_secure">تشفير المحادثة</string> |  | ||||||
|   <string name="action_add_account">إضافة حساب</string> |   <string name="action_add_account">إضافة حساب</string> | ||||||
|   <string name="action_edit_contact">تعديل الإسم</string> |   <string name="action_edit_contact">تعديل الإسم</string> | ||||||
|   <string name="action_add_phone_book">أضف إلى دفتر العناوين</string> |   <string name="action_add_phone_book">أضف إلى دفتر العناوين</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Нов разговор</string> |   <string name="action_add">Нов разговор</string> | ||||||
|   <string name="action_accounts">Управление на профилите</string> |   <string name="action_accounts">Управление на профилите</string> | ||||||
|   <string name="action_account">Управление на профила</string> |   <string name="action_account">Управление на профила</string> | ||||||
|   <string name="action_end_conversation">Затваряне на този разговор</string> |  | ||||||
|   <string name="action_contact_details">Подробности за контакта</string> |   <string name="action_contact_details">Подробности за контакта</string> | ||||||
|   <string name="action_muc_details">Подробности за груповия разговор</string> |   <string name="action_muc_details">Подробности за груповия разговор</string> | ||||||
|   <string name="channel_details">Подробности за канала</string> |   <string name="channel_details">Подробности за канала</string> | ||||||
|   <string name="action_secure">Защитен разговор</string> |  | ||||||
|   <string name="action_add_account">Добавяне на профил</string> |   <string name="action_add_account">Добавяне на профил</string> | ||||||
|   <string name="action_edit_contact">Редактиране на името</string> |   <string name="action_edit_contact">Редактиране на името</string> | ||||||
|   <string name="action_add_phone_book">Добавяне към адресния указател</string> |   <string name="action_add_phone_book">Добавяне към адресния указател</string> | ||||||
|  |  | ||||||
|  | @ -4,10 +4,8 @@ | ||||||
|   <string name="action_add">Nova conversa</string> |   <string name="action_add">Nova conversa</string> | ||||||
|   <string name="action_accounts">Gestiona els comptes</string> |   <string name="action_accounts">Gestiona els comptes</string> | ||||||
|   <string name="action_account">Administrar compte</string> |   <string name="action_account">Administrar compte</string> | ||||||
|   <string name="action_end_conversation">Tancar aquesta conversa</string> |  | ||||||
|   <string name="action_contact_details">Detalls del contacte</string> |   <string name="action_contact_details">Detalls del contacte</string> | ||||||
|   <string name="action_muc_details">Detalls del xat de grup</string> |   <string name="action_muc_details">Detalls del xat de grup</string> | ||||||
|   <string name="action_secure">Conversa segura</string> |  | ||||||
|   <string name="action_add_account">Afegeix un compte</string> |   <string name="action_add_account">Afegeix un compte</string> | ||||||
|   <string name="action_edit_contact">Edita el nom</string> |   <string name="action_edit_contact">Edita el nom</string> | ||||||
|   <string name="action_add_phone_book">Afegeix a la llibreta d\'adreces</string> |   <string name="action_add_phone_book">Afegeix a la llibreta d\'adreces</string> | ||||||
|  |  | ||||||
|  | @ -4,9 +4,7 @@ | ||||||
|   <string name="action_add">Nová konverzace</string> |   <string name="action_add">Nová konverzace</string> | ||||||
|   <string name="action_accounts">Nastavení účtů</string> |   <string name="action_accounts">Nastavení účtů</string> | ||||||
|   <string name="action_account">Nastavení účtu</string> |   <string name="action_account">Nastavení účtu</string> | ||||||
|   <string name="action_end_conversation">Zavřít tuto konverzaci</string> |  | ||||||
|   <string name="action_contact_details">Detaily kontaktu</string> |   <string name="action_contact_details">Detaily kontaktu</string> | ||||||
|   <string name="action_secure">Zabezpečená konverzace</string> |  | ||||||
|   <string name="action_add_account">Přidat účet</string> |   <string name="action_add_account">Přidat účet</string> | ||||||
|   <string name="action_edit_contact">Upravit jméno</string> |   <string name="action_edit_contact">Upravit jméno</string> | ||||||
|   <string name="action_add_phone_book">Přidat do adresáře</string> |   <string name="action_add_phone_book">Přidat do adresáře</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
|   <string name="action_add">Neue Unterhaltung</string> |   <string name="action_add">Neue Unterhaltung</string> | ||||||
|   <string name="action_accounts">Konten verwalten</string> |   <string name="action_accounts">Konten verwalten</string> | ||||||
|   <string name="action_account">Konto verwalten</string> |   <string name="action_account">Konto verwalten</string> | ||||||
|   <string name="action_end_conversation">Diese Unterhaltung beenden</string> |   <string name="action_end_conversation">Unterhaltung beenden</string> | ||||||
|   <string name="action_contact_details">Kontaktdetails</string> |   <string name="action_contact_details">Kontaktdetails</string> | ||||||
|   <string name="action_muc_details">Gruppenchatdetails</string> |   <string name="action_muc_details">Gruppenchatdetails</string> | ||||||
|   <string name="channel_details">Channeldetails</string> |   <string name="channel_details">Channeldetails</string> | ||||||
|   <string name="action_secure">Verschlüsselte Unterhaltung</string> |  | ||||||
|   <string name="action_add_account">Konto hinzufügen</string> |   <string name="action_add_account">Konto hinzufügen</string> | ||||||
|   <string name="action_edit_contact">Namen bearbeiten</string> |   <string name="action_edit_contact">Namen bearbeiten</string> | ||||||
|   <string name="action_add_phone_book">Zum Telefonbuch hinzufügen</string> |   <string name="action_add_phone_book">Zum Telefonbuch hinzufügen</string> | ||||||
|  | @ -754,6 +753,7 @@ | ||||||
|   <string name="ongoing_calls_channel_name">Laufende Anrufe</string> |   <string name="ongoing_calls_channel_name">Laufende Anrufe</string> | ||||||
|   <string name="silent_messages_channel_name">Lautlose Nachrichten</string> |   <string name="silent_messages_channel_name">Lautlose Nachrichten</string> | ||||||
|   <string name="silent_messages_channel_description">Diese Benachrichtigungsart wird verwendet, um Benachrichtigungen anzuzeigen, die keinen Ton auslösen sollen. Zum Beispiel, wenn du auf einem anderen Gerät aktiv bist (Schonfrist).</string> |   <string name="silent_messages_channel_description">Diese Benachrichtigungsart wird verwendet, um Benachrichtigungen anzuzeigen, die keinen Ton auslösen sollen. Zum Beispiel, wenn du auf einem anderen Gerät aktiv bist (Schonfrist).</string> | ||||||
|  |   <string name="delivery_failed_channel_name">Fehlgeschlagene Zustellungen</string> | ||||||
|   <string name="pref_message_notification_settings">Benachrichtigungseinstellungen</string> |   <string name="pref_message_notification_settings">Benachrichtigungseinstellungen</string> | ||||||
|   <string name="pref_incoming_call_notification_settings">Anrufeinstellungen</string> |   <string name="pref_incoming_call_notification_settings">Anrufeinstellungen</string> | ||||||
|   <string name="pref_more_notification_settings_summary">Wichtigkeit, Klang, Vibrationen</string> |   <string name="pref_more_notification_settings_summary">Wichtigkeit, Klang, Vibrationen</string> | ||||||
|  | @ -921,12 +921,30 @@ | ||||||
|   <string name="only_one_call_at_a_time">Du kannst immer nur einen Anruf zur gleichen Zeit machen.</string> |   <string name="only_one_call_at_a_time">Du kannst immer nur einen Anruf zur gleichen Zeit machen.</string> | ||||||
|   <string name="return_to_ongoing_call">Zurück zum laufenden Aufruf</string> |   <string name="return_to_ongoing_call">Zurück zum laufenden Aufruf</string> | ||||||
|   <string name="could_not_switch_camera">Kamera konnte nicht gewechselt werden</string> |   <string name="could_not_switch_camera">Kamera konnte nicht gewechselt werden</string> | ||||||
|   <string name="add_to_favorites">Zu Favoriten hinzufügen</string> |   <string name="add_to_favorites">Oben anheften</string> | ||||||
|   <string name="remove_from_favorites">Von Favoriten entfernen</string> |   <string name="remove_from_favorites">Von oben ablösen</string> | ||||||
|   <string name="gpx_track">GPX-Strecke</string> |   <string name="gpx_track">GPX-Strecke</string> | ||||||
|   <string name="could_not_correct_message">Nachricht konnte nicht korrigiert werden</string> |   <string name="could_not_correct_message">Nachricht konnte nicht korrigiert werden</string> | ||||||
|  |   <string name="search_all_conversations">Alle Unterhaltungen</string> | ||||||
|  |   <string name="search_this_conversation">Diese Unterhaltung</string> | ||||||
|  |   <string name="your_avatar">Dein Avatar</string> | ||||||
|  |   <string name="avatar_for_x">Avatar für %s</string> | ||||||
|  |   <string name="encrypted_with_omemo">Verschlüsselt mit OMEMO</string> | ||||||
|  |   <string name="encrypted_with_openpgp">Verschlüsselt mit OpenPGP</string> | ||||||
|  |   <string name="not_encrypted">Nicht verschlüsselt</string> | ||||||
|  |   <string name="exit">Beenden</string> | ||||||
|  |   <string name="record_voice_mail">Sprachnachricht aufzeichnen</string> | ||||||
|  |   <string name="play_audio">Audio abspielen</string> | ||||||
|  |   <string name="pause_audio">Audio anhalten</string> | ||||||
|  |   <string name="add_contact_or_create_or_join_group_chat">Kontakt hinzufügen, Gruppenchat erstellen oder beitreten oder Channels entdecken</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">%1$d Teilnehmer anzeigen</item> |     <item quantity="one">%1$d Teilnehmer anzeigen</item> | ||||||
|     <item quantity="other">%1$d Teilnehmer anzeigen</item> |     <item quantity="other">%1$d Teilnehmer anzeigen</item> | ||||||
|   </plurals> |   </plurals> | ||||||
|  |   <plurals name="some_messages_could_not_be_delivered"> | ||||||
|  |     <item quantity="one">Eine Nachricht konnte nicht zugestellt werden</item> | ||||||
|  |     <item quantity="other">Einige Nachrichten konnten nicht zugestellt werden</item> | ||||||
|  |   </plurals> | ||||||
|  |   <string name="failed_deliveries">Fehlgeschlagene Zustellungen</string> | ||||||
|  |   <string name="more_options">Weitere Optionen</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Νέα συζήτηση</string> |   <string name="action_add">Νέα συζήτηση</string> | ||||||
|   <string name="action_accounts">Διαχείριση λογαριασμών</string> |   <string name="action_accounts">Διαχείριση λογαριασμών</string> | ||||||
|   <string name="action_account">Διαχείριση λογαριασμού</string> |   <string name="action_account">Διαχείριση λογαριασμού</string> | ||||||
|   <string name="action_end_conversation">Κλείσιμο συζήτησης</string> |  | ||||||
|   <string name="action_contact_details">Λεπτομέρειες επαφής</string> |   <string name="action_contact_details">Λεπτομέρειες επαφής</string> | ||||||
|   <string name="action_muc_details">Λεπτομέρειες ομαδικής συζήτησης</string> |   <string name="action_muc_details">Λεπτομέρειες ομαδικής συζήτησης</string> | ||||||
|   <string name="channel_details">Λεπτομέρειες καναλιού</string> |   <string name="channel_details">Λεπτομέρειες καναλιού</string> | ||||||
|   <string name="action_secure">Ασφαλής συζήτηση</string> |  | ||||||
|   <string name="action_add_account">Προσθήκη λογαριασμού</string> |   <string name="action_add_account">Προσθήκη λογαριασμού</string> | ||||||
|   <string name="action_edit_contact">Επεξεργασία ονόματος</string> |   <string name="action_edit_contact">Επεξεργασία ονόματος</string> | ||||||
|   <string name="action_add_phone_book">Προσθήκη στην ατζέντα</string> |   <string name="action_add_phone_book">Προσθήκη στην ατζέντα</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
|   <string name="action_add">Nueva conversación</string> |   <string name="action_add">Nueva conversación</string> | ||||||
|   <string name="action_accounts">Gestionar cuentas</string> |   <string name="action_accounts">Gestionar cuentas</string> | ||||||
|   <string name="action_account">Gestionar cuenta</string> |   <string name="action_account">Gestionar cuenta</string> | ||||||
|   <string name="action_end_conversation">Cerrar esta conversación</string> |   <string name="action_end_conversation">Cerrar conversación</string> | ||||||
|   <string name="action_contact_details">Detalles del contacto</string> |   <string name="action_contact_details">Detalles del contacto</string> | ||||||
|   <string name="action_muc_details">Detalles de conversación</string> |   <string name="action_muc_details">Detalles de conversación</string> | ||||||
|   <string name="channel_details">Detalles del canal</string> |   <string name="channel_details">Detalles del canal</string> | ||||||
|   <string name="action_secure">Conversación segura</string> |  | ||||||
|   <string name="action_add_account">Añadir cuenta</string> |   <string name="action_add_account">Añadir cuenta</string> | ||||||
|   <string name="action_edit_contact">Editar contacto</string> |   <string name="action_edit_contact">Editar contacto</string> | ||||||
|   <string name="action_add_phone_book">Añadir a contactos</string> |   <string name="action_add_phone_book">Añadir a contactos</string> | ||||||
|  | @ -921,10 +920,20 @@ | ||||||
|   <string name="only_one_call_at_a_time">Solo puedes hacer una llamada a la vez</string> |   <string name="only_one_call_at_a_time">Solo puedes hacer una llamada a la vez</string> | ||||||
|   <string name="return_to_ongoing_call">Volver a la llamada en curso</string> |   <string name="return_to_ongoing_call">Volver a la llamada en curso</string> | ||||||
|   <string name="could_not_switch_camera">No se ha podido cambiar de cámara</string> |   <string name="could_not_switch_camera">No se ha podido cambiar de cámara</string> | ||||||
|   <string name="add_to_favorites">Añadir a los favoritos</string> |  | ||||||
|   <string name="remove_from_favorites">Eliminar de favoritos</string> |  | ||||||
|   <string name="gpx_track">Recorrido GPX</string> |   <string name="gpx_track">Recorrido GPX</string> | ||||||
|   <string name="could_not_correct_message">No se pudo corregir el mensaje</string> |   <string name="could_not_correct_message">No se pudo corregir el mensaje</string> | ||||||
|  |   <string name="search_all_conversations">Todas las conversaciones</string> | ||||||
|  |   <string name="search_this_conversation">Esta conversación</string> | ||||||
|  |   <string name="your_avatar">Tu imagen de perfil</string> | ||||||
|  |   <string name="avatar_for_x">Imagen de perfil de %s</string> | ||||||
|  |   <string name="encrypted_with_omemo">Encriptado con OMEMO</string> | ||||||
|  |   <string name="encrypted_with_openpgp">Encriptado con OpenPGP</string> | ||||||
|  |   <string name="not_encrypted">Sin encriptar</string> | ||||||
|  |   <string name="exit">Salir</string> | ||||||
|  |   <string name="record_voice_mail">Grabar mensaje de voz</string> | ||||||
|  |   <string name="play_audio">Reproducir audio</string> | ||||||
|  |   <string name="pause_audio">Pausar audio</string> | ||||||
|  |   <string name="add_contact_or_create_or_join_group_chat">Añadir contacto, crear o unirse a un grupo de chat, o descubrir canales</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Ver %1$d Participante</item> |     <item quantity="one">Ver %1$d Participante</item> | ||||||
|     <item quantity="other">Ver %1$d Participantes</item> |     <item quantity="other">Ver %1$d Participantes</item> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Elkarrizketa berria</string> |   <string name="action_add">Elkarrizketa berria</string> | ||||||
|   <string name="action_accounts">Kontuak kudeatu</string> |   <string name="action_accounts">Kontuak kudeatu</string> | ||||||
|   <string name="action_account">Kontua kudeatu</string> |   <string name="action_account">Kontua kudeatu</string> | ||||||
|   <string name="action_end_conversation">Elkarrizketa hau itxi</string> |  | ||||||
|   <string name="action_contact_details">Kontaktuaren xehetasunak</string> |   <string name="action_contact_details">Kontaktuaren xehetasunak</string> | ||||||
|   <string name="action_muc_details">Taldearen xehetasunak</string> |   <string name="action_muc_details">Taldearen xehetasunak</string> | ||||||
|   <string name="channel_details">Kanalaren xehetasunak</string> |   <string name="channel_details">Kanalaren xehetasunak</string> | ||||||
|   <string name="action_secure">Elkarrizketa segurua</string> |  | ||||||
|   <string name="action_add_account">Kontua gehitu</string> |   <string name="action_add_account">Kontua gehitu</string> | ||||||
|   <string name="action_edit_contact">Izena editatu</string> |   <string name="action_edit_contact">Izena editatu</string> | ||||||
|   <string name="action_add_phone_book">Helbideen liburura gehitu</string> |   <string name="action_add_phone_book">Helbideen liburura gehitu</string> | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
|   <string name="action_accounts">مدیریت حساب های کاربری</string> |   <string name="action_accounts">مدیریت حساب های کاربری</string> | ||||||
|   <string name="action_contact_details">جزییات مخاطب</string> |   <string name="action_contact_details">جزییات مخاطب</string> | ||||||
|   <string name="action_muc_details">جزئیات چت گروهی</string> |   <string name="action_muc_details">جزئیات چت گروهی</string> | ||||||
|   <string name="action_secure">مکالمه امن</string> |  | ||||||
|   <string name="action_add_account">اضافه کردن حساب کاربری</string> |   <string name="action_add_account">اضافه کردن حساب کاربری</string> | ||||||
|   <string name="action_edit_contact">تغییر نام</string> |   <string name="action_edit_contact">تغییر نام</string> | ||||||
|   <string name="action_add_phone_book">اضافه کردن به لیست ادرس ها</string> |   <string name="action_add_phone_book">اضافه کردن به لیست ادرس ها</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Nouvelle conversation</string> |   <string name="action_add">Nouvelle conversation</string> | ||||||
|   <string name="action_accounts">Gérer les comptes</string> |   <string name="action_accounts">Gérer les comptes</string> | ||||||
|   <string name="action_account">Gérer le compte</string> |   <string name="action_account">Gérer le compte</string> | ||||||
|   <string name="action_end_conversation">Fermer cette conversation</string> |  | ||||||
|   <string name="action_contact_details">Détails du contact</string> |   <string name="action_contact_details">Détails du contact</string> | ||||||
|   <string name="action_muc_details">Détails du groupe</string> |   <string name="action_muc_details">Détails du groupe</string> | ||||||
|   <string name="channel_details">Détails du canal</string> |   <string name="channel_details">Détails du canal</string> | ||||||
|   <string name="action_secure">Conversation sécurisée</string> |  | ||||||
|   <string name="action_add_account">Ajouter un compte</string> |   <string name="action_add_account">Ajouter un compte</string> | ||||||
|   <string name="action_edit_contact">Modifier le nom</string> |   <string name="action_edit_contact">Modifier le nom</string> | ||||||
|   <string name="action_add_phone_book">Ajouter au carnet d\'adresses</string> |   <string name="action_add_phone_book">Ajouter au carnet d\'adresses</string> | ||||||
|  | @ -913,8 +911,6 @@ | ||||||
|   <string name="only_one_call_at_a_time">Vous ne pouvez prendre qu\'un appel à la fois.</string> |   <string name="only_one_call_at_a_time">Vous ne pouvez prendre qu\'un appel à la fois.</string> | ||||||
|   <string name="return_to_ongoing_call">Reprendre l\'appel en cours</string> |   <string name="return_to_ongoing_call">Reprendre l\'appel en cours</string> | ||||||
|   <string name="could_not_switch_camera">Impossible de changer de caméra</string> |   <string name="could_not_switch_camera">Impossible de changer de caméra</string> | ||||||
|   <string name="add_to_favorites">Ajouter aux favoris</string> |  | ||||||
|   <string name="remove_from_favorites">Enlever des favoris</string> |  | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Voir %1$d participant</item> |     <item quantity="one">Voir %1$d participant</item> | ||||||
|     <item quantity="other">Voir %1$d participants</item> |     <item quantity="other">Voir %1$d participants</item> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
|   <string name="action_add">Nova conversa</string> |   <string name="action_add">Nova conversa</string> | ||||||
|   <string name="action_accounts">Xestionar contas</string> |   <string name="action_accounts">Xestionar contas</string> | ||||||
|   <string name="action_account">Xestionar conta</string> |   <string name="action_account">Xestionar conta</string> | ||||||
|   <string name="action_end_conversation">Pechar esta conversa</string> |   <string name="action_end_conversation">Pechar conversa</string> | ||||||
|   <string name="action_contact_details">Detalles do contacto</string> |   <string name="action_contact_details">Detalles do contacto</string> | ||||||
|   <string name="action_muc_details">Detalles da conversa de grupo</string> |   <string name="action_muc_details">Detalles da conversa de grupo</string> | ||||||
|   <string name="channel_details">Detalles do canal</string> |   <string name="channel_details">Detalles do canal</string> | ||||||
|   <string name="action_secure">Conversa segura</string> |  | ||||||
|   <string name="action_add_account">Engadir conta</string> |   <string name="action_add_account">Engadir conta</string> | ||||||
|   <string name="action_edit_contact">Editar contacto</string> |   <string name="action_edit_contact">Editar contacto</string> | ||||||
|   <string name="action_add_phone_book">Engadir a libreta de enderezos</string> |   <string name="action_add_phone_book">Engadir a libreta de enderezos</string> | ||||||
|  | @ -754,6 +753,7 @@ | ||||||
|   <string name="ongoing_calls_channel_name">Chamadas realizadas</string> |   <string name="ongoing_calls_channel_name">Chamadas realizadas</string> | ||||||
|   <string name="silent_messages_channel_name">Mensaxes acalados</string> |   <string name="silent_messages_channel_name">Mensaxes acalados</string> | ||||||
|   <string name="silent_messages_channel_description">Este grupo de notificacións é utilizado para mostrar notificacións que non debería activar ningún son. Por exemplo, cando está activo en outro dispositivo (Período de Graza).</string> |   <string name="silent_messages_channel_description">Este grupo de notificacións é utilizado para mostrar notificacións que non debería activar ningún son. Por exemplo, cando está activo en outro dispositivo (Período de Graza).</string> | ||||||
|  |   <string name="delivery_failed_channel_name">Entregas fallidas</string> | ||||||
|   <string name="pref_message_notification_settings">Axustes de notificación das mensaxes</string> |   <string name="pref_message_notification_settings">Axustes de notificación das mensaxes</string> | ||||||
|   <string name="pref_incoming_call_notification_settings">Axustes da notificación de chamadas</string> |   <string name="pref_incoming_call_notification_settings">Axustes da notificación de chamadas</string> | ||||||
|   <string name="pref_more_notification_settings_summary">Importancia, Son, Vibrar</string> |   <string name="pref_more_notification_settings_summary">Importancia, Son, Vibrar</string> | ||||||
|  | @ -921,12 +921,30 @@ | ||||||
|   <string name="only_one_call_at_a_time">Só podes manter unha chamada en cada momento.</string> |   <string name="only_one_call_at_a_time">Só podes manter unha chamada en cada momento.</string> | ||||||
|   <string name="return_to_ongoing_call">Voltar á chamada activa</string> |   <string name="return_to_ongoing_call">Voltar á chamada activa</string> | ||||||
|   <string name="could_not_switch_camera">Non se puido activar a cámara</string> |   <string name="could_not_switch_camera">Non se puido activar a cámara</string> | ||||||
|   <string name="add_to_favorites">Engadir a favoritas</string> |   <string name="add_to_favorites">Fixar enriba</string> | ||||||
|   <string name="remove_from_favorites">Eliminar das favoritas</string> |   <string name="remove_from_favorites">Desafixar de enriba</string> | ||||||
|   <string name="gpx_track">Ruta GPX</string> |   <string name="gpx_track">Ruta GPX</string> | ||||||
|   <string name="could_not_correct_message">No se pode correxir a mensaxe</string> |   <string name="could_not_correct_message">No se pode correxir a mensaxe</string> | ||||||
|  |   <string name="search_all_conversations">Todas as conversas</string> | ||||||
|  |   <string name="search_this_conversation">Esta conversa</string> | ||||||
|  |   <string name="your_avatar">O teu avatar</string> | ||||||
|  |   <string name="avatar_for_x">Avatar para %s</string> | ||||||
|  |   <string name="encrypted_with_omemo">Cifrado con OMEMO</string> | ||||||
|  |   <string name="encrypted_with_openpgp">Cifrado con OpenPGP</string> | ||||||
|  |   <string name="not_encrypted">Sen cifrar</string> | ||||||
|  |   <string name="exit">Saír</string> | ||||||
|  |   <string name="record_voice_mail">Gravar correo de voz</string> | ||||||
|  |   <string name="play_audio">Reproducir audio</string> | ||||||
|  |   <string name="pause_audio">Pausar audio</string> | ||||||
|  |   <string name="add_contact_or_create_or_join_group_chat">Engade un contacto, crea o únete a unha conversa en grupo ou descubre canles.</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Ver %1$d Participante</item> |     <item quantity="one">Ver %1$d Participante</item> | ||||||
|     <item quantity="other">Ver %1$d Participantes</item> |     <item quantity="other">Ver %1$d Participantes</item> | ||||||
|   </plurals> |   </plurals> | ||||||
|  |   <plurals name="some_messages_could_not_be_delivered"> | ||||||
|  |     <item quantity="one">Unha mensaxe non se entregou</item> | ||||||
|  |     <item quantity="other">Algunhas mensaxes non se entregaron</item> | ||||||
|  |   </plurals> | ||||||
|  |   <string name="failed_deliveries">Entregas fallidas</string> | ||||||
|  |   <string name="more_options">Máis opcións</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Új beszélgetés</string> |   <string name="action_add">Új beszélgetés</string> | ||||||
|   <string name="action_accounts">Fiókok kezelése</string> |   <string name="action_accounts">Fiókok kezelése</string> | ||||||
|   <string name="action_account">Fiók kezelése</string> |   <string name="action_account">Fiók kezelése</string> | ||||||
|   <string name="action_end_conversation">Beszélgetés bezárása</string> |  | ||||||
|   <string name="action_contact_details">Partner részletei</string> |   <string name="action_contact_details">Partner részletei</string> | ||||||
|   <string name="action_muc_details">Csoportos csevegés részletei</string> |   <string name="action_muc_details">Csoportos csevegés részletei</string> | ||||||
|   <string name="channel_details">Csatorna részletei</string> |   <string name="channel_details">Csatorna részletei</string> | ||||||
|   <string name="action_secure">Biztonságos beszélgetés</string> |  | ||||||
|   <string name="action_add_account">Fiók hozzáadása</string> |   <string name="action_add_account">Fiók hozzáadása</string> | ||||||
|   <string name="action_edit_contact">Név szerkesztése</string> |   <string name="action_edit_contact">Név szerkesztése</string> | ||||||
|   <string name="action_add_phone_book">Hozzáadás a címjegyzékhez</string> |   <string name="action_add_phone_book">Hozzáadás a címjegyzékhez</string> | ||||||
|  | @ -883,8 +881,6 @@ | ||||||
|   <string name="only_one_call_at_a_time">Egyszerre csak egy hívásban vehet részt.</string> |   <string name="only_one_call_at_a_time">Egyszerre csak egy hívásban vehet részt.</string> | ||||||
|   <string name="return_to_ongoing_call">Visszatérés a kimenő híváshoz</string> |   <string name="return_to_ongoing_call">Visszatérés a kimenő híváshoz</string> | ||||||
|   <string name="could_not_switch_camera">Nem sikerült átváltani a kamerát</string> |   <string name="could_not_switch_camera">Nem sikerült átváltani a kamerát</string> | ||||||
|   <string name="add_to_favorites">Hozzáadás a kedvencekhez</string> |  | ||||||
|   <string name="remove_from_favorites">Eltávolítás a kedvencekből</string> |  | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">%1$d résztvevő megtekintése</item> |     <item quantity="one">%1$d résztvevő megtekintése</item> | ||||||
|     <item quantity="other">%1$d résztvevő megtekintése</item> |     <item quantity="other">%1$d résztvevő megtekintése</item> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">Percakapan Baru</string> |   <string name="action_add">Percakapan Baru</string> | ||||||
|   <string name="action_accounts">Pengaturan Akun</string> |   <string name="action_accounts">Pengaturan Akun</string> | ||||||
|   <string name="action_contact_details">Detil Kontak</string> |   <string name="action_contact_details">Detil Kontak</string> | ||||||
|   <string name="action_secure">Amankan Percakapan</string> |  | ||||||
|   <string name="action_add_account">Tambah Akun</string> |   <string name="action_add_account">Tambah Akun</string> | ||||||
|   <string name="action_edit_contact">Ubah Nama</string> |   <string name="action_edit_contact">Ubah Nama</string> | ||||||
|   <string name="action_add_phone_book">Tambahkan ke daftar kontak</string> |   <string name="action_add_phone_book">Tambahkan ke daftar kontak</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Nuova conversazione</string> |   <string name="action_add">Nuova conversazione</string> | ||||||
|   <string name="action_accounts">Gestisci account</string> |   <string name="action_accounts">Gestisci account</string> | ||||||
|   <string name="action_account">Gestisci account</string> |   <string name="action_account">Gestisci account</string> | ||||||
|   <string name="action_end_conversation">Chiudi questa conversazione</string> |  | ||||||
|   <string name="action_contact_details">Dettagli del contatto</string> |   <string name="action_contact_details">Dettagli del contatto</string> | ||||||
|   <string name="action_muc_details">Dettagli chat di gruppo</string> |   <string name="action_muc_details">Dettagli chat di gruppo</string> | ||||||
|   <string name="channel_details">Dettagli canale</string> |   <string name="channel_details">Dettagli canale</string> | ||||||
|   <string name="action_secure">Conversazione sicura</string> |  | ||||||
|   <string name="action_add_account">Aggiungi account</string> |   <string name="action_add_account">Aggiungi account</string> | ||||||
|   <string name="action_edit_contact">Modifica il nome</string> |   <string name="action_edit_contact">Modifica il nome</string> | ||||||
|   <string name="action_add_phone_book">Aggiungi alla rubrica</string> |   <string name="action_add_phone_book">Aggiungi alla rubrica</string> | ||||||
|  | @ -461,7 +459,11 @@ | ||||||
|   <string name="server_info_broken">Rotto</string> |   <string name="server_info_broken">Rotto</string> | ||||||
|   <string name="pref_presence_settings">Disponibilità</string> |   <string name="pref_presence_settings">Disponibilità</string> | ||||||
|   <string name="pref_away_when_screen_off">\"Non disponibile\" a schermo spento</string> |   <string name="pref_away_when_screen_off">\"Non disponibile\" a schermo spento</string> | ||||||
|  |   <string name="pref_away_when_screen_off_summary">Imposta come non disponibile quando lo schermo è spento</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode">\"Occupato\" in modalità silenziosa</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode_summary">Imposta come occupato quando il dispositivo è in modalità silenziosa</string> | ||||||
|   <string name="pref_treat_vibrate_as_silent">Tratta vibrazione come modalità silenziosa</string> |   <string name="pref_treat_vibrate_as_silent">Tratta vibrazione come modalità silenziosa</string> | ||||||
|  |   <string name="pref_treat_vibrate_as_dnd_summary">Imposta come occupato quando il dispositivo è in modalità vibrazione</string> | ||||||
|   <string name="pref_show_connection_options">Impostazioni estese di connessione</string> |   <string name="pref_show_connection_options">Impostazioni estese di connessione</string> | ||||||
|   <string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un account</string> |   <string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un account</string> | ||||||
|   <string name="hostname_example">xmpp.esempio.it</string> |   <string name="hostname_example">xmpp.esempio.it</string> | ||||||
|  | @ -917,8 +919,8 @@ | ||||||
|   <string name="only_one_call_at_a_time">Puoi fare solo una chiamata alla volta.</string> |   <string name="only_one_call_at_a_time">Puoi fare solo una chiamata alla volta.</string> | ||||||
|   <string name="return_to_ongoing_call">Torna alla chiamata in corso</string> |   <string name="return_to_ongoing_call">Torna alla chiamata in corso</string> | ||||||
|   <string name="could_not_switch_camera">Impossibile cambiare fotocamera</string> |   <string name="could_not_switch_camera">Impossibile cambiare fotocamera</string> | ||||||
|   <string name="add_to_favorites">Aggiungi ai preferiti</string> |   <string name="gpx_track">Traccia GPX</string> | ||||||
|   <string name="remove_from_favorites">Rimuovi dai preferiti</string> |   <string name="could_not_correct_message">Impossibile correggere il messaggio</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Vedi %1$d partecipante</item> |     <item quantity="one">Vedi %1$d partecipante</item> | ||||||
|     <item quantity="other">Vedi %1$d partecipanti</item> |     <item quantity="other">Vedi %1$d partecipanti</item> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">שיחה חדשה</string> |   <string name="action_add">שיחה חדשה</string> | ||||||
|   <string name="action_accounts">נהל חשבונות</string> |   <string name="action_accounts">נהל חשבונות</string> | ||||||
|   <string name="action_contact_details">פרטי איש קשר</string> |   <string name="action_contact_details">פרטי איש קשר</string> | ||||||
|   <string name="action_secure">דיון מאובטח</string> |  | ||||||
|   <string name="action_add_account">הוסף חשבון</string> |   <string name="action_add_account">הוסף חשבון</string> | ||||||
|   <string name="action_edit_contact">ערוך שם</string> |   <string name="action_edit_contact">ערוך שם</string> | ||||||
|   <string name="action_delete_contact">מחק מרשימת אנשי הקשר</string> |   <string name="action_delete_contact">מחק מרשימת אנשי הקשר</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">新しい会話</string> |   <string name="action_add">新しい会話</string> | ||||||
|   <string name="action_accounts">アカウントの管理</string> |   <string name="action_accounts">アカウントの管理</string> | ||||||
|   <string name="action_account">アカウントの管理</string> |   <string name="action_account">アカウントの管理</string> | ||||||
|   <string name="action_end_conversation">この会話を閉じる</string> |  | ||||||
|   <string name="action_contact_details">連絡先の詳細</string> |   <string name="action_contact_details">連絡先の詳細</string> | ||||||
|   <string name="action_muc_details">談話室の詳細</string> |   <string name="action_muc_details">談話室の詳細</string> | ||||||
|   <string name="channel_details">チャンネルの詳細</string> |   <string name="channel_details">チャンネルの詳細</string> | ||||||
|   <string name="action_secure">安全に会話</string> |  | ||||||
|   <string name="action_add_account">アカウントを追加</string> |   <string name="action_add_account">アカウントを追加</string> | ||||||
|   <string name="action_edit_contact">名前の編集</string> |   <string name="action_edit_contact">名前の編集</string> | ||||||
|   <string name="action_add_phone_book">アドレス帳に追加</string> |   <string name="action_add_phone_book">アドレス帳に追加</string> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">새 대화</string> |   <string name="action_add">새 대화</string> | ||||||
|   <string name="action_accounts">계정 </string> |   <string name="action_accounts">계정 </string> | ||||||
|   <string name="action_contact_details">연락처 정보</string> |   <string name="action_contact_details">연락처 정보</string> | ||||||
|   <string name="action_secure">안전한 대화 </string> |  | ||||||
|   <string name="action_add_account">계정 추가 </string> |   <string name="action_add_account">계정 추가 </string> | ||||||
|   <string name="action_edit_contact">이름 편집 </string> |   <string name="action_edit_contact">이름 편집 </string> | ||||||
|   <string name="action_add_phone_book">주소록에 추가</string> |   <string name="action_add_phone_book">주소록에 추가</string> | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
|   <string name="action_accounts">Kontobehandling</string> |   <string name="action_accounts">Kontobehandling</string> | ||||||
|   <string name="action_contact_details">Kontaktdetaljer</string> |   <string name="action_contact_details">Kontaktdetaljer</string> | ||||||
|   <string name="action_muc_details">Gruppesludringsdetaljer</string> |   <string name="action_muc_details">Gruppesludringsdetaljer</string> | ||||||
|   <string name="action_secure">Sikret samtale</string> |  | ||||||
|   <string name="action_add_account">Legg til samtale</string> |   <string name="action_add_account">Legg til samtale</string> | ||||||
|   <string name="action_edit_contact">Rediger navn</string> |   <string name="action_edit_contact">Rediger navn</string> | ||||||
|   <string name="action_add_phone_book">Legg til i kontaktliste</string> |   <string name="action_add_phone_book">Legg til i kontaktliste</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Nieuw gesprek</string> |   <string name="action_add">Nieuw gesprek</string> | ||||||
|   <string name="action_accounts">Accounts beheren</string> |   <string name="action_accounts">Accounts beheren</string> | ||||||
|   <string name="action_account">Account beheren</string> |   <string name="action_account">Account beheren</string> | ||||||
|   <string name="action_end_conversation">Dit gesprek sluiten</string> |  | ||||||
|   <string name="action_contact_details">Contactgegevens</string> |   <string name="action_contact_details">Contactgegevens</string> | ||||||
|   <string name="action_muc_details">Gespreksgegevens</string> |   <string name="action_muc_details">Gespreksgegevens</string> | ||||||
|   <string name="channel_details">Kanaalinformatie</string> |   <string name="channel_details">Kanaalinformatie</string> | ||||||
|   <string name="action_secure">Beveiligd gesprek</string> |  | ||||||
|   <string name="action_add_account">Account toevoegen</string> |   <string name="action_add_account">Account toevoegen</string> | ||||||
|   <string name="action_edit_contact">Naam veranderen</string> |   <string name="action_edit_contact">Naam veranderen</string> | ||||||
|   <string name="action_add_phone_book">Toevoegen aan adresboek</string> |   <string name="action_add_phone_book">Toevoegen aan adresboek</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
|   <string name="action_add">Nowa konwersacja</string> |   <string name="action_add">Nowa konwersacja</string> | ||||||
|   <string name="action_accounts">Zarządzaj kontami</string> |   <string name="action_accounts">Zarządzaj kontami</string> | ||||||
|   <string name="action_account">Zarządzaj kontem</string> |   <string name="action_account">Zarządzaj kontem</string> | ||||||
|   <string name="action_end_conversation">Zamknij konwersację</string> |   <string name="action_end_conversation">Zamknij rozmowę</string> | ||||||
|   <string name="action_contact_details">Szczegóły kontaktu</string> |   <string name="action_contact_details">Szczegóły kontaktu</string> | ||||||
|   <string name="action_muc_details">Szczegóły konferencji</string> |   <string name="action_muc_details">Szczegóły konferencji</string> | ||||||
|   <string name="channel_details">Szczegóły kanału</string> |   <string name="channel_details">Szczegóły kanału</string> | ||||||
|   <string name="action_secure">Konwersacja szyfrowana</string> |  | ||||||
|   <string name="action_add_account">Dodaj konto</string> |   <string name="action_add_account">Dodaj konto</string> | ||||||
|   <string name="action_edit_contact">Edytuj nazwę</string> |   <string name="action_edit_contact">Edytuj nazwę</string> | ||||||
|   <string name="action_add_phone_book">Dodaj do kontaktów</string> |   <string name="action_add_phone_book">Dodaj do kontaktów</string> | ||||||
|  | @ -401,6 +400,7 @@ | ||||||
|   <string name="mark_as_read">Oznacz jako przeczytane</string> |   <string name="mark_as_read">Oznacz jako przeczytane</string> | ||||||
|   <string name="pref_input_options">Ustawienia wprowadzania</string> |   <string name="pref_input_options">Ustawienia wprowadzania</string> | ||||||
|   <string name="pref_enter_is_send">Enter wysyła</string> |   <string name="pref_enter_is_send">Enter wysyła</string> | ||||||
|  |   <string name="pref_enter_is_send_summary">Użyj klawisza Enter aby wysłać wiadomość. Możesz zawsze użyć Ctrl+Enter do wysyłania wiadomości, nawet jeśli ta opcja jest wyłączona.</string> | ||||||
|   <string name="pref_display_enter_key">Pokaż klawisz Enter</string> |   <string name="pref_display_enter_key">Pokaż klawisz Enter</string> | ||||||
|   <string name="pref_display_enter_key_summary">Zamień klawisz emotikon na klawisz Enter</string> |   <string name="pref_display_enter_key_summary">Zamień klawisz emotikon na klawisz Enter</string> | ||||||
|   <string name="audio">plik audio</string> |   <string name="audio">plik audio</string> | ||||||
|  | @ -424,8 +424,8 @@ | ||||||
|   <string name="no_application_found_to_display_location">Nie odnaleziono aplikacji do wyświetlenia lokalizacji</string> |   <string name="no_application_found_to_display_location">Nie odnaleziono aplikacji do wyświetlenia lokalizacji</string> | ||||||
|   <string name="location">Lokalizacja</string> |   <string name="location">Lokalizacja</string> | ||||||
|   <string name="title_undo_swipe_out_conversation">Zamknięto konwersację</string> |   <string name="title_undo_swipe_out_conversation">Zamknięto konwersację</string> | ||||||
|   <string name="title_undo_swipe_out_group_chat">Opuść prywatną rozmowę grupową</string> |   <string name="title_undo_swipe_out_group_chat">Opuszczono prywatną rozmowę grupową</string> | ||||||
|   <string name="title_undo_swipe_out_channel">Opuść publiczny kanał</string> |   <string name="title_undo_swipe_out_channel">Opuszczono publiczny kanał</string> | ||||||
|   <string name="pref_dont_trust_system_cas_title">Nie ufaj certyfikatom systemowym</string> |   <string name="pref_dont_trust_system_cas_title">Nie ufaj certyfikatom systemowym</string> | ||||||
|   <string name="pref_dont_trust_system_cas_summary">Wymagaj ręcznego potwierdzania certyfikatów</string> |   <string name="pref_dont_trust_system_cas_summary">Wymagaj ręcznego potwierdzania certyfikatów</string> | ||||||
|   <string name="pref_remove_trusted_certificates_title">Usuń certyfikaty</string> |   <string name="pref_remove_trusted_certificates_title">Usuń certyfikaty</string> | ||||||
|  | @ -462,7 +462,11 @@ | ||||||
|   <string name="server_info_broken">Zepsute</string> |   <string name="server_info_broken">Zepsute</string> | ||||||
|   <string name="pref_presence_settings">Dostępność</string> |   <string name="pref_presence_settings">Dostępność</string> | ||||||
|   <string name="pref_away_when_screen_off">Status \"Oddalony\" gdy wyświetlacz jest wyłączony</string> |   <string name="pref_away_when_screen_off">Status \"Oddalony\" gdy wyświetlacz jest wyłączony</string> | ||||||
|  |   <string name="pref_away_when_screen_off_summary">Pokaż jako Oddalony kiedy ekran jest wyłączony.</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode">Zajęty w trybie cichym</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode_summary">Pokaż jako Zajęty jeśli urządzenie jest w trybie cichym</string> | ||||||
|   <string name="pref_treat_vibrate_as_silent">Traktuj tryb wibracji jak tryb cichy</string> |   <string name="pref_treat_vibrate_as_silent">Traktuj tryb wibracji jak tryb cichy</string> | ||||||
|  |   <string name="pref_treat_vibrate_as_dnd_summary">Pokaż jako Zajęty kiedy urządzenie jest w trybie wibracji</string> | ||||||
|   <string name="pref_show_connection_options">Rozszerzone ustawienia połączenia</string> |   <string name="pref_show_connection_options">Rozszerzone ustawienia połączenia</string> | ||||||
|   <string name="pref_show_connection_options_summary">Pokaż nazwę hosta i ustawienia portu przy dodawaniu konta</string> |   <string name="pref_show_connection_options_summary">Pokaż nazwę hosta i ustawienia portu przy dodawaniu konta</string> | ||||||
|   <string name="hostname_example">xmpp.example.com</string> |   <string name="hostname_example">xmpp.example.com</string> | ||||||
|  | @ -767,6 +771,7 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż | ||||||
|   <string name="ongoing_calls_channel_name">Połączenia wychodzące</string> |   <string name="ongoing_calls_channel_name">Połączenia wychodzące</string> | ||||||
|   <string name="silent_messages_channel_name">Ciche wiadomości</string> |   <string name="silent_messages_channel_name">Ciche wiadomości</string> | ||||||
|   <string name="silent_messages_channel_description">Ta kategoria powiadomień jest używana aby wyświetlać powiadomienia które nie powodują żadnych dźwięków. Na przykład w ciągu aktywności na innym urządzeniu (okres karencji).</string> |   <string name="silent_messages_channel_description">Ta kategoria powiadomień jest używana aby wyświetlać powiadomienia które nie powodują żadnych dźwięków. Na przykład w ciągu aktywności na innym urządzeniu (okres karencji).</string> | ||||||
|  |   <string name="delivery_failed_channel_name">Nie dostarczone wiadomości</string> | ||||||
|   <string name="pref_message_notification_settings">Ustawienia powiadomień wiadomości</string> |   <string name="pref_message_notification_settings">Ustawienia powiadomień wiadomości</string> | ||||||
|   <string name="pref_incoming_call_notification_settings">Ustawienia powiadomień dla przychodzących połączeń</string> |   <string name="pref_incoming_call_notification_settings">Ustawienia powiadomień dla przychodzących połączeń</string> | ||||||
|   <string name="pref_more_notification_settings_summary">Ważność, Dźwięk, Wibracja</string> |   <string name="pref_more_notification_settings_summary">Ważność, Dźwięk, Wibracja</string> | ||||||
|  | @ -929,16 +934,39 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż | ||||||
|   <string name="audio_call">Połączenie audio</string> |   <string name="audio_call">Połączenie audio</string> | ||||||
|   <string name="video_call">Połączenie wideo</string> |   <string name="video_call">Połączenie wideo</string> | ||||||
|   <string name="help">Pomoc</string> |   <string name="help">Pomoc</string> | ||||||
|  |   <string name="switch_to_conversation">Przełącz do rozmowy</string> | ||||||
|   <string name="microphone_unavailable">Twój mikrofon jest niedostępny</string> |   <string name="microphone_unavailable">Twój mikrofon jest niedostępny</string> | ||||||
|   <string name="only_one_call_at_a_time">Możesz mieć tylko jedno połączenie na raz.</string> |   <string name="only_one_call_at_a_time">Możesz mieć tylko jedno połączenie na raz.</string> | ||||||
|   <string name="return_to_ongoing_call">Powróć do trwającego połączenia</string> |   <string name="return_to_ongoing_call">Powróć do trwającego połączenia</string> | ||||||
|   <string name="could_not_switch_camera">Nie można zmienić aparatu</string> |   <string name="could_not_switch_camera">Nie można zmienić aparatu</string> | ||||||
|   <string name="add_to_favorites">Dodaj do ulubionych</string> |   <string name="add_to_favorites">Przypnij</string> | ||||||
|   <string name="remove_from_favorites">Usuń z ulubionych</string> |   <string name="remove_from_favorites">Odepnij</string> | ||||||
|  |   <string name="gpx_track">Ścieżka GPX</string> | ||||||
|  |   <string name="could_not_correct_message">Nie można poprawić wiadomości</string> | ||||||
|  |   <string name="search_all_conversations">Wszystkie rozmowy</string> | ||||||
|  |   <string name="search_this_conversation">Ta rozmowa</string> | ||||||
|  |   <string name="your_avatar">Twój awatar</string> | ||||||
|  |   <string name="avatar_for_x">Awatar dla %s</string> | ||||||
|  |   <string name="encrypted_with_omemo">Zaszyfrowane OMEMO</string> | ||||||
|  |   <string name="encrypted_with_openpgp">Zaszyfrowane OpenPGP</string> | ||||||
|  |   <string name="not_encrypted">Niezaszyfrowane</string> | ||||||
|  |   <string name="exit">Wyjście</string> | ||||||
|  |   <string name="record_voice_mail">Zapisz pocztę głosową</string> | ||||||
|  |   <string name="play_audio">Odtwórz audio</string> | ||||||
|  |   <string name="pause_audio">Spauzuj audio</string> | ||||||
|  |   <string name="add_contact_or_create_or_join_group_chat">Dodaj kontakt, stwórz lub dołącz do rozmowy grupowej lub odkryj kanały</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Pokaż %1$d uczestnika</item> |     <item quantity="one">Pokaż %1$d uczestnika</item> | ||||||
|     <item quantity="few">Pokaż %1$d uczestników</item> |     <item quantity="few">Pokaż %1$d uczestników</item> | ||||||
|     <item quantity="many">Pokaż %1$d uczestników</item> |     <item quantity="many">Pokaż %1$d uczestników</item> | ||||||
|     <item quantity="other">Pokaż %1$d uczestników</item> |     <item quantity="other">Pokaż %1$d uczestników</item> | ||||||
|   </plurals> |   </plurals> | ||||||
|  |   <plurals name="some_messages_could_not_be_delivered"> | ||||||
|  |     <item quantity="one">Wiadomość nie mogła zostać dostarczona</item> | ||||||
|  |     <item quantity="few">Niektóre wiadomości nie mogły być dostarczone</item> | ||||||
|  |     <item quantity="many">Niektóre wiadomości nie mogły być dostarczone</item> | ||||||
|  |     <item quantity="other">Niektóre wiadomości nie mogły być dostarczone</item> | ||||||
|  |   </plurals> | ||||||
|  |   <string name="failed_deliveries">Nie dostarczone wiadomości</string> | ||||||
|  |   <string name="more_options">Więcej ustawień</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Nova conversa</string> |   <string name="action_add">Nova conversa</string> | ||||||
|   <string name="action_accounts">Gerenciar contas</string> |   <string name="action_accounts">Gerenciar contas</string> | ||||||
|   <string name="action_account">Gerenciar conta</string> |   <string name="action_account">Gerenciar conta</string> | ||||||
|   <string name="action_end_conversation">Encerrar essa conversa</string> |  | ||||||
|   <string name="action_contact_details">Detalhes do contato</string> |   <string name="action_contact_details">Detalhes do contato</string> | ||||||
|   <string name="action_muc_details">Detalhes da conversa em grupo</string> |   <string name="action_muc_details">Detalhes da conversa em grupo</string> | ||||||
|   <string name="channel_details">Detalhes do canal</string> |   <string name="channel_details">Detalhes do canal</string> | ||||||
|   <string name="action_secure">Conversa segura</string> |  | ||||||
|   <string name="action_add_account">Adicionar conta</string> |   <string name="action_add_account">Adicionar conta</string> | ||||||
|   <string name="action_edit_contact">Editar o nome</string> |   <string name="action_edit_contact">Editar o nome</string> | ||||||
|   <string name="action_add_phone_book">Adicionar ao livro de endereços</string> |   <string name="action_add_phone_book">Adicionar ao livro de endereços</string> | ||||||
|  | @ -921,8 +919,6 @@ | ||||||
|   <string name="only_one_call_at_a_time">Você só pode ter uma chamada de cada vez</string> |   <string name="only_one_call_at_a_time">Você só pode ter uma chamada de cada vez</string> | ||||||
|   <string name="return_to_ongoing_call">Retornar para a chamada em andamento</string> |   <string name="return_to_ongoing_call">Retornar para a chamada em andamento</string> | ||||||
|   <string name="could_not_switch_camera">Não foi possível trocar a câmera</string> |   <string name="could_not_switch_camera">Não foi possível trocar a câmera</string> | ||||||
|   <string name="add_to_favorites">Adicionar aos favoritos</string> |  | ||||||
|   <string name="remove_from_favorites">Remover dos favoritos</string> |  | ||||||
|   <string name="gpx_track">Trilha GPX</string> |   <string name="gpx_track">Trilha GPX</string> | ||||||
|   <string name="could_not_correct_message">Não foi possível corrigir a mensagem</string> |   <string name="could_not_correct_message">Não foi possível corrigir a mensagem</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">Nova conversa</string> |   <string name="action_add">Nova conversa</string> | ||||||
|   <string name="action_accounts">Gerir contas</string> |   <string name="action_accounts">Gerir contas</string> | ||||||
|   <string name="action_contact_details">Detalhes do contacto</string> |   <string name="action_contact_details">Detalhes do contacto</string> | ||||||
|   <string name="action_secure">Conversa segura</string> |  | ||||||
|   <string name="action_add_account">Adicionar conta</string> |   <string name="action_add_account">Adicionar conta</string> | ||||||
|   <string name="action_edit_contact">Editar nome</string> |   <string name="action_edit_contact">Editar nome</string> | ||||||
|   <string name="action_add_phone_book">Adicionar ao livro de endereços</string> |   <string name="action_add_phone_book">Adicionar ao livro de endereços</string> | ||||||
|  |  | ||||||
|  | @ -8,7 +8,6 @@ | ||||||
|   <string name="action_contact_details">Detalii contact</string> |   <string name="action_contact_details">Detalii contact</string> | ||||||
|   <string name="action_muc_details">Detalii discuție de grup</string> |   <string name="action_muc_details">Detalii discuție de grup</string> | ||||||
|   <string name="channel_details">Detalii canal</string> |   <string name="channel_details">Detalii canal</string> | ||||||
|   <string name="action_secure">Securizează conferința</string> |  | ||||||
|   <string name="action_add_account">Adaugă cont</string> |   <string name="action_add_account">Adaugă cont</string> | ||||||
|   <string name="action_edit_contact">Editează nume</string> |   <string name="action_edit_contact">Editează nume</string> | ||||||
|   <string name="action_add_phone_book">Adaugă la lista de contacte</string> |   <string name="action_add_phone_book">Adaugă la lista de contacte</string> | ||||||
|  | @ -762,6 +761,7 @@ | ||||||
|   <string name="ongoing_calls_channel_name">Apeluri în curs</string> |   <string name="ongoing_calls_channel_name">Apeluri în curs</string> | ||||||
|   <string name="silent_messages_channel_name">Mesaje silențioase</string> |   <string name="silent_messages_channel_name">Mesaje silențioase</string> | ||||||
|   <string name="silent_messages_channel_description">Acest grup de notificări este folosit pentru a arăta notificări care nu emit sunete. De exemplu atunci când sunteți activi pe un alt dispozitiv (Perioada de grație).</string> |   <string name="silent_messages_channel_description">Acest grup de notificări este folosit pentru a arăta notificări care nu emit sunete. De exemplu atunci când sunteți activi pe un alt dispozitiv (Perioada de grație).</string> | ||||||
|  |   <string name="delivery_failed_channel_name">Trimiteri eșuate</string> | ||||||
|   <string name="pref_message_notification_settings">Setări de notificare ale mesajelor</string> |   <string name="pref_message_notification_settings">Setări de notificare ale mesajelor</string> | ||||||
|   <string name="pref_incoming_call_notification_settings">Setări de notificare ale apelurilor primite</string> |   <string name="pref_incoming_call_notification_settings">Setări de notificare ale apelurilor primite</string> | ||||||
|   <string name="pref_more_notification_settings_summary">Importanță, sunete, vibrații</string> |   <string name="pref_more_notification_settings_summary">Importanță, sunete, vibrații</string> | ||||||
|  | @ -929,13 +929,32 @@ | ||||||
|   <string name="only_one_call_at_a_time">Puteți avea un singur apel simultan.</string> |   <string name="only_one_call_at_a_time">Puteți avea un singur apel simultan.</string> | ||||||
|   <string name="return_to_ongoing_call">Reveniți la apelul în curs</string> |   <string name="return_to_ongoing_call">Reveniți la apelul în curs</string> | ||||||
|   <string name="could_not_switch_camera">Nu s-a putut face comutarea camerei foto</string> |   <string name="could_not_switch_camera">Nu s-a putut face comutarea camerei foto</string> | ||||||
|   <string name="add_to_favorites">Adaugă la favorite</string> |   <string name="add_to_favorites">Fixează sus</string> | ||||||
|   <string name="remove_from_favorites">Înlătură din favorite</string> |   <string name="remove_from_favorites">Anulează fixarea</string> | ||||||
|   <string name="gpx_track">Traseu GPX</string> |   <string name="gpx_track">Traseu GPX</string> | ||||||
|   <string name="could_not_correct_message">Nu s-a putut corecta mesajul</string> |   <string name="could_not_correct_message">Nu s-a putut corecta mesajul</string> | ||||||
|  |   <string name="search_all_conversations">Toate conversațiile</string> | ||||||
|  |   <string name="search_this_conversation">Această conversație</string> | ||||||
|  |   <string name="your_avatar">Avatarul dumneavoastră</string> | ||||||
|  |   <string name="avatar_for_x">Avatar pentru %s</string> | ||||||
|  |   <string name="encrypted_with_omemo">Criptare OMEMO</string> | ||||||
|  |   <string name="encrypted_with_openpgp">Criptare OpenPGP</string> | ||||||
|  |   <string name="not_encrypted">Fără criptare</string> | ||||||
|  |   <string name="exit">Ieșire</string> | ||||||
|  |   <string name="record_voice_mail">Înregistrare mesaj vocal</string> | ||||||
|  |   <string name="play_audio">Redare audio</string> | ||||||
|  |   <string name="pause_audio">Pauză audio</string> | ||||||
|  |   <string name="add_contact_or_create_or_join_group_chat">Adaugă contact, creează sau alătură-te discuției de grup, sau descoperă canale</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Arată %1$d participant</item> |     <item quantity="one">Arată %1$d participant</item> | ||||||
|     <item quantity="few">Arată %1$d participanți</item> |     <item quantity="few">Arată %1$d participanți</item> | ||||||
|     <item quantity="other">Arată %1$d de participanți</item> |     <item quantity="other">Arată %1$d de participanți</item> | ||||||
|   </plurals> |   </plurals> | ||||||
|  |   <plurals name="some_messages_could_not_be_delivered"> | ||||||
|  |     <item quantity="one">Un mesaj nu a putut fi livrat</item> | ||||||
|  |     <item quantity="few">Niște mesaje nu au putut fi livrate</item> | ||||||
|  |     <item quantity="other">Niște mesaje nu au putut fi livrate</item> | ||||||
|  |   </plurals> | ||||||
|  |   <string name="failed_deliveries">Trimiteri eșuate</string> | ||||||
|  |   <string name="more_options">Mai multe</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Новая беседа</string> |   <string name="action_add">Новая беседа</string> | ||||||
|   <string name="action_accounts">Управление аккаунтами</string> |   <string name="action_accounts">Управление аккаунтами</string> | ||||||
|   <string name="action_account">Управление аккаунтом</string> |   <string name="action_account">Управление аккаунтом</string> | ||||||
|   <string name="action_end_conversation">Закрыть текущую беседу</string> |  | ||||||
|   <string name="action_contact_details">Сведения о контакте</string> |   <string name="action_contact_details">Сведения о контакте</string> | ||||||
|   <string name="action_muc_details">Подробности конференции</string> |   <string name="action_muc_details">Подробности конференции</string> | ||||||
|   <string name="channel_details">Сведения о канале</string> |   <string name="channel_details">Сведения о канале</string> | ||||||
|   <string name="action_secure">Защищённая беседа</string> |  | ||||||
|   <string name="action_add_account">Добавить аккаунт</string> |   <string name="action_add_account">Добавить аккаунт</string> | ||||||
|   <string name="action_edit_contact">Редактировать контакт</string> |   <string name="action_edit_contact">Редактировать контакт</string> | ||||||
|   <string name="action_add_phone_book">Добавить в адресную книгу</string> |   <string name="action_add_phone_book">Добавить в адресную книгу</string> | ||||||
|  | @ -933,8 +931,6 @@ | ||||||
|   <string name="only_one_call_at_a_time">Нельзя одновременно совершать больше одного звонка.</string> |   <string name="only_one_call_at_a_time">Нельзя одновременно совершать больше одного звонка.</string> | ||||||
|   <string name="return_to_ongoing_call">Вернуться к текущему звонку</string> |   <string name="return_to_ongoing_call">Вернуться к текущему звонку</string> | ||||||
|   <string name="could_not_switch_camera">Не удалось переключить камеру</string> |   <string name="could_not_switch_camera">Не удалось переключить камеру</string> | ||||||
|   <string name="add_to_favorites">Добавить в избранные</string> |  | ||||||
|   <string name="remove_from_favorites">Убрать из избранных</string> |  | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Просмотр %1$d участника</item> |     <item quantity="one">Просмотр %1$d участника</item> | ||||||
|     <item quantity="few">Просмотр %1$d участников</item> |     <item quantity="few">Просмотр %1$d участников</item> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">Nová konverzácia</string> |   <string name="action_add">Nová konverzácia</string> | ||||||
|   <string name="action_accounts">Nastavenie účtov</string> |   <string name="action_accounts">Nastavenie účtov</string> | ||||||
|   <string name="action_contact_details">Detaily kontaktu</string> |   <string name="action_contact_details">Detaily kontaktu</string> | ||||||
|   <string name="action_secure">Zabezpečená konverzácia</string> |  | ||||||
|   <string name="action_add_account">Pridať účet</string> |   <string name="action_add_account">Pridať účet</string> | ||||||
|   <string name="action_edit_contact">Upraviť meno</string> |   <string name="action_edit_contact">Upraviť meno</string> | ||||||
|   <string name="action_delete_contact">Vymazať zo zoznamu</string> |   <string name="action_delete_contact">Vymazať zo zoznamu</string> | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
|   <string name="action_accounts">Управљај налозима</string> |   <string name="action_accounts">Управљај налозима</string> | ||||||
|   <string name="action_contact_details">Детаљи контакта</string> |   <string name="action_contact_details">Детаљи контакта</string> | ||||||
|   <string name="action_muc_details">Детаљи групног ћаскања</string> |   <string name="action_muc_details">Детаљи групног ћаскања</string> | ||||||
|   <string name="action_secure">Безбедна преписка</string> |  | ||||||
|   <string name="action_add_account">Додај налог</string> |   <string name="action_add_account">Додај налог</string> | ||||||
|   <string name="action_edit_contact">Уреди име</string> |   <string name="action_edit_contact">Уреди име</string> | ||||||
|   <string name="action_add_phone_book">Додај у именик</string> |   <string name="action_add_phone_book">Додај у именик</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Ny konversation</string> |   <string name="action_add">Ny konversation</string> | ||||||
|   <string name="action_accounts">Kontoinställningar</string> |   <string name="action_accounts">Kontoinställningar</string> | ||||||
|   <string name="action_account">Hantera konto</string> |   <string name="action_account">Hantera konto</string> | ||||||
|   <string name="action_end_conversation">Stäng denna konversation</string> |  | ||||||
|   <string name="action_contact_details">Kontaktdetaljer</string> |   <string name="action_contact_details">Kontaktdetaljer</string> | ||||||
|   <string name="action_muc_details">Gruppchattdetaljer</string> |   <string name="action_muc_details">Gruppchattdetaljer</string> | ||||||
|   <string name="channel_details">Kanaldetaljer</string> |   <string name="channel_details">Kanaldetaljer</string> | ||||||
|   <string name="action_secure">Säker konversation</string> |  | ||||||
|   <string name="action_add_account">Lägg till konto</string> |   <string name="action_add_account">Lägg till konto</string> | ||||||
|   <string name="action_edit_contact">Ändra namn</string> |   <string name="action_edit_contact">Ändra namn</string> | ||||||
|   <string name="action_add_phone_book">Lägg till i kontakter</string> |   <string name="action_add_phone_book">Lägg till i kontakter</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Yeni konuşma</string> |   <string name="action_add">Yeni konuşma</string> | ||||||
|   <string name="action_accounts">Hesapları yönet</string> |   <string name="action_accounts">Hesapları yönet</string> | ||||||
|   <string name="action_account">Hesabı yönet</string> |   <string name="action_account">Hesabı yönet</string> | ||||||
|   <string name="action_end_conversation">Bu konuşmayı kapat</string> |  | ||||||
|   <string name="action_contact_details">Kişi bilgileri</string> |   <string name="action_contact_details">Kişi bilgileri</string> | ||||||
|   <string name="action_muc_details">Küme konuşması ayrıntıları</string> |   <string name="action_muc_details">Küme konuşması ayrıntıları</string> | ||||||
|   <string name="channel_details">Kanal ayrıntıları</string> |   <string name="channel_details">Kanal ayrıntıları</string> | ||||||
|   <string name="action_secure">Güvenli konuşma</string> |  | ||||||
|   <string name="action_add_account">Hesap ekle</string> |   <string name="action_add_account">Hesap ekle</string> | ||||||
|   <string name="action_edit_contact">İsmi düzenle</string> |   <string name="action_edit_contact">İsmi düzenle</string> | ||||||
|   <string name="action_add_phone_book">Telefon rehberine ekle</string> |   <string name="action_add_phone_book">Telefon rehberine ekle</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">Нова розмова</string> |   <string name="action_add">Нова розмова</string> | ||||||
|   <string name="action_accounts">Мої облікові записи</string> |   <string name="action_accounts">Мої облікові записи</string> | ||||||
|   <string name="action_account">Мій обліковий запис</string> |   <string name="action_account">Мій обліковий запис</string> | ||||||
|   <string name="action_end_conversation">Завершити розмову</string> |  | ||||||
|   <string name="action_contact_details">Деталі контакту</string> |   <string name="action_contact_details">Деталі контакту</string> | ||||||
|   <string name="action_muc_details">Деталі групи</string> |   <string name="action_muc_details">Деталі групи</string> | ||||||
|   <string name="channel_details">Деталі каналу</string> |   <string name="channel_details">Деталі каналу</string> | ||||||
|   <string name="action_secure">Захищена розмова</string> |  | ||||||
|   <string name="action_add_account">Додати обліковий запис</string> |   <string name="action_add_account">Додати обліковий запис</string> | ||||||
|   <string name="action_edit_contact">Редагувати ім\'я</string> |   <string name="action_edit_contact">Редагувати ім\'я</string> | ||||||
|   <string name="action_add_phone_book">Додати до контактів</string> |   <string name="action_add_phone_book">Додати до контактів</string> | ||||||
|  | @ -933,8 +931,6 @@ | ||||||
|   <string name="only_one_call_at_a_time">Водночас можливо здійснювати лише один виклик.</string> |   <string name="only_one_call_at_a_time">Водночас можливо здійснювати лише один виклик.</string> | ||||||
|   <string name="return_to_ongoing_call">Назад до активного виклику</string> |   <string name="return_to_ongoing_call">Назад до активного виклику</string> | ||||||
|   <string name="could_not_switch_camera">Неможливо перемкнути камеру</string> |   <string name="could_not_switch_camera">Неможливо перемкнути камеру</string> | ||||||
|   <string name="add_to_favorites">Додати до обраного</string> |  | ||||||
|   <string name="remove_from_favorites">Вилучити з обраного</string> |  | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="one">Перегляд %1$d учасника</item> |     <item quantity="one">Перегляд %1$d учасника</item> | ||||||
|     <item quantity="few">Перегляд %1$d учасників</item> |     <item quantity="few">Перегляд %1$d учасників</item> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">Hội thoại mới</string> |   <string name="action_add">Hội thoại mới</string> | ||||||
|   <string name="action_accounts">Quản lý tài khoản</string> |   <string name="action_accounts">Quản lý tài khoản</string> | ||||||
|   <string name="action_contact_details">Thông tin liên hệ</string> |   <string name="action_contact_details">Thông tin liên hệ</string> | ||||||
|   <string name="action_secure">Bảo mật hội thoại</string> |  | ||||||
|   <string name="action_add_account">Thêm tài khoản</string> |   <string name="action_add_account">Thêm tài khoản</string> | ||||||
|   <string name="action_edit_contact">Chỉnh sửa tên</string> |   <string name="action_edit_contact">Chỉnh sửa tên</string> | ||||||
|   <string name="action_add_phone_book">Thêm vào danh bạ</string> |   <string name="action_add_phone_book">Thêm vào danh bạ</string> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <resources> | <resources> | ||||||
|     <bool name="show_qr_code_scan">false</bool> |     <bool name="show_qr_code_scan">false</bool> | ||||||
|  |     <bool name="show_individual_search_options">false</bool> | ||||||
|  |     <bool name="show_combined_search_options">true</bool> | ||||||
| </resources> | </resources> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ | ||||||
|   <string name="action_add">新对话</string> |   <string name="action_add">新对话</string> | ||||||
|   <string name="action_accounts">管理账户</string> |   <string name="action_accounts">管理账户</string> | ||||||
|   <string name="action_account">管理账户</string> |   <string name="action_account">管理账户</string> | ||||||
|   <string name="action_end_conversation">关闭对话</string> |  | ||||||
|   <string name="action_contact_details">联系人详情</string> |   <string name="action_contact_details">联系人详情</string> | ||||||
|   <string name="action_muc_details">群聊详情</string> |   <string name="action_muc_details">群聊详情</string> | ||||||
|   <string name="channel_details">频道详情</string> |   <string name="channel_details">频道详情</string> | ||||||
|   <string name="action_secure">加密对话</string> |  | ||||||
|   <string name="action_add_account">添加账户</string> |   <string name="action_add_account">添加账户</string> | ||||||
|   <string name="action_edit_contact">编辑名称</string> |   <string name="action_edit_contact">编辑名称</string> | ||||||
|   <string name="action_add_phone_book">添加到通讯录</string> |   <string name="action_add_phone_book">添加到通讯录</string> | ||||||
|  | @ -460,7 +458,11 @@ | ||||||
|   <string name="server_info_broken">损坏</string> |   <string name="server_info_broken">损坏</string> | ||||||
|   <string name="pref_presence_settings">可用性</string> |   <string name="pref_presence_settings">可用性</string> | ||||||
|   <string name="pref_away_when_screen_off">锁屏时显示离开</string> |   <string name="pref_away_when_screen_off">锁屏时显示离开</string> | ||||||
|  |   <string name="pref_away_when_screen_off_summary">屏幕关闭时显示为“离开”</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode">在静音模式显示为忙碌</string> | ||||||
|  |   <string name="pref_dnd_on_silent_mode_summary">设备处于静音模式时显示为忙碌</string> | ||||||
|   <string name="pref_treat_vibrate_as_silent">将振动看作静音</string> |   <string name="pref_treat_vibrate_as_silent">将振动看作静音</string> | ||||||
|  |   <string name="pref_treat_vibrate_as_dnd_summary">设备振动时显示为忙碌</string> | ||||||
|   <string name="pref_show_connection_options">高级连接设置</string> |   <string name="pref_show_connection_options">高级连接设置</string> | ||||||
|   <string name="pref_show_connection_options_summary">注册账户时显示主机名和端口</string> |   <string name="pref_show_connection_options_summary">注册账户时显示主机名和端口</string> | ||||||
|   <string name="hostname_example">xmpp.example.com</string> |   <string name="hostname_example">xmpp.example.com</string> | ||||||
|  | @ -909,8 +911,8 @@ | ||||||
|   <string name="only_one_call_at_a_time">只能同时打一通电话</string> |   <string name="only_one_call_at_a_time">只能同时打一通电话</string> | ||||||
|   <string name="return_to_ongoing_call">返回正在进行的通话</string> |   <string name="return_to_ongoing_call">返回正在进行的通话</string> | ||||||
|   <string name="could_not_switch_camera">无法切换摄像头</string> |   <string name="could_not_switch_camera">无法切换摄像头</string> | ||||||
|   <string name="add_to_favorites">添加到收藏夹</string> |   <string name="gpx_track">GPX轨迹</string> | ||||||
|   <string name="remove_from_favorites">从收藏夹删除</string> |   <string name="could_not_correct_message">无法更正消息</string> | ||||||
|   <plurals name="view_users"> |   <plurals name="view_users"> | ||||||
|     <item quantity="other">查看%1$d成员</item> |     <item quantity="other">查看%1$d成员</item> | ||||||
|   </plurals> |   </plurals> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|   <string name="action_add">新對話</string> |   <string name="action_add">新對話</string> | ||||||
|   <string name="action_accounts">管理帳戶</string> |   <string name="action_accounts">管理帳戶</string> | ||||||
|   <string name="action_contact_details">聯絡人詳情</string> |   <string name="action_contact_details">聯絡人詳情</string> | ||||||
|   <string name="action_secure">安全對話</string> |  | ||||||
|   <string name="action_add_account">新增帳戶</string> |   <string name="action_add_account">新增帳戶</string> | ||||||
|   <string name="action_edit_contact">編輯姓名</string> |   <string name="action_edit_contact">編輯姓名</string> | ||||||
|   <string name="action_add_phone_book">添加到地址薄</string> |   <string name="action_add_phone_book">添加到地址薄</string> | ||||||
|  |  | ||||||
|  | @ -26,6 +26,8 @@ | ||||||
| 	<color name="green500">#ff4CAF50</color> | 	<color name="green500">#ff4CAF50</color> | ||||||
| 	<color name="blue_a100">#ff82B1FF</color> | 	<color name="blue_a100">#ff82B1FF</color> | ||||||
| 	<color name="blue_a200">#ff448AFF</color> | 	<color name="blue_a200">#ff448AFF</color> | ||||||
|  | 	<color name="blue_a400">#ff2979FF</color> | ||||||
|  | 	<color name="blue_a700">#ff2962FF</color> | ||||||
| 	<color name="orange500">#ffff9800</color> | 	<color name="orange500">#ffff9800</color> | ||||||
| 	<color name="orange600">#fffb8c00</color> | 	<color name="orange600">#fffb8c00</color> | ||||||
| 	<color name="orange700">#ffF57C00</color> | 	<color name="orange700">#ffF57C00</color> | ||||||
|  |  | ||||||
|  | @ -34,6 +34,8 @@ | ||||||
|     <bool name="never_send">false</bool> |     <bool name="never_send">false</bool> | ||||||
|     <bool name="validate_hostname">false</bool> |     <bool name="validate_hostname">false</bool> | ||||||
|     <bool name="show_qr_code_scan">true</bool> |     <bool name="show_qr_code_scan">true</bool> | ||||||
|  |     <bool name="show_individual_search_options">true</bool> | ||||||
|  |     <bool name="show_combined_search_options">false</bool> | ||||||
|     <bool name="scroll_to_bottom">true</bool> |     <bool name="scroll_to_bottom">true</bool> | ||||||
|     <string name="omemo_setting_default">default_on</string> |     <string name="omemo_setting_default">default_on</string> | ||||||
|     <string name="default_font_size">small</string> |     <string name="default_font_size">small</string> | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
|     <string name="action_add">New conversation</string> |     <string name="action_add">New conversation</string> | ||||||
|     <string name="action_accounts">Manage accounts</string> |     <string name="action_accounts">Manage accounts</string> | ||||||
|     <string name="action_account">Manage account</string> |     <string name="action_account">Manage account</string> | ||||||
|     <string name="action_end_conversation">Close this conversation</string> |     <string name="action_end_conversation">Close conversation</string> | ||||||
|     <string name="action_contact_details">Contact details</string> |     <string name="action_contact_details">Contact details</string> | ||||||
|     <string name="action_muc_details">Group chat details</string> |     <string name="action_muc_details">Group chat details</string> | ||||||
|     <string name="channel_details">Channel details</string> |     <string name="channel_details">Channel details</string> | ||||||
|     <string name="action_secure">Secure conversation</string> |  | ||||||
|     <string name="action_add_account">Add account</string> |     <string name="action_add_account">Add account</string> | ||||||
|     <string name="action_edit_contact">Edit name</string> |     <string name="action_edit_contact">Edit name</string> | ||||||
|     <string name="action_add_phone_book">Add to address book</string> |     <string name="action_add_phone_book">Add to address book</string> | ||||||
|  | @ -756,6 +755,7 @@ | ||||||
|     <string name="ongoing_calls_channel_name">Ongoing calls</string> |     <string name="ongoing_calls_channel_name">Ongoing calls</string> | ||||||
|     <string name="silent_messages_channel_name">Silent messages</string> |     <string name="silent_messages_channel_name">Silent messages</string> | ||||||
|     <string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string> |     <string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string> | ||||||
|  |     <string name="delivery_failed_channel_name">Failed deliveries</string> | ||||||
|     <string name="pref_message_notification_settings">Message notification settings</string> |     <string name="pref_message_notification_settings">Message notification settings</string> | ||||||
|     <string name="pref_incoming_call_notification_settings">Incoming calls notification settings</string> |     <string name="pref_incoming_call_notification_settings">Incoming calls notification settings</string> | ||||||
|     <string name="pref_more_notification_settings_summary">Importance, Sound, Vibrate</string> |     <string name="pref_more_notification_settings_summary">Importance, Sound, Vibrate</string> | ||||||
|  | @ -923,12 +923,30 @@ | ||||||
|     <string name="only_one_call_at_a_time">You can only have one call at a time.</string> |     <string name="only_one_call_at_a_time">You can only have one call at a time.</string> | ||||||
|     <string name="return_to_ongoing_call">Return to ongoing call</string> |     <string name="return_to_ongoing_call">Return to ongoing call</string> | ||||||
|     <string name="could_not_switch_camera">Could not switch camera</string> |     <string name="could_not_switch_camera">Could not switch camera</string> | ||||||
|     <string name="add_to_favorites">Add to favorites</string> |     <string name="add_to_favorites">Pin to top</string> | ||||||
|     <string name="remove_from_favorites">Remove from favorites</string> |     <string name="remove_from_favorites">Unpin from top</string> | ||||||
|     <string name="gpx_track">GPX track</string> |     <string name="gpx_track">GPX track</string> | ||||||
|     <string name="could_not_correct_message">Could not correct message</string> |     <string name="could_not_correct_message">Could not correct message</string> | ||||||
|  |     <string name="search_all_conversations">All conversations</string> | ||||||
|  |     <string name="search_this_conversation">This conversation</string> | ||||||
|  |     <string name="your_avatar">Your avatar</string> | ||||||
|  |     <string name="avatar_for_x">Avatar for %s</string> | ||||||
|  |     <string name="encrypted_with_omemo">Encrypted with OMEMO</string> | ||||||
|  |     <string name="encrypted_with_openpgp">Encrypted with OpenPGP</string> | ||||||
|  |     <string name="not_encrypted">Not encrypted</string> | ||||||
|  |     <string name="exit">Exit</string> | ||||||
|  |     <string name="record_voice_mail">Record voice mail</string> | ||||||
|  |     <string name="play_audio">Play audio</string> | ||||||
|  |     <string name="pause_audio">Pause audio</string> | ||||||
|  |     <string name="add_contact_or_create_or_join_group_chat">Add contact, create or join group chat, or discover channels</string> | ||||||
|     <plurals name="view_users"> |     <plurals name="view_users"> | ||||||
|         <item quantity="one">View %1$d Participant</item> |         <item quantity="one">View %1$d Participant</item> | ||||||
|         <item quantity="other">View %1$d Participants</item> |         <item quantity="other">View %1$d Participants</item> | ||||||
|     </plurals> |     </plurals> | ||||||
|  |     <plurals name="some_messages_could_not_be_delivered"> | ||||||
|  |         <item quantity="one">A message could not be delivered</item> | ||||||
|  |         <item quantity="other">Some messages could not be delivered</item> | ||||||
|  |     </plurals> | ||||||
|  |     <string name="failed_deliveries">Failed deliveries</string> | ||||||
|  |     <string name="more_options">More options</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|     <style name="ConversationsTheme" parent="Theme.AppCompat.Light.NoActionBar"> |     <style name="ConversationsTheme" parent="Theme.AppCompat.Light.NoActionBar"> | ||||||
|         <item name="colorPrimary">@color/orange600</item> |         <item name="colorPrimary">@color/orange600</item> | ||||||
|         <item name="colorPrimaryDark">@color/orange800</item> |         <item name="colorPrimaryDark">@color/orange800</item> | ||||||
|         <item name="colorAccent">@color/blue_a200</item> |         <item name="colorAccent">@color/blue_a400</item> | ||||||
|         <item name="popupOverlayStyle">@style/ThemeOverlay.AppCompat.Light</item> |         <item name="popupOverlayStyle">@style/ThemeOverlay.AppCompat.Light</item> | ||||||
| 
 | 
 | ||||||
|         <item name="color_background_primary">@color/grey50</item> |         <item name="color_background_primary">@color/grey50</item> | ||||||
|  | @ -371,7 +371,7 @@ | ||||||
|     <style name="ConversationsTheme.Dialog" parent="@style/Theme.AppCompat.Light.Dialog"> |     <style name="ConversationsTheme.Dialog" parent="@style/Theme.AppCompat.Light.Dialog"> | ||||||
|         <item name="colorPrimary">@color/orange600</item> |         <item name="colorPrimary">@color/orange600</item> | ||||||
|         <item name="colorPrimaryDark">@color/orange700</item> |         <item name="colorPrimaryDark">@color/orange700</item> | ||||||
|         <item name="colorAccent">@color/blue_a200</item> |         <item name="colorAccent">@color/blue_a400</item> | ||||||
|         <item name="color_background_primary">@color/grey50</item> |         <item name="color_background_primary">@color/grey50</item> | ||||||
|         <item name="divider">@color/black12</item> |         <item name="divider">@color/black12</item> | ||||||
|         <item name="TextSizeTitle">18sp</item> |         <item name="TextSizeTitle">18sp</item> | ||||||
|  |  | ||||||
|  | @ -55,7 +55,7 @@ public class PushManagementService { | ||||||
|                         e.printStackTrace(); |                         e.printStackTrace(); | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server"); |                     Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": failed to enable push. invalid response from app server "+response); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||