aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md20
-rw-r--r--README.md10
-rw-r--r--build.gradle5
-rw-r--r--docs/XEPs.md1
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/OtrService.java40
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java12
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java29
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java8
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Account.java100
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Contact.java4
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Message.java7
-rw-r--r--src/main/java/eu/siacs/conversations/entities/MucOptions.java1
-rw-r--r--src/main/java/eu/siacs/conversations/generator/IqGenerator.java8
-rw-r--r--src/main/java/eu/siacs/conversations/generator/MessageGenerator.java4
-rw-r--r--src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java4
-rw-r--r--src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java4
-rw-r--r--src/main/java/eu/siacs/conversations/parser/IqParser.java8
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java47
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java3
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java35
-rw-r--r--src/main/java/eu/siacs/conversations/services/NotificationService.java51
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java104
-rw-r--r--src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java33
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java9
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java11
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java28
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java25
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java36
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java9
-rw-r--r--src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java16
-rw-r--r--src/main/java/eu/siacs/conversations/ui/SettingsActivity.java72
-rw-r--r--src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java6
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java3
-rw-r--r--src/main/java/eu/siacs/conversations/utils/CryptoHelper.java10
-rw-r--r--src/main/java/eu/siacs/conversations/utils/PhoneHelper.java4
-rw-r--r--src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java4
-rw-r--r--src/main/java/eu/siacs/conversations/utils/UIHelper.java4
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java37
-rw-r--r--src/main/res/layout/activity_edit_account.xml52
-rw-r--r--src/main/res/layout/activity_muc_details.xml6
-rw-r--r--src/main/res/layout/create_conference_dialog.xml16
-rw-r--r--src/main/res/layout/dialog_block_contact.xml25
-rw-r--r--src/main/res/layout/dialog_clear_history.xml7
-rw-r--r--src/main/res/layout/dialog_show_password.xml5
-rw-r--r--src/main/res/layout/enter_jid_dialog.xml20
-rw-r--r--src/main/res/layout/magic_create.xml13
-rw-r--r--src/main/res/layout/welcome.xml13
-rw-r--r--src/main/res/values-ar/strings.xml1
-rw-r--r--src/main/res/values-bg/strings.xml12
-rw-r--r--src/main/res/values-ca/strings.xml1
-rw-r--r--src/main/res/values-cs/strings.xml13
-rw-r--r--src/main/res/values-de/strings.xml15
-rw-r--r--src/main/res/values-el/strings.xml1
-rw-r--r--src/main/res/values-es/strings.xml28
-rw-r--r--src/main/res/values-eu/strings.xml15
-rw-r--r--src/main/res/values-fr/strings.xml20
-rw-r--r--src/main/res/values-id/strings.xml1
-rw-r--r--src/main/res/values-it/strings.xml13
-rw-r--r--src/main/res/values-iw/strings.xml1
-rw-r--r--src/main/res/values-ja/strings.xml13
-rw-r--r--src/main/res/values-ko/strings.xml1
-rw-r--r--src/main/res/values-nb-rNO/strings.xml1
-rw-r--r--src/main/res/values-nl/strings.xml23
-rw-r--r--src/main/res/values-pl/strings.xml3
-rw-r--r--src/main/res/values-pt-rBR/strings.xml10
-rw-r--r--src/main/res/values-pt/strings.xml1
-rw-r--r--src/main/res/values-ro-rRO/strings.xml15
-rw-r--r--src/main/res/values-ru/strings.xml251
-rw-r--r--src/main/res/values-sk/strings.xml1
-rw-r--r--src/main/res/values-sr/strings.xml16
-rw-r--r--src/main/res/values-sv/strings.xml11
-rw-r--r--src/main/res/values-tr-rTR/strings.xml11
-rw-r--r--src/main/res/values-uk/strings.xml3
-rw-r--r--src/main/res/values-v21/themes.xml6
-rw-r--r--src/main/res/values-vi/strings.xml1
-rw-r--r--src/main/res/values-w360dp/fineprint.xml4
-rw-r--r--src/main/res/values-w384dp/dimens.xml1
-rw-r--r--src/main/res/values-zh-rCN/strings.xml29
-rw-r--r--src/main/res/values-zh-rTW/strings.xml1
-rw-r--r--src/main/res/values/attrs.xml3
-rw-r--r--src/main/res/values/dimens.xml1
-rw-r--r--src/main/res/values/fineprint.xml4
-rw-r--r--src/main/res/values/strings.xml13
-rw-r--r--src/main/res/values/themes.xml6
-rw-r--r--src/main/res/xml/preferences.xml6
87 files changed, 1038 insertions, 501 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae9a73cd..bad5098f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
###Changelog
+####Version 1.14.6
+* make error notification dismissable
+* bug fixes
+
+
+####Version 1.14.5
+* expert setting to delete OMEMO identities
+* bug fixes
+
+####Version 1.14.4
+* bug fixes
+
+####Version 1.14.3
+* XEP-0377: Spam Reporting
+* fix rare start up crashes
+
+####Version 1.14.2
+* support ANONYMOUS SASL
+* bug fixes
+
####Version 1.14.1
* Press lock icon to see why OMEMO is deactivated
* bug fixes
diff --git a/README.md b/README.md
index f33de43c..55da8888 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Conversations: the very last word in instant messaging
## Features
-* End-to-end encryption with [OMEMO](http://conversations.im/omemo/), [OTR](https://otr.cypherpunks.ca/), or [OpenPGP](http://www.openpgp.org/about_openpgp/)
+* End-to-end encryption with [OMEMO](http://conversations.im/omemo/), [OTR](https://otr.cypherpunks.ca/), or [OpenPGP](http://openpgp.org/about/)
* Send and receive images as well as other kind of files
* Share your location via an external [plug-in](https://play.google.com/store/apps/details?id=eu.siacs.conversations.sharelocation&referrer=utm_source%3Dgithub)
* Indication when your contact has read your message
@@ -329,6 +329,14 @@ feature is regarded experimental. Conversations is the only client that uses
XEP-0027 with conferences. (The XEP neither specifically allows nor disallows
this.)
+### What clients do I use on other platforms
+There are XMPP Clients available for all major platforms.
+####Windows / Linux
+For your desktop computer we recommand that you use [Gajim](https://gajim.org). You need to install the plugins `OMEMO`, `HTTP Upload` and `URL image preview` to get the best compatibiltiy with Conversations. Plugins can be installed from withhin the app.
+####iOS
+Unfortunatly we don‘t have a recommandation for iPhones right now. There are two clients available [ChatSecure](https://chatsecure.org/) and [Monal](https://monal.im/). Both with their own pros and cons.
+
+
### Development
<a name="beta"></a>
diff --git a/build.gradle b/build.gradle
index 35fb52d9..4e0e9ce1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -39,7 +39,6 @@ dependencies {
compile 'com.kyleduo.switchbutton:library:1.2.8'
compile 'org.whispersystems:axolotl-android:1.3.4'
compile 'com.makeramen:roundedimageview:2.2.0'
- compile 'com.google.android.gms:play-services-gcm:9.4.0'
compile "com.wefika:flowlayout:0.4.1"
}
@@ -56,8 +55,8 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 24
- versionCode 172
- versionName "1.14.1"
+ versionCode 179
+ versionName "1.14.6"
archivesBaseName += "-$versionName"
applicationId "eu.siacs.conversations"
}
diff --git a/docs/XEPs.md b/docs/XEPs.md
index 0c33546a..f88686e9 100644
--- a/docs/XEPs.md
+++ b/docs/XEPs.md
@@ -28,3 +28,4 @@
* XEP-0357: Push Notifications
* XEP-0363: HTTP File Upload
* XEP-0368: SRV records for XMPP over TLS
+* XEP-0377: Spam Reporting
diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrService.java b/src/main/java/eu/siacs/conversations/crypto/OtrService.java
index af11756f..3663cd3b 100644
--- a/src/main/java/eu/siacs/conversations/crypto/OtrService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/OtrService.java
@@ -53,28 +53,30 @@ public class OtrService extends OtrCryptoEngineImpl implements OtrEngineHost {
this.mXmppConnectionService = service;
}
- private KeyPair loadKey(JSONObject keys) {
+ private KeyPair loadKey(final JSONObject keys) {
if (keys == null) {
return null;
}
- try {
- BigInteger x = new BigInteger(keys.getString("otr_x"), 16);
- BigInteger y = new BigInteger(keys.getString("otr_y"), 16);
- BigInteger p = new BigInteger(keys.getString("otr_p"), 16);
- BigInteger q = new BigInteger(keys.getString("otr_q"), 16);
- BigInteger g = new BigInteger(keys.getString("otr_g"), 16);
- KeyFactory keyFactory = KeyFactory.getInstance("DSA");
- DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, p, q, g);
- DSAPrivateKeySpec privateKeySpec = new DSAPrivateKeySpec(x, p, q, g);
- PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
- PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
- return new KeyPair(publicKey, privateKey);
- } catch (JSONException e) {
- return null;
- } catch (NoSuchAlgorithmException e) {
- return null;
- } catch (InvalidKeySpecException e) {
- return null;
+ synchronized (keys) {
+ try {
+ BigInteger x = new BigInteger(keys.getString("otr_x"), 16);
+ BigInteger y = new BigInteger(keys.getString("otr_y"), 16);
+ BigInteger p = new BigInteger(keys.getString("otr_p"), 16);
+ BigInteger q = new BigInteger(keys.getString("otr_q"), 16);
+ BigInteger g = new BigInteger(keys.getString("otr_g"), 16);
+ KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+ DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, p, q, g);
+ DSAPrivateKeySpec privateKeySpec = new DSAPrivateKeySpec(x, p, q, g);
+ PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
+ PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
+ return new KeyPair(publicKey, privateKey);
+ } catch (JSONException e) {
+ return null;
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ } catch (InvalidKeySpecException e) {
+ return null;
+ }
}
}
diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java
index 53768714..87b58613 100644
--- a/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java
@@ -115,7 +115,11 @@ public class PgpDecryptionService {
case OpenPgpApi.RESULT_CODE_SUCCESS:
try {
os.flush();
- message.setBody(os.toString());
+ final String body = os.toString();
+ if (body == null) {
+ throw new IOException("body was null");
+ }
+ message.setBody(body);
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
if (message.trusted()
@@ -130,9 +134,10 @@ public class PgpDecryptionService {
break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
synchronized (PgpDecryptionService.this) {
+ PendingIntent pendingIntent = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
messages.addFirst(message);
currentMessage = null;
- storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+ storePendingIntent(pendingIntent);
}
break;
case OpenPgpApi.RESULT_CODE_ERROR:
@@ -160,9 +165,10 @@ public class PgpDecryptionService {
break;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
synchronized (PgpDecryptionService.this) {
+ PendingIntent pendingIntent = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
messages.addFirst(message);
currentMessage = null;
- storePendingIntent((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+ storePendingIntent(pendingIntent);
}
break;
case OpenPgpApi.RESULT_CODE_ERROR:
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
index 28085085..1bc5fa83 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
@@ -660,24 +660,25 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
}
public Pair<AxolotlCapability,Jid> isConversationAxolotlCapableDetailed(Conversation conversation) {
- final List<Jid> jids = getCryptoTargets(conversation);
- for(Jid jid : jids) {
- if (!hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty())) {
- if (conversation.getAccount().getRoster().getContact(jid).trusted()) {
- return new Pair<>(AxolotlCapability.MISSING_KEYS,jid);
- } else {
- return new Pair<>(AxolotlCapability.MISSING_PRESENCE,jid);
+ if (conversation.getMode() == Conversation.MODE_SINGLE
+ || (conversation.getMucOptions().membersOnly() && conversation.getMucOptions().nonanonymous())) {
+ final List<Jid> jids = getCryptoTargets(conversation);
+ for(Jid jid : jids) {
+ if (!hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty())) {
+ if (conversation.getAccount().getRoster().getContact(jid).mutualPresenceSubscription()) {
+ return new Pair<>(AxolotlCapability.MISSING_KEYS,jid);
+ } else {
+ return new Pair<>(AxolotlCapability.MISSING_PRESENCE,jid);
+ }
}
}
- }
- if (jids.size() > 0) {
- return new Pair<>(AxolotlCapability.FULL, null);
- } else {
- if (conversation.getMucOptions().membersOnly() && conversation.getMucOptions().nonanonymous()) {
- return new Pair<>(AxolotlCapability.NO_MEMBERS, null);
+ if (jids.size() > 0) {
+ return new Pair<>(AxolotlCapability.FULL, null);
} else {
- return new Pair<>(AxolotlCapability.WRONG_CONFIGURATION, null);
+ return new Pair<>(AxolotlCapability.NO_MEMBERS, null);
}
+ } else {
+ return new Pair<>(AxolotlCapability.WRONG_CONFIGURATION, null);
}
}
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
index e8ec5426..0b3164f8 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
@@ -91,7 +91,11 @@ public class XmppAxolotlMessage {
private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException {
this.from = from;
Element header = axolotlMessage.findChild(HEADER);
- this.sourceDeviceId = Integer.parseInt(header.getAttribute(SOURCEID));
+ try {
+ this.sourceDeviceId = Integer.parseInt(header.getAttribute(SOURCEID));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("invalid source id");
+ }
List<Element> keyElements = header.getChildren();
this.keys = new HashMap<>(keyElements.size());
for (Element keyElement : keyElements) {
@@ -102,7 +106,7 @@ public class XmppAxolotlMessage {
byte[] key = Base64.decode(keyElement.getContent().trim(), Base64.DEFAULT);
this.keys.put(recipientId, key);
} catch (NumberFormatException e) {
- throw new IllegalArgumentException(e);
+ throw new IllegalArgumentException("invalid remote id");
}
break;
case IVTAG:
diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java
index 38b5a999..7d60dcf7 100644
--- a/src/main/java/eu/siacs/conversations/entities/Account.java
+++ b/src/main/java/eu/siacs/conversations/entities/Account.java
@@ -91,6 +91,17 @@ public class Account extends AbstractEntity {
return pgpDecryptionService != null && pgpDecryptionService.isConnected();
}
+ public boolean setShowErrorNotification(boolean newValue) {
+ boolean oldValue = showErrorNotification();
+ setKey("show_error",Boolean.toString(newValue));
+ return newValue != oldValue;
+ }
+
+ public boolean showErrorNotification() {
+ String key = getKey("show_error");
+ return key == null || Boolean.parseBoolean(key);
+ }
+
public enum State {
DISABLED,
OFFLINE,
@@ -192,7 +203,7 @@ public class Account extends AbstractEntity {
protected int options = 0;
protected String rosterVersion;
protected State status = State.OFFLINE;
- protected JSONObject keys = new JSONObject();
+ protected final JSONObject keys;
protected String avatar;
protected String displayName = null;
protected String hostname = null;
@@ -227,11 +238,13 @@ public class Account extends AbstractEntity {
this.password = password;
this.options = options;
this.rosterVersion = rosterVersion;
+ JSONObject tmp;
try {
- this.keys = new JSONObject(keys);
- } catch (final JSONException ignored) {
- this.keys = new JSONObject();
+ tmp = new JSONObject(keys);
+ } catch(JSONException e) {
+ tmp = new JSONObject();
}
+ this.keys = tmp;
this.avatar = avatar;
this.displayName = displayName;
this.hostname = hostname;
@@ -380,15 +393,28 @@ public class Account extends AbstractEntity {
}
public String getKey(final String name) {
- return this.keys.optString(name, null);
+ synchronized (this.keys) {
+ return this.keys.optString(name, null);
+ }
}
- public boolean setKey(final String keyName, final String keyValue) {
+ public int getKeyAsInt(final String name, int defaultValue) {
+ String key = getKey(name);
try {
- this.keys.put(keyName, keyValue);
- return true;
- } catch (final JSONException e) {
- return false;
+ return key == null ? defaultValue : Integer.parseInt(key);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ public boolean setKey(final String keyName, final String keyValue) {
+ synchronized (this.keys) {
+ try {
+ this.keys.put(keyName, keyValue);
+ return true;
+ } catch (final JSONException e) {
+ return false;
+ }
}
}
@@ -408,7 +434,9 @@ public class Account extends AbstractEntity {
values.put(SERVER, jid.getDomainpart());
values.put(PASSWORD, password);
values.put(OPTIONS, options);
- values.put(KEYS, this.keys.toString());
+ synchronized (this.keys) {
+ values.put(KEYS, this.keys.toString());
+ }
values.put(ROSTERVERSION, rosterVersion);
values.put(AVATAR, avatar);
values.put(DISPLAY_NAME, displayName);
@@ -485,54 +513,42 @@ public class Account extends AbstractEntity {
}
public String getPgpSignature() {
- try {
- if (keys.has(KEY_PGP_SIGNATURE) && !"null".equals(keys.getString(KEY_PGP_SIGNATURE))) {
- return keys.getString(KEY_PGP_SIGNATURE);
- } else {
- return null;
- }
- } catch (final JSONException e) {
- return null;
- }
+ return getKey(KEY_PGP_SIGNATURE);
}
public boolean setPgpSignature(String signature) {
- try {
- keys.put(KEY_PGP_SIGNATURE, signature);
- } catch (JSONException e) {
- return false;
- }
- return true;
+ return setKey(KEY_PGP_SIGNATURE, signature);
}
public boolean unsetPgpSignature() {
- try {
- keys.put(KEY_PGP_SIGNATURE, JSONObject.NULL);
- } catch (JSONException e) {
- return false;
+ synchronized (this.keys) {
+ return keys.remove(KEY_PGP_SIGNATURE) != null;
}
- return true;
}
public long getPgpId() {
- if (keys.has(KEY_PGP_ID)) {
- try {
- return keys.getLong(KEY_PGP_ID);
- } catch (JSONException e) {
+ synchronized (this.keys) {
+ if (keys.has(KEY_PGP_ID)) {
+ try {
+ return keys.getLong(KEY_PGP_ID);
+ } catch (JSONException e) {
+ return 0;
+ }
+ } else {
return 0;
}
- } else {
- return 0;
}
}
public boolean setPgpSignId(long pgpID) {
- try {
- keys.put(KEY_PGP_ID, pgpID);
- } catch (JSONException e) {
- return false;
+ synchronized (this.keys) {
+ try {
+ keys.put(KEY_PGP_ID, pgpID);
+ } catch (JSONException e) {
+ return false;
+ }
+ return true;
}
- return true;
}
public Roster getRoster() {
diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java
index e512b586..70af45d4 100644
--- a/src/main/java/eu/siacs/conversations/entities/Contact.java
+++ b/src/main/java/eu/siacs/conversations/entities/Contact.java
@@ -118,7 +118,7 @@ public class Contact implements ListItem, Blockable {
return this.systemName;
} else if (this.serverName != null) {
return this.serverName;
- } else if (this.presenceName != null && trusted()) {
+ } else if (this.presenceName != null && mutualPresenceSubscription()) {
return this.presenceName;
} else if (jid.hasLocalpart()) {
return jid.getLocalpart();
@@ -487,7 +487,7 @@ public class Contact implements ListItem, Blockable {
}
}
- public boolean trusted() {
+ public boolean mutualPresenceSubscription() {
return getOption(Options.FROM) && getOption(Options.TO);
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java
index 1b38d349..e3577b06 100644
--- a/src/main/java/eu/siacs/conversations/entities/Message.java
+++ b/src/main/java/eu/siacs/conversations/entities/Message.java
@@ -124,7 +124,7 @@ public class Message extends AbstractEntity {
this.conversationUuid = conversationUUid;
this.counterpart = counterpart;
this.trueCounterpart = trueCounterpart;
- this.body = body;
+ this.body = body == null ? "" : body;
this.timeSent = timeSent;
this.encryption = encryption;
this.status = status;
@@ -266,6 +266,9 @@ public class Message extends AbstractEntity {
}
public void setBody(String body) {
+ if (body == null) {
+ throw new Error("You should not set the message body to null");
+ }
this.body = body;
}
@@ -539,7 +542,7 @@ public class Message extends AbstractEntity {
public boolean trusted() {
Contact contact = this.getContact();
- return (status > STATUS_RECEIVED || (contact != null && contact.trusted()));
+ return (status > STATUS_RECEIVED || (contact != null && contact.mutualPresenceSubscription()));
}
public boolean fixCounterpart() {
diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
index 9d54a86d..fa6afcfa 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -127,7 +127,6 @@ public class MucOptions {
UNKNOWN
}
- public static final String STATUS_CODE_ROOM_CONFIG_CHANGED = "104";
public static final String STATUS_CODE_SELF_PRESENCE = "110";
public static final String STATUS_CODE_ROOM_CREATED = "201";
public static final String STATUS_CODE_BANNED = "301";
diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
index 884bc4af..cb9ffd96 100644
--- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
@@ -254,10 +254,14 @@ public class IqGenerator extends AbstractGenerator {
return iq;
}
- public IqPacket generateSetBlockRequest(final Jid jid) {
+ public IqPacket generateSetBlockRequest(final Jid jid, boolean reportSpam) {
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
final Element block = iq.addChild("block", Xmlns.BLOCKING);
- block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
+ final Element item = block.addChild("item").setAttribute("jid", jid.toBareJid().toString());
+ if (reportSpam) {
+ item.addChild("report", "urn:xmpp:reporting:0").addChild("spam");
+ }
+ Log.d(Config.LOGTAG,iq.toString());
return iq;
}
diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
index 5ef47a33..f5c701cc 100644
--- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
@@ -183,6 +183,10 @@ public class MessageGenerator extends AbstractGenerator {
packet.setFrom(conversation.getAccount().getJid());
Element x = packet.addChild("x", "jabber:x:conference");
x.setAttribute("jid", conversation.getJid().toBareJid().toString());
+ String password = conversation.getMucOptions().getPassword();
+ if (password != null) {
+ x.setAttribute("password",password);
+ }
return packet;
}
diff --git a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
index 741ea98d..a9bffe3e 100644
--- a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
+++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
@@ -212,6 +212,8 @@ public class HttpDownloadConnection implements Transferable {
if (connection instanceof HttpsURLConnection) {
mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive);
}
+ connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
+ connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
connection.connect();
String contentLength = connection.getHeaderField("Content-Length");
connection.disconnect();
@@ -279,6 +281,8 @@ public class HttpDownloadConnection implements Transferable {
long size = file.getSize();
connection.setRequestProperty("Range", "bytes="+size+"-");
}
+ connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
+ connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
connection.connect();
is = new BufferedInputStream(connection.getInputStream());
boolean serverResumed = "bytes".equals(connection.getHeaderField("Accept-Ranges"));
diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
index 1bb70690..1bd6a8e4 100644
--- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
+++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java
@@ -171,10 +171,12 @@ public class HttpUploadConnection implements Transferable {
connection.setRequestProperty("Content-Type", mime == null ? "application/octet-stream" : mime);
connection.setRequestProperty("User-Agent",mXmppConnectionService.getIqGenerator().getIdentityName());
connection.setDoOutput(true);
+ connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
+ connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
connection.connect();
os = connection.getOutputStream();
transmitted = 0;
- int count = -1;
+ int count;
byte[] buffer = new byte[4096];
while (((count = mFileInputStream.read(buffer)) != -1) && !canceled) {
transmitted += count;
diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java
index a679d00c..49b0db21 100644
--- a/src/main/java/eu/siacs/conversations/parser/IqParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java
@@ -139,7 +139,11 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
if(signedPreKeyPublic == null) {
return null;
}
- return Integer.valueOf(signedPreKeyPublic.getAttribute("signedPreKeyId"));
+ try {
+ return Integer.valueOf(signedPreKeyPublic.getAttribute("signedPreKeyId"));
+ } catch (NumberFormatException e) {
+ return null;
+ }
}
public ECPublicKey signedPreKeyPublic(final Element bundle) {
@@ -255,7 +259,7 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
Integer signedPreKeyId = signedPreKeyId(bundleElement);
byte[] signedPreKeySignature = signedPreKeySignature(bundleElement);
IdentityKey identityKey = identityKey(bundleElement);
- if(signedPreKeyPublic == null || identityKey == null) {
+ if(signedPreKeyId == null || signedPreKeyPublic == null || identityKey == null) {
return null;
}
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index f4fe80b5..81b68ed9 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -333,7 +333,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
if (timestamp == null) {
- timestamp = AbstractParser.parseTimestamp(packet);
+ timestamp = AbstractParser.parseTimestamp(original,AbstractParser.parseTimestamp(packet));
}
final String body = packet.getBody();
final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
@@ -539,7 +539,11 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
mXmppConnectionService.updateConversationUi();
}
- if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) {
+ if (mXmppConnectionService.confirmMessages()
+ && message.trusted()
+ && remoteMsgId != null
+ && !isForwarded
+ && !isTypeGroupChat) {
sendMessageReceipts(account, packet);
}
@@ -583,26 +587,27 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
}
if (conversation != null && mucUserElement != null && from.isBareJid()) {
- if (mucUserElement.hasChild("status")) {
- for (Element child : mucUserElement.getChildren()) {
- if (child.getName().equals("status")
- && MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED.equals(child.getAttribute("code"))) {
- mXmppConnectionService.fetchConferenceConfiguration(conversation);
- }
- }
- } else if (mucUserElement.hasChild("item")) {
- for(Element child : mucUserElement.getChildren()) {
- if ("item".equals(child.getName())) {
- MucOptions.User user = AbstractParser.parseItem(conversation,child);
- Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for "
- +user.getRealJid()+" to "+user.getAffiliation()+" in "
- +conversation.getJid().toBareJid());
- if (!user.realJidMatchesAccount()) {
- conversation.getMucOptions().addUser(user);
- mXmppConnectionService.getAvatarService().clear(conversation);
- mXmppConnectionService.updateMucRosterUi();
- mXmppConnectionService.updateConversationUi();
+ for (Element child : mucUserElement.getChildren()) {
+ if ("status".equals(child.getName())) {
+ try {
+ int code = Integer.parseInt(child.getAttribute("code"));
+ if ((code >= 170 && code <= 174) || (code >= 102 && code <= 104)) {
+ mXmppConnectionService.fetchConferenceConfiguration(conversation);
+ break;
}
+ } catch (Exception e) {
+ //ignored
+ }
+ } else if ("item".equals(child.getName())) {
+ MucOptions.User user = AbstractParser.parseItem(conversation,child);
+ Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for "
+ +user.getRealJid()+" to "+user.getAffiliation()+" in "
+ +conversation.getJid().toBareJid());
+ if (!user.realJidMatchesAccount()) {
+ conversation.getMucOptions().addUser(user);
+ mXmppConnectionService.getAvatarService().clear(conversation);
+ mXmppConnectionService.updateMucRosterUi();
+ mXmppConnectionService.updateConversationUi();
}
}
}
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index 484b7b15..d8b6b4e1 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -1184,9 +1184,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
storeIdentityKey(account, account.getJid().toBareJid().toString(), true, identityKeyPair.getPublicKey().getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKeyPair.serialize(), Base64.DEFAULT), XmppAxolotlSession.Trust.TRUSTED);
}
- public void recreateAxolotlDb() {
- recreateAxolotlDb(getWritableDatabase());
- }
public void recreateAxolotlDb(SQLiteDatabase db) {
Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + ">>> (RE)CREATING AXOLOTL DATABASE <<<");
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index 8fcda7c2..bc919788 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -14,7 +14,6 @@ import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
-import android.os.FileObserver;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
@@ -58,7 +57,9 @@ import eu.siacs.conversations.utils.FileUtils;
import eu.siacs.conversations.xmpp.pep.Avatar;
public class FileBackend {
- private final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
+ private static final SimpleDateFormat IMAGE_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
+
+ public static final String CONVERSATIONS_FILE_PROVIDER = "eu.siacs.conversations.files";
private XmppConnectionService mXmppConnectionService;
@@ -226,6 +227,7 @@ public class FileBackend {
}
public void copyFileToPrivateStorage(File file, Uri uri) throws FileCopyException {
+ Log.d(Config.LOGTAG,"copy file ("+uri.toString()+") to private storage "+file.getAbsolutePath());
file.getParentFile().mkdirs();
OutputStream os = null;
InputStream is = null;
@@ -248,7 +250,6 @@ public class FileBackend {
close(os);
close(is);
}
- Log.d(Config.LOGTAG, "output file name " + file.getAbsolutePath());
}
public void copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException {
@@ -338,6 +339,7 @@ public class FileBackend {
}
public void copyImageToPrivateStorage(File file, Uri image) throws FileCopyException {
+ Log.d(Config.LOGTAG,"copy image ("+image.toString()+") to private storage "+file.getAbsolutePath());
copyImageToPrivateStorage(file, image, 0);
}
@@ -431,16 +433,27 @@ public class FileBackend {
return frame;
}
+ private static String getTakePhotoPath() {
+ return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+"/Camera/";
+ }
+
public Uri getTakePhotoUri() {
- StringBuilder pathBuilder = new StringBuilder();
- pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
- pathBuilder.append('/');
- pathBuilder.append("Camera");
- pathBuilder.append('/');
- pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) + ".jpg");
- File file = new File(pathBuilder.toString());
+ File file = new File(getTakePhotoPath()+"IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg");
file.getParentFile().mkdirs();
- return FileProvider.getUriForFile(mXmppConnectionService,"eu.siacs.conversations.files",file);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ return FileProvider.getUriForFile(mXmppConnectionService, CONVERSATIONS_FILE_PROVIDER, file);
+ } else {
+ return Uri.fromFile(file);
+ }
+ }
+
+ public static Uri getIndexableTakePhotoUri(Uri original) {
+ if ("file".equals(original.getScheme())) {
+ return original;
+ } else {
+ List<String> segments = original.getPathSegments();
+ return Uri.parse("file://"+getTakePhotoPath()+segments.get(segments.size() - 1));
+ }
}
public Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) {
diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java
index 7cfe2433..6e1d6c4b 100644
--- a/src/main/java/eu/siacs/conversations/services/NotificationService.java
+++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java
@@ -2,7 +2,6 @@ package eu.siacs.conversations.services;
import android.app.Notification;
import android.app.PendingIntent;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
@@ -14,18 +13,13 @@ import android.support.v4.app.NotificationCompat.BigPictureStyle;
import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;
-import android.support.v4.app.TaskStackBuilder;
import android.text.Html;
import android.util.DisplayMetrics;
import android.util.Log;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -297,11 +291,11 @@ public class NotificationService {
modifyForTextOnly(mBuilder, messages);
}
RemoteInput remoteInput = new RemoteInput.Builder("text_reply").setLabel(UIHelper.getMessageHint(mXmppConnectionService, conversation)).build();
- NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_send_text_offline, "Reply", createReplyIntent(conversation)).addRemoteInput(remoteInput).build();
+ NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(R.drawable.ic_send_text_offline, "Reply", createReplyIntent(conversation, false)).addRemoteInput(remoteInput).build();
+ NotificationCompat.Action wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_send_text_offline, "Reply", createReplyIntent(conversation, true)).addRemoteInput(remoteInput).build();
+ mBuilder.extend(new NotificationCompat.WearableExtender().addAction(wearReplyAction));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- mBuilder.addAction(action);
- } else {
- mBuilder.extend(new NotificationCompat.WearableExtender().addAction(action));
+ mBuilder.addAction(replyAction);
}
if ((message = getFirstDownloadableMessage(messages)) != null) {
mBuilder.addAction(
@@ -474,11 +468,13 @@ public class NotificationService {
return PendingIntent.getService(mXmppConnectionService, 0, intent, 0);
}
- private PendingIntent createReplyIntent(Conversation conversation) {
+ private PendingIntent createReplyIntent(Conversation conversation, boolean dismissAfterReply) {
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_REPLY_TO_CONVERSATION);
intent.putExtra("uuid",conversation.getUuid());
- return PendingIntent.getService(mXmppConnectionService, conversation.getUuid().hashCode() % 402361, intent, 0);
+ intent.putExtra("dismiss_notification",dismissAfterReply);
+ int id = conversation.getUuid().hashCode() % (dismissAfterReply ? 402359 : 426583);
+ return PendingIntent.getService(mXmppConnectionService, id, intent, 0);
}
private PendingIntent createDisableForeground() {
@@ -494,11 +490,10 @@ public class NotificationService {
return PendingIntent.getService(mXmppConnectionService, 45, intent, 0);
}
- private PendingIntent createDisableAccountIntent(final Account account) {
+ private PendingIntent createDismissErrorIntent() {
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
- intent.setAction(XmppConnectionService.ACTION_DISABLE_ACCOUNT);
- intent.putExtra("account", account.getJid().toBareJid().toString());
- return PendingIntent.getService(mXmppConnectionService, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ intent.setAction(XmppConnectionService.ACTION_DISMISS_ERROR_NOTIFICATIONS);
+ return PendingIntent.getService(mXmppConnectionService, 69, intent, 0);
}
private boolean wasHighlightedOrPrivate(final Message message) {
@@ -592,7 +587,7 @@ public class NotificationService {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService);
final List<Account> errors = new ArrayList<>();
for (final Account account : mXmppConnectionService.getAccounts()) {
- if (account.hasErrorStatus()) {
+ if (account.hasErrorStatus() && account.showErrorNotification()) {
errors.add(account);
}
}
@@ -613,27 +608,17 @@ public class NotificationService {
mBuilder.addAction(R.drawable.ic_autorenew_white_24dp,
mXmppConnectionService.getString(R.string.try_again),
createTryAgainIntent());
- if (errors.size() == 1) {
- mBuilder.addAction(R.drawable.ic_block_white_24dp,
- mXmppConnectionService.getString(R.string.disable_account),
- createDisableAccountIntent(errors.get(0)));
- }
- mBuilder.setOngoing(true);
- //mBuilder.setLights(0xffffffff, 2000, 4000);
+ mBuilder.setDeleteIntent(createDismissErrorIntent());
+ mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp);
} else {
mBuilder.setSmallIcon(R.drawable.ic_stat_alert_warning);
}
- final TaskStackBuilder stackBuilder = TaskStackBuilder.create(mXmppConnectionService);
- stackBuilder.addParentStack(ConversationActivity.class);
-
- final Intent manageAccountsIntent = new Intent(mXmppConnectionService, ManageAccountActivity.class);
- stackBuilder.addNextIntent(manageAccountsIntent);
-
- final PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
-
- mBuilder.setContentIntent(resultPendingIntent);
+ mBuilder.setContentIntent(PendingIntent.getActivity(mXmppConnectionService,
+ 145,
+ new Intent(mXmppConnectionService,ManageAccountActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT));
notificationManager.notify(ERROR_NOTIFICATION_ID, mBuilder.build());
}
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 3bf1e745..774842a7 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -132,8 +132,8 @@ public class XmppConnectionService extends Service {
public static final String ACTION_REPLY_TO_CONVERSATION = "reply_to_conversations";
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
+ public static final String ACTION_DISMISS_ERROR_NOTIFICATIONS = "dismiss_error";
public static final String ACTION_TRY_AGAIN = "try_again";
- public static final String ACTION_DISABLE_ACCOUNT = "disable_account";
public static final String ACTION_IDLE_PING = "idle_ping";
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh";
@@ -294,6 +294,9 @@ public class XmppConnectionService extends Service {
mOnAccountUpdate.onAccountUpdate();
}
if (account.getStatus() == Account.State.ONLINE) {
+ if (account.setShowErrorNotification(true)) {
+ databaseBackend.updateAccount(account);
+ }
mMessageArchiveService.executePendingQueries(account);
if (connection != null && connection.getFeatures().csi()) {
if (checkListeners()) {
@@ -323,7 +326,7 @@ public class XmppConnectionService extends Service {
}
account.pendingConferenceJoins.clear();
scheduleWakeUpCall(Config.PUSH_MODE ? Config.PING_MIN_INTERVAL : Config.PING_MAX_INTERVAL, account.getUuid().hashCode());
- } else if (account.getStatus() == Account.State.OFFLINE) {
+ } else if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED) {
resetSendingToWaiting(account);
final boolean disabled = account.isOptionSet(Account.OPTION_DISABLED);
final boolean listeners = checkListeners();
@@ -340,6 +343,7 @@ public class XmppConnectionService extends Service {
reconnectAccount(account, true, false);
} else if ((account.getStatus() != Account.State.CONNECTING)
&& (account.getStatus() != Account.State.NO_INTERNET)) {
+ resetSendingToWaiting(account);
if (connection != null) {
int next = connection.getTimeToNextAttempt();
Log.d(Config.LOGTAG, account.getJid().toBareJid()
@@ -526,6 +530,7 @@ public class XmppConnectionService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent == null ? null : intent.getAction();
+ String pushedAccountHash = null;
boolean interactive = false;
if (action != null) {
final Conversation c = findConversationByUuid(intent.getStringExtra("uuid"));
@@ -554,28 +559,20 @@ public class XmppConnectionService extends Service {
getPreferences().edit().putBoolean("keep_foreground_service", false).commit();
toggleForegroundService();
break;
+ case ACTION_DISMISS_ERROR_NOTIFICATIONS:
+ dismissErrorNotifications();
+ break;
case ACTION_TRY_AGAIN:
resetAllAttemptCounts(false);
interactive = true;
break;
- case ACTION_DISABLE_ACCOUNT:
- try {
- String jid = intent.getStringExtra("account");
- Account account = jid == null ? null : findAccountByJid(Jid.fromString(jid));
- if (account != null) {
- account.setOption(Account.OPTION_DISABLED, true);
- updateAccount(account);
- }
- } catch (final InvalidJidException ignored) {
- break;
- }
- break;
case ACTION_REPLY_TO_CONVERSATION:
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null && c != null) {
-
- String body = remoteInput.getString("text_reply");
- directReply(c,body);
+ final CharSequence body = remoteInput.getCharSequence("text_reply");
+ if (body != null && body.length() > 0) {
+ directReply(c, body.toString(),intent.getBooleanExtra("dismiss_notification",false));
+ }
}
break;
case AudioManager.RINGER_MODE_CHANGED_ACTION:
@@ -601,6 +598,7 @@ public class XmppConnectionService extends Service {
break;
case ACTION_GCM_MESSAGE_RECEIVED:
Log.d(Config.LOGTAG,"gcm push message arrived in service. extras="+intent.getExtras());
+ pushedAccountHash = intent.getStringExtra("account");
break;
}
}
@@ -639,7 +637,7 @@ public class XmppConnectionService extends Service {
}
} else {
pingCandidates.add(account);
- if (msToNextPing <= 0) {
+ if (msToNextPing <= 0 || CryptoHelper.getAccountFingerprint(account).equals(pushedAccountHash)) {
pingNow = true;
} else {
this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode());
@@ -707,7 +705,7 @@ public class XmppConnectionService extends Service {
}
}
- private void directReply(Conversation conversation, String body) {
+ private void directReply(Conversation conversation, String body, final boolean dismissAfterReply) {
Message message = new Message(conversation,body,conversation.getNextEncryption());
message.markUnread();
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
@@ -716,7 +714,11 @@ public class XmppConnectionService extends Service {
public void success(Message message) {
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
sendMessage(message);
- mNotificationService.pushFromDirectReply(message);
+ if (dismissAfterReply) {
+ markRead(message.getConversation(),true);
+ } else {
+ mNotificationService.pushFromDirectReply(message);
+ }
}
@Override
@@ -731,7 +733,11 @@ public class XmppConnectionService extends Service {
});
} else {
sendMessage(message);
- mNotificationService.pushFromDirectReply(message);
+ if (dismissAfterReply) {
+ markRead(conversation,true);
+ } else {
+ mNotificationService.pushFromDirectReply(message);
+ }
}
}
@@ -802,6 +808,21 @@ public class XmppConnectionService extends Service {
connection.resetAttemptCount();
}
}
+ if (account.setShowErrorNotification(true)) {
+ databaseBackend.updateAccount(account);
+ }
+ }
+ mNotificationService.updateErrorNotification();
+ }
+
+ private void dismissErrorNotifications() {
+ for (final Account account : this.accounts) {
+ if (account.hasErrorStatus()) {
+ Log.d(Config.LOGTAG,account.getJid().toBareJid()+": dismissing error notification");
+ if (account.setShowErrorNotification(false)) {
+ databaseBackend.updateAccount(account);
+ }
+ }
}
}
@@ -976,8 +997,16 @@ public class XmppConnectionService extends Service {
public XmppConnection createConnection(final Account account) {
final SharedPreferences sharedPref = getPreferences();
- account.setResource(sharedPref.getString("resource", getString(R.string.default_resource))
- .toLowerCase(Locale.getDefault()));
+ String resource;
+ try {
+ resource = sharedPref.getString("resource", getString(R.string.default_resource)).toLowerCase(Locale.ENGLISH);
+ if (resource.trim().isEmpty()) {
+ throw new Exception();
+ }
+ } catch (Exception e) {
+ resource = "conversations";
+ }
+ account.setResource(resource);
final XmppConnection connection = new XmppConnection(account, this);
connection.setOnMessagePacketReceivedListener(this.mMessageParser);
connection.setOnStatusChangedListener(this.statusListener);
@@ -1018,6 +1047,10 @@ public class XmppConnectionService extends Service {
private void sendMessage(final Message message, final boolean resend, final boolean delay) {
final Account account = message.getConversation().getAccount();
+ if (account.setShowErrorNotification(true)) {
+ databaseBackend.updateAccount(account);
+ mNotificationService.updateErrorNotification();
+ }
final Conversation conversation = message.getConversation();
account.deactivateGracePeriod();
MessagePacket packet = null;
@@ -1110,7 +1143,8 @@ public class XmppConnectionService extends Service {
}
if (packet != null) {
- if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) {
+ if (account.getXmppConnection().getFeatures().sm()
+ || (conversation.getMode() == Conversation.MODE_MULTI && message.getCounterpart().isBareJid())) {
message.setStatus(Message.STATUS_UNSEND);
} else {
message.setStatus(Message.STATUS_SEND);
@@ -1152,7 +1186,8 @@ public class XmppConnectionService extends Service {
if (resend) {
if (packet != null && addToConversation) {
- if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) {
+ if (account.getXmppConnection().getFeatures().sm()
+ || (conversation.getMode() == Conversation.MODE_MULTI && message.getCounterpart().isBareJid())) {
markMessage(message, Message.STATUS_UNSEND);
} else {
markMessage(message, Message.STATUS_SEND);
@@ -1288,6 +1323,13 @@ public class XmppConnectionService extends Service {
for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
checkDeletedFiles(conversation);
+ conversation.findUnsentTextMessages(new Conversation.OnMessageFound() {
+
+ @Override
+ public void onMessageFound(Message message) {
+ markMessage(message, Message.STATUS_WAITING);
+ }
+ });
conversation.findUnreadMessages(new Conversation.OnMessageFound() {
@Override
public void onMessageFound(Message message) {
@@ -1508,7 +1550,6 @@ public class XmppConnectionService extends Service {
conversation.setMode(Conversation.MODE_SINGLE);
conversation.setContactJid(jid.toBareJid());
}
- conversation.setNextEncryption(-1);
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
this.databaseBackend.updateConversation(conversation);
} else {
@@ -1549,7 +1590,6 @@ public class XmppConnectionService extends Service {
public void archiveConversation(Conversation conversation) {
getNotificationService().clear(conversation);
conversation.setStatus(Conversation.STATUS_ARCHIVED);
- conversation.setNextEncryption(-1);
synchronized (this.conversations) {
if (conversation.getMode() == Conversation.MODE_MULTI) {
if (conversation.getAccount().getStatus() == Account.State.ONLINE) {
@@ -1644,6 +1684,7 @@ public class XmppConnectionService extends Service {
public boolean updateAccount(final Account account) {
if (databaseBackend.updateAccount(account)) {
+ account.setShowErrorNotification(true);
this.statusListener.onStatusChanged(account);
databaseBackend.updateAccount(account);
reconnectAccountInBackground(account);
@@ -3091,7 +3132,10 @@ public class XmppConnectionService extends Service {
if (this.markRead(conversation)) {
updateConversationUi();
}
- if (confirmMessages() && markable != null && markable.getRemoteMsgId() != null) {
+ if (confirmMessages()
+ && markable != null
+ && markable.trusted()
+ && markable.getRemoteMsgId() != null) {
Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending read marker to " + markable.getCounterpart().toString());
Account account = conversation.getAccount();
final Jid to = markable.getCounterpart();
@@ -3346,10 +3390,10 @@ public class XmppConnectionService extends Service {
mDatabaseExecutor.execute(runnable);
}
- public void sendBlockRequest(final Blockable blockable) {
+ public void sendBlockRequest(final Blockable blockable, boolean reportSpam) {
if (blockable != null && blockable.getBlockedJid() != null) {
final Jid jid = blockable.getBlockedJid();
- this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetBlockRequest(jid), new OnIqPacketReceived() {
+ this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetBlockRequest(jid, reportSpam), new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(final Account account, final IqPacket packet) {
diff --git a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
index 9cf7e9f8..91ce34a9 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
@@ -3,6 +3,14 @@ package eu.siacs.conversations.ui;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.style.TypefaceSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Blockable;
@@ -15,16 +23,31 @@ public final class BlockContactDialog {
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
final boolean isBlocked = blockable.isBlocked();
builder.setNegativeButton(R.string.cancel, null);
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LinearLayout view = (LinearLayout) inflater.inflate(R.layout.dialog_block_contact,null);
+ TextView message = (TextView) view.findViewById(R.id.text);
+ final CheckBox report = (CheckBox) view.findViewById(R.id.report_spam);
+ final boolean reporting = blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
+ report.setVisibility(!isBlocked && reporting ? View.VISIBLE : View.GONE);
+ builder.setView(view);
+ String value;
+ SpannableString spannable;
if (blockable.getJid().isDomainJid() || blockable.getAccount().isBlocked(blockable.getJid().toDomainJid())) {
builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
- builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text,
- blockable.getJid().toDomainJid()));
+ value = blockable.getJid().toDomainJid().toString();
+ spannable = new SpannableString(context.getString(isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text, value));
+ message.setText(spannable);
} else {
builder.setTitle(isBlocked ? R.string.action_unblock_contact : R.string.action_block_contact);
- builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text,
- blockable.getJid().toBareJid()));
+ value = blockable.getJid().toBareJid().toString();
+ spannable = new SpannableString(context.getString(isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text, value));
}
+ int start = spannable.toString().indexOf(value);
+ if (start >= 0) {
+ spannable.setSpan(new TypefaceSpan("monospace"),start,start + value.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ message.setText(spannable);
builder.setPositiveButton(isBlocked ? R.string.unblock : R.string.block, new DialogInterface.OnClickListener() {
@Override
@@ -32,7 +55,7 @@ public final class BlockContactDialog {
if (isBlocked) {
xmppConnectionService.sendUnblockRequest(blockable);
} else {
- xmppConnectionService.sendBlockRequest(blockable);
+ xmppConnectionService.sendBlockRequest(blockable, report.isChecked());
}
}
});
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index e6f7fc5d..7791372a 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -271,6 +271,15 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
@Override
+ protected void onStart() {
+ super.onStart();
+ final int theme = findTheme();
+ if (this.mTheme != theme) {
+ recreate();
+ }
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case android.R.id.home:
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index 836e345b..08128094 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -227,9 +227,14 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
@Override
public void onStart() {
super.onStart();
- final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
- this.showDynamicTags = preferences.getBoolean("show_dynamic_tags",false);
- this.showLastSeen = preferences.getBoolean("last_activity", false);
+ final int theme = findTheme();
+ if (this.mTheme != theme) {
+ recreate();
+ } else {
+ final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ this.showDynamicTags = preferences.getBoolean("show_dynamic_tags", false);
+ this.showLastSeen = preferences.getBoolean("last_activity", false);
+ }
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 2c8b27b0..82b59dfc 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -153,11 +153,7 @@ public class ConversationActivity extends XmppActivity
}
public boolean isConversationsOverviewHideable() {
- if (mContentView instanceof SlidingPaneLayout) {
- return true;
- } else {
- return false;
- }
+ return mContentView instanceof SlidingPaneLayout;
}
public boolean isConversationsOverviewVisable() {
@@ -185,6 +181,7 @@ public class ConversationActivity extends XmppActivity
}
String pending = savedInstanceState.getString(STATE_PENDING_URI, null);
if (pending != null) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onCreate() - restoring pending image uri");
mPendingImageUris.clear();
mPendingImageUris.add(Uri.parse(pending));
}
@@ -454,14 +451,15 @@ public class ConversationActivity extends XmppActivity
private boolean quickOmemoDebugger(Conversation c) {
if (c != null) {
+ boolean single = c.getMode() == Conversation.MODE_SINGLE;
AxolotlService axolotlService = c.getAccount().getAxolotlService();
Pair<AxolotlService.AxolotlCapability,Jid> capabilityJidPair = axolotlService.isConversationAxolotlCapableDetailed(c);
switch (capabilityJidPair.first) {
case MISSING_PRESENCE:
- Toast.makeText(ConversationActivity.this,getString(R.string.missing_presence_subscription_with_x,capabilityJidPair.second.toBareJid().toString()),Toast.LENGTH_SHORT).show();
+ Toast.makeText(ConversationActivity.this,single ? getString(R.string.missing_presence_subscription) : getString(R.string.missing_presence_subscription_with_x,capabilityJidPair.second.toBareJid().toString()),Toast.LENGTH_SHORT).show();
return true;
case MISSING_KEYS:
- Toast.makeText(ConversationActivity.this,getString(R.string.missing_keys_from_x,capabilityJidPair.second.toBareJid().toString()),Toast.LENGTH_SHORT).show();
+ Toast.makeText(ConversationActivity.this,single ? getString(R.string.missing_omemo_keys) : getString(R.string.missing_keys_from_x,capabilityJidPair.second.toBareJid().toString()),Toast.LENGTH_SHORT).show();
return true;
case WRONG_CONFIGURATION:
Toast.makeText(ConversationActivity.this,R.string.wrong_conference_configuration, Toast.LENGTH_SHORT).show();
@@ -1150,6 +1148,7 @@ public class ConversationActivity extends XmppActivity
}
savedInstanceState.putBoolean(STATE_PANEL_OPEN, isConversationsOverviewVisable());
if (this.mPendingImageUris.size() >= 1) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onSaveInstanceState() - saving pending image uri");
savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUris.get(0).toString());
} else {
savedInstanceState.remove(STATE_PENDING_URI);
@@ -1237,13 +1236,22 @@ public class ConversationActivity extends XmppActivity
this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second);
}
+ final boolean stopping;
+ if (Build.VERSION.SDK_INT >= 17) {
+ stopping = isFinishing() || isDestroyed();
+ } else {
+ stopping = isFinishing();
+ }
+
if (!forbidProcessingPendings) {
for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) {
Uri foo = i.next();
+ Log.d(Config.LOGTAG,"ConversationsActivity.onBackendConnected() - attaching image to conversations. stopping="+Boolean.toString(stopping));
attachImageToConversation(getSelectedConversation(), foo);
}
for (Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onBackendConnected() - attaching file to conversations. stopping="+Boolean.toString(stopping));
attachFileToConversation(getSelectedConversation(), i.next());
}
@@ -1368,6 +1376,7 @@ public class ConversationActivity extends XmppActivity
mPendingImageUris.addAll(extractUriFromIntent(data));
if (xmppConnectionServiceBound) {
for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onActivityResult() - attaching image to conversations. CHOOSE_IMAGE");
attachImageToConversation(getSelectedConversation(), i.next());
}
}
@@ -1381,6 +1390,7 @@ public class ConversationActivity extends XmppActivity
mPendingFileUris.addAll(uris);
if (xmppConnectionServiceBound) {
for (Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onActivityResult() - attaching file to conversations. CHOOSE_FILE/RECORD_VOICE");
attachFileToConversation(c, i.next());
}
}
@@ -1395,8 +1405,10 @@ public class ConversationActivity extends XmppActivity
}
} else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
if (mPendingImageUris.size() == 1) {
- Uri uri = mPendingImageUris.get(0);
+ Uri uri = FileBackend.getIndexableTakePhotoUri(mPendingImageUris.get(0));
+ mPendingImageUris.set(0, uri);
if (xmppConnectionServiceBound) {
+ Log.d(Config.LOGTAG,"ConversationsActivity.onActivityResult() - attaching image to conversations. TAKE_PHOTO");
attachImageToConversation(getSelectedConversation(), uri);
mPendingImageUris.clear();
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 14469355..df01e87c 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -576,9 +576,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
downloadFile.setVisible(true);
downloadFile.setTitle(activity.getString(R.string.download_x_file,UIHelper.getFileDescriptionString(activity, m)));
}
- if ((t != null && !(t instanceof TransferablePlaceholder))
- || (m.isFileOrImage() && (m.getStatus() == Message.STATUS_WAITING
- || m.getStatus() == Message.STATUS_OFFERED))) {
+ boolean waitingOfferedSending = m.getStatus() == Message.STATUS_WAITING
+ || m.getStatus() == Message.STATUS_UNSEND
+ || m.getStatus() == Message.STATUS_OFFERED;
+ if ((t != null && !(t instanceof TransferablePlaceholder)) || waitingOfferedSending && m.needsUploading()) {
cancelTransmission.setVisible(true);
}
if (treatAsFile) {
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index c10d2741..cc178179 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -519,6 +519,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener);
this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener);
this.mMoreTable = (TableLayout) findViewById(R.id.server_info_more);
+ if (savedInstanceState != null && savedInstanceState.getBoolean("showMoreTable")) {
+ changeMoreTableVisibility(true);
+ }
final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(final CompoundButton buttonView,
@@ -585,9 +588,21 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
@Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more);
+ if (showMoreInfo.isVisible()) {
+ showMoreInfo.setChecked(mMoreTable.getVisibility() == View.VISIBLE);
+ }
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
protected void onStart() {
super.onStart();
- if (getIntent() != null) {
+ final int theme = findTheme();
+ if (this.mTheme != theme) {
+ recreate();
+ } else if (getIntent() != null) {
try {
this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid"));
} catch (final InvalidJidException | NullPointerException ignored) {
@@ -625,6 +640,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if (mAccount != null) {
savedInstanceState.putString("account", mAccount.getJid().toBareJid().toString());
savedInstanceState.putBoolean("initMode", mInitMode);
+ savedInstanceState.putBoolean("showMoreTable", mMoreTable.getVisibility() == View.VISIBLE);
}
super.onSaveInstanceState(savedInstanceState);
}
@@ -692,8 +708,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
startActivity(showBlocklistIntent);
break;
case R.id.action_server_info_show_more:
- mMoreTable.setVisibility(item.isChecked() ? View.GONE : View.VISIBLE);
- item.setChecked(!item.isChecked());
+ changeMoreTableVisibility(!item.isChecked());
break;
case R.id.action_change_password_on_server:
gotoChangePassword(null);
@@ -717,6 +732,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
return super.onOptionsItemSelected(item);
}
+ private void changeMoreTableVisibility(boolean visible) {
+ mMoreTable.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
private void gotoChangePassword(String newPassword) {
final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
diff --git a/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java b/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java
deleted file mode 100644
index bedb4172..00000000
--- a/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package eu.siacs.conversations.ui;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.preference.Preference;
-import android.util.AttributeSet;
-
-import eu.siacs.conversations.services.ExportLogsService;
-
-public class ExportLogsPreference extends Preference {
-
- public ExportLogsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public ExportLogsPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public ExportLogsPreference(Context context) {
- super(context);
- }
-
- protected void onClick() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
- && getContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- return;
- }
- final Intent startIntent = new Intent(getContext(), ExportLogsService.class);
- getContext().startService(startIntent);
- super.onClick();
- }
-} \ No newline at end of file
diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
index f52ccb19..0f6b58ef 100644
--- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -103,6 +103,15 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
}
@Override
+ protected void onStart() {
+ super.onStart();
+ final int theme = findTheme();
+ if (this.mTheme != theme) {
+ recreate();
+ }
+ }
+
+ @Override
public void onSaveInstanceState(final Bundle savedInstanceState) {
if (selectedAccount != null) {
savedInstanceState.putString(STATE_SELECTED_ACCOUNT, selectedAccount.getJid().toBareJid().toString());
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
index 0752ae32..9a699b51 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
@@ -141,7 +141,7 @@ public class PublishProfilePictureActivity extends XmppActivity {
}
});
- this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext());
+ this.defaultUri = PhoneHelper.getSelfiUri(getApplicationContext());
}
private void chooseAvatar(boolean crop) {
@@ -250,8 +250,11 @@ public class PublishProfilePictureActivity extends XmppActivity {
if (!support) {
this.hintOrWarning
.setTextColor(getWarningTextColor());
- this.hintOrWarning
- .setText(R.string.error_publish_avatar_no_server_support);
+ if (account.getStatus() == Account.State.ONLINE) {
+ this.hintOrWarning.setText(R.string.error_publish_avatar_no_server_support);
+ } else {
+ this.hintOrWarning.setText(R.string.error_publish_avatar_offline);
+ }
}
} else {
this.avatarUri = this.defaultUri;
@@ -306,8 +309,11 @@ public class PublishProfilePictureActivity extends XmppActivity {
} else {
disablePublishButton();
this.hintOrWarning.setTextColor(getWarningTextColor());
- this.hintOrWarning
- .setText(R.string.error_publish_avatar_no_server_support);
+ if (account.getStatus() == Account.State.ONLINE) {
+ this.hintOrWarning.setText(R.string.error_publish_avatar_no_server_support);
+ } else {
+ this.hintOrWarning.setText(R.string.error_publish_avatar_offline);
+ }
}
if (this.defaultUri != null && uri.equals(this.defaultUri)) {
this.secondaryHint.setVisibility(View.INVISIBLE);
diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
index 17ade702..c2bf20ac 100644
--- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
@@ -29,6 +29,8 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.ExportLogsService;
import eu.siacs.conversations.xmpp.XmppConnection;
+import eu.siacs.conversations.xmpp.jid.InvalidJidException;
+import eu.siacs.conversations.xmpp.jid.Jid;
public class SettingsActivity extends XmppActivity implements
OnSharedPreferenceChangeListener {
@@ -91,7 +93,7 @@ public class SettingsActivity extends XmppActivity implements
displayToast(getString(R.string.toast_no_trusted_certs));
return true;
}
- final ArrayList selectedItems = new ArrayList<Integer>();
+ final ArrayList selectedItems = new ArrayList<>();
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(SettingsActivity.this);
dialogBuilder.setTitle(getResources().getString(R.string.dialog_manage_certs_title));
dialogBuilder.setMultiChoiceItems(aliases.toArray(new CharSequence[aliases.size()]), null,
@@ -147,12 +149,72 @@ public class SettingsActivity extends XmppActivity implements
exportLogsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- hasStoragePermission(REQUEST_WRITE_LOGS);
+ if (hasStoragePermission(REQUEST_WRITE_LOGS)) {
+ startExport();
+ }
+ return true;
+ }
+ });
+
+ final Preference deleteOmemoPreference = mSettingsFragment.findPreference("delete_omemo_identities");
+ deleteOmemoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ deleteOmemoIdentities();
return true;
}
});
}
+ private void deleteOmemoIdentities() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.pref_delete_omemo_identities);
+ final List<CharSequence> accounts = new ArrayList<>();
+ for(Account account : xmppConnectionService.getAccounts()) {
+ if (!account.isOptionSet(Account.OPTION_DISABLED)) {
+ accounts.add(account.getJid().toBareJid().toString());
+ }
+ }
+ final boolean[] checkedItems = new boolean[accounts.size()];
+ builder.setMultiChoiceItems(accounts.toArray(new CharSequence[accounts.size()]), checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+ checkedItems[which] = isChecked;
+ final AlertDialog alertDialog = (AlertDialog) dialog;
+ for(boolean item : checkedItems) {
+ if (item) {
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
+ return;
+ }
+ }
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
+ }
+ });
+ builder.setNegativeButton(R.string.cancel,null);
+ builder.setPositiveButton(R.string.delete_selected_keys, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ for(int i = 0; i < checkedItems.length; ++i) {
+ if (checkedItems[i]) {
+ try {
+ Jid jid = Jid.fromString(accounts.get(i).toString());
+ Account account = xmppConnectionService.findAccountByJid(jid);
+ if (account != null) {
+ account.getAxolotlService().regenerateKeys(true);
+ }
+ } catch (InvalidJidException e) {
+ //
+ }
+
+ }
+ }
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
+ }
+
@Override
public void onStop() {
super.onStop();
@@ -213,13 +275,17 @@ public class SettingsActivity extends XmppActivity implements
if (grantResults.length > 0)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == REQUEST_WRITE_LOGS) {
- getApplicationContext().startService(new Intent(getApplicationContext(), ExportLogsService.class));
+ startExport();
}
} else {
Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
}
}
+ private void startExport() {
+ startService(new Intent(getApplicationContext(), ExportLogsService.class));
+ }
+
private void displayToast(final String msg) {
runOnUiThread(new Runnable() {
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index 768961c1..ec5559ae 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -282,7 +282,12 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
@Override
public void onStart() {
super.onStart();
- askForContactsPermissions();
+ final int theme = findTheme();
+ if (this.mTheme != theme) {
+ recreate();
+ } else {
+ askForContactsPermissions();
+ }
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
index 3c837b94..59d58db5 100644
--- a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.ui;
+import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -16,6 +17,11 @@ public class WelcomeActivity extends Activity {
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
+ final ActionBar ab = getActionBar();
+ if (ab != null) {
+ ab.setDisplayShowHomeEnabled(false);
+ ab.setDisplayHomeAsUpEnabled(false);
+ }
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome);
final Button createAccount = (Button) findViewById(R.id.create_account);
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index b24c9539..4505e632 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -51,6 +51,7 @@ import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Message.FileParams;
import eu.siacs.conversations.entities.Transferable;
+import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.ui.widget.ClickableMovementMethod;
import eu.siacs.conversations.ui.widget.ListSelectionManager;
@@ -710,7 +711,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
- uri = FileProvider.getUriForFile(activity, "eu.siacs.conversations.files", file);
+ uri = FileProvider.getUriForFile(activity, FileBackend.CONVERSATIONS_FILE_PROVIDER, file);
} catch (IllegalArgumentException e) {
Toast.makeText(activity,activity.getString(R.string.no_permission_to_access_x,file.getAbsolutePath()), Toast.LENGTH_SHORT).show();
return;
diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
index 429c349a..38ebced1 100644
--- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@@ -204,6 +205,15 @@ public final class CryptoHelper {
return prettifyFingerprintCert(bytesToHex(fingerprint));
}
+ public static String getAccountFingerprint(Account account) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ return bytesToHex(md.digest(account.getJid().toBareJid().toString().getBytes("UTF-8")));
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
public static int encryptionTypeToText(int encryption) {
switch (encryption) {
case Message.ENCRYPTION_OTR:
diff --git a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
index e3a24fcf..3242cfcf 100644
--- a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java
@@ -93,14 +93,14 @@ public class PhoneHelper {
try {
return (super.loadInBackground());
- } catch (SecurityException e) {
+ } catch (Throwable e) {
return(null);
}
}
}
- public static Uri getSefliUri(Context context) {
+ public static Uri getSelfiUri(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
return null;
diff --git a/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java b/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java
index 768e9f17..81f93653 100644
--- a/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java
+++ b/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java
@@ -12,6 +12,8 @@ import eu.siacs.conversations.Config;
public class SocksSocketFactory {
+ private static final byte[] LOCALHOST = new byte[]{127,0,0,1};
+
public static void createSocksConnection(Socket socket, String destination, int port) throws IOException {
InputStream proxyIs = socket.getInputStream();
OutputStream proxyOs = socket.getOutputStream();
@@ -44,7 +46,7 @@ public class SocksSocketFactory {
}
public static Socket createSocketOverTor(String destination, int port) throws IOException {
- return createSocket(new InetSocketAddress(InetAddress.getLocalHost(), 9050), destination, port);
+ return createSocket(new InetSocketAddress(InetAddress.getByAddress(LOCALHOST), 9050), destination, port);
}
static class SocksConnectionException extends IOException {
diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
index bf997bc1..faf4b3a5 100644
--- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
@@ -181,9 +181,7 @@ public class UIHelper {
}
} else {
String body = message.getBody();
- if (body == null) {
- body = "";
- } else if (body.length() > 256) {
+ if (body.length() > 256) {
body = body.substring(0,256);
}
if (body.startsWith(Message.ME_COMMAND)) {
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index e3af48e3..383e990d 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -136,7 +136,7 @@ public class XmppConnection implements Runnable {
private SaslMechanism saslMechanism;
- private X509KeyManager mKeyManager = new X509KeyManager() {
+ private class MyKeyManager implements X509KeyManager {
@Override
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
return account.getPrivateKeyAlias();
@@ -149,9 +149,11 @@ public class XmppConnection implements Runnable {
@Override
public X509Certificate[] getCertificateChain(String alias) {
+ Log.d(Config.LOGTAG,"getting certificate chain");
try {
return KeyChain.getCertificateChain(mXmppConnectionService, alias);
} catch (Exception e) {
+ Log.d(Config.LOGTAG,e.getMessage());
return new X509Certificate[0];
}
}
@@ -174,7 +176,8 @@ public class XmppConnection implements Runnable {
return null;
}
}
- };
+ }
+
private Identity mServerIdentity = Identity.UNKNOWN;
public final OnIqPacketReceived registrationResponseListener = new OnIqPacketReceived() {
@@ -241,6 +244,9 @@ public class XmppConnection implements Runnable {
}
protected void connect() {
+ if (mXmppConnectionService.areMessagesInitialized()) {
+ mXmppConnectionService.resetSendingToWaiting(account);
+ }
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting");
features.encryptionEnabled = false;
this.attempt++;
@@ -458,7 +464,7 @@ public class XmppConnection implements Runnable {
MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
KeyManager[] keyManager;
if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) {
- keyManager = new KeyManager[]{mKeyManager};
+ keyManager = new KeyManager[]{new MyKeyManager()};
} else {
keyManager = null;
}
@@ -846,18 +852,13 @@ public class XmppConnection implements Runnable {
saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG());
}
if (saslMechanism != null) {
- final JSONObject keys = account.getKeys();
- try {
- if (keys.has(Account.PINNED_MECHANISM_KEY) &&
- keys.getInt(Account.PINNED_MECHANISM_KEY) > saslMechanism.getPriority()) {
- Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() +
- " has lower priority (" + String.valueOf(saslMechanism.getPriority()) +
- ") than pinned priority (" + keys.getInt(Account.PINNED_MECHANISM_KEY) +
- "). Possible downgrade attack?");
- throw new SecurityException();
- }
- } catch (final JSONException e) {
- Log.d(Config.LOGTAG, "Parse error while checking pinned auth mechanism");
+ final int pinnedMechanism = account.getKeyAsInt(Account.PINNED_MECHANISM_KEY, -1);
+ if (pinnedMechanism > saslMechanism.getPriority()) {
+ Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() +
+ " has lower priority (" + String.valueOf(saslMechanism.getPriority()) +
+ ") than pinned priority (" + pinnedMechanism +
+ "). Possible downgrade attack?");
+ throw new SecurityException();
}
Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism());
auth.setAttribute("mechanism", saslMechanism.getMechanism());
@@ -1072,7 +1073,7 @@ public class XmppConnection implements Runnable {
this.disco.clear();
}
mPendingServiceDiscoveries.set(0);
- mWaitForDisco.set(mServerIdentity != Identity.NIMBUZZ);
+ mWaitForDisco.set(mServerIdentity != Identity.NIMBUZZ && smVersion != 0);
lastDiscoStarted = SystemClock.elapsedRealtime();
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": starting service discovery");
mXmppConnectionService.scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode());
@@ -1600,6 +1601,10 @@ public class XmppConnection implements Runnable {
return hasDiscoFeature(account.getServer(), Xmlns.BLOCKING);
}
+ public boolean spamReporting() {
+ return hasDiscoFeature(account.getServer(), "urn:xmpp:reporting:reason:spam:0");
+ }
+
public boolean register() {
return hasDiscoFeature(account.getServer(), Xmlns.REGISTER);
}
diff --git a/src/main/res/layout/activity_edit_account.xml b/src/main/res/layout/activity_edit_account.xml
index 555f18ff..64393b25 100644
--- a/src/main/res/layout/activity_edit_account.xml
+++ b/src/main/res/layout/activity_edit_account.xml
@@ -221,6 +221,7 @@
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:shrinkColumns="0"
android:stretchColumns="1">
<TableRow
@@ -233,13 +234,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_session_established"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/session_est"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -250,6 +254,7 @@
android:id="@+id/server_info_more"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:shrinkColumns="0"
android:stretchColumns="1"
android:visibility="gone">
@@ -262,13 +267,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_pep"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_pep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -283,13 +291,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_blocking"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_blocking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -304,13 +315,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_stream_management"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_sm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -325,13 +339,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_roster_version"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_roster_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -346,13 +363,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_carbon_messages"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_carbons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -367,13 +387,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_mam"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_mam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -388,13 +411,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_csi"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_csi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"
tools:ignore="RtlHardcoded"/>
@@ -409,13 +435,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_push"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_push"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"/>
</TableRow>
@@ -428,13 +457,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_http_upload"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end"/>
<TextView
android:id="@+id/server_info_http_upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody"/>
</TableRow>
diff --git a/src/main/res/layout/activity_muc_details.xml b/src/main/res/layout/activity_muc_details.xml
index 7ff91e15..f4e45598 100644
--- a/src/main/res/layout/activity_muc_details.xml
+++ b/src/main/res/layout/activity_muc_details.xml
@@ -141,6 +141,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/muc_info_more"
+ android:shrinkColumns="0"
android:stretchColumns="1"
android:visibility="gone">
@@ -153,13 +154,16 @@
android:layout_height="wrap_content"
android:text="@string/server_info_mam"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody" />
+ android:textSize="?attr/TextSizeBody"
+ android:singleLine="true"
+ android:ellipsize="end" />
<TextView
android:id="@+id/muc_info_mam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:paddingLeft="4dp"
android:textColor="?attr/color_text_primary"
android:textSize="?attr/TextSizeBody" />
</TableRow>
diff --git a/src/main/res/layout/create_conference_dialog.xml b/src/main/res/layout/create_conference_dialog.xml
index 8aae08a6..d81ed0f2 100644
--- a/src/main/res/layout/create_conference_dialog.xml
+++ b/src/main/res/layout/create_conference_dialog.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingBottom="8dp"
- android:paddingLeft="24dp"
- android:paddingRight="24dp"
- android:paddingTop="16dp">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="?attr/dialog_vertical_padding"
+ android:paddingLeft="?attr/dialog_horizontal_padding"
+ android:paddingRight="?attr/dialog_horizontal_padding"
+ android:paddingTop="?attr/dialog_vertical_padding">
<TextView
android:id="@+id/your_account"
@@ -37,6 +37,6 @@
android:inputType="textAutoComplete"
android:textColor="?attr/color_text_primary"
android:textColorHint="?attr/color_text_secondary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody" />
</LinearLayout>
diff --git a/src/main/res/layout/dialog_block_contact.xml b/src/main/res/layout/dialog_block_contact.xml
new file mode 100644
index 00000000..661af7d5
--- /dev/null
+++ b/src/main/res/layout/dialog_block_contact.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingLeft="?attr/dialog_horizontal_padding"
+ android:paddingRight="?attr/dialog_horizontal_padding"
+ android:paddingBottom="?attr/dialog_vertical_padding"
+ android:paddingTop="?attr/dialog_vertical_padding">
+
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="?attr/TextSizeBody"
+ android:textColor="?attr/color_text_primary"/>
+ <CheckBox
+ android:layout_marginTop="8dp"
+ android:id="@+id/report_spam"
+ android:layout_width="wrap_content"
+ android:textColor="?attr/color_text_primary"
+ android:layout_height="wrap_content"
+ android:text="@string/report_jid_as_spammer" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/layout/dialog_clear_history.xml b/src/main/res/layout/dialog_clear_history.xml
index 252808c8..d130b710 100644
--- a/src/main/res/layout/dialog_clear_history.xml
+++ b/src/main/res/layout/dialog_clear_history.xml
@@ -3,11 +3,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:padding="8dp" >
+ android:paddingLeft="?attr/dialog_horizontal_padding"
+ android:paddingRight="?attr/dialog_horizontal_padding"
+ android:paddingBottom="?attr/dialog_vertical_padding"
+ android:paddingTop="?attr/dialog_vertical_padding">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textColor="?attr/color_text_primary"
android:paddingBottom="8dp"
android:text="@string/clear_histor_msg"
android:textSize="?attr/TextSizeBody" />
@@ -15,6 +19,7 @@
<CheckBox
android:id="@+id/end_conversation_checkbox"
android:layout_width="wrap_content"
+ android:textColor="?attr/color_text_primary"
android:layout_height="wrap_content"
android:text="@string/also_end_conversation" />
diff --git a/src/main/res/layout/dialog_show_password.xml b/src/main/res/layout/dialog_show_password.xml
index dba0690c..16765963 100644
--- a/src/main/res/layout/dialog_show_password.xml
+++ b/src/main/res/layout/dialog_show_password.xml
@@ -3,7 +3,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:padding="16dp" >
+ android:paddingLeft="?attr/dialog_horizontal_padding"
+ android:paddingRight="?attr/dialog_horizontal_padding"
+ android:paddingBottom="?attr/dialog_vertical_padding"
+ android:paddingTop="?attr/dialog_vertical_padding">
<TextView
android:id="@+id/password"
diff --git a/src/main/res/layout/enter_jid_dialog.xml b/src/main/res/layout/enter_jid_dialog.xml
index f8a861a9..700fea9b 100644
--- a/src/main/res/layout/enter_jid_dialog.xml
+++ b/src/main/res/layout/enter_jid_dialog.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingBottom="8dp"
- android:paddingLeft="24dp"
- android:paddingRight="24dp"
- android:paddingTop="16dp">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="?attr/dialog_vertical_padding"
+ android:paddingLeft="?attr/dialog_horizontal_padding"
+ android:paddingRight="?attr/dialog_horizontal_padding"
+ android:paddingTop="?attr/dialog_vertical_padding">
<TextView
android:id="@+id/your_account"
@@ -14,12 +14,12 @@
android:layout_height="wrap_content"
android:text="@string/your_account"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody" />
<Spinner
android:id="@+id/account"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content" />
<TextView
android:id="@+id/jabber_id"
@@ -28,7 +28,7 @@
android:layout_marginTop="8dp"
android:text="@string/account_settings_jabber_id"
android:textColor="?attr/color_text_primary"
- android:textSize="?attr/TextSizeBody"/>
+ android:textSize="?attr/TextSizeBody" />
<AutoCompleteTextView
android:id="@+id/jid"
diff --git a/src/main/res/layout/magic_create.xml b/src/main/res/layout/magic_create.xml
index e21ce5c0..02ba65bc 100644
--- a/src/main/res/layout/magic_create.xml
+++ b/src/main/res/layout/magic_create.xml
@@ -17,7 +17,7 @@
android:layout_alignParentStart="true"
android:minHeight="256dp"
android:orientation="vertical"
- android:paddingBottom="8dp"
+ android:paddingBottom="10dp"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<Space
@@ -79,5 +79,16 @@
android:padding="8dp"
android:src="@drawable/main_logo"/>
</RelativeLayout>
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:textColor="?attr/color_text_secondary"
+ android:textSize="@dimen/fineprint_size"
+ android:maxLines="1"
+ android:text="@string/free_for_six_month"
+ android:layout_centerHorizontal="true"/>
</RelativeLayout>
</ScrollView> \ No newline at end of file
diff --git a/src/main/res/layout/welcome.xml b/src/main/res/layout/welcome.xml
index 3d618675..228fe6b6 100644
--- a/src/main/res/layout/welcome.xml
+++ b/src/main/res/layout/welcome.xml
@@ -17,7 +17,7 @@
android:layout_alignParentStart="true"
android:minHeight="256dp"
android:orientation="vertical"
- android:paddingBottom="8dp"
+ android:paddingBottom="10dp"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<Space
@@ -70,5 +70,16 @@
android:padding="8dp"
android:src="@drawable/main_logo"/>
</RelativeLayout>
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:textColor="?attr/color_text_secondary"
+ android:textSize="@dimen/fineprint_size"
+ android:maxLines="1"
+ android:text="@string/free_for_six_month"
+ android:layout_centerHorizontal="true"/>
</RelativeLayout>
</ScrollView> \ No newline at end of file
diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml
index 84f59bb3..b54de99c 100644
--- a/src/main/res/values-ar/strings.xml
+++ b/src/main/res/values-ar/strings.xml
@@ -166,7 +166,6 @@
<string name="contact_already_exists">جهة الاتصال موجودة لديك مسبقا</string>
<string name="join">دخول</string>
<string name="conference_address">اسم الغرفة كامل</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">حفظ بالمفضلة</string>
<string name="delete_bookmark">حذف من المفضلة</string>
<string name="bookmark_already_exists">موجوده بالمفضلة سابقا</string>
diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml
index da322608..868ea5e2 100644
--- a/src/main/res/values-bg/strings.xml
+++ b/src/main/res/values-bg/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Контактът вече съществува</string>
<string name="join">Присъединяване</string>
<string name="conference_address">Адрес на беседата</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">стая@беседа.сървър.com/псевдоним</string>
<string name="save_as_bookmark">Запазване като отметка</string>
<string name="delete_bookmark">Изтриване на отметка</string>
<string name="bookmark_already_exists">Вече съществува такава отметка</string>
@@ -313,7 +313,7 @@
<string name="pref_use_send_button_to_indicate_status_summary">Оцветяване на бутона за изпращане в зависимост от състоянието на контакта</string>
<string name="pref_expert_options_other">Други</string>
<string name="pref_conference_name">Име на беседата</string>
- <string name="pref_conference_name_summary">Използване на темата на стаята вместо JID идентификатора за беседите</string>
+ <string name="pref_conference_name_summary">Използване на темата на стаята вместо идентификатора JID за беседите</string>
<string name="pref_autojoin">Автоматично присъединяване към беседите</string>
<string name="pref_autojoin_summary">Спазване на флага за автоматично присъединяване в отметките на беседите</string>
<string name="toast_message_otr_fingerprint">Отпечатъкът OTR е копиран!</string>
@@ -595,8 +595,8 @@
<string name="security_error_invalid_file_access">Грешка в сигурността: неправилен достъп до файл</string>
<string name="no_application_to_share_uri">Няма намерено приложение за споделяне на адреса</string>
<string name="share_uri_with">Споделяне на адреса с…</string>
- <string name="welcome_text">XMPP е протокол, който не е обвързан с конкретен доставчик. Можете да използвате клиента с всеки сървър, който работи с протокола XMPP.\nЗа Ваше удобство, ние предоставяме лесен начин да си създадете профил в conversations.im — сървър, пригоден да работи добре с Conversations.</string>
- <string name="magic_create_text">Ще преминем заедно с Вас през процеса за създаване на профил в conversations.im.\nАко изберете да използвате conversations.im, ще можете да общувате с потребители, използващи други сървъри, като им дадете своя пълен Jabber идентификатор.</string>
+ <string name="welcome_text">XMPP е протокол, който не е обвързан с конкретен доставчик. Можете да използвате клиента с всеки сървър, който работи с протокола XMPP.\nЗа Ваше удобство, ние предоставяме лесен начин да си създадете профил в conversations.im¹ — сървър, пригоден да работи добре с Conversations.</string>
+ <string name="magic_create_text">Ще преминем заедно с Вас през процеса за създаване на профил в conversations.im.¹\nАко изберете да използвате conversations.im, ще можете да общувате с потребители, използващи други сървъри, като им дадете своя пълен Jabber идентификатор.</string>
<string name="your_full_jid_will_be">Вашият пълен Jabber идентификатор ще бъде: %s</string>
<string name="create_account">Създаване на профил</string>
<string name="use_own_provider">Използване на собствен сървър</string>
@@ -653,4 +653,8 @@
<string name="missing_keys_from_x">Липсват ключове OMEMO от %s.</string>
<string name="wrong_conference_configuration">Това не е лична, не-анонимна беседа.</string>
<string name="this_conference_has_no_members">Няма участници в тази беседа.</string>
+ <string name="report_jid_as_spammer">Докладване на този JID за изпращане на нежелани съобщения.</string>
+ <string name="pref_delete_omemo_identities">Изтриване на идентификаторите OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Пресъздайте своите ключове OMEMO. Всички Ваши контакти ще трябва да Ви потвърдят отново. Използвайте това само в краен случай.</string>
+ <string name="delete_selected_keys">Изтриване на избраните ключове.</string>
</resources>
diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml
index 2210069a..b2f051e9 100644
--- a/src/main/res/values-ca/strings.xml
+++ b/src/main/res/values-ca/strings.xml
@@ -199,7 +199,6 @@
<string name="contact_already_exists">El contacte ja existeix</string>
<string name="join">Unir-se</string>
<string name="conference_address">Direcció de la sala</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Guardar com a favorits</string>
<string name="delete_bookmark">Eliminar de favorits</string>
<string name="bookmark_already_exists">Aquesta llista de favorits ja existeix</string>
diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml
index 2c7931d1..54af09db 100644
--- a/src/main/res/values-cs/strings.xml
+++ b/src/main/res/values-cs/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Kontakt již existuje</string>
<string name="join">Vstoupit</string>
<string name="conference_address">Adresa konference</string>
- <string name="conference_address_example">mistnost@konference.server.cz</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Uložit jako záložku</string>
<string name="delete_bookmark">Smazat záložku</string>
<string name="bookmark_already_exists">Tato záložka již existuje</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Konference vyžaduje heslo</string>
<string name="enter_password">Vložit heslo</string>
<string name="missing_presence_updates">Chybí informace o změnách stavu kontaktu</string>
+ <string name="missing_presence_subscription">Chybí informace o změnách stavu</string>
<string name="request_presence_updates">Nejdříve si prosím vyžádejte povolení o zasílání změn stavu kontaktu.\n\n<small>To bude poté použito pro zjištění jakou aplikaci tento kontakt používá.</small></string>
<string name="request_now">Ihned vyžádat</string>
<string name="delete_fingerprint">Smazat identifikátor</string>
@@ -598,8 +599,8 @@
<string name="security_error_invalid_file_access">Chyba zabezpečení: Neplatný přístup k souboru</string>
<string name="no_application_to_share_uri">Nebyla nalezena aplikace pro sdílení URI</string>
<string name="share_uri_with">Sdílet URI s...</string>
- <string name="welcome_text">XMPP je protokol nezávislý na poskytovateli. Tohoto klienta můžete použít s jakýmkoliv XMPP serverem dle svého výběru.\nPro lepší uživatelskou přívětivost jsme připravili možnost vytvořit účet u conversations.im; speciálné připraveného poskytovatele pro použití s aplikací Conversations.</string>
- <string name="magic_create_text">Provedeme vás procesem založení uživatelského účtu u conversations.im.\nVybráním conversations.im za svého poskytovatele budete moci komunikovat s uživateli u jiných poskytovatelů poté co jim sdělíte své Jabber ID.</string>
+ <string name="welcome_text">XMPP je protokol nezávislý na poskytovateli. Tohoto klienta můžete použít s jakýmkoliv XMPP serverem dle svého výběru.\nPro lepší uživatelskou přívětivost jsme připravili možnost vytvořit účet u conversations.im¹; poskytovatele speciálné připraveného pro použití s aplikací Conversations.</string>
+ <string name="magic_create_text">Provedeme vás procesem založení uživatelského účtu u conversations.im.¹\nVybráním conversations.im za svého poskytovatele budete moci komunikovat s uživateli u jiných poskytovatelů, poté co jim sdělíte své Jabber ID.</string>
<string name="your_full_jid_will_be">Vaše celé Jabber ID bude: %s</string>
<string name="create_account">Vytvořit účet</string>
<string name="use_own_provider">Použít vlastního provozovatele</string>
@@ -654,6 +655,12 @@
<string name="unable_to_update_account">Nelze aktualizovat účet</string>
<string name="missing_presence_subscription_with_x">Chybí informace o změnách stavu od %s.</string>
<string name="missing_keys_from_x">Chybí OMEMO klíče od %s.</string>
+ <string name="missing_omemo_keys">Chybí OMEMO klíče</string>
<string name="wrong_conference_configuration">Toto není soukromá, neanonymní konference.</string>
<string name="this_conference_has_no_members">V této konferenci nejsou žádní členové.</string>
+ <string name="report_jid_as_spammer">Nahlásit toto JID jako odesilatele nevyžádaného obsahu.</string>
+ <string name="pref_delete_omemo_identities">Smazat OMEMO identity</string>
+ <string name="pref_delete_omemo_identities_summary">Znovu vygenerovat OMEMO klíče. Vyžaduje potvrzení od všech vašich kontaktů. POužijte pouze jako poslední řešení.</string>
+ <string name="delete_selected_keys">Smazat vybrané klíče</string>
+ <string name="error_publish_avatar_offline">Pro zveřejnění svého avatara musíte být online.</string>
</resources>
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index 91df36f4..962a6b3b 100644
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Der Kontakt existiert bereits</string>
<string name="join">Beitreten</string>
<string name="conference_address">Konferenz-Adresse</string>
- <string name="conference_address_example">raum@conference.domain.de</string>
+ <string name="conference_address_example">raum@conference.beispiel.de/Nickname</string>
<string name="save_as_bookmark">Zur Kontaktliste hinzufügen</string>
<string name="delete_bookmark">Von Kontaktliste entfernen</string>
<string name="bookmark_already_exists">Die Konferenz befindet sich bereits auf deiner Kontaktliste</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Konferenz ist passwortgeschützt</string>
<string name="enter_password">Passwort eingeben</string>
<string name="missing_presence_updates">Fehlender Online-Status des Kontakts</string>
+ <string name="missing_presence_subscription">Online-Status nicht vorhanden</string>
<string name="request_presence_updates">Bitte erst Online-Status vom Kontakt anfragen.\n\n<small>Dies wird verwendet, um festzustellen, welche Client(s) der Kontakt benutzt.</small></string>
<string name="request_now">Jetzt anfordern</string>
<string name="delete_fingerprint">Fingerabdruck löschen</string>
@@ -516,7 +517,7 @@
<string name="pref_use_white_background_summary">Empfangene Nachrichten als schwarzen Text auf weißem Hintergrund anzeigen</string>
<string name="account_status_tor_unavailable">Tor-Netzwerk nicht verfügbar</string>
<string name="account_status_bind_failure">Bindungsfehler</string>
- <string name="account_status_host_unknown">Server haftet nicht für die Domain</string>
+ <string name="account_status_host_unknown">Unbekannte Domain</string>
<string name="server_info_broken">Fehlerhaft</string>
<string name="pref_presence_settings">Status</string>
<string name="pref_away_when_screen_off">Abwesend bei abgeschaltetem Bildschirm</string>
@@ -595,8 +596,8 @@
<string name="security_error_invalid_file_access">Sicherheitsfehler: Dateizugriff nicht erlaubt</string>
<string name="no_application_to_share_uri">Keine Anwendung zum Teilen der URI gefunden</string>
<string name="share_uri_with">Teile URI mit…</string>
- <string name="welcome_text">XMPP ist ein providerunabhängiges Protokoll. Du kannst diesen Client mit jedem beliebigen XMPP-Server benutzen.\nUm es Dir leicht zu machen haben wir die Möglichkeit geschaffen, ein Konto auf conversations.im anzulegen. Dieser Provider ist besonders gut für Conversations geeignet. </string>
- <string name="magic_create_text">Wir führen dich durch den Prozess der Kontoerstellung auf conversations.im.\nWenn du conversations.im als Provider wählst, kannst du mit Nutzern anderer Anbieter kommunizieren, indem du ihnen deine vollständige Jabber-ID gibst.</string>
+ <string name="welcome_text">XMPP ist ein providerunabhängiges Protokoll. Du kannst diesen Client mit jedem beliebigen XMPP-Server benutzen.\nUm es Dir leicht zu machen haben wir die Möglichkeit geschaffen, ein Konto auf conversations.im¹ anzulegen. Dieser Provider ist besonders gut für Conversations geeignet. </string>
+ <string name="magic_create_text">Wir führen dich durch den Prozess der Kontoerstellung auf conversations.im.¹\nWenn du conversations.im als Provider wählst, kannst du mit Nutzern anderer Anbieter kommunizieren, indem du ihnen deine vollständige Jabber-ID gibst.</string>
<string name="your_full_jid_will_be">Deine vollständige Jabber ID lautet: %s</string>
<string name="create_account">Konto erstellen</string>
<string name="use_own_provider">Nutze eigenen Provider</string>
@@ -651,6 +652,12 @@
<string name="unable_to_update_account">Konto kann nicht aktualisiert werden.</string>
<string name="missing_presence_subscription_with_x">Fehlender Online-Status von %s.</string>
<string name="missing_keys_from_x">OMEMO-Schlüssel von %s fehlen.</string>
+ <string name="missing_omemo_keys">OMEMO-Schlüssel fehlen</string>
<string name="wrong_conference_configuration">Dies ist keine private, nicht-anonyme Konferenz.</string>
<string name="this_conference_has_no_members">Diese Konferenz enthält keine Teilnehmer.</string>
+ <string name="report_jid_as_spammer">Melde die JID als Sender unerwünschter Nachrichten.</string>
+ <string name="pref_delete_omemo_identities">OMEMO Identitäten zurücksetzen</string>
+ <string name="pref_delete_omemo_identities_summary">Regeneriere deine OMEMO-Schlüssel. Alle deine Kontakte müssen dich neu verifizieren. Nutze dies als letzten Ausweg.</string>
+ <string name="delete_selected_keys">Ausgewählte Schlüssel löschen</string>
+ <string name="error_publish_avatar_offline">Du musst verbunden sein um deinen Avatar zu veröffentlichen</string>
</resources>
diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml
index a08ec2b8..1c2fd858 100644
--- a/src/main/res/values-el/strings.xml
+++ b/src/main/res/values-el/strings.xml
@@ -199,7 +199,6 @@
<string name="contact_already_exists">Η επαφή υπάρχει ήδη</string>
<string name="join">Συμμετοχή</string>
<string name="conference_address">Διεύθυνση συνδιάσκεψης</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Αποθήκευση σαν σελιδοδείκτη</string>
<string name="delete_bookmark">Διαγραφή σελιδοδείκτη</string>
<string name="bookmark_already_exists">Αυτός ο σελιδοδείκτης υπάρχει ήδη</string>
diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml
index bff5c19d..eede5b98 100644
--- a/src/main/res/values-es/strings.xml
+++ b/src/main/res/values-es/strings.xml
@@ -128,8 +128,8 @@
<string name="error_decrypting_file">Error descifrando archivo</string>
<string name="accept">Aceptar</string>
<string name="error">Ha ocurrido un error</string>
- <string name="pref_grant_presence_updates">Suscripción de presencia</string>
- <string name="pref_grant_presence_updates_summary">De forma automática solicitar y conceder suscripciones de presencia de los contactos que has creado</string>
+ <string name="pref_grant_presence_updates">Suscripción de presencia automática</string>
+ <string name="pref_grant_presence_updates_summary">De forma automática solicitar y conceder la suscripción de presencia de los contactos que has creado</string>
<string name="subscriptions">Suscripciones</string>
<string name="your_account">Tu cuenta</string>
<string name="keys">Claves</string>
@@ -247,7 +247,7 @@
<string name="contact_already_exists">El contacto ya existe</string>
<string name="join">Unirse</string>
<string name="conference_address">Dirección</string>
- <string name="conference_address_example">nombre@salas.ejemplo.com</string>
+ <string name="conference_address_example">sala@salas.ejemplo.com/nick</string>
<string name="save_as_bookmark">Guardar en marcadores</string>
<string name="delete_bookmark">Eliminar marcador</string>
<string name="bookmark_already_exists">Este marcador ya existe</string>
@@ -282,13 +282,14 @@
<string name="enable">Habilitar</string>
<string name="conference_requires_password">Esta conversación requiere contraseña</string>
<string name="enter_password">Introduce la contraseña</string>
- <string name="missing_presence_updates">Suscripción de actualizaciones de presencia del contacto perdida</string>
- <string name="request_presence_updates">Por favor, solicita la suscripción de presencia a tu contacto primero.\n\n<small>Esto será usado para determinar qué cliente(s) está usando tu contacto.</small></string>
+ <string name="missing_presence_updates">Se ha perdido la suscripción de presencia del contacto</string>
+ <string name="missing_presence_subscription">Se ha perdido la suscripción de presencia</string>
+ <string name="request_presence_updates">Por favor, solicita la suscripción de presencia a tu contacto primero.\n\n<small>Esto se usará para determinar qué cliente(s) está usando tu contacto.</small></string>
<string name="request_now">Solicitar ahora</string>
<string name="delete_fingerprint">Eliminar huella digital OTR</string>
<string name="sure_delete_fingerprint">¿Estás seguro de que quieres eliminar esta huella digital OTR?</string>
<string name="ignore">Ignorar</string>
- <string name="without_mutual_presence_updates"><b>Aviso:</b> Enviando esto sin suscripción de presencia por ambas partes podría causar problemas inesperados.\n\n<small>Verficia la suscripción de presencia en detalles del contacto.</small></string>
+ <string name="without_mutual_presence_updates"><b>Aviso:</b> Si envías esto sin suscripción de presencia con tu contacto se podrían producir problemas inesperados.\n\n<small>Verifica la suscripción de presencia en detalles del contacto.</small></string>
<string name="pref_security_settings">Seguridad</string>
<string name="pref_force_encryption">Forzar cifrado end-to-end</string>
<string name="pref_force_encryption_summary">Siempre enviar mensajes cifrados (excepto para conversaciones en grupo)</string>
@@ -595,8 +596,8 @@
<string name="security_error_invalid_file_access">Error de seguridad: Acceso a fichero inválido</string>
<string name="no_application_to_share_uri">No se ha encontrado ninguna aplicación para compartir la URI</string>
<string name="share_uri_with">Compartir URI con...</string>
- <string name="welcome_text">XMPP es un protocolo independiente del proveedor. Puedes usar este cliente con cualquier servidor de XMPP que elijas.\nDe todas formas, para tu comodidad, hemos facilitado la creación de una cuenta en conversations.im; un proveedor alojado especialmente para su uso con Conversations.</string>
- <string name="magic_create_text">Te guiaremos durante el proceso de creación de la cuenta en conversations.im.\nCuando selecciones conversations.im como proveedor, podrás comunicarte con usuarios de otros servidores mediante tu identificador Jabber.</string>
+ <string name="welcome_text">XMPP es un protocolo independiente del proveedor. Puedes usar este cliente con cualquier servidor de XMPP que elijas.\nDe todas formas, para tu comodidad, hemos facilitado la creación de una cuenta en conversations.im¹; un proveedor alojado especialmente para su uso con Conversations.</string>
+ <string name="magic_create_text">Te guiaremos durante el proceso de creación de la cuenta en conversations.im.¹\nCuando selecciones conversations.im como proveedor, podrás comunicarte con usuarios de otros servidores mediante tu identificador Jabber.</string>
<string name="your_full_jid_will_be">Tu identificador Jabber será: %s</string>
<string name="create_account">Crear cuenta</string>
<string name="use_own_provider">Usar otro proveedor de mi elección</string>
@@ -648,4 +649,15 @@
<string name="allow">Permitir</string>
<string name="no_permission_to_access_x">Sin permiso de acceso a %s</string>
<string name="remote_server_not_found">Servidor no encontrado</string>
+ <string name="unable_to_update_account">No se ha podido actualizar la cuenta</string>
+ <string name="missing_presence_subscription_with_x">Se ha perdido la suscripción de presencia con %s.</string>
+ <string name="missing_keys_from_x">Se ha perdido la clave OMEMO de %s.</string>
+ <string name="missing_omemo_keys">Se han perdido las claves OMEMO</string>
+ <string name="wrong_conference_configuration">Ésta no es una conversación privada no anónima.</string>
+ <string name="this_conference_has_no_members">No hay miembros en esta conversación.</string>
+ <string name="report_jid_as_spammer">Reportar a este Id Jabber por enviar mensajes no deseados</string>
+ <string name="pref_delete_omemo_identities">Eliminar identidades OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Regenerar tus clave OMEMO. Todos tus contactos tendrán que verificarte de nuevo. Usa esta opción como último recurso.</string>
+ <string name="delete_selected_keys">Eliminar claves seleccionadas</string>
+ <string name="error_publish_avatar_offline">Debes estar conectado para publicar la imagen de perfil</string>
</resources>
diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml
index f2b0f247..3ebfd517 100644
--- a/src/main/res/values-eu/strings.xml
+++ b/src/main/res/values-eu/strings.xml
@@ -247,7 +247,6 @@
<string name="contact_already_exists">Kontaktua existitzen da dagoeneko</string>
<string name="join">Batu</string>
<string name="conference_address">Konferentziaren helbidea</string>
- <string name="conference_address_example">gela@conference.example.com</string>
<string name="save_as_bookmark">Gorde laster-marka bezala</string>
<string name="delete_bookmark">Laster-marka ezabatu</string>
<string name="bookmark_already_exists">Laster-marka hau existitzen da dagoeneko</string>
@@ -595,8 +594,8 @@
<string name="security_error_invalid_file_access">Segurtasun akatsa: fitxategi sarrera baliogabea</string>
<string name="no_application_to_share_uri">Ez da aplikaziorik aurkitu URIa partekatzeko</string>
<string name="share_uri_with">URIa honekin partekatu...</string>
- <string name="welcome_text">XMPP hornitzaleez independiente den protokolo bat da. Bezero hau aukeratzen duzun edozein XMPP zerbitzariarekin erabili dezakezu.\nHala ere zure erosotasunerako conversations.im-en, Conversationsekin bereziki erabiltzeko egokia den hornitzaile batean, kontu bat sortzea erraz egin dugu.</string>
- <string name="magic_create_text">conversations.im-en kontu bat sortzeko prozesuan zehar gidatuko zaitugu.\nconversations.im hornitzaile bezala aukeratzerakoan beste hornitzaileen erabiltzaileekin komunikatzeko gai izango zara haiei zure Jabber ID osoa emanez.</string>
+ <string name="welcome_text">XMPP hornitzaleez independiente den protokolo bat da. Bezero hau aukeratzen duzun edozein XMPP zerbitzariarekin erabili dezakezu.\nHala ere zure erosotasunerako conversations.im¹-en, Conversationsekin bereziki erabiltzeko egokia den hornitzaile batean, kontu bat sortzea erraz egin dugu.</string>
+ <string name="magic_create_text">conversations.im-en kontu bat sortzeko prozesuan zehar gidatuko zaitugu.\nconversations.im¹ hornitzaile bezala aukeratzerakoan beste hornitzaileen erabiltzaileekin komunikatzeko gai izango zara haiei zure Jabber ID osoa emanez.</string>
<string name="your_full_jid_will_be">Zure Jabber ID osoa %s izango da</string>
<string name="create_account">Kontua sortu</string>
<string name="use_own_provider">Nire hornitzale propioa erabili</string>
@@ -643,4 +642,14 @@
<string name="type_console">Kontsola</string>
<string name="payment_required">Ordainketa beharrezkoa da</string>
<string name="missing_internet_permission">Interneterako baimena falta da</string>
+ <string name="me">Ni</string>
+ <string name="contact_asks_for_presence_subscription">Kontaktuak presentzia harpidetza eskatzen du</string>
+ <string name="allow">Baimendu</string>
+ <string name="no_permission_to_access_x">%s(e)ra sartzeko baimenik ez</string>
+ <string name="remote_server_not_found">Urruneko zerbitzaria ez da aurkitu</string>
+ <string name="unable_to_update_account">Ezin izan da kontua eguneratu</string>
+ <string name="missing_presence_subscription_with_x">%s(r)ekin presentzia harpidetza falta da</string>
+ <string name="missing_keys_from_x">%s(r)en OMEMO gakoak falta dira.</string>
+ <string name="wrong_conference_configuration">Hau ez da konferentzia pribatu, ez anonimo bat.</string>
+ <string name="this_conference_has_no_members">Ez dago kiderik konferentzia honetan.</string>
</resources>
diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml
index d86f1364..63576e0e 100644
--- a/src/main/res/values-fr/strings.xml
+++ b/src/main/res/values-fr/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Le contact existe déjà.</string>
<string name="join">Rejoindre</string>
<string name="conference_address">Adresse de la conférence</string>
- <string name="conference_address_example">salle@conference.exemple.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Enregistrer comme favori</string>
<string name="delete_bookmark">Supprimer le favori</string>
<string name="bookmark_already_exists">Le favori existe déjà</string>
@@ -595,8 +595,8 @@
<string name="security_error_invalid_file_access">Erreur de sécurité : accès fichier non-valide</string>
<string name="no_application_to_share_uri">Aucune application trouvée pour partager l\'URI</string>
<string name="share_uri_with">Partager l\'URI avec...</string>
- <string name="welcome_text">XMPP est un protocole indépendant. Vous pouvez utiliser ce client avec le serveur XMPP de votre choix.\nCependant, pour votre confort, vous pouvez créer un compte sur conversations.im, un fournisseur spécialement approprié pour Conversations.</string>
- <string name="magic_create_text">Nous vous guiderons pendant toute la procédure de création d\'un compte utilisateur sur conversations.im.\nEn choisissant conversations.im comme fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur transmettant votre Jabber ID complet. </string>
+ <string name="welcome_text">XMPP est un protocole indépendant. Vous pouvez utiliser ce client avec le serveur XMPP de votre choix.\nCependant, pour votre confort, vous pouvez créer un compte sur conversations.im¹, un fournisseur spécialement approprié pour Conversations.</string>
+ <string name="magic_create_text">Nous vous guiderons pendant toute la procédure de création d\'un compte utilisateur sur conversations.im.¹\nEn choisissant conversations.im comme fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur transmettant votre Jabber ID complet. </string>
<string name="your_full_jid_will_be">Votre Jabber ID complet sera : %s</string>
<string name="create_account">Créer un compte</string>
<string name="use_own_provider">Utiliser votre propre fournisseur</string>
@@ -643,4 +643,18 @@
<string name="type_console">Console</string>
<string name="payment_required">Paiement Obligatoire</string>
<string name="missing_internet_permission">Permission Internet Manquante</string>
+ <string name="me">Moi</string>
+ <string name="contact_asks_for_presence_subscription">Le contact demande la notification de présence</string>
+ <string name="allow">Autoriser</string>
+ <string name="no_permission_to_access_x">Permission d\'accès refusée à %s</string>
+ <string name="remote_server_not_found">Serveur distant non trouvé</string>
+ <string name="unable_to_update_account">Mise à jour du compte impossible</string>
+ <string name="missing_presence_subscription_with_x">La notification de présence est manquante avec %s</string>
+ <string name="missing_keys_from_x">La clef OMEMO de %s est manquante</string>
+ <string name="wrong_conference_configuration">La conférence n\'est ni privée, ni anonyme</string>
+ <string name="this_conference_has_no_members">Aucun membre dans cette conférence</string>
+ <string name="report_jid_as_spammer">Signaler ce JID comme envoyant des messages non sollicités</string>
+ <string name="pref_delete_omemo_identities">Effacer les identités OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Régénérer vos clef OMEMO. Tous vos contacts devront les vérifier à nouveau. A n\'utiliser qu\'en dernier recours.</string>
+ <string name="delete_selected_keys">Supprimer les clefs sélectionnées</string>
</resources>
diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml
index 880700e7..6ba858c7 100644
--- a/src/main/res/values-id/strings.xml
+++ b/src/main/res/values-id/strings.xml
@@ -222,7 +222,6 @@
<string name="contact_already_exists">Kontak ini sudah ada</string>
<string name="join">Gabung</string>
<string name="conference_address">Alamat conference</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Simpan sebagai bookmark</string>
<string name="delete_bookmark">Hapus bookmark</string>
<string name="bookmark_already_exists">Bookmark ini sudah ada</string>
diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml
index 455b5e6e..d409b53f 100644
--- a/src/main/res/values-it/strings.xml
+++ b/src/main/res/values-it/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Il contatto esiste già</string>
<string name="join">Entra</string>
<string name="conference_address">Indirizzo conferenza</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Salva come segnalibro</string>
<string name="delete_bookmark">Elimina segnalibro</string>
<string name="bookmark_already_exists">Questo segnalibro esiste già</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">La conferenza richiede una password</string>
<string name="enter_password">Inserisci la password</string>
<string name="missing_presence_updates">Aggiornamenti della presenza del contatto mancanti</string>
+ <string name="missing_presence_subscription">Sottoiscrizione alla presenza mancante</string>
<string name="request_presence_updates">Richiedi gli aggiornamenti della presenza dal tuo contatto.\n\n<small>Questo verrà usato per determinare quali client sta usando il tuo contatto.</small></string>
<string name="request_now">Rechiedi adesso</string>
<string name="delete_fingerprint">Elimina Impronta</string>
@@ -595,8 +596,8 @@
<string name="security_error_invalid_file_access">Errore di sicurezza: accesso file non valido</string>
<string name="no_application_to_share_uri">Nessuna applicazione trovata per condividere l\'URI</string>
<string name="share_uri_with">Condividi l\'URI con...</string>
- <string name="welcome_text">XMPP è un protocollo che non dipende da un provider. Puoi usare questo client con qualsiasi server XMPP scelto.\nTuttavia per comodità abbiamo semplificato la creazione di un account su conversations.im; un provider particolarmente adatto all\'uso con Conversations.</string>
- <string name="magic_create_text">Ti guideremo nel processo di creazione di un account su conversations.im.\nQuando scegli conversations.im come provider potrai comunicare con utenti di altri provider dando il tuo ID Jabber completo.</string>
+ <string name="welcome_text">XMPP è un protocollo che non dipende da un provider. Puoi usare questo client con qualsiasi server XMPP scelto.\nTuttavia per comodità abbiamo semplificato la creazione di un account su conversations.im¹; un provider particolarmente adatto all\'uso con Conversations.</string>
+ <string name="magic_create_text">Ti guideremo nel processo di creazione di un account su conversations.im.¹\nQuando scegli conversations.im come provider potrai comunicare con utenti di altri provider dando il tuo ID Jabber completo.</string>
<string name="your_full_jid_will_be">Il tuo ID Jabber completo sarà: %s</string>
<string name="create_account">Crea account</string>
<string name="use_own_provider">Usa un altro provider</string>
@@ -651,6 +652,12 @@
<string name="unable_to_update_account">Impossibile aggiornare l\'account</string>
<string name="missing_presence_subscription_with_x">Sottoscrizione della presenza con %s mancante.</string>
<string name="missing_keys_from_x">Chiavi OMEMO da %s mancanti.</string>
+ <string name="missing_omemo_keys">Chiave OMEMO mancante</string>
<string name="wrong_conference_configuration">Questa non è un conferenza privata/anonima.</string>
<string name="this_conference_has_no_members">Non ci sono membri in questa conferenza.</string>
+ <string name="report_jid_as_spammer">Questo JID invia messaggi non richiesti.</string>
+ <string name="pref_delete_omemo_identities">Elimina identità OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Rigenera le tue chiavi OMEMO. I tuoi contatti dovranno verificare un\'altra volta la tua identità. Solo come ultima possibilità.</string>
+ <string name="delete_selected_keys">Cancella le chiavi selezionate</string>
+ <string name="error_publish_avatar_offline">Devi essere connesso per pubblicare l\'avatar.</string>
</resources>
diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml
index 22718d55..8ed4739f 100644
--- a/src/main/res/values-iw/strings.xml
+++ b/src/main/res/values-iw/strings.xml
@@ -215,7 +215,6 @@
<string name="contact_already_exists">איש קשר כבר קיים</string>
<string name="join">הצטרף</string>
<string name="conference_address">כתובת ועידה</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">שמור בתור סימנייה</string>
<string name="delete_bookmark">מחק סימנייה</string>
<string name="bookmark_already_exists">סימנייה זו כבר קיימת</string>
diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml
index dc0f518f..3e55d17a 100644
--- a/src/main/res/values-ja/strings.xml
+++ b/src/main/res/values-ja/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">連絡先はすでに存在します</string>
<string name="join">参加</string>
<string name="conference_address">会議アドレス</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">ブックマークとして保存</string>
<string name="delete_bookmark">ブックマークを削除</string>
<string name="bookmark_already_exists">このブックマークはすでに存在します</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">会議はパスワードが必要です</string>
<string name="enter_password">パスワードを入力してください</string>
<string name="missing_presence_updates">連絡先からの参加アップデートがありません</string>
+ <string name="missing_presence_subscription">参加サブスクリプションが見つかりません</string>
<string name="request_presence_updates">最初に連絡先から参加アップデートを要求してください。\n\n<small>これは、連絡先が何のクライアントを使用しているかを決めるために使用されます。</small></string>
<string name="request_now">今すぐ要求</string>
<string name="delete_fingerprint">フィンガープリントを削除</string>
@@ -390,7 +391,7 @@
<string name="account_image_description">アカウント アバター</string>
<string name="copy_otr_clipboard_description">OTR フィンガープリントをクリップボードにコピー</string>
<string name="copy_omemo_clipboard_description">OMEMO フィンガープリントをクリップボードにコピー</string>
- <string name="regenerate_omemo_key">OMEMO キーを再生成</string>
+ <string name="regenerate_omemo_key">OMEMO 鍵を再生成</string>
<string name="wipe_omemo_pep">PEP から他のデバイスを消去</string>
<string name="clear_other_devices">デバイスをクリア</string>
<string name="clear_other_devices_desc">OMEMO のアナウンスから他のすべてのデバイスをクリアしてもよろしいですか? お使いのデバイスが次回接続したとき、それらは自分自身を再アナウンスしますが、それらはその間に送信されたメッセージを受信できない場合があります。</string>
@@ -592,7 +593,7 @@
<string name="security_error_invalid_file_access">セキュリティエラー: 不正なファイルアクセス</string>
<string name="no_application_to_share_uri">URI を共有するアプリケーションが見つかりません</string>
<string name="share_uri_with">…で URI を共有</string>
- <string name="welcome_text">XMPPはプロバイダーに依存しないプロトコルです。これまであなたが選択したどのXMPPサーバーでも、このクライアントを使用することができます。\nしかしあなたが便利なように、Conversationsで使用するのに最適なプロバイダーconversations.imで簡単にアカウントを作成することができるようにしています。</string>
+ <string name="welcome_text">XMPPはプロバイダーに依存しないプロトコルです。これまであなたが選択したどのXMPPサーバーでも、このクライアントを使用することができます。\nしかしあなたが便利なように、Conversationsで使用するのに最適なプロバイダーconversations.im¹で簡単にアカウントを作成することができるようにしています。</string>
<string name="magic_create_text">conversations.imのアカウントを作成する手順をガイドします。\nプロバイダーとしてconversations.imを選択すると、あなたの完全なJabber IDを指定することによって、他のプロバイダーのユーザと通信することができるようになります。</string>
<string name="your_full_jid_will_be">あなたの完全な Jabber ID は: %s</string>
<string name="create_account">アカウントを作成</string>
@@ -648,6 +649,12 @@
<string name="unable_to_update_account">アカウントを更新できません</string>
<string name="missing_presence_subscription_with_x">%s の、参加サブスクリプションが見つかりません。</string>
<string name="missing_keys_from_x">%s からの OMEMO 鍵が見つかりません。</string>
+ <string name="missing_omemo_keys">OMEMO 鍵が見つかりません</string>
<string name="wrong_conference_configuration">これはプライベートではない、非匿名の会議です。</string>
<string name="this_conference_has_no_members">この会議にメンバーはいません</string>
+ <string name="report_jid_as_spammer">この JID を不要なメッセージ送信として報告します。</string>
+ <string name="pref_delete_omemo_identities">OMEMO ID を削除</string>
+ <string name="pref_delete_omemo_identities_summary">OMEMO 鍵を再生成します。すべての連絡先を再度確認する必要があります。最後の手段としてのみ使用してください。</string>
+ <string name="delete_selected_keys">選択した鍵を削除</string>
+ <string name="error_publish_avatar_offline">アバターを公開するには接続する必要があります。</string>
</resources>
diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml
index 08ea1ca6..1860cbc2 100644
--- a/src/main/res/values-ko/strings.xml
+++ b/src/main/res/values-ko/strings.xml
@@ -223,7 +223,6 @@
<string name="contact_already_exists">이미 존재하는 연락처입니다 </string>
<string name="join">참석 </string>
<string name="conference_address">회의 주소 </string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">즐겨찾기로 저장 </string>
<string name="delete_bookmark">즐겨찾기 삭제 </string>
<string name="bookmark_already_exists">즐겨찾기가 이미 존재합니다 </string>
diff --git a/src/main/res/values-nb-rNO/strings.xml b/src/main/res/values-nb-rNO/strings.xml
index 424eb2e0..55671015 100644
--- a/src/main/res/values-nb-rNO/strings.xml
+++ b/src/main/res/values-nb-rNO/strings.xml
@@ -223,7 +223,6 @@
<string name="contact_already_exists">Kontakten finnes allerede</string>
<string name="join">Ta del i</string>
<string name="conference_address">Konferanse-adresse</string>
- <string name="conference_address_example">rom@konferanse.eksempel.no</string>
<string name="save_as_bookmark">Lagre som bokmerke</string>
<string name="delete_bookmark">Slett bokmerke</string>
<string name="bookmark_already_exists">Dette bokmerket finnes allerede</string>
diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml
index 132e7200..4d55e33d 100644
--- a/src/main/res/values-nl/strings.xml
+++ b/src/main/res/values-nl/strings.xml
@@ -168,9 +168,9 @@
<string name="mgmt_account_delete">Account verwijderen</string>
<string name="mgmt_account_disable">Tijdelijk uitschakelen</string>
<string name="mgmt_account_publish_avatar">Avatar publiceren</string>
- <string name="mgmt_account_publish_pgp">Publiceer OpenPGP publieke sleutel</string>
- <string name="openpgp_has_been_published">Publieke OpenPGP-sleutel is gepubliceerd.</string>
- <string name="republish_pgp_keys">Vergeet niet je publieke OpenPGP-sleutels opnieuw te publiceren!</string>
+ <string name="mgmt_account_publish_pgp">OpenPGP-publieke sleutel publiceren</string>
+ <string name="openpgp_has_been_published">OpenPGP-publieke sleutel is gepubliceerd.</string>
+ <string name="republish_pgp_keys">Vergeet niet je OpenPGP-publieke sleutels opnieuw te publiceren!</string>
<string name="mgmt_account_enable">Account inschakelen</string>
<string name="mgmt_account_are_you_sure">Ben je zeker?</string>
<string name="mgmt_account_delete_confirm_text">Als je je account verwijdert wordt je volledige gespreksgeschiedenis gewist</string>
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Het contact bestaat al</string>
<string name="join">Deelnemen</string>
<string name="conference_address">Gespreksadres</string>
- <string name="conference_address_example">kamer@groepsgesprek.voorbeeld.be</string>
+ <string name="conference_address_example">ruimte@groepsgesprek.voorbeeld.be/naam</string>
<string name="save_as_bookmark">Opslaan als bladwijzer</string>
<string name="delete_bookmark">Bladwijzer verwijderen</string>
<string name="bookmark_already_exists">Deze bladwijzer bestaat al</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Wachtwoord nodig voor toegang tot groepsgesprek</string>
<string name="enter_password">Wachtwoord invoeren</string>
<string name="missing_presence_updates">Ontbrekende aanwezigheidsupdates van contact</string>
+ <string name="missing_presence_subscription">Geen aanwezigheidsupdates</string>
<string name="request_presence_updates">Vraag eerst aanwezigheidsupdates van je contact aan.\n\n<small>Dit wordt gebruikt om te bepalen welke client(s) je contact gebruikt.</small></string>
<string name="request_now">Nu aanvragen</string>
<string name="delete_fingerprint">Vingerafdruk verwijderen</string>
@@ -563,7 +564,7 @@
<string name="shared_text_with_x">Tekst gedeeld met %s</string>
<string name="no_storage_permission">Conversations heeft toegang nodig tot de externe opslag</string>
<string name="sync_with_contacts">Synchroniseer met contacten</string>
- <string name="sync_with_contacts_long">Conversations wil je XMPP-rooster met je contacten vergelijken om hun volledige namen en profielfoto\'s te tonen.\n\nConversations zal je contacten enkel lokaal lezen en vergelijken zonder ze te uploaden naar je server.\n\nJe zal nu gevraagd worden Conversations toegang te verlenen tot je contacten.</string>
+ <string name="sync_with_contacts_long">Conversations wil je XMPP-rooster met je contacten vergelijken om hun volledige namen en avatars te tonen.\n\nConversations zal je contacten enkel lokaal lezen en vergelijken zonder ze te uploaden naar je server.\n\nJe zal nu gevraagd worden Conversations toegang te verlenen tot je contacten.</string>
<string name="certificate_information">Certificaatinformatie</string>
<string name="certificate_subject">Onderwerp</string>
<string name="certificate_issuer">Uitgever</string>
@@ -595,8 +596,8 @@
<string name="security_error_invalid_file_access">Beveiligingsfout: Ongeldige bestandstoegang</string>
<string name="no_application_to_share_uri">Geen applicatie om URI te delen</string>
<string name="share_uri_with">URI delen met…</string>
- <string name="welcome_text">XMPP is een protocol onafhankelijk van de providers. Je kan deze toepassing gebruiken met eender welke XMPP-server.\nOm het eenvoudig te houden hebben we het makkelijk gemaakt een account aan te maken op conversations.im; een provider speciaal geschikt voor Conversations.</string>
- <string name="magic_create_text">We zullen je helpen een account op conversations.im aan te maken.\nWanneer je conversations.im als je provider kiest kan je met gebruikers van andere providers communiceren door hen je volledige Jabber-ID te geven.</string>
+ <string name="welcome_text">XMPP is een protocol onafhankelijk van de providers. Je kan deze cliënt gebruiken met eender welke XMPP-server.\nOm het eenvoudig te houden hebben we het makkelijk gemaakt een account aan te maken op conversations.im¹; een provider speciaal geschikt voor Conversations.</string>
+ <string name="magic_create_text">We zullen je helpen een account op conversations.im¹ aan te maken.\nWanneer je conversations.im als je provider kiest kan je met gebruikers van andere providers communiceren door hen je volledige Jabber-ID te geven.</string>
<string name="your_full_jid_will_be">Je volledige Jabber-ID zal %s zijn</string>
<string name="create_account">Account aanmaken</string>
<string name="use_own_provider">Gebruik mijn eigen provider</string>
@@ -650,7 +651,13 @@
<string name="remote_server_not_found">Externe server niet gevonden</string>
<string name="unable_to_update_account">Kan account niet bijwerken</string>
<string name="missing_presence_subscription_with_x">Geen aanwezigheidsupdates van %s.</string>
- <string name="missing_keys_from_x">Geen OMEMO sleutels van %s.</string>
+ <string name="missing_keys_from_x">Geen OMEMO-sleutels van %s.</string>
+ <string name="missing_omemo_keys">Geen OMEMO-sleutels</string>
<string name="wrong_conference_configuration">Dit is geen privé, niet-anoniem groepsgesprek.</string>
<string name="this_conference_has_no_members">Er neemt niemand deel aan dit groepsgesprek.</string>
+ <string name="report_jid_as_spammer">Rapporteer deze JID voor het sturen van ongewenste berichten</string>
+ <string name="pref_delete_omemo_identities">OMEMO-identiteiten verwijderen</string>
+ <string name="pref_delete_omemo_identities_summary">Maak je OMEMO-sleutels opnieuw aan. Al je contacten zullen je opnieuw moeten verifiëren. Gebruik dit enkel als een laatste reddingsmiddel.</string>
+ <string name="delete_selected_keys">Geselecteerde sleutels verwijderen</string>
+ <string name="error_publish_avatar_offline">Je moet verbonden zijn om je avatar te kunnen publiceren.</string>
</resources>
diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml
index cc9ce245..7cbb7655 100644
--- a/src/main/res/values-pl/strings.xml
+++ b/src/main/res/values-pl/strings.xml
@@ -238,7 +238,6 @@
<string name="contact_already_exists">Kontakt już istnieje</string>
<string name="join">Dołącz</string>
<string name="conference_address">Adres konferencji</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Dodaj jako zakładkę</string>
<string name="delete_bookmark">Usuń zakładkę</string>
<string name="bookmark_already_exists">Zakładka już istnieje</string>
@@ -583,8 +582,6 @@
<string name="security_error_invalid_file_access">Błąd bezpieczeństwa: nieprawidłowy dostęp do pliku</string>
<string name="no_application_to_share_uri">Nie odnaleziono aplikacji skojarzonej z URI</string>
<string name="share_uri_with">Udostępnij URI za pomocą...</string>
- <string name="welcome_text">XMPP jest protokołem niezależnym od dostawcy usług. Możesz używać tego klienta z dowolnym serwerem XMPP.\nJednak dla Twojej wygody ułatwiliśmy Ci stworzenie konta na conversations.im, serwerze specjalnie przystosowanym do używania z Conversations.</string>
- <string name="magic_create_text">Przeprowadzimy Cię przez proces tworzenia konta na conversations.im.\nKiedy wybierzesz konto na serwerze conversations.im, będziesz mógł komunikować się z użytkownikami na innych serwerach podając im swój pełen Jabber ID.</string>
<string name="your_full_jid_will_be">Twój pełen Jabber ID będzie następujący: %s</string>
<string name="create_account">Utwórz Konto</string>
<string name="use_own_provider">Użyj innego serwera</string>
diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml
index 789bdff3..4f66ba80 100644
--- a/src/main/res/values-pt-rBR/strings.xml
+++ b/src/main/res/values-pt-rBR/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Esse contato já existe</string>
<string name="join">Entrar</string>
<string name="conference_address">Endereço da conferência</string>
- <string name="conference_address_example">sala@conferencia.example.com</string>
+ <string name="conference_address_example">sala@conferencia.exemplo.com/apelido</string>
<string name="save_as_bookmark">Salvar como favorito</string>
<string name="delete_bookmark">Excluir o favorito</string>
<string name="bookmark_already_exists">Esse favorito já existe</string>
@@ -595,8 +595,8 @@
<string name="security_error_invalid_file_access">Erro de segurança: Acesso inválido ao arquivo</string>
<string name="no_application_to_share_uri">Não foi encontrada nenhuma aplicação para compartilhar a URI</string>
<string name="share_uri_with">Compartilhar a URI com...</string>
- <string name="welcome_text">O XMPP é um protocolo independente de provedor. Você pode usar esse cliente com qualquer servidor que você escolher.\nEntretanto, para sua conveniência, nós simplificamos o processo de criação de uma conta em conversations.im, um provedor especialmente configurado para usar com o Conversations.</string>
- <string name="magic_create_text">Nós guiaremos você ao longo do processo de criar uma conta em conversations.im.\nAo usar esse provedor você também poderá se comunicar com usuários de outros provedores. Basta fornecê-los a sua identificação Jabber completa.</string>
+ <string name="welcome_text">O XMPP é um protocolo independente de provedor. Você pode usar esse cliente com qualquer servidor que você escolher.\nEntretanto, para sua conveniência, nós simplificamos o processo de criação de uma conta em conversations.im¹, um provedor especialmente configurado para usar com o Conversations.</string>
+ <string name="magic_create_text">Nós guiaremos você ao longo do processo de criar uma conta em conversations.im.¹\nAo usar esse provedor você também poderá se comunicar com usuários de outros provedores. Basta fornecê-los a sua identificação Jabber completa.</string>
<string name="your_full_jid_will_be">Sua ID Jabber será: %s</string>
<string name="create_account">Criar conta</string>
<string name="use_own_provider">Usar meu próprio provedor</string>
@@ -653,4 +653,8 @@
<string name="missing_keys_from_x">Sem chaves OMEMO para %s.</string>
<string name="wrong_conference_configuration">Essa conferência não é privada nem anônima.</string>
<string name="this_conference_has_no_members">Não existem ninguém nessa conferência.</string>
+ <string name="report_jid_as_spammer">Informe que esse JID está enviando mensagens indesejáveis</string>
+ <string name="pref_delete_omemo_identities">Excluir identidades OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Regerar suas chaves OMEMO. Todos os seus contatos terão que verificá-lo novamente. Utilize isso somente como último recurso.</string>
+ <string name="delete_selected_keys">Excluir as chaves selecionadas</string>
</resources>
diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml
index bc8167ff..9d5bd169 100644
--- a/src/main/res/values-pt/strings.xml
+++ b/src/main/res/values-pt/strings.xml
@@ -237,7 +237,6 @@
<string name="contact_already_exists">O contacto já existe</string>
<string name="join">Juntar</string>
<string name="conference_address">Endereço da conferência</string>
- <string name="conference_address_example">sala@conferencia.example.com</string>
<string name="save_as_bookmark">Guardar como favorito</string>
<string name="delete_bookmark">Apagar favorito</string>
<string name="bookmark_already_exists">O favorito já existe</string>
diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml
index 0f6c5452..909b14d2 100644
--- a/src/main/res/values-ro-rRO/strings.xml
+++ b/src/main/res/values-ro-rRO/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Contactul exista deja</string>
<string name="join">Alatura-te</string>
<string name="conference_address">Adresa conferinta</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">camera@conferinta.exemplu.ro/nume_utilizator</string>
<string name="save_as_bookmark">Salveaza semn de carte</string>
<string name="delete_bookmark">Sterge semn de carte</string>
<string name="bookmark_already_exists">Acest semn de carte exista</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Conferinta necesita parola</string>
<string name="enter_password">Introdu parola</string>
<string name="missing_presence_updates">Au lipsit actualizarile de prezenta de la contact</string>
+ <string name="missing_presence_subscription">Lipseste abonarea de la actualizarea prezentei</string>
<string name="request_presence_updates">Te rog mai intai cere actualizari de prezente de la contact.\n\n<small>Asta va fi folosita pentru a determina ce aplicatii client foloseste contactul tau</small></string>
<string name="request_now">Cere acum</string>
<string name="delete_fingerprint">Sterge amprenta</string>
@@ -550,7 +551,7 @@
<string name="pref_use_tor_summary">Trimite toate conexiunile prin reteaua Tor. Necesita Orbot</string>
<string name="account_settings_hostname">Nume gazda</string>
<string name="account_settings_port">Port</string>
- <string name="hostname_or_onion">Adresa server- sau .onion</string>
+ <string name="hostname_or_onion">Adresa server sau .onion</string>
<string name="not_a_valid_port">Acesta nu este un numar de port valabil</string>
<string name="not_valid_hostname">Acesta nu este un nume de gazda valabila</string>
<string name="connected_accounts">%1$d din %2$d conturi conectate</string>
@@ -599,8 +600,8 @@ Emitent</string>
<string name="security_error_invalid_file_access">Eroare de securitate.: Acces fisier invalid</string>
<string name="no_application_to_share_uri">Nu s-a gasit nici o aplicatie care sa partajeze URI</string>
<string name="share_uri_with">Partajeaza URI cu...</string>
- <string name="welcome_text">XMPP este un protocol independent ce nu depinde de un anume furnizor. Aveți posibilitatea sa utilizati acest client cu orice server XMPP doriti.\nTotusi pentru confortul dumneavoastra am facilitat crearea unui cont pe conversations.im; un furnizor potrivit pentru utilizarea cu aplicatia Conversations.</string>
- <string name="magic_create_text">Va vom ghida prin procesul de creare al unui cont pe conversations.im.\nCand alegeti conversations.im ca furnizor veti putea comunica cu utilizatorii altor furnizori oferindu-le ID-ul dumneavoastra Jabber.</string>
+ <string name="welcome_text">XMPP este un protocol independent ce nu depinde de un anume furnizor. Aveți posibilitatea sa utilizati acest client cu orice server XMPP doriti.\nTotusi pentru confortul dumneavoastra am facilitat crearea unui cont pe conversations.im¹; un furnizor potrivit pentru utilizarea cu aplicatia Conversations.</string>
+ <string name="magic_create_text">Va vom ghida prin procesul de creare al unui cont pe conversations.im.¹\nCand alegeti conversations.im ca furnizor veti putea comunica cu utilizatorii altor furnizori oferindu-le ID-ul dumneavoastra Jabber.</string>
<string name="your_full_jid_will_be">ID-ul Jabber va fi: %s</string>
<string name="create_account">Creeaza cont</string>
<string name="use_own_provider">Foloseste furnizorul meu</string>
@@ -655,6 +656,12 @@ Emitent</string>
<string name="unable_to_update_account">Nu se poate actualiza contul</string>
<string name="missing_presence_subscription_with_x">Lipsesc actualizarile de prezenta cu %s.</string>
<string name="missing_keys_from_x">Cheie OMEMO lipsa din %s.</string>
+ <string name="missing_omemo_keys">Chei OMEMO lipsa</string>
<string name="wrong_conference_configuration">Aceasta este o conferinta care nu este privata si nu este anonima.</string>
<string name="this_conference_has_no_members">Conferinta nu are nici un membru.</string>
+ <string name="report_jid_as_spammer">Raporteaza ca aceasta identitate (JID) trimite mesaje nedorite.</string>
+ <string name="pref_delete_omemo_identities">Sterge identitatile OMEMO</string>
+ <string name="pref_delete_omemo_identities_summary">Regenereaza cheile personale OMEMO. Toate contactele vor fi obligate sa verifice cheile tale din nou. Foloseste asta ca o ultima optiune.</string>
+ <string name="delete_selected_keys">Sterge cheile selectate</string>
+ <string name="error_publish_avatar_offline">Pentru a putea publica avatarul trebuie sa existe o conexiune.</string>
</resources>
diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml
index c551962e..bc692996 100644
--- a/src/main/res/values-ru/strings.xml
+++ b/src/main/res/values-ru/strings.xml
@@ -6,7 +6,7 @@
<string name="action_end_conversation">Закончить текущую беседу</string>
<string name="action_contact_details">Сведения о контакте</string>
<string name="action_muc_details">Сведения о конференции</string>
- <string name="action_secure">Защищенная беседа</string>
+ <string name="action_secure">Защищённая беседа</string>
<string name="action_add_account">Добавить аккаунт</string>
<string name="action_edit_contact">Редактировать контакт</string>
<string name="action_add_phone_book">Добавить в адресную книгу</string>
@@ -15,20 +15,20 @@
<string name="action_unblock_contact">Разблокировать контакт</string>
<string name="action_block_domain">Заблокировать домен</string>
<string name="action_unblock_domain">Разблокировать домен</string>
- <string name="title_activity_manage_accounts">Управление Аккаунтами</string>
+ <string name="title_activity_manage_accounts">Управление аккаунтами</string>
<string name="title_activity_settings">Настройки</string>
- <string name="title_activity_conference_details">Сведения о Конференции</string>
- <string name="title_activity_contact_details">Сведения о Контакте</string>
+ <string name="title_activity_conference_details">Сведения о конференции</string>
+ <string name="title_activity_contact_details">Сведения о контакте</string>
<string name="title_activity_sharewith">Поделиться</string>
<string name="title_activity_start_conversation">Начать беседу</string>
<string name="title_activity_choose_contact">Выберите собеседника</string>
- <string name="title_activity_block_list">Черный список</string>
+ <string name="title_activity_block_list">Чёрный список</string>
<string name="just_now">только что</string>
<string name="minute_ago">1 минуту назад</string>
<string name="minutes_ago">%d мин. назад</string>
- <string name="unread_conversations">непрочитанных сообщений</string>
+ <string name="unread_conversations">сообщен. не прочитано</string>
<string name="sending">отправка…</string>
- <string name="message_decrypting">Расшифровка сообщения. Подождите...</string>
+ <string name="message_decrypting">Расшифровка сообщения. Подождите…</string>
<string name="pgp_message">OpenPGP зашифрованное сообщение</string>
<string name="nick_in_use">Имя уже используется</string>
<string name="admin">Администратор</string>
@@ -59,11 +59,11 @@
<string name="save">Сохранить</string>
<string name="ok">ОК</string>
<string name="crash_report_title">Conversations был неожиданно остановлен</string>
- <string name="crash_report_message">Отправляя отчеты об ошибках, вы помогаете исправить и улучшить программу, поддерживая дальнейшее развитие программы\n<b>Предупреждение:</b>Отчет об ошибке будет отправлен разработчику, используя ваш аккаунт XMPP.</string>
+ <string name="crash_report_message">Отправляя отчёты об ошибках, вы помогаете исправить и улучшить Conversations\n<b>Предупреждение:</b> Отчёт будет отправлен разработчику с вашего XMPP аккаунта. </string>
<string name="send_now">Отправить сейчас</string>
<string name="send_never">Больше не спрашивать</string>
- <string name="problem_connecting_to_account">Не удается подключиться к аккаунту</string>
- <string name="problem_connecting_to_accounts">Не удается подключиться к аккаунтам</string>
+ <string name="problem_connecting_to_account">Не удаётся подключиться к аккаунту</string>
+ <string name="problem_connecting_to_accounts">Не удаётся подключиться к аккаунтам</string>
<string name="touch_to_fix">Нажмите здесь, чтобы настроить свои аккаунты</string>
<string name="attach_file">Прикрепить файл</string>
<string name="not_in_roster">Контакт не находится в вашем списке. Хотите добавить его?</string>
@@ -72,55 +72,56 @@
<string name="send_rejected">отклонено</string>
<string name="preparing_image">Подготовка изображения к передаче</string>
<string name="preparing_images">Подготовка изображений для передачи</string>
- <string name="sharing_files_please_wait">Обмен файлами. Пожалуйста, подождите...</string>
+ <string name="sharing_files_please_wait">Обмен файлами. Пожалуйста, подождите…</string>
<string name="action_clear_history">Очистить историю</string>
<string name="clear_conversation_history">Очистить историю</string>
<string name="clear_histor_msg">Вы хотите удалить все сообщения в этой беседе?\n\n<b>Предупреждение:</b> Данная операция не повлияет на сообщения, хранящиеся на других устройствах.</string>
<string name="delete_messages">Удалить сообщения</string>
<string name="also_end_conversation">Закончить эту беседу впоследствии</string>
- <string name="send_unencrypted_message">Отправить нешифрованное сообщение</string>
- <string name="send_message_to_x">Отправить сообщение для %s</string>
- <string name="send_otr_message">Отправить OTR защифрованное сообщение</string>
- <string name="send_omemo_message">Отправить OMEMO защифрованное сообщение</string>
- <string name="send_omemo_x509_message">Послать v\\OMEMO зашифрованное сообщение</string>
- <string name="send_pgp_message">Отправить OpenPGP защифрованное сообщение</string>
- <string name="your_nick_has_been_changed">Ваш псевдоним был изменен</string>
+ <string name="choose_presence">Выберите устройство</string>
+ <string name="send_unencrypted_message">Нешифрованное сообщение</string>
+ <string name="send_message_to_x">Сообщение для %s</string>
+ <string name="send_otr_message">OTR зашифрованное сообщение</string>
+ <string name="send_omemo_message">OMEMO зашифрованное сообщение</string>
+ <string name="send_omemo_x509_message">v\\OMEMO зашифрованное сообщение</string>
+ <string name="send_pgp_message">OpenPGP зашифрованное сообщение</string>
+ <string name="your_nick_has_been_changed">Ваш псевдоним был изменён</string>
<string name="send_unencrypted">Отправить в незашифрованном виде</string>
<string name="decryption_failed">Расшифровка не удалась. Вероятно, что у вас нет надлежащего ключа.</string>
<string name="openkeychain_required">Установите OpenKeychain</string>
<string name="openkeychain_required_long">Conversations использует стороннее приложение под названием <b>OpenKeychain</b> для шифрования и расшифрования сообщений и управления открытыми ключами.\nПрограмма OpenKeychain распространяется под лицензией GPLv3 и доступна для загрузки через F-Droid или Google Play.\n\n<small>(Потребуется перезапуск Conversations после установки.)</small></string>
<string name="restart">Перезапуск</string>
<string name="install">Установка</string>
- <string name="openkeychain_not_installed">Установите OpenKeychain пожалуйста</string>
+ <string name="openkeychain_not_installed">Пожалуйста, установите OpenKeychain</string>
<string name="offering">предложение…</string>
<string name="waiting">ожидание…</string>
<string name="no_pgp_key">Нет OpenPGP ключа</string>
- <string name="contact_has_no_pgp_key">Conversations не может зашифровать сообщение, потому что удаленный пользователь не анонсирует свой открытый ключ.\n\n<small>Пожалуйста, попросите удаленного пользователя тоже установить OpenPGP.</small></string>
+ <string name="contact_has_no_pgp_key">Conversations не может зашифровать сообщение, потому что удалённый пользователь не анонсирует свой открытый ключ.\n\n<small>Пожалуйста, попросите удалённого пользователя установить OpenPGP.</small></string>
<string name="no_pgp_keys">Нет OpenPGP ключей</string>
- <string name="contacts_have_no_pgp_keys">Conversations не может зашифровать сообщения, потому что удаленные пользователи не анонсируют свои открытые ключи.\n\n<small>Пожалуйста, попросите удаленных пользователей тоже установить OpenPGP.</small></string>
+ <string name="contacts_have_no_pgp_keys">Conversations не может зашифровать сообщения, потому что удалённые пользователи не анонсируют свои открытые ключи.\n\n<small>Пожалуйста, попросите удалённых пользователей установить OpenPGP.</small></string>
<string name="pref_general">Общие</string>
<string name="pref_xmpp_resource">Название ресурса</string>
- <string name="pref_xmpp_resource_summary">Имя которым Conversations идентифицирует себя</string>
+ <string name="pref_xmpp_resource_summary">Имя, которым клиент идентифицирует себя</string>
<string name="pref_accept_files">Принимать файлы</string>
- <string name="pref_accept_files_summary">Автоматический прием файлов…</string>
+ <string name="pref_accept_files_summary">Автоматический приём файлов…</string>
<string name="pref_attachments">Вложения</string>
<string name="pref_return_to_previous">Быстрый обмен</string>
<string name="pref_return_to_previous_summary">Мгновенный возврат на предыдущий экран вместо открытия беседы после обмена</string>
<string name="pref_notification_settings">Уведомление</string>
- <string name="pref_notifications">Уведомление</string>
+ <string name="pref_notifications">Уведомления</string>
<string name="pref_notifications_summary">Использовать звуковое уведомление когда приходят новые сообщения</string>
<string name="pref_vibrate">Вибрация</string>
- <string name="pref_vibrate_summary">Вибирировать, когда приходят новые сообщения</string>
+ <string name="pref_vibrate_summary">Вибрировать, когда приходят новые сообщения</string>
<string name="pref_led">Светодиодное уведомление</string>
<string name="pref_led_summary">Мерцание индикатора при получении нового сообщения</string>
- <string name="pref_sound">Рингтон</string>
- <string name="pref_sound_summary">Воспроизводить звук, когда приходят новые сообщения</string>
+ <string name="pref_sound">Звук уведомления</string>
+ <string name="pref_sound_summary">Звук при поступлении новых сообщений</string>
<string name="pref_notification_grace_period">Грейс-период</string>
<string name="pref_notification_grace_period_summary">Промежуток времени, в течение которого Conversations хранит молчание при обнаружении активности на другом устройстве</string>
<string name="pref_advanced_options">Дополнительно</string>
- <string name="pref_never_send_crash">Отчеты об ошибках</string>
- <string name="pref_never_send_crash_summary">Отправляя отчеты об ошибках, вы помогаете исправить и улучшить Conversations, поддерживая дальнейшее развитие программы</string>
- <string name="pref_confirm_messages">Отчеты о получении</string>
+ <string name="pref_never_send_crash">Не отправлять отчёты об ошибках</string>
+ <string name="pref_never_send_crash_summary">Отправляя отчёты об ошибках, вы помогаете исправить и улучшить Conversations</string>
+ <string name="pref_confirm_messages">Отчёты о получении</string>
<string name="pref_confirm_messages_summary">Разрешить уведомлять отправителя, когда вы получили и прочитали сообщение</string>
<string name="pref_ui_options">Интерфейс</string>
<string name="openpgp_error">Возникла ошибка в OpenKeychain</string>
@@ -132,11 +133,11 @@
<string name="subscriptions">Подписки</string>
<string name="your_account">Ваш аккаунт</string>
<string name="keys">Ключи</string>
- <string name="send_presence_updates">Анонсировать статус присутствия</string>
- <string name="receive_presence_updates">Получать обновления статусов присутствия</string>
- <string name="ask_for_presence_updates">Запрашивать обновления статусов присутствия</string>
- <string name="attach_choose_picture">Выберите изображение</string>
- <string name="attach_take_picture">Снимите изображение</string>
+ <string name="send_presence_updates">Отправлять присутствие</string>
+ <string name="receive_presence_updates">Получать присутствие</string>
+ <string name="ask_for_presence_updates">Запрашивать присутствие</string>
+ <string name="attach_choose_picture">Выбрать изображение</string>
+ <string name="attach_take_picture">Сделать снимок</string>
<string name="preemptively_grant">Удовлетворять запросы на подписки</string>
<string name="error_not_an_image_file">Выбранный файл не является изображением</string>
<string name="error_compressing_image">Ошибка при преобразовании изображения</string>
@@ -144,7 +145,7 @@
<string name="error_io_exception">Общая ошибка ввода/вывода. Возможно, на устройстве недостаточно свободного места?</string>
<string name="error_security_exception_during_image_copy">Приложение, которое было использовано для выбора изображения не имеет достаточных прав для чтения файла.\n\n<small>Используйте другой файловый менеджер, чтобы выбрать изображение</small></string>
<string name="account_status_unknown">Неизвестен</string>
- <string name="account_status_disabled">Временно отключен</string>
+ <string name="account_status_disabled">Временно отключён</string>
<string name="account_status_online">В сети</string>
<string name="account_status_connecting">Соединение\u2026</string>
<string name="account_status_offline">Не в сети</string>
@@ -156,30 +157,32 @@
<string name="account_status_regis_success">Регистрация завершена</string>
<string name="account_status_regis_not_sup">Сервер не поддерживает регистрацию</string>
<string name="account_status_security_error">Ошибка безопасности</string>
+ <string name="account_status_policy_violation">Нарушение правил</string>
<string name="account_status_incompatible_server">Несовместимый сервер</string>
+ <string name="account_status_stream_error">Ошибка потока</string>
<string name="encryption_choice_unencrypted">Без шифра</string>
<string name="encryption_choice_otr">OTR</string>
<string name="encryption_choice_pgp">OpenPGP</string>
<string name="encryption_choice_omemo">OMEMO</string>
<string name="mgmt_account_edit">Редактировать аккаунт</string>
- <string name="mgmt_account_delete">Удалить</string>
- <string name="mgmt_account_disable">Отключить</string>
+ <string name="mgmt_account_delete">Удалить аккаунт</string>
+ <string name="mgmt_account_disable">Временно отключить</string>
<string name="mgmt_account_publish_avatar">Разместить аватар</string>
<string name="mgmt_account_publish_pgp">Анонсировать OpenPGP ключ</string>
<string name="openpgp_has_been_published">Открытый ключ OpenPGP был опубликован.</string>
<string name="republish_pgp_keys">Не забудьте повторно анонсировать свои OpenPGP ключи!</string>
- <string name="mgmt_account_enable">Включить</string>
+ <string name="mgmt_account_enable">Включить аккаунт</string>
<string name="mgmt_account_are_you_sure">Вы уверены?</string>
<string name="mgmt_account_delete_confirm_text">Если вы удалите свой аккаунт, вся ваша история будет потеряна</string>
<string name="attach_record_voice">Запись голоса</string>
- <string name="account_settings_jabber_id">JID (Джаббер ID)</string>
+ <string name="account_settings_jabber_id">Jabber ID</string>
<string name="account_settings_password">Пароль</string>
<string name="account_settings_example_jabber_id">username@example.com</string>
<string name="account_settings_confirm_password">Подтвердите пароль</string>
<string name="password">Пароль</string>
<string name="confirm_password">Подтвердите пароль</string>
<string name="passwords_do_not_match">Пароли не совпадают</string>
- <string name="invalid_jid">Недопустимый JID (Джаббер ID)</string>
+ <string name="invalid_jid">Недопустимый Jabber ID</string>
<string name="error_out_of_memory">Недостаточно памяти. Изображение слишком большое</string>
<string name="add_phone_book_text">Вы хотите добавить %s в вашу адресную книгу?</string>
<string name="contact_status_online">в сети</string>
@@ -191,17 +194,17 @@
<string name="muc_details_conference">Конференция</string>
<string name="muc_details_other_members">Другие участники</string>
<string name="server_info_show_more">Информация о сервере</string>
- <string name="server_info_mam">XEP-0313: Сохранение сообщений в архив</string>
- <string name="server_info_carbon_messages">Дублирование сообщений</string>
- <string name="server_info_csi">XEP-0352: Индикатор Состояния Клиента</string>
- <string name="server_info_blocking">XEP-0191: Команда Блокирования</string>
- <string name="server_info_roster_version">XEP-0237: Управление версиями списков</string>
+ <string name="server_info_mam">XEP-0313: Архив сообщений</string>
+ <string name="server_info_carbon_messages">XEP-0280: Дублиров. сообщений</string>
+ <string name="server_info_csi">XEP-0352: Состояние клиента</string>
+ <string name="server_info_blocking">XEP-0191: Команда блокирования</string>
+ <string name="server_info_roster_version">XEP-0237: Версии списков</string>
<string name="server_info_stream_management">XEP-0198: Управление потоками</string>
<string name="server_info_pep">XEP-0163: PEP (Аватары / OMEMO)</string>
- <string name="server_info_http_upload">XEP-0363: Загрузка файлов по HTTP</string>
- <string name="server_info_push">XEP-0357: Push уведомления</string>
- <string name="server_info_available">доступен</string>
- <string name="server_info_unavailable">недоступен</string>
+ <string name="server_info_http_upload">XEP-0363: Загрузка по HTTP</string>
+ <string name="server_info_push">XEP-0357: Push-уведомления</string>
+ <string name="server_info_available">доступно</string>
+ <string name="server_info_unavailable">недоступно</string>
<string name="missing_public_keys">Отсутствие анонсирования открытых ключей</string>
<string name="last_seen_now">Присутствие: только что</string>
<string name="last_seen_min">Присутствие: 1 минуту назад</string>
@@ -210,13 +213,15 @@
<string name="last_seen_hours">Присутствие: %d час. назад</string>
<string name="last_seen_day">Присутствие: 1 день назад</string>
<string name="last_seen_days">Присутствие: %d дн. назад</string>
- <string name="never_seen">Никогда</string>
- <string name="install_openkeychain">Зашифрованное сообщение. Пожалуйста, установите OpenKeychain для дешифрования.</string>
- <string name="unknown_otr_fingerprint">Неизвестная контрольная сумма криптографического протокола OTR</string>
+ <string name="never_seen">никогда</string>
+ <string name="install_openkeychain">Зашифрованное сообщение. Пожалуйста, установите OpenKeychain для расшифрования.</string>
+ <string name="unknown_otr_fingerprint">Неизвестный отпечаток OTR</string>
<string name="openpgp_messages_found">Найдены OpenPGP зашифрованые сообщения</string>
- <string name="reception_failed">Прием не удался</string>
- <string name="your_fingerprint">Контрольная сумма</string>
- <string name="otr_fingerprint">OTR контрольная сумма</string>
+ <string name="reception_failed">Приём не удался</string>
+ <string name="your_fingerprint">Ваш отпечаток</string>
+ <string name="otr_fingerprint">OTR отпечаток</string>
+ <string name="otr_fingerprint_selected_message">OTR отпечаток сообщения</string>
+ <string name="openpgp_key_id">ID OpenPGP ключа</string>
<string name="omemo_fingerprint">OMEMO отпечаток</string>
<string name="omemo_fingerprint_x509">v\\OMEMO отпечаток</string>
<string name="omemo_fingerprint_selected_message">OMEMO отпечаток сообщения</string>
@@ -227,29 +232,29 @@
<string name="fetching_keys">Получение ключей…</string>
<string name="done">Готово</string>
<string name="verify">Подтвердить</string>
- <string name="decrypt">Дешифровать</string>
+ <string name="decrypt">Расшифровать</string>
<string name="conferences">Конференции</string>
<string name="search">Поиск</string>
- <string name="create_contact">Создать контакт</string>
+ <string name="create_contact">Новый контакт</string>
<string name="enter_contact">Добавить контакт</string>
<string name="join_conference">Присоединиться к конференции</string>
- <string name="delete_contact">Удалить Контакт</string>
+ <string name="delete_contact">Удалить контакт</string>
<string name="view_contact_details">Посмотреть данные контакта</string>
<string name="block_contact">Заблокировать контакт</string>
<string name="unblock_contact">Разблокировать контакт</string>
<string name="create">Создать</string>
- <string name="select">Select</string>
+ <string name="select">Выбрать</string>
<string name="contact_already_exists">Контакт уже существует</string>
<string name="join">Присоединиться</string>
<string name="conference_address">Адрес конференции</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Сохранить закладку</string>
<string name="delete_bookmark">Удалить закладку</string>
<string name="bookmark_already_exists">Такая закладка уже существует</string>
<string name="you">Вы</string>
<string name="action_edit_subject">Редактировать тему конференции</string>
<string name="edit_subject_hint">Тема конференции</string>
- <string name="joining_conference">Вход в конференцию...</string>
+ <string name="joining_conference">Вход в конференцию…</string>
<string name="leave">Покинуть</string>
<string name="contact_added_you">Собеседник добавил вас в список контактов</string>
<string name="add_back">Добавить в ответ</string>
@@ -263,11 +268,11 @@
<string name="error_saving_avatar">Не удалось сохранить аватар</string>
<string name="or_long_press_for_default">(Или долгое прикосновение, чтобы вернуть значения по умолчанию)</string>
<string name="error_publish_avatar_no_server_support">Ваш сервер не поддерживает публикацию аватаров</string>
- <string name="private_message">Отправить личное сообщение для %s</string>
+ <string name="private_message">шёпот</string>
<string name="private_message_to">отправить %s</string>
<string name="send_private_message_to">Отправить личное сообщение для %s</string>
<string name="connect">Подключиться</string>
- <string name="account_already_exists">Эта учетная запись уже существует</string>
+ <string name="account_already_exists">Аккаунт уже существует</string>
<string name="next">Далее</string>
<string name="server_info_session_established">Текущий сеанс установлен</string>
<string name="additional_information">Дополнительная информация</string>
@@ -278,11 +283,12 @@
<string name="conference_requires_password">Конференция требует авторизации</string>
<string name="enter_password">Введите пароль</string>
<string name="missing_presence_updates">Обновления присутствия недоступны</string>
+ <string name="missing_presence_subscription">Отсутствует подписка</string>
<string name="request_presence_updates">Пожалуйста, прежде запросите обновления присутствия у вашего собеседника.\n\n<small>Эта информация будет использоваться для определения того, каким клиентом(ами) пользуетя ваш собеседник.</small></string>
<string name="request_now">Запросить сейчас</string>
- <string name="delete_fingerprint">Удалить Контрольную Сумму</string>
- <string name="sure_delete_fingerprint">Вы уверены, что хотите удалить данную контрольную сумму?</string>
- <string name="ignore">Отменить</string>
+ <string name="delete_fingerprint">Удалить отпечаток</string>
+ <string name="sure_delete_fingerprint">Вы уверены, что хотите удалить данный отпечаток?</string>
+ <string name="ignore">Игнорировать</string>
<string name="without_mutual_presence_updates"><b>Внимание:</b> Если обновления присутствия не включены на обеих сторонах, это может привести к возникновению неожиданных проблемам.\n\n<small>Уточните сведения о контакте, проверив настройки обновлений присутствия.</small></string>
<string name="pref_security_settings">Безопасность</string>
<string name="pref_force_encryption">Обязательное сквозное шифрование</string>
@@ -295,7 +301,7 @@
<string name="pref_expert_options_summary">Пожалуйста, будьте осторожны с данными настройками</string>
<string name="title_activity_about">О Conversations</string>
<string name="pref_about_conversations_summary">Информация о билде и лицензировании</string>
- <string name="title_pref_quiet_hours">Тихие Часы</string>
+ <string name="title_pref_quiet_hours">Тихие часы</string>
<string name="title_pref_quiet_hours_start_time">Начало</string>
<string name="title_pref_quiet_hours_end_time">Окончание</string>
<string name="title_pref_enable_quiet_hours">Включить режим «тихих часов»</string>
@@ -304,13 +310,13 @@
<string name="pref_use_larger_font_summary">Установите больший размер шрифта по всей программе</string>
<string name="pref_use_send_button_to_indicate_status">Использовать кнопку-индикатор</string>
<string name="pref_use_indicate_received">Запрос в получении сообщения</string>
- <string name="pref_use_indicate_received_summary">Если поддерживается, поступившие сообщения будут отмечены зеленой галочкой</string>
+ <string name="pref_use_indicate_received_summary">Если поддерживается, поступившие сообщения будут отмечены зелёной галочкой</string>
<string name="pref_use_send_button_to_indicate_status_summary">Раскрасить кнопку отправить, указывая текущий статус собеседника</string>
<string name="pref_expert_options_other">Другие</string>
<string name="pref_conference_name">Название конференции</string>
<string name="pref_conference_name_summary">Использовать тему беседы заместо JID для отображения конференций</string>
<string name="pref_autojoin">Автоматический вход в конференции</string>
- <string name="pref_autojoin_summary">Автоматический вход в конференции</string>
+ <string name="pref_autojoin_summary">Автоматически входить в конференции при установленном флаге автовхода закладки</string>
<string name="toast_message_otr_fingerprint">OTR-отпечаток скопирован в буфер обмена!</string>
<string name="toast_message_omemo_fingerprint">OMEMO отпечаток скопирован в буфер обмена!</string>
<string name="conference_banned">Вы заблокированы в этой конференции</string>
@@ -318,11 +324,11 @@
<string name="conference_kicked">Вы были удалены из конференции</string>
<string name="conference_shutdown">Конференция была остановлена</string>
<string name="conference_unknown_error">Вы больше не состоите в конференции</string>
- <string name="using_account">использовать учётную запись %s</string>
+ <string name="using_account">используется аккаунт %s</string>
<string name="checking_x">Проверка %s на сервере HTTP</string>
<string name="not_connected_try_again">Вы неподключены. Попробуйте позже</string>
- <string name="check_x_filesize">Проверьте размер %s</string>
- <string name="check_x_filesize_on_host">Проверьте размер %1$s на %2$s</string>
+ <string name="check_x_filesize">Проверить размер %s</string>
+ <string name="check_x_filesize_on_host">Проверить размер %1$s на %2$s</string>
<string name="message_options">Опции сообщения</string>
<string name="copy_text">Копировать текст</string>
<string name="select_text">Выбрать текст</string>
@@ -353,13 +359,15 @@
<string name="verified">Подтверждён!</string>
<string name="smp_requested">Контакт запросил подтверждение SMP</string>
<string name="no_otr_session_found">Действительная OTR-сессия не найдена!</string>
- <string name="conversations_foreground_service">Диалоги</string>
+ <string name="conversations_foreground_service">Conversations</string>
<string name="pref_keep_foreground_service">Оставить службу на переднем плане</string>
<string name="pref_keep_foreground_service_summary">Не позволяет операционной системе закрыть ваше соединение</string>
+ <string name="pref_export_logs">Экспорт истории</string>
+ <string name="pref_export_logs_summary">Записать историю бесед на SD карту</string>
<string name="notification_export_logs_title">Запись истории на SD карту</string>
- <string name="choose_file">Выберите файл</string>
- <string name="receiving_x_file">Получение %1$s (%2$d%% выполнено)</string>
- <string name="download_x_file">Загружено %s</string>
+ <string name="choose_file">Выбрать файл</string>
+ <string name="receiving_x_file">%1$s загружается (%2$d%% выполнено)</string>
+ <string name="download_x_file">Загрузить %s</string>
<string name="delete_x_file">Удалить %s</string>
<string name="file">файл</string>
<string name="open_x_file">Открыть %s</string>
@@ -376,12 +384,12 @@
<string name="pref_show_dynamic_tags">Показывать динамические тэги</string>
<string name="pref_show_dynamic_tags_summary">Отображать теги только для чтения под контактами</string>
<string name="enable_notifications">Включить уведомления</string>
- <string name="conference_with">Создать конференцию с...</string>
+ <string name="conference_with">Создать конференцию с…</string>
<string name="no_conference_server_found">Сервер конференции не был найден</string>
<string name="conference_creation_failed">Не удалось создать конференцию!</string>
<string name="secret_accepted">Секретный ключ принят!</string>
<string name="reset">Сброс</string>
- <string name="account_image_description">Изображение учётной записи</string>
+ <string name="account_image_description">Аватар аккаунта</string>
<string name="copy_otr_clipboard_description">Скопировать OTR-отпечаток в буфер обмена</string>
<string name="copy_omemo_clipboard_description">Скопировать OMEMO-отпечаток в буфер обмена</string>
<string name="regenerate_omemo_key">Создать заново ключ OMEMO</string>
@@ -396,7 +404,7 @@
<string name="error_trustkeys_title">Ошибка</string>
<string name="fetching_history_from_server">Получение истории с сервера</string>
<string name="no_more_history_on_server">На сервере больше нет истории</string>
- <string name="updating">Обновление...</string>
+ <string name="updating">Обновление…</string>
<string name="password_changed">Пароль изменён!</string>
<string name="could_not_change_password">Не удалось изменить пароль</string>
<string name="otr_session_not_started">Отправить сообщение чтобы начать зашифрованный чат</string>
@@ -410,17 +418,17 @@
<string name="current_password">Текущий пароль</string>
<string name="new_password">Новый пароль</string>
<string name="password_should_not_be_empty">Пароль не может быть пустым</string>
- <string name="enable_all_accounts">Включить все учётные записи</string>
- <string name="disable_all_accounts">Отключить все учётные записи</string>
+ <string name="enable_all_accounts">Включить все аккаунты</string>
+ <string name="disable_all_accounts">Отключить все аккаунты</string>
<string name="perform_action_with">Взаимодействовать с</string>
- <string name="no_affiliation">Не является участником</string>
+ <string name="no_affiliation">Посетитель</string>
<string name="no_role">Не в сети</string>
- <string name="outcast">Заблокированный пользователь</string>
+ <string name="outcast">Заблокирован</string>
<string name="member">Участник</string>
<string name="advanced_mode">Расширенный режим</string>
<string name="grant_membership">Предоставить участие</string>
<string name="remove_membership">Отменить участие</string>
- <string name="grant_admin_privileges">Назначить административные права</string>
+ <string name="grant_admin_privileges">Назначить администратором</string>
<string name="remove_admin_privileges">Снять административные права</string>
<string name="remove_from_room">Исключить из конференции</string>
<string name="could_not_change_affiliation">Не удалось изменить принадлежность %s</string>
@@ -429,10 +437,10 @@
<string name="ban_now">Заблокировать</string>
<string name="could_not_change_role">Не удалось сменить роль %s</string>
<string name="public_conference">Публичная конференция</string>
- <string name="private_conference">Приватная конференция только для членов</string>
+ <string name="private_conference">Приватная конференция</string>
<string name="conference_options">Настройки конференции</string>
- <string name="members_only">Частная, только для участников</string>
- <string name="non_anonymous">Не анонимно </string>
+ <string name="members_only">Приватная</string>
+ <string name="non_anonymous">Неанонимная</string>
<string name="moderated">Модерируемая</string>
<string name="you_are_not_participating">Вы не участвуете</string>
<string name="modified_conference_options">Настройки конференции изменены!</string>
@@ -461,7 +469,7 @@
<string name="sending_x_file">Отправляется %s</string>
<string name="offering_x_file">Предложен %s</string>
<string name="hide_offline">Скрыть пользователей вне сети</string>
- <string name="disable_account">Отключить учётную запись</string>
+ <string name="disable_account">Отключить аккаунт</string>
<string name="contact_is_typing">%s печатает…</string>
<string name="contact_has_stopped_typing">%s прекратил набор</string>
<string name="pref_chat_states">Оповещения о наборе</string>
@@ -472,24 +480,24 @@
<string name="location">Местоположение</string>
<string name="received_location">Получено местоположение</string>
<string name="title_undo_swipe_out_conversation">Беседа окончена</string>
- <string name="title_undo_swipe_out_muc">Покинул беседу</string>
+ <string name="title_undo_swipe_out_muc">Выход из конференции</string>
<string name="pref_dont_trust_system_cas_title">Не доверять системным УЦ</string>
<string name="pref_dont_trust_system_cas_summary">Все сертификаты должны быть подтверждены вручную</string>
- <string name="pref_remove_trusted_certificates_title">Удалить сертификат</string>
+ <string name="pref_remove_trusted_certificates_title">Удалить сертификаты</string>
<string name="pref_remove_trusted_certificates_summary">Удалить сертификаты, подтверждённые вручную</string>
<string name="toast_no_trusted_certs">Не найдено сертификатов, подтверждённых вручную</string>
<string name="dialog_manage_certs_title">Удалить сертификаты</string>
- <string name="dialog_manage_certs_positivebutton">Удалить отмеченное</string>
+ <string name="dialog_manage_certs_positivebutton">Удалить отмеченные</string>
<string name="dialog_manage_certs_negativebutton">Отмена</string>
<plurals name="toast_delete_certificates">
<item quantity="one">Удалён %d сертификат</item>
- <item quantity="few">Удалено %d сертификатов</item>
+ <item quantity="few">Удалено %d сертификата</item>
<item quantity="many">Удалено %d сертификатов</item>
<item quantity="other">Удалено %d сертификатов</item>
</plurals>
<plurals name="select_contact">
<item quantity="one">Выбран %d контакт</item>
- <item quantity="few">Выбрано %d контактов</item>
+ <item quantity="few">Выбрано %d контакта</item>
<item quantity="many">Выбрано %d контактов</item>
<item quantity="other">Выбрано %d контактов</item>
</plurals>
@@ -511,17 +519,18 @@
<string name="download_failed_could_not_connect">Загрузка не удалась: не удалось подключиться к серверу</string>
<string name="download_failed_could_not_write_file">Загрузка не удалась: ошибка записи файла</string>
<string name="pref_use_white_background">Использовать белый фон</string>
- <string name="pref_use_white_background_summary">Показывать принятые сообщения черным текстом на белом фоне</string>
+ <string name="pref_use_white_background_summary">Показывать принятые сообщения чёрным текстом на белом фоне</string>
<string name="account_status_tor_unavailable">Сеть Tor недоступна</string>
<string name="account_status_bind_failure">Ошибка связывания</string>
+ <string name="account_status_host_unknown">Сервер не ответственен за домен</string>
<string name="server_info_broken">Повреждено</string>
<string name="pref_presence_settings">Присутствие</string>
<string name="pref_away_when_screen_off">Вышел когда экран выключен</string>
- <string name="pref_away_when_screen_off_summary">Отмечает ваш ресурс как \"вышел\" когда экран выключен</string>
+ <string name="pref_away_when_screen_off_summary">Отмечает ваш ресурс как «вышел» когда экран выключен</string>
<string name="pref_xa_on_silent_mode">Не доступен в режиме без звука</string>
- <string name="pref_xa_on_silent_mode_summary">Отмечает ваш ресурс как \"не доступен\", когда телефон в беззвучном режиме</string>
+ <string name="pref_xa_on_silent_mode_summary">Отмечает ваш ресурс как «не доступен», когда телефон в беззвучном режиме</string>
<string name="pref_treat_vibrate_as_silent">Не доступен в режиме вибрации</string>
- <string name="pref_treat_vibrate_as_silent_summary">Отмечает ваш ресурс как \"не доступен\", когда телефон в режиме вибрации</string>
+ <string name="pref_treat_vibrate_as_silent_summary">Отмечает ваш ресурс как «не доступен», когда телефон в режиме вибрации</string>
<string name="pref_show_connection_options">Расширенные настройки подключения</string>
<string name="pref_show_connection_options_summary">Показывать имя сервера и порт в настройках аккаунтов</string>
<string name="hostname_example">xmpp.example.com</string>
@@ -542,10 +551,10 @@
<string name="device_does_not_support_certificates">Ваше устройство не поддерживает выбор клиентских сертификатов!</string>
<string name="pref_connection_options">Подключение</string>
<string name="pref_use_tor">Соединение через Tor</string>
- <string name="pref_use_tor_summary">Направить все соединения через сеть TOR. Требуется Orbot</string>
+ <string name="pref_use_tor_summary">Направить все соединения через сеть Tor. Требуется Orbot</string>
<string name="account_settings_hostname">Имя сервера</string>
<string name="account_settings_port">Порт</string>
- <string name="hostname_or_onion">Сервер- или .onion-Адрес</string>
+ <string name="hostname_or_onion">Сервер- или .onion-адрес</string>
<string name="not_a_valid_port">Это недопустимый номер порта</string>
<string name="not_valid_hostname">Это недопустимое имя сервера</string>
<string name="connected_accounts">%1$d из %2$d аккаунтов соединены</string>
@@ -571,9 +580,9 @@
<string name="certificate_sha1">SHA-1</string>
<string name="certicate_info_not_available">(недоступно)</string>
<string name="certificate_not_found">Сертификатов не найдено</string>
- <string name="notify_on_all_messages">Уведомлять о всех сообщениях</string>
- <string name="notify_only_when_highlighted">Оповещение только при обращениях</string>
- <string name="notify_never">Уведомления запрещены</string>
+ <string name="notify_on_all_messages">Все сообщения</string>
+ <string name="notify_only_when_highlighted">При обращении</string>
+ <string name="notify_never">Без уведомления</string>
<string name="notify_paused">Уведомления приостановлены</string>
<string name="pref_picture_compression">Сжать изображения</string>
<string name="pref_picture_compression_summary">Изменить размер и сжать изображения</string>
@@ -588,16 +597,16 @@
<string name="this_field_is_required">Незаполненное поле</string>
<string name="correct_message">Исправить сообщение</string>
<string name="send_corrected_message">Отправить исправленное сообщение</string>
- <string name="no_keys_just_confirm">Вы уже доверяете этому контакту. Выбрав \'готово\', вы только подтвердите, что %s является участником конференции.</string>
+ <string name="no_keys_just_confirm">Вы уже доверяете этому контакту. Выбрав «готово», вы только подтвердите, что %s является участником конференции.</string>
<string name="select_image_and_crop">Выбрать изображение</string>
<string name="this_account_is_disabled">Вы отключили этот аккаунт</string>
<string name="security_error_invalid_file_access">Ошибка безопасности: недействительный доступ к файлу</string>
<string name="no_application_to_share_uri">Не найдено приложения для отправки</string>
<string name="share_uri_with">Отправить URI…</string>
- <string name="welcome_text">Протокол XMPP не зависит от провайдера. Вы можете выбрать любой другой сервер XMPP.\nОднако, для удобства мы упростили процедуру создания аккаунта на conversations.im; данный провайдер максимально подходит для использования с Conversations.</string>
- <string name="magic_create_text">Мы поможем создать аккаунт на conversations.im\nВыбрав conversations.im в качестве провайдера, вы сможете общаться с пользователями других провайдеров, сообщив им свой полный Jabber ID.</string>
+ <string name="welcome_text">XMPP — независимый протокол. Вы можете использовать клиент для работы с любым XMPP сервером.\nОднако, для Вашего удобства мы упростили процедуру создания аккаунта на conversations.im¹; данный провайдер максимально подходит для использования с Conversations.</string>
+ <string name="magic_create_text">Мы поможем Вам создать аккаунт на conversations.im¹.\nВыбрав conversations.im в качестве провайдера, вы сможете общаться с пользователями других провайдеров, сообщив им свой полный Jabber ID.</string>
<string name="your_full_jid_will_be">Ваш полный Jabber ID: %s</string>
- <string name="create_account">Создать Аккаунт</string>
+ <string name="create_account">Создать аккаунт</string>
<string name="use_own_provider">Использовать свой провайдер</string>
<string name="pick_your_username">Выберите имя пользователя</string>
<string name="pref_manually_change_presence">Ручная смена присутствия</string>
@@ -614,6 +623,7 @@
<string name="device_does_not_support_battery_op">Ваше устройство не поддерживает отключение оптимизации энергопотребления</string>
<string name="show_password">Показать пароль</string>
<string name="registration_please_wait">Регистрация не удалась: повторите попытку позднее</string>
+ <string name="registration_password_too_weak">Регистрация не удалась: слишком слабый пароль</string>
<string name="create_conference">Создать конференцию</string>
<string name="join_or_create_conference">Присоединиться или создать конференцию</string>
<string name="conference_subject">Тема</string>
@@ -630,6 +640,31 @@
<string name="pref_theme_options_summary">Выбрать цветовую палитру</string>
<string name="pref_theme_light">Светлая тема</string>
<string name="pref_theme_dark">Тёмная тема</string>
- <string name="pref_use_green_background">Зелёный Фон</string>
+ <string name="pref_use_green_background">Зелёный фон</string>
<string name="pref_use_green_background_summary">Использовать зелёный фон для полученных сообщений</string>
+ <string name="unable_to_connect_to_keychain">Не удаётся подключиться к OpenKeychain</string>
+ <string name="this_device_is_no_longer_in_use">Данное устройство больше не используется</string>
+ <string name="type_pc">Компьютер</string>
+ <string name="type_phone">Телефон</string>
+ <string name="type_tablet">Планшет</string>
+ <string name="type_web">Веб браузер</string>
+ <string name="type_console">Консоль</string>
+ <string name="payment_required">Требуется оплата</string>
+ <string name="missing_internet_permission">Доступ в интернет запрещён</string>
+ <string name="me">Я</string>
+ <string name="contact_asks_for_presence_subscription">Контакт запрашивает подписку</string>
+ <string name="allow">Разрешить</string>
+ <string name="no_permission_to_access_x">Нет доступа к %s</string>
+ <string name="remote_server_not_found">Удалённый сервер не найден</string>
+ <string name="unable_to_update_account">Невозможно обновить аккаунт</string>
+ <string name="missing_presence_subscription_with_x">Отсутствует подписка на %s</string>
+ <string name="missing_keys_from_x">Отсутствуют OMEMO ключи %s</string>
+ <string name="missing_omemo_keys">Отсутствуют OMEMO ключи</string>
+ <string name="wrong_conference_configuration">Неприватная неанонимная конференция.</string>
+ <string name="this_conference_has_no_members">Конференция пуста.</string>
+ <string name="report_jid_as_spammer">Отправить жалобу на нежелательные сообщения.</string>
+ <string name="pref_delete_omemo_identities">Удалить OMEMO ключи</string>
+ <string name="pref_delete_omemo_identities_summary">Создать заново OMEMO ключи. Необходимо повторное подтверждение. Используйте только в крайнем случае.</string>
+ <string name="delete_selected_keys">Удалить отмеченные</string>
+ <string name="error_publish_avatar_offline">Вы должны подключиться для публикации аватара.</string>
</resources>
diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml
index a850e802..a1c3e89c 100644
--- a/src/main/res/values-sk/strings.xml
+++ b/src/main/res/values-sk/strings.xml
@@ -212,7 +212,6 @@
<string name="contact_already_exists">Kontakt už existuje</string>
<string name="join">Vstúpiť</string>
<string name="conference_address">Adresa</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Uložiť ako záložku</string>
<string name="delete_bookmark">Vymazať záložku</string>
<string name="bookmark_already_exists">Táto záložka už existuje</string>
diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml
index fee1842e..46723f17 100644
--- a/src/main/res/values-sr/strings.xml
+++ b/src/main/res/values-sr/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Контакт већ постоји</string>
<string name="join">Придружи се</string>
<string name="conference_address">Адреса групног ћаскања</string>
- <string name="conference_address_example">soba@konferencija.primer.com</string>
+ <string name="conference_address_example">soba@konferencija.primer.com/nadimak</string>
<string name="save_as_bookmark">Сачувај као обележивач</string>
<string name="delete_bookmark">Обриши обележивач</string>
<string name="bookmark_already_exists">Овај обележивач већ постоји</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Групно ћаскање захтева лозинку</string>
<string name="enter_password">Унесите лозинку</string>
<string name="missing_presence_updates">Нема ажуриране присутности од контакта</string>
+ <string name="missing_presence_subscription">Нема претплате на присутност</string>
<string name="request_presence_updates">Најпре захтевајте ажурирање присутности од вашег контакта.\n\n<small>Ово ће омогућити да се одреди којег клијента ваш контакт користи.</small></string>
<string name="request_now">Захтевај одмах</string>
<string name="delete_fingerprint">Обриши отисак</string>
@@ -598,8 +599,6 @@
<string name="security_error_invalid_file_access">Безбедносна грешка: неисправан приступ фајлу</string>
<string name="no_application_to_share_uri">Нема апликације за дељење веза</string>
<string name="share_uri_with">Подели везу помоћу…</string>
- <string name="welcome_text">ИксМПП је протокол независан од провајдера. Можете да користите овог клијента са било којим ИксМПП сервером.\nИпак, због погодности смо олакшали стварање налога на conversations.im, провајдер посебно прилагођен за коришћење са Конверзацијом.</string>
- <string name="magic_create_text">Водићемо вас кроз процес прављења налога на conversations.im.\nАко изаберете conversations.im за даваоца услуге моћи ћете да комуницирате са другим корисницима ако им дате ваш Џабер ИД.</string>
<string name="your_full_jid_will_be">Ваш пуни Џабер ИД ће бити: %s</string>
<string name="create_account">Направи налог</string>
<string name="use_own_provider">Користићу сопствени провајдер</string>
@@ -651,4 +650,15 @@
<string name="allow">Дозволи</string>
<string name="no_permission_to_access_x">Нема дозвола за приступ %s</string>
<string name="remote_server_not_found">Удаљени сервер није нађен</string>
+ <string name="unable_to_update_account">Не могох да се ажурирам налог</string>
+ <string name="missing_presence_subscription_with_x">Нема претплате на присутност са %s.</string>
+ <string name="missing_keys_from_x">Нема ОМЕМО кључева у %s.</string>
+ <string name="missing_omemo_keys">Нема ОМЕМО кључева</string>
+ <string name="wrong_conference_configuration">Ово није приватно, неанонимно групно ћаскање.</string>
+ <string name="this_conference_has_no_members">Нема учесника у овом групном ћаскању.</string>
+ <string name="report_jid_as_spammer">Пријави да овај ЈИД шаље нежељене поруке.</string>
+ <string name="pref_delete_omemo_identities">Обриши ОМЕМО идентитете</string>
+ <string name="pref_delete_omemo_identities_summary">Поновно генерисање ОМЕМО кључева. Сви ваши контакти ће морати поново да вас овере. Користите ово само у крајњем случају.</string>
+ <string name="delete_selected_keys">Обриши изабране кључеве</string>
+ <string name="error_publish_avatar_offline">Морате бити повезани да бисте објавили ваш аватар.</string>
</resources>
diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml
index a9a82d5b..51cf173d 100644
--- a/src/main/res/values-sv/strings.xml
+++ b/src/main/res/values-sv/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Kontakten finns redan</string>
<string name="join">Gå med</string>
<string name="conference_address">Konferensadress</string>
- <string name="conference_address_example">rum@conference.exempel.se</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Spara som bokmärke</string>
<string name="delete_bookmark">Ta bort bokmärke</string>
<string name="bookmark_already_exists">Detta bokmärke finns redan</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Konferensen kräver lösenord</string>
<string name="enter_password">Fyll i lösenord</string>
<string name="missing_presence_updates">Saknar tillgänglighetsuppdateringar från kontakt</string>
+ <string name="missing_presence_subscription">Saknar tillgänglighetsuppdateringar</string>
<string name="request_presence_updates">Begär tillgänglighetsuppdateringar från din kontakt först.\n\n<small>Detta används för att se vilken klient/klienter din kontakt använder.</small></string>
<string name="request_now">Begär nu</string>
<string name="delete_fingerprint">Ta bort fingeravtryck</string>
@@ -595,8 +596,6 @@
<string name="security_error_invalid_file_access">Säkerhetsfel: Ogiltig filaccess</string>
<string name="no_application_to_share_uri">Ingen applikation kunde hittas för att dela URI</string>
<string name="share_uri_with">Dela URI med...</string>
- <string name="welcome_text">XMPP är ett leverantörsoberoende protokoll. Du kan använda denna klient med vilken XMPP server du vill.\nFör din bekvämlighet har vi gjort det enkelt att skapa ett konto hos conversations.im; en leverantör speciellt anpassad för att användas med Conversations.</string>
- <string name="magic_create_text">Du kommer nu att få hjälp med att skapa ett konto på conversations.im.\nNär conversations.im väljs som leverantör kommer du kunna kommunicera med användare hos andra leverantörer genom att ge dem ditt Jabber ID.</string>
<string name="your_full_jid_will_be">Ditt jabber ID blir: %s</string>
<string name="create_account">Skapa konto</string>
<string name="use_own_provider">Använd min egen leverantör</string>
@@ -651,6 +650,12 @@
<string name="unable_to_update_account">Kan inte uppdatera konto</string>
<string name="missing_presence_subscription_with_x">Saknar tillgänglighetsuppdateringar från %s.</string>
<string name="missing_keys_from_x">Saknar OMEMO nyckel från %s.</string>
+ <string name="missing_omemo_keys">Saknar OMEMO nycklar</string>
<string name="wrong_conference_configuration">Detta är inte en privat, icke-anonym konferens.</string>
<string name="this_conference_has_no_members">Det finns inga medlemmar i denna konferens.</string>
+ <string name="report_jid_as_spammer">Rapportera detta JID för skickande av oönskade meddelanden.</string>
+ <string name="pref_delete_omemo_identities">Ta bort OMEMO identiteter</string>
+ <string name="pref_delete_omemo_identities_summary">Regenerera din OMEMO-nyckel. Alla dina kontakter kommer att behöva verifiera dig igen. Använd detta endast som en sista utväg.</string>
+ <string name="delete_selected_keys">Ta bort valda nycklar</string>
+ <string name="error_publish_avatar_offline">Du måste vara ansluten för att publicera din avatarbild</string>
</resources>
diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml
index 8137611d..f0c07049 100644
--- a/src/main/res/values-tr-rTR/strings.xml
+++ b/src/main/res/values-tr-rTR/strings.xml
@@ -247,7 +247,7 @@
<string name="contact_already_exists">Kişi zaten mevcut</string>
<string name="join">Katıl</string>
<string name="conference_address">Grup sohbet adresi</string>
- <string name="conference_address_example">oda@conference.ornek.com</string>
+ <string name="conference_address_example">oda@conference.ornek.com/nick</string>
<string name="save_as_bookmark">Yer imi olarak kaydet</string>
<string name="delete_bookmark">Yer imini sil</string>
<string name="bookmark_already_exists">Bu yer imi zaten mevcut</string>
@@ -283,6 +283,7 @@
<string name="conference_requires_password">Grup sohbet için parola gerekiyor</string>
<string name="enter_password">Parolayı gir</string>
<string name="missing_presence_updates">Kişinin çevrimiçi durum bildirimi güncellemesi kayıp</string>
+ <string name="missing_presence_subscription">Durum bildirimi aboneliği eksik.</string>
<string name="request_presence_updates">Lütfen öncelikle kişiden çevrimiçi durum güncellemelerini isteyin.\n\n<small>Bu bilgi kişinin kullandığı istemcinin belirlenmesinde kullanılacaktır.</small></string>
<string name="request_now">Şimdi iste</string>
<string name="delete_fingerprint">Parmak izini sil</string>
@@ -592,7 +593,7 @@
<string name="security_error_invalid_file_access">Güvenlik hatası: Geçersiz dosya erişimi</string>
<string name="no_application_to_share_uri">URI paylaşmak için uygulama bulunamadı</string>
<string name="share_uri_with">URI paylaş ile...</string>
- <string name="welcome_text">XMPP sağlayıcıdan bağımsız bir protokoldür. Bu istemciyi tercih ettiğiniz herhangi bir XMMP sunucusuyla kullanabilirsiniz.\n Kullanılabilirlik sağlamak için conversation.im sağlayıcısında hesap oluşturmayı daha kolay hale getirdik; Conversation için özelleşmiş bir servis sağlayıcı. </string>
+ <string name="welcome_text">XMPP servis sağlayıcısından bağımsız bir protokoldür. Bu istemciyi dilediğiniz XMMPP sunucularıyla birlikte kullanabilirsiniz\n Lakin sizin rahat etmeniz için Conversations istemcisiyle kullanmanız için oluşturduğumuz conversation.im sunucusu üzerinde hesap açmayı kolaylaştırdık.</string>
<string name="magic_create_text">conversation.im sağlayıcısında hesap açma sürecinde size yol göstereceğiz.\nconversation.im i bir servis sağlayıcı olarak kullandığınızda diğer sağlayıcıları kullanan kullanıcılar tam Jabber kimliğinizi vererek iletişim kurabilirsiniz. </string>
<string name="your_full_jid_will_be">Tam Jabber kimliğiniz %s olacak</string>
<string name="create_account">Hesap Oluştur</string>
@@ -648,6 +649,12 @@
<string name="unable_to_update_account">Hesap güncellenemiyor</string>
<string name="missing_presence_subscription_with_x">%s ile durum bildirimi aboneliği eksik.</string>
<string name="missing_keys_from_x">%s den eksik OMEMO anahtarları var.</string>
+ <string name="missing_omemo_keys">Eksik OMEMO anahtarları var.</string>
<string name="wrong_conference_configuration">Bu özel ve anonim olmayan bir sohbet.</string>
<string name="this_conference_has_no_members">Bu konferansta herhangi bir üye yok. </string>
+ <string name="report_jid_as_spammer">Bu kişiyi istenmeyen ileti gönderen olarak rapor et.</string>
+ <string name="pref_delete_omemo_identities">OMEMO kimiliğini sil</string>
+ <string name="pref_delete_omemo_identities_summary">OMEMO anahtarını tekrar oluştur. Tüm kişilerinizin sizi tekrar doğrulaması gerekecek. Bunu sadece son çare olarak kullanın.</string>
+ <string name="delete_selected_keys">Seçilen anahtarları sil</string>
+ <string name="error_publish_avatar_offline">Avatarınızı yayınlamak için bağlı olmalısınız.</string>
</resources>
diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml
index 517af6f5..576c7310 100644
--- a/src/main/res/values-uk/strings.xml
+++ b/src/main/res/values-uk/strings.xml
@@ -246,7 +246,6 @@
<string name="contact_already_exists">Контакт уже існує</string>
<string name="join">Долучитися</string>
<string name="conference_address">Адреса конференції</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Зберегти як закладку</string>
<string name="delete_bookmark">Видалити закладку</string>
<string name="bookmark_already_exists">Ця закладка вже існує</string>
@@ -595,8 +594,6 @@
<string name="security_error_invalid_file_access">Помилка безпеки: Недійсний доступ до файлу</string>
<string name="no_application_to_share_uri">Не знайдено програми, щоб поділитися URI</string>
<string name="share_uri_with">Поділитися URI з…</string>
- <string name="welcome_text">XMPP надає незалежний протокол. Ви можете використати цей клієнт з будь-яким XMPP сервером на Ваш вибір.\nДля Вашої зручності, ми зробили так, що Ви можете просто створити обліковий запис на conversations.im; це один із провайдерів, який спеціально підходящий для використання з програмою.</string>
- <string name="magic_create_text">Ми проведемо Вас через процес створення облікового запису на conversations.im.\nУ разі вибору conversations.im у якості провайдера, Ви зможете спілкуватися з користувачами інших провайдерів, надавши їм Ваш повний Jabber ID.</string>
<string name="your_full_jid_will_be">Ваш повний Jabber ID буде: %s</string>
<string name="create_account">Створити обліковий запис</string>
<string name="use_own_provider">Використати мого власного провайдера</string>
diff --git a/src/main/res/values-v21/themes.xml b/src/main/res/values-v21/themes.xml
index 330bd610..d6612552 100644
--- a/src/main/res/values-v21/themes.xml
+++ b/src/main/res/values-v21/themes.xml
@@ -37,6 +37,9 @@
<item name="attr/icon_alpha">0.54</item>
+ <item name="attr/dialog_horizontal_padding">24dp</item>
+ <item name="attr/dialog_vertical_padding">16dp</item>
+
<item name="attr/icon_add_group">@drawable/ic_group_add_white_24dp</item>
<item name="attr/icon_add_person">@drawable/ic_person_add_white_24dp</item>
<item name="attr/icon_cancel">@drawable/ic_cancel_white_24dp</item>
@@ -100,6 +103,9 @@
<item name="attr/icon_alpha">1.0</item>
+ <item name="attr/dialog_horizontal_padding">24dp</item>
+ <item name="attr/dialog_vertical_padding">16dp</item>
+
<item name="attr/icon_add_group">@drawable/ic_group_add_white_24dp</item>
<item name="attr/icon_add_person">@drawable/ic_person_add_white_24dp</item>
<item name="attr/icon_cancel">@drawable/ic_cancel_white_24dp</item>
diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml
index 4e094fcb..0a1f24b6 100644
--- a/src/main/res/values-vi/strings.xml
+++ b/src/main/res/values-vi/strings.xml
@@ -223,7 +223,6 @@
<string name="contact_already_exists">Đã có liên hệ này rồi</string>
<string name="join">Tham gia</string>
<string name="conference_address">Địa chỉ diễn đàn</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">Lưu thành đánh dấu</string>
<string name="delete_bookmark">Xoá đánh dấu</string>
<string name="bookmark_already_exists">Đã có đánh dấu này rồi</string>
diff --git a/src/main/res/values-w360dp/fineprint.xml b/src/main/res/values-w360dp/fineprint.xml
new file mode 100644
index 00000000..fa28fbed
--- /dev/null
+++ b/src/main/res/values-w360dp/fineprint.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="free_for_six_month">¹ Optional conversations.im account €8/year. First 6 month free.</string>
+</resources> \ No newline at end of file
diff --git a/src/main/res/values-w384dp/dimens.xml b/src/main/res/values-w384dp/dimens.xml
index 5026848e..441e1103 100644
--- a/src/main/res/values-w384dp/dimens.xml
+++ b/src/main/res/values-w384dp/dimens.xml
@@ -1,3 +1,4 @@
<resources>
<dimen name="conversations_overview_width">336dp</dimen>
+ <dimen name="fineprint_size">12sp</dimen>
</resources>
diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml
index 087b9e51..a2585623 100644
--- a/src/main/res/values-zh-rCN/strings.xml
+++ b/src/main/res/values-zh-rCN/strings.xml
@@ -78,6 +78,7 @@
<string name="clear_histor_msg">删除该会话中所有信息?\n\n<b>注:</b> 该操作不会影响其他设备或服务器保存的信息。</string>
<string name="delete_messages">删除消息</string>
<string name="also_end_conversation">结束此会话以后</string>
+ <string name="choose_presence">选择设备</string>
<string name="send_unencrypted_message">发送未加密的信息</string>
<string name="send_message_to_x">发信息给 %s</string>
<string name="send_otr_message">发送 OTR 加密信息</string>
@@ -217,6 +218,8 @@
<string name="reception_failed">接收失败</string>
<string name="your_fingerprint">你的指纹</string>
<string name="otr_fingerprint">OTR 指纹</string>
+ <string name="otr_fingerprint_selected_message">消息的 OTR 指纹</string>
+ <string name="openpgp_key_id">OpenPGP 密钥 ID</string>
<string name="omemo_fingerprint">OMEMO 指纹</string>
<string name="omemo_fingerprint_x509">v\\OMEMO 指纹</string>
<string name="omemo_fingerprint_selected_message">消息的 OMEMO 指纹</string>
@@ -242,7 +245,7 @@
<string name="contact_already_exists">联系人已存在</string>
<string name="join">加入</string>
<string name="conference_address">讨论组地址</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">保存为书签</string>
<string name="delete_bookmark">删除书签</string>
<string name="bookmark_already_exists">该书签已存在</string>
@@ -355,6 +358,8 @@
<string name="conversations_foreground_service">Conversations</string>
<string name="pref_keep_foreground_service">保持前台服务</string>
<string name="pref_keep_foreground_service_summary">防止操作系统中断你的连接</string>
+ <string name="pref_export_logs">导出历史记录</string>
+ <string name="pref_export_logs_summary">将 conversations 的历史日志写到 SD 卡</string>
<string name="notification_export_logs_title">正在将日志写入 SD 卡</string>
<string name="choose_file">选择文件</string>
<string name="receiving_x_file">接收中 %1$s (已完成 %2$d%%)</string>
@@ -586,8 +591,6 @@
<string name="security_error_invalid_file_access">安全错误:文件访问权限无效</string>
<string name="no_application_to_share_uri">没有可以分享此链接的应用</string>
<string name="share_uri_with">分享链接...</string>
- <string name="welcome_text">XMPP 是一种独立于服务端的协议。你可以选择任何 XMPP 服务器来使用本客户端。\n当然为了方便您的使用,我们可以为您在 conversations.im ——一个特别为 Conversations 设计的服务端——上创建一个账户。</string>
- <string name="magic_create_text">我们将指导您在 conversations.im 上创建一个账户。\n当您选择 conversations.im 作为服务端后,您将可以通过提供您完整的 Jabber ID 来与他人进行会话。</string>
<string name="your_full_jid_will_be">您完整的 Jabble ID 是:%s </string>
<string name="create_account">创建账户</string>
<string name="use_own_provider">使用我自己的服务端</string>
@@ -606,6 +609,7 @@
<string name="device_does_not_support_battery_op">该设备不支持禁用电池优化</string>
<string name="show_password">显示密码</string>
<string name="registration_please_wait">注册失败:请重试</string>
+ <string name="registration_password_too_weak">注册失败:密码太弱</string>
<string name="create_conference">创建讨论组</string>
<string name="join_or_create_conference">加入创建讨论组</string>
<string name="conference_subject">主题</string>
@@ -624,4 +628,23 @@
<string name="pref_theme_dark">黑暗主题</string>
<string name="pref_use_green_background">绿色背景</string>
<string name="pref_use_green_background_summary">接收到的消息使用绿色背景</string>
+ <string name="unable_to_connect_to_keychain">无法连接到 OpenKeychain</string>
+ <string name="this_device_is_no_longer_in_use">此设备不再使用</string>
+ <string name="type_pc">计算机</string>
+ <string name="type_phone">移动电话</string>
+ <string name="type_tablet">平板</string>
+ <string name="type_web">浏览器</string>
+ <string name="type_console">控制台</string>
+ <string name="payment_required">需要付款</string>
+ <string name="allow">允许</string>
+ <string name="no_permission_to_access_x">没有访问 %s 的许可</string>
+ <string name="remote_server_not_found">找不到远程服务器</string>
+ <string name="unable_to_update_account">无法更新账户</string>
+ <string name="missing_keys_from_x">缺少来自 %s 的 OMEMO 密钥。</string>
+ <string name="wrong_conference_configuration">这不是一个私密,非匿名的会议室。</string>
+ <string name="this_conference_has_no_members">这个会议室中没有成员。</string>
+ <string name="report_jid_as_spammer">报告这个 JID 发送不想要的消息。</string>
+ <string name="pref_delete_omemo_identities">删除 OMEMO 身份</string>
+ <string name="pref_delete_omemo_identities_summary">重新生成你的 OMEMO 密钥。你的所有联系人不得不对你进行再认证。请将此作为最后的办法。</string>
+ <string name="delete_selected_keys">删除选择的密钥</string>
</resources>
diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml
index 7f48dd19..00557f09 100644
--- a/src/main/res/values-zh-rTW/strings.xml
+++ b/src/main/res/values-zh-rTW/strings.xml
@@ -174,7 +174,6 @@
<string name="contact_already_exists">聯絡人已存在</string>
<string name="join">加入</string>
<string name="conference_address">群組地址</string>
- <string name="conference_address_example">room@conference.example.com</string>
<string name="save_as_bookmark">儲存為書籤</string>
<string name="delete_bookmark">刪除書籤</string>
<string name="bookmark_already_exists">該書籤已存在</string>
diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml
index 8062cd7e..82f9db89 100644
--- a/src/main/res/values/attrs.xml
+++ b/src/main/res/values/attrs.xml
@@ -53,4 +53,7 @@
<attr name="icon_notifications_paused" format="reference"/>
<attr name="icon_notifications_none" format="reference"/>
+ <attr name="dialog_horizontal_padding" format="dimension"/>
+ <attr name="dialog_vertical_padding" format="dimension"/>
+
</resources> \ No newline at end of file
diff --git a/src/main/res/values/dimens.xml b/src/main/res/values/dimens.xml
index 95e80055..4ce44f22 100644
--- a/src/main/res/values/dimens.xml
+++ b/src/main/res/values/dimens.xml
@@ -5,4 +5,5 @@
<dimen name="infocard_padding">16dp</dimen>
<dimen name="conversations_overview_width">288dp</dimen>
<dimen name="image_button_padding">8dp</dimen>
+ <dimen name="fineprint_size">11sp</dimen>
</resources>
diff --git a/src/main/res/values/fineprint.xml b/src/main/res/values/fineprint.xml
new file mode 100644
index 00000000..55eeccb6
--- /dev/null
+++ b/src/main/res/values/fineprint.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="free_for_six_month">¹ Optional conversations.im account €8/year. 6 month free.</string>
+</resources> \ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 1d53a278..c2f86189 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -248,7 +248,7 @@
<string name="contact_already_exists">The contact already exists</string>
<string name="join">Join</string>
<string name="conference_address">Conference address</string>
- <string name="conference_address_example">room@conference.example.com</string>
+ <string name="conference_address_example">room@conference.example.com/nick</string>
<string name="save_as_bookmark">Save as bookmark</string>
<string name="delete_bookmark">Delete bookmark</string>
<string name="bookmark_already_exists">This bookmark already exists</string>
@@ -284,6 +284,7 @@
<string name="conference_requires_password">Conference requires password</string>
<string name="enter_password">Enter password</string>
<string name="missing_presence_updates">Missing presence updates from contact</string>
+ <string name="missing_presence_subscription">Missing presence subscription</string>
<string name="request_presence_updates">Please request presence updates from your contact first.\n\n<small>This will be used to determine what client(s) your contact is using.</small></string>
<string name="request_now">Request now</string>
<string name="delete_fingerprint">Delete Fingerprint</string>
@@ -629,8 +630,8 @@
<string name="no_application_to_share_uri">No application found to share URI</string>
<string name="share_uri_with">Share URI with…</string>
<string translatable="false" name="welcome_header">Join the Conversation</string>
- <string name="welcome_text">XMPP is a provider independent protocol. You can use this client with what ever XMPP server you choose.\nHowever for your convenience we made it easy to create an account on conversations.im; a provider specially suited for the use with Conversations.</string>
- <string name="magic_create_text">We will guide you through the process of creating an account on conversations.im.\nWhen picking conversations.im as a provider you will be able to communicate with users of other providers by giving them your full Jabber ID.</string>
+ <string name="welcome_text">XMPP is a provider independent protocol. You can use this client with what ever XMPP server you choose.\nHowever for your convenience we made it easy to create an account on conversations.im¹; a provider specially suited for the use with Conversations.</string>
+ <string name="magic_create_text">We will guide you through the process of creating an account on conversations.im.¹\nWhen picking conversations.im as a provider you will be able to communicate with users of other providers by giving them your full Jabber ID.</string>
<string name="your_full_jid_will_be">Your full Jabber ID will be: %s</string>
<string name="create_account">Create Account</string>
<string name="use_own_provider">Use my own provider</string>
@@ -685,6 +686,12 @@
<string name="unable_to_update_account">Unable to update account</string>
<string name="missing_presence_subscription_with_x">Missing presence subscription with %s.</string>
<string name="missing_keys_from_x">Missing OMEMO keys from %s.</string>
+ <string name="missing_omemo_keys">Missing OMEMO keys</string>
<string name="wrong_conference_configuration">This is not a private, non-anonymous conference.</string>
<string name="this_conference_has_no_members">There are no members in this conference.</string>
+ <string name="report_jid_as_spammer">Report this JID as sending unwanted messages.</string>
+ <string name="pref_delete_omemo_identities">Delete OMEMO identities</string>
+ <string name="pref_delete_omemo_identities_summary">Regenerate your OMEMO keys. All your contacts will have to verify you again. Use this only as a last resort.</string>
+ <string name="delete_selected_keys">Delete selected keys</string>
+ <string name="error_publish_avatar_offline">You need to be connected to publish your avatar.</string>
</resources>
diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml
index 1b3a4098..f15822c9 100644
--- a/src/main/res/values/themes.xml
+++ b/src/main/res/values/themes.xml
@@ -43,6 +43,9 @@
<item name="attr/icon_alpha">1.0</item>
+ <item name="attr/dialog_horizontal_padding">16dp</item>
+ <item name="attr/dialog_vertical_padding">16dp</item>
+
<item name="attr/icon_group">@drawable/ic_action_group</item>
<item name="attr/icon_new">@drawable/ic_action_new</item>
<item name="attr/icon_new_attachment">@drawable/ic_action_new_attachment</item>
@@ -93,6 +96,9 @@
<item name="attr/icon_alpha">1.0</item>
+ <item name="attr/dialog_horizontal_padding">16dp</item>
+ <item name="attr/dialog_vertical_padding">16dp</item>
+
<item name="attr/icon_add_group">@drawable/ic_action_add_group</item>
<item name="attr/icon_add_person">@drawable/ic_action_add_person</item>
<item name="attr/icon_cancel">@drawable/ic_action_cancel</item>
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index 68b2f73a..cee43491 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -183,6 +183,10 @@
android:key="allow_message_correction"
android:title="@string/pref_allow_message_correction"
android:summary="@string/pref_allow_message_correction_summary"/>
+ <Preference
+ android:key="delete_omemo_identities"
+ android:title="@string/pref_delete_omemo_identities"
+ android:summary="@string/pref_delete_omemo_identities_summary"/>
</PreferenceCategory>
<PreferenceCategory
android:key="connection_options"
@@ -253,7 +257,7 @@
android:key="keep_foreground_service"
android:summary="@string/pref_keep_foreground_service_summary"
android:title="@string/pref_keep_foreground_service"/>
- <eu.siacs.conversations.ui.ExportLogsPreference
+ <Preference
android:key="export_logs"
android:summary="@string/pref_export_logs_summary"
android:title="@string/pref_export_logs"/>