diff options
Diffstat (limited to '')
82 files changed, 909 insertions, 530 deletions
@@ -7,6 +7,8 @@ src/playstore/res/values/gcm.xml # https://github.com/github/gitignore/blob/master/Gradle.gitignore .gradle/ build/ +captures/ +gradle.properties # Ignore Gradle GUI config gradle-app.setting diff --git a/.travis.yml b/.travis.yml index e26ccaa4..9d37a4f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,6 @@ android: - platform-tools - tools - build-tools-23.0.2 - - build-tools-23.0.1 - - build-tools-23.0.0 - - build-tools-22.0.1 - - build-tools-21.1.2 - build-tools-19.1.0 - android-23 - extra-android-m2repository diff --git a/CHANGELOG.md b/CHANGELOG.md index 85e7c5ee..ed65a8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ ###Changelog +####Version 1.11.7 +* Share xmpp uri from conference details +* add setting to allow quick sharing +* various bug fixes + +####Version 1.11.6 +* added preference to disable notification light +* various bug fixes + +####Version 1.11.5 +* check file ownership to not accidentally share private files + +####Version 1.11.4 +* fixed a bug where contacts are shown as offline +* improved broken PEP detection + ####Version 1.11.3 * check maximum file size when using HTTP Upload * properly calculate caps hash diff --git a/build.gradle b/build.gradle index 61162aba..de4d418e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:2.0.0' } } @@ -57,6 +57,12 @@ dependencies { compile 'com.android.support:support-v13:23.2.0' } +ext { + travisBuild = System.getenv("TRAVIS") == "true" + // allows for -Dpre-dex=false to be set + preDexEnabled = "true".equals(System.getProperty("pre-dex", "true")) +} + android { compileSdkVersion 23 buildToolsVersion "23.0.2" @@ -64,9 +70,15 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 23 - versionCode 8 - versionName "0.0.7" + versionCode 9 + versionName "0.0.8" archivesBaseName += "-$versionName" + apply from: 'configuration.gradle' + } + + dexOptions { + // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false. + preDexLibraries = preDexEnabled && !travisBuild } compileOptions { diff --git a/configuration.gradle b/configuration.gradle new file mode 100644 index 00000000..fbb02b6e --- /dev/null +++ b/configuration.gradle @@ -0,0 +1,51 @@ + +apply plugin: 'com.android.application' + + +android { + + productFlavors { + free { + buildConfigField 'String', 'LOGTAG', '"conversationsplus"' // JUST AS EXAMPLE + } + } + + defaultConfig { + buildConfigField 'String', 'LOGTAG', '"conversationsplus"' + buildConfigField 'String', 'LOCKED_IN_DOMAIN', 'null' // only allow account creation for this domain + buildConfigField 'String', 'LOCKED_IN_DOMAIN_CONFERENCES', 'null' // only allow conference creation for this domain + buildConfigField 'boolean', 'CONTACTS_CONFERENCES_LOCKED_TO_DOMAIN', 'false' // only add contacts and conferences for own domains + buildConfigField 'boolean', 'ACCOUNT_SETTINGS_LOCKED', 'false' // set to true to disallow account and settings editing + buildConfigField 'boolean', 'DISALLOW_REGISTRATION_IN_UI', 'false' // hide the register checkbox + buildConfigField 'boolean', 'ALLOW_NON_TLS_CONNECTIONS', 'false' // very dangerous. you should have a good reason to set this to true + buildConfigField 'boolean', 'HIDE_MESSAGE_TEXT_IN_NOTIFICATION', 'false' // + buildConfigField 'boolean', 'SHOW_CONNECTED_ACCOUNTS_IN_FOREGROUND_NOTIFICATION', 'false' // show number of connected accounts in foreground notification + buildConfigField 'int', 'PING_MAX_INTERVAL', '300' // maximum ping interval in seconds + buildConfigField 'int', 'PING_MIN_INTERVAL', '30' // minimum ping interval in seconds + buildConfigField 'int', 'PING_TIMEOUT', '15' // ping timeout in seconds + buildConfigField 'int', 'SOCKET_TIMEOUT', '15' // socket timeout in seconds + buildConfigField 'int', 'CONNECT_TIMEOUT', '90' // connect timeout in seconds + buildConfigField 'int', 'CONNECT_DISCO_TIMEOUT', '20' // disco timeout while connecting in seconds + buildConfigField 'int', 'CARBON_GRACE_PERIOD', '90' // carbon grace period in seconds + buildConfigField 'int', 'MINI_GRACE_PERIOD', '750' // whatever ??? + buildConfigField 'boolean', 'CLOSE_TCP_WHEN_SWITCHING_TO_BACKGROUND', 'false' // + buildConfigField 'int', 'AVATAR_SIZE', '192' // height and width of an avatar + buildConfigField 'int', 'PAGE_SIZE', '50' // maximum messages per page + buildConfigField 'int', 'MAX_NUM_PAGES', '3' // maximum pages + buildConfigField 'int', 'REFRESH_UI_INTERVAL', '500' // Refresh UI interval in milliseonds + buildConfigField 'android.graphics.Bitmap.CompressFormat', 'AVATAR_FORMAT', 'android.graphics.Bitmap.CompressFormat.PNG' // Format of an avatar + buildConfigField 'boolean', 'DISABLE_PROXY_LOOKUP', 'false' // disables proxy lookup for JingleConnections - useful to debug ibb + buildConfigField 'boolean', 'DISABLE_HTTP_UPLOAD', 'false' // + buildConfigField 'boolean', 'DISABLE_STRING_PREP', 'false' // setting to true might increase startup performance + buildConfigField 'boolean', 'EXTENDED_SM_LOGGING', 'false' // log stanza counts + buildConfigField 'boolean', 'RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE', 'true' // setting to true might increase power consumption + buildConfigField 'boolean', 'ENCRYPT_ON_HTTP_UPLOADED', 'false' // + buildConfigField 'boolean', 'REPORT_WRONG_FILESIZE_IN_OTR_JINGLE', 'true' // + buildConfigField 'boolean', 'SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON', 'false' // + buildConfigField 'boolean', 'X509_VERIFICATION_OF_OMEMO_KEYS', 'false' // use x509 certificates to verify OMEMO keys + buildConfigField 'boolean', 'IGNORE_ID_REWRITE_IN_MUC', 'true' // + buildConfigField 'boolean', 'REQUEST_DISCO', 'true' // + buildConfigField 'int', 'MAM_MAX_MESSAGES', '500' // maximum number of messages to load via MAM + buildConfigField 'int', 'TYPING_TIMEOUT', '8' // Typing timeout in seconds + } +}
\ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5b7e8296..61de9bb3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Nov 22 17:47:57 CET 2014 +#Sat Apr 09 13:15:52 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip diff --git a/libs/MemorizingTrustManager/build.gradle b/libs/MemorizingTrustManager/build.gradle index 47491fec..dc2e7b60 100644 --- a/libs/MemorizingTrustManager/build.gradle +++ b/libs/MemorizingTrustManager/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'com.android.tools.build:gradle:2.0.0' } } diff --git a/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/adapters/LogCatArrayAdapter.java b/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/adapters/LogCatArrayAdapter.java index c8a96ea3..eb4efc98 100644 --- a/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/adapters/LogCatArrayAdapter.java +++ b/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/adapters/LogCatArrayAdapter.java @@ -116,7 +116,11 @@ public class LogCatArrayAdapter extends ArrayAdapter<String> { logcatItems.remove(object); } - public ArrayList<String> getItems() { - return this.logcatItems; + /** + * Returns an unmodifiable copy of the log cat entries. + * @return UnmodifiableList of logcat entries. + */ + public List<String> getItems() { + return Collections.unmodifiableList(this.logcatItems); } } diff --git a/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/ui/LogCatOutputCopyOnClickListener.java b/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/ui/LogCatOutputCopyOnClickListener.java deleted file mode 100644 index 1be04c9c..00000000 --- a/libs/thedevstacklogcat/src/main/java/de/thedevstack/android/logcat/ui/LogCatOutputCopyOnClickListener.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.thedevstack.android.logcat.ui; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.view.View; -import android.widget.Toast; - -import java.util.ArrayList; - -import de.thedevstack.android.logcat.Logging; -import de.thedevstack.android.logcat.adapters.LogCatArrayAdapter; - -/** - * Created by tzur on 20.11.2015. - */ -public class LogCatOutputCopyOnClickListener implements View.OnClickListener { - private final LogCatArrayAdapter logCatOutputAdapter; - private final Context context; - private final int resIdLogcatCopied; - private final int resIdLogcatNotCopied; - - public LogCatOutputCopyOnClickListener(Context context, LogCatArrayAdapter logCatOutputAdapter, int resIdLogcatCopied, int resIdLogcatNotCopied) { - this.logCatOutputAdapter = logCatOutputAdapter; - this.context = context; - this.resIdLogcatCopied = resIdLogcatCopied; - this.resIdLogcatNotCopied = resIdLogcatNotCopied; - } - - @Override - public void onClick(View v) { - Logging.d("copylogcat", "Start Copying log cat"); - ArrayList<String> items = this.logCatOutputAdapter.getItems(); - if (null != items && !items.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (String item : items) { - sb.append(item); - sb.append("\n"); - } - ClipboardManager clipboard = (ClipboardManager) this.context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("c+logcat", sb.toString()); - clipboard.setPrimaryClip(clip); - Toast.makeText(this.context, this.context.getText(this.resIdLogcatCopied), Toast.LENGTH_LONG).show(); - } else { - Toast.makeText(this.context, this.context.getText(this.resIdLogcatNotCopied), Toast.LENGTH_LONG).show(); - } - } -} diff --git a/libs/thedevstacklogcat/src/test/java/de/thedevstack/android/logcat/ExampleUnitTest.java b/libs/thedevstacklogcat/src/test/java/de/thedevstack/android/logcat/ExampleUnitTest.java deleted file mode 100644 index 1d2bc545..00000000 --- a/libs/thedevstacklogcat/src/test/java/de/thedevstack/android/logcat/ExampleUnitTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.thedevstack.android.logcat; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -}
\ No newline at end of file diff --git a/src/main/java/de/thedevstack/conversationsplus/Config.java b/src/main/java/de/thedevstack/conversationsplus/Config.java index 2f35ad6e..a6825246 100644 --- a/src/main/java/de/thedevstack/conversationsplus/Config.java +++ b/src/main/java/de/thedevstack/conversationsplus/Config.java @@ -34,77 +34,62 @@ public final class Config { return (ENCRYPTION_MASK & (ENCRYPTION_MASK - 1)) != 0; } - public static final String LOGTAG = "conversations"; + public static final String LOGTAG = BuildConfig.LOGTAG; + public static final String DOMAIN_LOCK = BuildConfig.LOCKED_IN_DOMAIN; //only allow account creation for this domain + public static final String CONFERENCE_DOMAIN_LOCK = BuildConfig.LOCKED_IN_DOMAIN_CONFERENCES; //only allow conference creation for this domain + public static final boolean LOCK_DOMAINS_IN_CONVERSATIONS = BuildConfig.CONTACTS_CONFERENCES_LOCKED_TO_DOMAIN; //only add contacts and conferences for own domains - public static final String DOMAIN_LOCK = null; //only allow account creation for this domain - public static final String CONFERENCE_DOMAIN_LOCK = null; //only allow conference creation for this domain - public static final boolean LOCK_DOMAINS_IN_CONVERSATIONS = false; //only add contacts and conferences for own domains + public static final boolean LOCK_SETTINGS = BuildConfig.ACCOUNT_SETTINGS_LOCKED; //set to true to disallow account and settings editing + public static final boolean DISALLOW_REGISTRATION_IN_UI = BuildConfig.DISALLOW_REGISTRATION_IN_UI; //hide the register checkbox - public static final boolean LOCK_SETTINGS = false; //set to true to disallow account and settings editing - public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox + public static final boolean ALLOW_NON_TLS_CONNECTIONS = BuildConfig.ALLOW_NON_TLS_CONNECTIONS; //very dangerous. you should have a good reason to set this to true + public static final boolean HIDE_MESSAGE_TEXT_IN_NOTIFICATION = BuildConfig.HIDE_MESSAGE_TEXT_IN_NOTIFICATION; + public static final boolean SHOW_CONNECTED_ACCOUNTS = BuildConfig.SHOW_CONNECTED_ACCOUNTS_IN_FOREGROUND_NOTIFICATION; //show number of connected accounts in foreground notification - public static final boolean ALLOW_NON_TLS_CONNECTIONS = false; //very dangerous. you should have a good reason to set this to true - public static final boolean HIDE_MESSAGE_TEXT_IN_NOTIFICATION = false; - public static final boolean SHOW_CONNECTED_ACCOUNTS = false; //show number of connected accounts in foreground notification + public static final int PING_MAX_INTERVAL = BuildConfig.PING_MAX_INTERVAL; + public static final int PING_MIN_INTERVAL = BuildConfig.PING_MIN_INTERVAL; + public static final int PING_TIMEOUT = BuildConfig.PING_TIMEOUT; + public static final int SOCKET_TIMEOUT = BuildConfig.SOCKET_TIMEOUT; + public static final int CONNECT_TIMEOUT = BuildConfig.CONNECT_TIMEOUT; + public static final int CONNECT_DISCO_TIMEOUT = BuildConfig.CONNECT_DISCO_TIMEOUT; + public static final int CARBON_GRACE_PERIOD = BuildConfig.CARBON_GRACE_PERIOD; + public static final int MINI_GRACE_PERIOD = BuildConfig.MINI_GRACE_PERIOD; - public static final boolean ALWAYS_NOTIFY_BY_DEFAULT = false; + public static final boolean CLOSE_TCP_WHEN_SWITCHING_TO_BACKGROUND = BuildConfig.CLOSE_TCP_WHEN_SWITCHING_TO_BACKGROUND; - public static final boolean LEGACY_NAMESPACE_HTTP_UPLOAD = false; + public static final int AVATAR_SIZE = BuildConfig.AVATAR_SIZE; + public static final Bitmap.CompressFormat AVATAR_FORMAT = BuildConfig.AVATAR_FORMAT; - public static final int PING_MAX_INTERVAL = 300; - public static final int PING_MIN_INTERVAL = 30; - public static final int PING_TIMEOUT = 15; - public static final int SOCKET_TIMEOUT = 15; - public static final int CONNECT_TIMEOUT = 90; - public static final int CONNECT_DISCO_TIMEOUT = 20; - public static final int CARBON_GRACE_PERIOD = 90; - public static final int MINI_GRACE_PERIOD = 750; + public static final int PAGE_SIZE = BuildConfig.PAGE_SIZE; + public static final int MAX_NUM_PAGES = BuildConfig.MAX_NUM_PAGES; - public static final boolean CLOSE_TCP_WHEN_SWITCHING_TO_BACKGROUND = false; + public static final int REFRESH_UI_INTERVAL = BuildConfig.REFRESH_UI_INTERVAL; - public static final int AVATAR_SIZE = 192; - public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.PNG; + public static final boolean DISABLE_PROXY_LOOKUP = BuildConfig.DISABLE_PROXY_LOOKUP; //useful to debug ibb + public static final boolean DISABLE_HTTP_UPLOAD = BuildConfig.DISABLE_HTTP_UPLOAD; + public static final boolean DISABLE_STRING_PREP = BuildConfig.DISABLE_STRING_PREP; // setting to true might increase startup performance + public static final boolean EXTENDED_SM_LOGGING = BuildConfig.EXTENDED_SM_LOGGING; // log stanza counts + public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = BuildConfig.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE; //setting to true might increase power consumption - public static final int IMAGE_SIZE = 1920; - public static final Bitmap.CompressFormat IMAGE_FORMAT = Bitmap.CompressFormat.JPEG; - public static final int IMAGE_QUALITY = 75; - public static final int IMAGE_MAX_SIZE = 524288; //512KiB + public static final boolean ENCRYPT_ON_HTTP_UPLOADED = BuildConfig.ENCRYPT_ON_HTTP_UPLOADED; - public static final int MESSAGE_MERGE_WINDOW = 20; + public static final boolean REPORT_WRONG_FILESIZE_IN_OTR_JINGLE = BuildConfig.REPORT_WRONG_FILESIZE_IN_OTR_JINGLE; - public static final boolean UTF8_EMOTICONS = false; + public static final boolean SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON = BuildConfig.SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON; - public static final int PAGE_SIZE = 50; - public static final int MAX_NUM_PAGES = 3; + public static final boolean X509_VERIFICATION = BuildConfig.X509_VERIFICATION_OF_OMEMO_KEYS; //use x509 certificates to verify OMEMO keys - public static final int PROGRESS_UI_UPDATE_INTERVAL = 750; - public static final int REFRESH_UI_INTERVAL = 500; + public static final boolean IGNORE_ID_REWRITE_IN_MUC = BuildConfig.IGNORE_ID_REWRITE_IN_MUC; - public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb - public static final boolean DISABLE_HTTP_UPLOAD = false; - public static final boolean DISABLE_STRING_PREP = false; // setting to true might increase startup performance - public static final boolean EXTENDED_SM_LOGGING = false; // log stanza counts - public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption - - public static final boolean ENCRYPT_ON_HTTP_UPLOADED = false; - - public static final boolean REPORT_WRONG_FILESIZE_IN_OTR_JINGLE = true; - - public static final boolean SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON = false; - - public static final boolean X509_VERIFICATION = false; //use x509 certificates to verify OMEMO keys - - public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; - - public static final boolean REQUEST_DISCO = true; + public static final boolean REQUEST_DISCO = BuildConfig.REQUEST_DISCO; public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; - public static final int MAM_MAX_MESSAGES = 500; + public static final int MAM_MAX_MESSAGES = BuildConfig.MAM_MAX_MESSAGES; public static final ChatState DEFAULT_CHATSTATE = ChatState.ACTIVE; - public static final int TYPING_TIMEOUT = 8; + public static final int TYPING_TIMEOUT = BuildConfig.TYPING_TIMEOUT; public static final String ENABLED_CIPHERS[] = { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", diff --git a/src/main/java/de/thedevstack/conversationsplus/ConversationsPlusPreferences.java b/src/main/java/de/thedevstack/conversationsplus/ConversationsPlusPreferences.java index dda4208c..70eec7a2 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ConversationsPlusPreferences.java +++ b/src/main/java/de/thedevstack/conversationsplus/ConversationsPlusPreferences.java @@ -81,6 +81,49 @@ public class ConversationsPlusPreferences extends Settings { return getBoolean("enable_legacy_ssl", false); } + public static boolean showBatteryOptimization() { + return getBoolean("show_battery_optimization", true); + } + + public static void commitShowBatteryOptimization(boolean showBatteryOptimization) { + commitBoolean("show_battery_optimization", showBatteryOptimization); + } + + public static boolean advancedMucMode() { + return getBoolean("advanced_muc_mode", false); + } + + public static void commitAdvancedMucMode(boolean advancedMucMode) { + commitBoolean("advanced_muc_mode", advancedMucMode); + } + + /** + * Whether to show extended connection options or not + * @return + */ + public static boolean showConnectionOptions() { + return getBoolean("show_connection_options", false); + } + + /** + * Whether to respect auto join on bookmarks or not. + * @return + */ + public static boolean autojoin() { + return getBoolean("autojoin", true); + } + public static boolean xaOnSilentMode() { + return getBoolean("xa_on_silent_mode", false); + } + + public static boolean treatVibrateAsSilent() { + return getBoolean("treat_vibrate_as_silent", false); + } + + public static boolean awayWhenScreenOff() { + return getBoolean("away_when_screen_off", false); + } + public static boolean useSubject() { return getBoolean("use_subject", true); } @@ -194,6 +237,14 @@ public class ConversationsPlusPreferences extends Settings { return getBoolean("allow_message_correction", true); } + public static boolean returnToPrevious() { + return getBoolean("return_to_previous", false); + } + + public static boolean led() { + return getBoolean("led", true); + } + private ConversationsPlusPreferences(SharedPreferences sharedPreferences) { this.sharedPreferences = sharedPreferences; } diff --git a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlService.java b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlService.java index 49cd6033..52418553 100644 --- a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlService.java +++ b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlService.java @@ -115,4 +115,6 @@ public interface AxolotlService extends OnAdvancedStreamFeaturesLoaded { boolean hasPendingKeyFetches(Account account, List<Jid> jids); void prepareKeyTransportMessage(Conversation conversation, OnMessageCreatedCallback onMessageCreatedCallback); + + void resetBrokenness(); } diff --git a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceImpl.java b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceImpl.java index 2463a795..f8856f90 100644 --- a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceImpl.java +++ b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceImpl.java @@ -43,12 +43,13 @@ import de.thedevstack.conversationsplus.services.XmppConnectionService; import de.thedevstack.conversationsplus.utils.CryptoHelper; import de.thedevstack.conversationsplus.utils.SerialSingleThreadExecutor; import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.xmpp.OnAdvancedStreamFeaturesLoaded; import de.thedevstack.conversationsplus.xmpp.OnIqPacketReceived; import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; import de.thedevstack.conversationsplus.xmpp.jid.Jid; import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket; -public class AxolotlServiceImpl implements AxolotlService { +public class AxolotlServiceImpl implements OnAdvancedStreamFeaturesLoaded, AxolotlService { public static final int publishTriesThreshold = 3; @@ -223,6 +224,7 @@ public class AxolotlServiceImpl implements AxolotlService { return axolotlStore.getIdentityKeyPair().getPublicKey().getFingerprint().replaceAll("\\s", ""); } + @Override public Set<IdentityKey> getKeysWithTrust(XmppAxolotlSession.Trust trust) { return axolotlStore.getContactKeysWithTrust(account.getJid().toBareJid().toString(), trust); } @@ -302,6 +304,11 @@ public class AxolotlServiceImpl implements AxolotlService { return this.pepBroken; } + public void resetBrokenness() { + this.pepBroken = false; + numPublishTriesOnEmptyPep = 0; + } + public void regenerateKeys(boolean wipeOther) { axolotlStore.regenerate(); sessions.clear(); @@ -436,7 +443,8 @@ public class AxolotlServiceImpl implements AxolotlService { mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() != IqPacket.TYPE.RESULT) { + if (packet.getType() == IqPacket.TYPE.ERROR) { + pepBroken = true; Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing own device id" + packet.findChild("error")); } } @@ -600,7 +608,8 @@ public class AxolotlServiceImpl implements AxolotlService { Log.d(Config.LOGTAG, getLogprefix(account) + "Announcing device " + getOwnDeviceId()); publishOwnDeviceIdIfNeeded(); } - } else { + } else if (packet.getType() == IqPacket.TYPE.ERROR) { + pepBroken = true; Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing bundle: " + packet.findChild("error")); } } @@ -1037,4 +1046,4 @@ public class AxolotlServiceImpl implements AxolotlService { } } } -}
\ No newline at end of file +} diff --git a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceStub.java b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceStub.java index 858cdf08..7db99b75 100644 --- a/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceStub.java +++ b/src/main/java/de/thedevstack/conversationsplus/crypto/axolotl/AxolotlServiceStub.java @@ -204,4 +204,9 @@ public class AxolotlServiceStub implements AxolotlService { public void onAdvancedStreamFeaturesAvailable(Account account) { } + + @Override + public void resetBrokenness() { + + } } diff --git a/src/main/java/de/thedevstack/conversationsplus/entities/Conversation.java b/src/main/java/de/thedevstack/conversationsplus/entities/Conversation.java index 50b1e4a7..9e9366d7 100644 --- a/src/main/java/de/thedevstack/conversationsplus/entities/Conversation.java +++ b/src/main/java/de/thedevstack/conversationsplus/entities/Conversation.java @@ -317,14 +317,6 @@ public class Conversation extends AbstractEntity implements Blockable { setAttribute(ATTRIBUTE_CRYPTO_TARGETS, acceptedTargets); } - public void setCorrectingMessage(Message correctingMessage) { - this.correctingMessage = correctingMessage; - } - - public Message getCorrectingMessage() { - return this.correctingMessage; - } - public interface OnMessageFound { void onMessageFound(final Message message); } @@ -790,7 +782,7 @@ public class Conversation extends AbstractEntity implements Blockable { } public boolean alwaysNotify() { - return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY, Config.ALWAYS_NOTIFY_BY_DEFAULT || isPnNA()); + return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY, true); } public boolean setAttribute(String key, String value) { diff --git a/src/main/java/de/thedevstack/conversationsplus/entities/MucOptions.java b/src/main/java/de/thedevstack/conversationsplus/entities/MucOptions.java index 4a330f30..1af538ec 100644 --- a/src/main/java/de/thedevstack/conversationsplus/entities/MucOptions.java +++ b/src/main/java/de/thedevstack/conversationsplus/entities/MucOptions.java @@ -469,6 +469,9 @@ public class MucOptions { } public Jid getTrueCounterpart(String name) { + if (name.equals(getSelf().getName())) { + return account.getJid().toBareJid(); + } User user = findUser(name); return user == null ? null : user.getJid(); } diff --git a/src/main/java/de/thedevstack/conversationsplus/http/HttpUploadConnection.java b/src/main/java/de/thedevstack/conversationsplus/http/HttpUploadConnection.java index f28dee36..6c546fee 100644 --- a/src/main/java/de/thedevstack/conversationsplus/http/HttpUploadConnection.java +++ b/src/main/java/de/thedevstack/conversationsplus/http/HttpUploadConnection.java @@ -220,8 +220,12 @@ public class HttpUploadConnection implements Transferable { fail(); } } catch (IOException e) { - errorStream = connection.getErrorStream(); - Logging.e("httpupload", "http response: " + new Scanner(errorStream).useDelimiter("\\A").next() + ", exception message: " + e.getMessage()); + errorStream = (null != connection) ? connection.getErrorStream() : null; + String httpResponseMessage = null; + if (null != errorStream) { + httpResponseMessage = new Scanner(errorStream).useDelimiter("\\A").next(); + } + Logging.e("httpupload", ((null != httpResponseMessage) ? ("http response: " + httpResponseMessage + ", ") : "") + "exception message: " + e.getMessage()); fail(); } finally { StreamUtil.close(os); diff --git a/src/main/java/de/thedevstack/conversationsplus/parser/MessageParser.java b/src/main/java/de/thedevstack/conversationsplus/parser/MessageParser.java index c65df887..6fb18266 100644 --- a/src/main/java/de/thedevstack/conversationsplus/parser/MessageParser.java +++ b/src/main/java/de/thedevstack/conversationsplus/parser/MessageParser.java @@ -415,7 +415,7 @@ public class MessageParser extends AbstractParser implements || (isTypeGroupChat && packet.hasChild("delay","urn:xmpp:delay")) || message.getType() == Message.TYPE_PRIVATE; if (checkForDuplicates && conversation.hasDuplicateMessage(message)) { - Log.d(Config.LOGTAG,"skipping duplicate message from "+message.getCounterpart().toString()+" "+message.getBody()); + Logging.d(Config.LOGTAG, "skipping duplicate message from '" + message.getCounterpart().toString() + "' with remote id " + message.getRemoteMsgId()); return; } diff --git a/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java b/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java index 6311d739..ed9c259f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java @@ -31,14 +31,17 @@ import de.thedevstack.conversationsplus.entities.Message; import de.thedevstack.conversationsplus.entities.MucOptions; import de.thedevstack.conversationsplus.generator.IqGenerator; import de.thedevstack.conversationsplus.persistance.DatabaseBackend; +import de.thedevstack.conversationsplus.persistance.FileBackend; import de.thedevstack.conversationsplus.ui.UiCallback; import de.thedevstack.conversationsplus.utils.UIHelper; import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.xmpp.OnAdvancedStreamFeaturesLoaded; import de.thedevstack.conversationsplus.xmpp.OnIqPacketReceived; +import de.thedevstack.conversationsplus.xmpp.XmppConnection; import de.thedevstack.conversationsplus.xmpp.pep.Avatar; import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket; -public class AvatarService { +public class AvatarService implements OnAdvancedStreamFeaturesLoaded { private static final int FG_COLOR = 0xFFFAFAFA; private static final int TRANSPARENT = 0x00000000; @@ -408,6 +411,17 @@ public class AvatarService { return true; } + @Override + public void onAdvancedStreamFeaturesAvailable(Account account) { + XmppConnection.Features features = account.getXmppConnection().getFeatures(); + if (features.pep() && !features.pepPersistent()) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": has pep but is not persistent"); + if (account.getAvatar() != null) { + republishAvatarIfNeeded(account); + } + } + } + public void publishAvatar(final Account account, final Uri image, final UiCallback<Avatar> callback) { @@ -428,47 +442,79 @@ public class AvatarService { callback.error(R.string.error_saving_avatar, avatar); return; } - final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); - XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarMetadataPacket(avatar); - XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, - IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - if (account.setAvatar(avatar.getFilename())) { - AvatarService.getInstance().clear(account); - DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); - } - callback.success(avatar); - } else { - callback.error( - R.string.error_publish_avatar_server_reject, - avatar); - } - } - }); - } else { + sendAndReceiveIqPackages(avatar, account, callback); + } else { + callback.error(R.string.error_publish_avatar_converting, null); + } + } + + public void publishAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + sendAndReceiveIqPackages(avatar, account, callback); + } else { + if (callback != null) { callback.error( R.string.error_publish_avatar_server_reject, avatar); } } - }); - } else { - callback.error(R.string.error_publish_avatar_converting, null); - } + } + }); } private static String generateFetchKey(Account account, final Avatar avatar) { return account.getJid().toBareJid()+"_"+avatar.owner+"_"+avatar.sha1sum; } + public void republishAvatarIfNeeded(Account account) { + if (account.getAxolotlService().isPepBroken()) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping republication of avatar because pep is broken"); + return; + } + IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarMetadataPacket(null); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + private Avatar parseAvatar(IqPacket packet) { + Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub"); + if (pubsub != null) { + Element items = pubsub.findChild("items"); + if (items != null) { + return Avatar.parseMetadata(items); + } + } + return null; + } + + private boolean errorIsItemNotFound(IqPacket packet) { + Element error = packet.findChild("error"); + return packet.getType() == IqPacket.TYPE.ERROR + && error != null + && error.hasChild("item-not-found"); + } + + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT || errorIsItemNotFound(packet)) { + Avatar serverAvatar = parseAvatar(packet); + if (serverAvatar == null && account.getAvatar() != null) { + Avatar avatar = AvatarUtil.getStoredPepAvatar(account.getAvatar()); + if (avatar != null) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": avatar on server was null. republishing"); + publishAvatar(account, AvatarUtil.getStoredPepAvatar(account.getAvatar()), null); + } else { + Logging.e(Config.LOGTAG, account.getJid().toBareJid()+": error rereading avatar"); + } + } + } + } + }); + } + public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { final String KEY = generateFetchKey(account, avatar); synchronized(this.mInProgressAvatarFetches) { @@ -624,4 +670,40 @@ public class AvatarService { } } } + + private void sendAndReceiveIqPackages(final Avatar avatar, final Account account, final UiCallback callback) { + + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarMetadataPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, + IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + if (account.setAvatar(avatar.getFilename())) { + AvatarService.getInstance().clear(account); + DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); + } + callback.success(avatar); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } } diff --git a/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java b/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java index 8d48d686..6256609c 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java @@ -48,7 +48,7 @@ public class ContactChooserTargetService extends ChooserTargetService implements final Conversation conversation = conversations.get(i); final String name = conversation.getName(); final Icon icon = Icon.createWithBitmap(AvatarService.getInstance().get(conversation, pixel)); - final float score = (1.0f / MAX_TARGETS) * i; + final float score = 1 - (1.0f / MAX_TARGETS) * i; final Bundle extras = new Bundle(); extras.putString("uuid", conversation.getUuid()); chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras)); diff --git a/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java b/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java index f2298d8c..cd55b42f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java @@ -45,8 +45,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } - long startCatchup = getLastMessageTransmitted(account); + Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); + long startCatchup = pair == null ? 0 : pair.first; long endCatchup = account.getXmppConnection().getLastSessionEstablished(); + final Query query; if (startCatchup == 0) { return; } else if (endCatchup - startCatchup >= Config.MAM_MAX_CATCHUP) { @@ -57,8 +59,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.query(conversation,startCatchup); } } + query = new Query(account, startCatchup, endCatchup); + } else { + query = new Query(account, startCatchup, endCatchup); + query.reference = pair.second; } - final Query query = new Query(account, startCatchup, endCatchup); this.queries.add(query); this.execute(query); } @@ -75,11 +80,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } - private long getLastMessageTransmitted(final Account account) { - Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); - return pair == null ? 0 : pair.first; - } - public Query query(final Conversation conversation) { if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) { return query(conversation, @@ -292,7 +292,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.end = end; this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); } - + private Query page(String reference) { Query query = new Query(this.account,this.start,this.end); query.reference = reference; diff --git a/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java b/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java index 1baec3a5..a3142df4 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java @@ -176,6 +176,7 @@ public class NotificationService { final String ringtone = ConversationsPlusPreferences.notificationRingtone(); final boolean vibrate = ConversationsPlusPreferences.vibrateOnNotification(); + final boolean led = ConversationsPlusPreferences.led(); if (notifications.size() == 0) { notificationManager.cancel(NOTIFICATION_ID); @@ -206,7 +207,9 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(Settings.LED_COLOR, 2000, 4000); + if (led) { + mBuilder.setLights(Settings.LED_COLOR, 2000, 4000); + } final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } @@ -537,7 +540,7 @@ public class NotificationService { errors.add(account); } } - if (mXmppConnectionService.getPreferences().getBoolean("keep_foreground_service", false)) { + if (ConversationsPlusPreferences.keepForegroundService()) { notificationManager.notify(FOREGROUND_NOTIFICATION_ID, createForegroundNotification()); } final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService); diff --git a/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java b/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java index d92401ba..c1426080 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java @@ -455,7 +455,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } return START_STICKY; case Intent.ACTION_SHUTDOWN: - logoutAndSave(); + logoutAndSave(true); return START_NOT_STICKY; case ACTION_CLEAR_NOTIFICATION: mNotificationService.clear(); @@ -481,13 +481,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } break; case AudioManager.RINGER_MODE_CHANGED_ACTION: - if (xaOnSilentMode()) { + if (ConversationsPlusPreferences.xaOnSilentMode()) { refreshAllPresences(); } break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_SCREEN_ON: - if (awayWhenScreenOff()) { + if (ConversationsPlusPreferences.awayWhenScreenOff()) { refreshAllPresences(); } break; @@ -572,22 +572,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return START_STICKY; } - private boolean xaOnSilentMode() { - return getPreferences().getBoolean("xa_on_silent_mode", false); - } - - private boolean treatVibrateAsSilent() { - return getPreferences().getBoolean("treat_vibrate_as_silent", false); - } - - private boolean awayWhenScreenOff() { - return getPreferences().getBoolean("away_when_screen_off", false); - } - private Presence.Status getTargetPresence() { - if (xaOnSilentMode() && isPhoneSilenced()) { + if (ConversationsPlusPreferences.xaOnSilentMode() && isPhoneSilenced()) { return Presence.Status.XA; - } else if (awayWhenScreenOff() && !isInteractive()) { + } else if (ConversationsPlusPreferences.awayWhenScreenOff() && !isInteractive()) { return Presence.Status.AWAY; } else { return Presence.Status.ONLINE; @@ -610,7 +598,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private boolean isPhoneSilenced() { AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (treatVibrateAsSilent()) { + if (ConversationsPlusPreferences.treatVibrateAsSilent()) { return audioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; } else { return audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT; @@ -725,7 +713,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void toggleScreenEventReceiver() { - if (awayWhenScreenOff()) { + if (ConversationsPlusPreferences.awayWhenScreenOff()) { final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(this.mEventReceiver, filter); @@ -750,12 +738,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); if (!ConversationsPlusPreferences.keepForegroundService()) { - this.logoutAndSave(); + this.logoutAndSave(false); } } - private void logoutAndSave() { + private void logoutAndSave(boolean stop) { + int activeAccounts = 0; for (final Account account : accounts) { + if (account.getStatus() != Account.State.DISABLED) { + activeAccounts++; + } databaseBackend.writeRoster(account.getRoster()); if (account.getXmppConnection() != null) { new Thread(new Runnable() { @@ -764,11 +756,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa disconnect(account, false); } }).start(); - cancelWakeUpCall(account.getUuid().hashCode()); } } - Logging.d(Config.LOGTAG, "good bye"); - stopSelf(); + if (stop || activeAccounts == 0) { + Logging.d(Config.LOGTAG, "good bye"); + stopSelf(); + } } private void cancelWakeUpCall(int requestCode) { @@ -801,6 +794,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa connection.setOnBindListener(this.mOnBindListener); connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener); connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService); + connection.addOnAdvancedStreamFeaturesAvailableListener(AvatarService.getInstance()); AxolotlService axolotlService = account.getAxolotlService(); if (axolotlService != null) { connection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService); @@ -967,7 +961,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (addToConversation) { conversation.add(message); } - if (message.getEncryption() == Message.ENCRYPTION_NONE || saveEncryptedMessages()) { + if (message.getEncryption() == Message.ENCRYPTION_NONE || !ConversationsPlusPreferences.dontSaveEncrypted()) { if (saveInDb) { databaseBackend.createMessage(message); } else if (message.edited()) { @@ -992,11 +986,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private void sendUnsentMessages(final Conversation conversation) { conversation.findWaitingMessages(new Conversation.OnMessageFound() { - @Override - public void onMessageFound(Message message) { - resendMessage(message, true); - } - }); + @Override + public void onMessageFound(Message message) { + resendMessage(message, true); + } + }); } public void resendMessage(final Message message, final boolean delay) { @@ -1027,7 +1021,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final Element query = packet.query(); final HashMap<Jid, Bookmark> bookmarks = new HashMap<>(); final Element storage = query.findChild("storage", "storage:bookmarks"); - final boolean autojoin = respectAutojoin(); if (storage != null) { for (final Element item : storage.getChildren()) { if (item.getName().equals("conference")) { @@ -1039,7 +1032,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Conversation conversation = find(bookmark); if (conversation != null) { conversation.setBookmark(bookmark); - } else if (bookmark.autojoin() && bookmark.getJid() != null && autojoin) { + } else if (bookmark.autojoin() && bookmark.getJid() != null && ConversationsPlusPreferences.autojoin()) { conversation = findOrCreateConversation( account, bookmark.getJid(), true); conversation.setBookmark(bookmark); @@ -1219,19 +1212,19 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } Collections.sort(list, new Comparator<Conversation>() { - @Override - public int compare(Conversation lhs, Conversation rhs) { - Message left = lhs.getLatestMessage(); - Message right = rhs.getLatestMessage(); - if (left.getTimeSent() > right.getTimeSent()) { - return -1; - } else if (left.getTimeSent() < right.getTimeSent()) { - return 1; - } else { - return 0; - } - } - }); + @Override + public int compare(Conversation lhs, Conversation rhs) { + Message left = lhs.getLatestMessage(); + Message right = rhs.getLatestMessage(); + if (left.getTimeSent() > right.getTimeSent()) { + return -1; + } else if (left.getTimeSent() < right.getTimeSent()) { + return 1; + } else { + return 0; + } + } + }); } public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) { @@ -1380,7 +1373,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (conversation.getMode() == Conversation.MODE_MULTI) { if (conversation.getAccount().getStatus() == Account.State.ONLINE) { Bookmark bookmark = conversation.getBookmark(); - if (bookmark != null && bookmark.autojoin() && respectAutojoin()) { + if (bookmark != null && bookmark.autojoin() && ConversationsPlusPreferences.autojoin()) { bookmark.setAutojoin(false); pushBookmarks(bookmark.getAccount()); } @@ -1886,9 +1879,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (conversation.getMode() == Conversation.MODE_MULTI) { conversation.getMucOptions().setPassword(password); if (conversation.getBookmark() != null) { - if (respectAutojoin()) { - conversation.getBookmark().setAutojoin(true); - } + conversation.getBookmark().setAutojoin(ConversationsPlusPreferences.autojoin()); pushBookmarks(conversation.getAccount()); } databaseBackend.updateConversation(conversation); @@ -2240,9 +2231,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final Account account = conversation.getAccount(); final Session otrSession = conversation.getOtrSession(); Logging.d(Config.LOGTAG, - account.getJid().toBareJid() + " otr session established with " - + conversation.getJid() + "/" - + otrSession.getSessionID().getUserID()); + account.getJid().toBareJid() + " otr session established with " + + conversation.getJid() + "/" + + otrSession.getSessionID().getUserID()); conversation.findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR, new Conversation.OnMessageFound() { @Override @@ -2280,7 +2271,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa packet.setFrom(account.getJid()); MessageGenerator.addMessageHints(packet); packet.setAttribute("to", otrSession.getSessionID().getAccountID() + "/" - + otrSession.getSessionID().getUserID()); + + otrSession.getSessionID().getUserID()); try { packet.setBody(otrSession .transformSending(CryptoHelper.FILETRANSFER @@ -2346,12 +2337,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!force) { disconnect(account, false); - try { - Logging.d(Config.LOGTAG, "wait for disconnect"); - Thread.sleep(500); //sleep wait for disconnect - } catch (InterruptedException e) { - //ignored - } } Thread thread = new Thread(connection); connection.setInteractive(interactive); @@ -2362,6 +2347,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa disconnect(account, force); account.getRoster().clearPresences(); connection.resetEverything(); + account.getAxolotlService().resetBrokenness(); } } } @@ -2441,23 +2427,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa updateConversationUi(); } - public SharedPreferences getPreferences() { - return PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - } - - public boolean saveEncryptedMessages() { - return !getPreferences().getBoolean("dont_save_encrypted", false); - } - - private boolean respectAutojoin() { - return getPreferences().getBoolean("autojoin", true); - } - - public boolean showExtendedConnectionOptions() { - return getPreferences().getBoolean("show_connection_options", false); - } - public int unreadCount() { int count = 0; for (Conversation conversation : getConversations()) { diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java index 12ff2a52..2a3cd7fe 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java @@ -3,8 +3,10 @@ package de.thedevstack.conversationsplus.ui; import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.PendingIntent; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.content.IntentSender.SendIntentException; import android.os.Build; import android.os.Bundle; @@ -30,6 +32,7 @@ import java.util.Comparator; import java.util.concurrent.atomic.AtomicInteger; import de.thedevstack.conversationsplus.Config; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; import de.thedevstack.conversationsplus.R; import de.thedevstack.conversationsplus.crypto.PgpEngine; import de.thedevstack.conversationsplus.entities.Account; @@ -262,7 +265,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }); } }); - this.mAdvancedMode = getPreferences().getBoolean("advanced_muc_mode", false); + this.mAdvancedMode = ConversationsPlusPreferences.advancedMucMode(); this.mConferenceInfoTable = (TableLayout) findViewById(R.id.muc_info_more); mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); this.mConferenceInfoMam = (TextView) findViewById(R.id.muc_info_mam); @@ -282,6 +285,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers quickEdit(mConversation.getName(),this.onSubjectEdited); } break; + case R.id.action_share: + share(); + break; case R.id.action_save_as_bookmark: saveAsBookmark(); break; @@ -291,7 +297,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers case R.id.action_advanced_mode: this.mAdvancedMode = !menuItem.isChecked(); menuItem.setChecked(this.mAdvancedMode); - getPreferences().edit().putBoolean("advanced_muc_mode", mAdvancedMode).commit(); + ConversationsPlusPreferences.commitAdvancedMucMode(mAdvancedMode); mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); invalidateOptionsMenu(); updateView(); @@ -309,6 +315,18 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } + private void share() { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_TEXT, getShareableUri()); + shareIntent.setType("text/plain"); + try { + startActivity(Intent.createChooser(shareIntent, getText(R.string.share_uri_with))); + } catch (ActivityNotFoundException e) { + Toast.makeText(this, R.string.no_application_to_share_uri, Toast.LENGTH_SHORT).show(); + } + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark); @@ -468,7 +486,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers bookmark.setNick(mConversation.getJid().getResourcepart()); } bookmark.setBookmarkName(mConversation.getMucOptions().getSubject()); - bookmark.setAutojoin(getPreferences().getBoolean("autojoin",true)); + bookmark.setAutojoin(ConversationsPlusPreferences.autojoin()); account.getBookmarks().add(bookmark); xmppConnectionService.pushBookmarks(account); mConversation.setBookmark(bookmark); diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java index dbaa5a7c..e46095e7 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java @@ -113,6 +113,7 @@ public class ConversationActivity extends XmppActivity private Message mPendingDownloadableMessage = null; private boolean conversationWasSelectedByKeyboard = false; + protected boolean mUsingEnterKey = false; private View mContentView; private View avatarLogoView; @@ -190,6 +191,7 @@ public class ConversationActivity extends XmppActivity mPendingImageUris.add(Uri.parse(pending)); } } + this.mUsingEnterKey = ConversationsPlusPreferences.displayEnterKey(); setContentView(R.layout.fragment_conversations_overview); @@ -337,12 +339,12 @@ public class ConversationActivity extends XmppActivity public void switchToConversation(Conversation conversation) { setSelectedConversation(conversation); runOnUiThread(new Runnable() { - @Override - public void run() { - ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); - openConversation(); - } - }); + @Override + public void run() { + ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); + openConversation(); + } + }); } private void updateActionBarTitle() { @@ -776,19 +778,19 @@ public class ConversationActivity extends XmppActivity builder.setView(dialogView); builder.setNegativeButton(getString(R.string.cancel), null); builder.setPositiveButton(getString(R.string.delete_messages), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - ConversationActivity.this.xmppConnectionService.clearConversationHistory(conversation); - if (endConversationCheckBox.isChecked()) { - endConversation(conversation); - } else { - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - } - } - }); + new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + ConversationActivity.this.xmppConnectionService.clearConversationHistory(conversation); + if (endConversationCheckBox.isChecked()) { + endConversation(conversation); + } else { + updateConversationList(); + ConversationActivity.this.mConversationFragment.updateMessages(); + } + } + }); builder.create().show(); } @@ -959,24 +961,24 @@ public class ConversationActivity extends XmppActivity builder.setTitle(R.string.disable_notifications); final int[] durations = getResources().getIntArray(R.array.mute_options_durations); builder.setItems(R.array.mute_options_descriptions, - new OnClickListener() { - - @Override - public void onClick(final DialogInterface dialog, final int which) { - final long till; - if (durations[which] == -1) { - till = Long.MAX_VALUE; - } else { - till = System.currentTimeMillis() + (durations[which] * 1000); - } - conversation.setMutedTill(till); - ConversationActivity.this.xmppConnectionService.databaseBackend - .updateConversation(conversation); - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - invalidateOptionsMenu(); - } - }); + new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + final long till; + if (durations[which] == -1) { + till = Long.MAX_VALUE; + } else { + till = System.currentTimeMillis() + (durations[which] * 1000); + } + conversation.setMutedTill(till); + ConversationActivity.this.xmppConnectionService.databaseBackend + .updateConversation(conversation); + updateConversationList(); + ConversationActivity.this.mConversationFragment.updateMessages(); + invalidateOptionsMenu(); + } + }); builder.create().show(); } @@ -1372,10 +1374,6 @@ public class ConversationActivity extends XmppActivity } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) { final List<Uri> uris = extractUriFromIntent(data); final Conversation c = getSelectedConversation(); - final long max = c.getAccount() - .getXmppConnection() - .getFeatures() - .getMaxHttpUploadSize(); final OnPresenceSelected callback = new OnPresenceSelected() { @Override public void onPresenceSelected() { @@ -1389,7 +1387,7 @@ public class ConversationActivity extends XmppActivity } }; if (c.getMode() == Conversation.MODE_MULTI - || FileUtils.allFilesUnderSize(this, uris, max) + || FileUtils.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c)) || c.getNextEncryption() == Message.ENCRYPTION_OTR) { callback.onPresenceSelected(); } else { @@ -1433,19 +1431,20 @@ public class ConversationActivity extends XmppActivity mConversationFragment.onActivityResult(requestCode, resultCode, data); } if (requestCode == REQUEST_BATTERY_OP) { - setNeverAskForBatteryOptimizationsAgain(); + // Never Ask For Battery Optimizations Again + ConversationsPlusPreferences.commitShowBatteryOptimization(false); } } } - private void setNeverAskForBatteryOptimizationsAgain() { - getPreferences().edit().putBoolean("show_battery_optimization", false).commit(); + private long getMaxHttpUploadSize(Conversation conversation) { + return conversation.getAccount().getXmppConnection().getFeatures().getMaxHttpUploadSize(); } private void openBatteryOptimizationDialogIfNeeded() { if (hasAccountWithoutPush() && isOptimizingBattery() - && getPreferences().getBoolean("show_battery_optimization", true)) { + && ConversationsPlusPreferences.showBatteryOptimization()) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.battery_optimizations_enabled); builder.setMessage(R.string.battery_optimizations_enabled_dialog); @@ -1462,7 +1461,7 @@ public class ConversationActivity extends XmppActivity builder.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { - setNeverAskForBatteryOptimizationsAgain(); + ConversationsPlusPreferences.commitShowBatteryOptimization(false); } }); } diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java index 7c5f6ffa..4ae88a5e 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java @@ -313,10 +313,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa public void setupIme() { if (activity == null) { return; - } else if (activity.usingEnterKey() && ConversationsPlusPreferences.enterIsSend()) { + } else if (ConversationsPlusPreferences.displayEnterKey() && ConversationsPlusPreferences.enterIsSend()) { mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE)); mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); - } else if (activity.usingEnterKey()) { + } else if (ConversationsPlusPreferences.displayEnterKey()) { mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); } else { diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java index 2b8e619f..1a868949 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java @@ -39,6 +39,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import de.thedevstack.conversationsplus.ConversationsPlusColors; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; import de.thedevstack.conversationsplus.Config; import de.thedevstack.conversationsplus.R; @@ -246,12 +247,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate mFetchingAvatar = true; AvatarService.getInstance().checkForAvatar(mAccount, mAvatarFetchCallback); } - } else { - updateSaveButton(); } if (mAccount != null) { updateAccountInformation(false); } + updateSaveButton(); } @Override @@ -522,8 +522,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } } } - SharedPreferences preferences = getPreferences(); - this.mShowOptions = preferences.getBoolean("show_connection_options", false); + this.mShowOptions = ConversationsPlusPreferences.showConnectionOptions(); this.mNamePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE); } @@ -531,6 +530,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate protected void onBackendConnected() { if (this.jidToEdit != null) { this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit); + this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); if (this.mAccount != null) { if (this.mAccount.getPrivateKeyAlias() != null) { this.mPassword.setHint(R.string.authenticate_with_certificate); @@ -625,6 +625,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (!mInitMode) { this.mAvatar.setVisibility(View.VISIBLE); this.mAvatar.setImageBitmap(AvatarService.getInstance().get(this.mAccount, getPixel(72))); + } else { + this.mAvatar.setVisibility(View.GONE); } if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) { this.mRegisterNew.setVisibility(View.VISIBLE); diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java index d15b59c6..fe7968cb 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java @@ -2,27 +2,55 @@ package de.thedevstack.conversationsplus.ui; import android.app.Activity; import android.os.Bundle; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import de.thedevstack.android.logcat.adapters.LogCatArrayAdapter; import de.thedevstack.android.logcat.tasks.ReadLogCatAsyncTask; -import de.thedevstack.android.logcat.ui.LogCatOutputCopyOnClickListener; import de.thedevstack.conversationsplus.R; +import de.thedevstack.conversationsplus.ui.listeners.LogCatOutputCopyOnClickListener; +import de.thedevstack.conversationsplus.utils.ClipboardUtil; /** - * Created by tzur on 07.10.2015. + * Activity to display the logcat output. */ public class LogCatOutputActivity extends Activity { + /** + * List adapter containing the logcat entries. + */ + private LogCatArrayAdapter logCatArrayAdapter; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_logcatoutput); ListView lv = (ListView)findViewById(R.id.actLogInfoOutput); - LogCatArrayAdapter logCatOutputAdapter = new LogCatArrayAdapter(this, R.layout.list_item_logcatoutput); - lv.setAdapter(logCatOutputAdapter); - new ReadLogCatAsyncTask(logCatOutputAdapter).execute(); + this.logCatArrayAdapter = new LogCatArrayAdapter(this, R.layout.list_item_logcatoutput); + lv.setAdapter(this.logCatArrayAdapter); + new ReadLogCatAsyncTask(this.logCatArrayAdapter).execute(); Button copyButton = (Button) findViewById(R.id.actLogOutputCopyButton); - copyButton.setOnClickListener(new LogCatOutputCopyOnClickListener(this, logCatOutputAdapter, R.string.cplus_copied_to_clipboard, R.string.cplus_not_copied_to_clipboard_empty)); + copyButton.setOnClickListener(new LogCatOutputCopyOnClickListener(this.logCatArrayAdapter)); + registerForContextMenu(lv); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + menu.add(0, 123456789, 0, R.string.cplus_copy_item); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + if (123456789 == item.getItemId()) { + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + String itemText = this.logCatArrayAdapter.getItems().get(info.position); + ClipboardUtil.copyToClipboard(itemText); + return true; + } + return super.onContextItemSelected(item); } } diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java index 51fe92bb..fe3ed73f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java @@ -37,6 +37,8 @@ import de.thedevstack.conversationsplus.xmpp.jid.Jid; public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate { + private boolean mReturnToPrevious = false; + @Override public void onConversationUpdate() { refreshUi(); @@ -85,7 +87,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer resId = R.string.shared_file_with_x; } replaceToast(getString(resId, message.getConversation().getName())); - if (share.uuid != null) { + if (mReturnToPrevious) { finish(); } else { switchToConversation(message.getConversation()); @@ -186,6 +188,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer if (intent == null) { return; } + this.mReturnToPrevious = ConversationsPlusPreferences.returnToPrevious(); final String type = intent.getType(); final String action = intent.getAction(); Log.d(Config.LOGTAG, "action: "+action+ ", type:"+type); @@ -306,8 +309,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer }; } if (account.httpUploadAvailable() - && ((share.image && !neverCompressPictures()) - || conversation.getMode() == Conversation.MODE_MULTI + && (conversation.getMode() == Conversation.MODE_MULTI || FileUtils.allFilesUnderSize(this, share.uris, max)) && conversation.getNextEncryption() != Message.ENCRYPTION_OTR) { callback.onPresenceSelected(); @@ -315,8 +317,28 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer selectPresence(conversation, callback); } } else { - switchToConversation(conversation, this.share.text, true); - finish(); + if (mReturnToPrevious && this.share.text != null && !this.share.text.isEmpty() ) { + final OnPresenceSelected callback = new OnPresenceSelected() { + @Override + public void onPresenceSelected() { + Message message = new Message(conversation,share.text, conversation.getNextEncryption()); + if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) { + message.setCounterpart(conversation.getNextCounterpart()); + } + xmppConnectionService.sendMessage(message); + replaceToast(getString(R.string.shared_text_with_x, conversation.getName())); + finish(); + } + }; + if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) { + selectPresence(conversation, callback); + } else { + callback.onPresenceSelected(); + } + } else { + switchToConversation(conversation, this.share.text, true); + finish(); + } } } diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java index bd3dd684..2dc8d1a5 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java @@ -288,7 +288,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU if (!conversation.getMucOptions().online()) { xmppConnectionService.joinMuc(conversation); } - if (!bookmark.autojoin() && getPreferences().getBoolean("autojoin", true)) { + if (!bookmark.autojoin() && ConversationsPlusPreferences.autojoin()) { bookmark.setAutojoin(true); xmppConnectionService.pushBookmarks(bookmark.getAccount()); } @@ -438,7 +438,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU jid.setError(getString(R.string.bookmark_already_exists)); } else { final Bookmark bookmark = new Bookmark(account, conferenceJid.toBareJid()); - bookmark.setAutojoin(getPreferences().getBoolean("autojoin", true)); + bookmark.setAutojoin(ConversationsPlusPreferences.autojoin()); String nick = conferenceJid.getResourcepart(); if (nick != null && !nick.isEmpty()) { bookmark.setNick(nick); diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java index f2ee20a0..726facac 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java @@ -104,11 +104,8 @@ public abstract class XmppActivity extends Activity { public boolean xmppConnectionServiceBound = false; protected boolean registeredListeners = false; - protected boolean mUseSubject = true; - private DisplayMetrics metrics; protected int mTheme; - protected boolean mUsingEnterKey = false; private long mLastUiRefresh = 0; private Handler mRefreshUiHandler = new Handler(); @@ -353,8 +350,6 @@ public abstract class XmppActivity extends Activity { ExceptionHelper.init(getApplicationContext()); this.mTheme = findTheme(); setTheme(this.mTheme); - this.mUsingEnterKey = ConversationsPlusPreferences.displayEnterKey(); - mUseSubject = getPreferences().getBoolean("use_subject", true); final ActionBar ab = getActionBar(); if (ab!=null) { ab.setDisplayHomeAsUpEnabled(true); @@ -383,19 +378,6 @@ public abstract class XmppActivity extends Activity { } } - protected boolean usingEnterKey() { - return getPreferences().getBoolean("display_enter_key", false); - } - - protected SharedPreferences getPreferences() { - return PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - } - - public boolean useSubjectToIdentifyConference() { - return mUseSubject; - } - public void switchToConversation(Conversation conversation) { switchToConversation(conversation, null, false); } @@ -957,10 +939,6 @@ public abstract class XmppActivity extends Activity { } } - protected boolean neverCompressPictures() { - return getPreferences().getString("picture_compression", "auto").equals("never"); - } - protected void unregisterNdefPushMessageCallback() { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null && nfcAdapter.isEnabled()) { diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java index 2b2d9298..e28774f2 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.concurrent.RejectedExecutionException; import de.thedevstack.conversationsplus.ConversationsPlusColors; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; import de.tzur.conversations.Settings; import de.thedevstack.conversationsplus.R; @@ -58,7 +59,7 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> { view.findViewById(R.id.conversationListRowFrame).setBackgroundColor(c); } TextView convName = (TextView) view.findViewById(R.id.conversation_name); - if (conversation.getMode() == Conversation.MODE_SINGLE || activity.useSubjectToIdentifyConference()) { + if (conversation.getMode() == Conversation.MODE_SINGLE || ConversationsPlusPreferences.useSubject()) { convName.setText(conversation.getName()); } else { convName.setText(conversation.getJid().toBareJid().toString()); diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/LogCatOutputCopyOnClickListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/LogCatOutputCopyOnClickListener.java new file mode 100644 index 00000000..f71c67db --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/LogCatOutputCopyOnClickListener.java @@ -0,0 +1,41 @@ +package de.thedevstack.conversationsplus.ui.listeners; + +import android.view.View; + +import java.util.List; + +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.android.logcat.adapters.LogCatArrayAdapter; +import de.thedevstack.conversationsplus.utils.ClipboardUtil; + +/** + * OnClickListener to copy logcat entries from LogCatArrayAdapter to clipboard. + */ +public class LogCatOutputCopyOnClickListener implements View.OnClickListener { + private final LogCatArrayAdapter logCatOutputAdapter; + + public LogCatOutputCopyOnClickListener(LogCatArrayAdapter logCatOutputAdapter) { + this.logCatOutputAdapter = logCatOutputAdapter; + } + + /** + * Copies the entries of LogCatArrayAdapter separated by a new line to the clipboard. + * + * @param v The view that was clicked. + */ + @Override + public void onClick(View v) { + Logging.d("copylogcat", "Start Copying log cat"); + List<String> items = this.logCatOutputAdapter.getItems(); + String textToCopy = null; + if (null != items && !items.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String item : items) { + sb.append(item); + sb.append("\n"); + } + textToCopy = sb.toString(); + } + ClipboardUtil.copyToClipboard("c+logcat", textToCopy); + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java index 206ee668..9f6071bb 100644 --- a/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java +++ b/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java @@ -1,12 +1,14 @@ package de.thedevstack.conversationsplus.utils; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.util.Base64; import android.util.Base64OutputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -59,6 +61,44 @@ public final class AvatarUtil { } catch (IOException e) { return null; } + + } + + public static Avatar getStoredPepAvatar(String hash) { + if (hash == null) { + return null; + } + Avatar avatar = new Avatar(); + File file = new File(getAvatarPath(hash)); + FileInputStream is = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + is = new FileInputStream(file); + ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); + Base64OutputStream mBase64OutputStream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + DigestOutputStream os = new DigestOutputStream(mBase64OutputStream, digest); + byte[] buffer = new byte[4096]; + int length; + while ((length = is.read(buffer)) > 0) { + os.write(buffer, 0, length); + } + os.flush(); + os.close(); + avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); + avatar.image = new String(mByteArrayOutputStream.toByteArray()); + avatar.height = options.outHeight; + avatar.width = options.outWidth; + return avatar; + } catch (IOException e) { + return null; + } catch (NoSuchAlgorithmException e) { + return null; + } finally { + StreamUtil.close(is); + } } /** diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/ClipboardUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/ClipboardUtil.java new file mode 100644 index 00000000..1ef7cba9 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/ClipboardUtil.java @@ -0,0 +1,47 @@ +package de.thedevstack.conversationsplus.utils; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.widget.Toast; + +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.R; + +/** + * Util class to work with the Clipboard. + */ +public final class ClipboardUtil { + private static final String CLIPBOARD_LABEL = "c+clipboard"; + + /** + * Copies a text to the clipboard. + * @param clipboardLabel the label to show to a user to allow identifying the text in clipboard. + * @param text the text to copy + */ + public static void copyToClipboard(String clipboardLabel, String text) { + Context context = ConversationsPlusApplication.getAppContext(); + if (null != text && !text.isEmpty()) { + String label = (null == clipboardLabel) ? CLIPBOARD_LABEL : clipboardLabel; + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(label, text); + clipboard.setPrimaryClip(clip); + Toast.makeText(context, R.string.cplus_copied_to_clipboard, Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(context, R.string.cplus_not_copied_to_clipboard_empty, Toast.LENGTH_LONG).show(); + } + + } + + /** + * Copies a text to the clipboard. + * @param text the text to copy + */ + public static void copyToClipboard(String text) { + copyToClipboard(CLIPBOARD_LABEL, text); + } + + private ClipboardUtil() { + // helper class - avoid instantiation + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/Xmlns.java b/src/main/java/de/thedevstack/conversationsplus/utils/Xmlns.java index f937e35f..35adf6ec 100644 --- a/src/main/java/de/thedevstack/conversationsplus/utils/Xmlns.java +++ b/src/main/java/de/thedevstack/conversationsplus/utils/Xmlns.java @@ -7,5 +7,5 @@ public final class Xmlns { public static final String ROSTER = "jabber:iq:roster"; public static final String REGISTER = "jabber:iq:register"; public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; - public static final String HTTP_UPLOAD = Config.LEGACY_NAMESPACE_HTTP_UPLOAD ? "eu:siacs:conversations:http:upload" : "urn:xmpp:http:upload"; + public static final String HTTP_UPLOAD = "urn:xmpp:http:upload"; } diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java index 58352d4f..a89f308f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java @@ -37,6 +37,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; @@ -48,6 +50,7 @@ import javax.net.ssl.X509TrustManager; import de.duenndns.ssl.MemorizingTrustManager; import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; import de.thedevstack.conversationsplus.dto.SrvRecord; import de.thedevstack.conversationsplus.Config; import de.thedevstack.conversationsplus.crypto.XmppDomainVerifier; @@ -113,7 +116,9 @@ public class XmppConnection implements Runnable { private long lastConnect = 0; private long lastSessionStarted = 0; private long lastDiscoStarted = 0; - private int mPendingServiceDiscoveries = 0; + private AtomicInteger mPendingServiceDiscoveries = new AtomicInteger(0); + private AtomicBoolean mIsServiceItemsDiscoveryPending = new AtomicBoolean(true); + private boolean mWaitForDisco = true; private final ArrayList<String> mPendingServiceDiscoveriesIds = new ArrayList<>(); private boolean mInteractive = false; private int attempt = 0; @@ -245,7 +250,7 @@ public class XmppConnection implements Runnable { tagReader = new XmlReader(wakeLock); tagWriter = new TagWriter(); this.changeStatus(Account.State.CONNECTING); - final boolean extended = mXmppConnectionService.showExtendedConnectionOptions(); + final boolean extended = ConversationsPlusPreferences.showConnectionOptions(); if (extended && account.getHostname() != null && !account.getHostname().isEmpty()) { socket = new Socket(); try { @@ -525,7 +530,6 @@ public class XmppConnection implements Runnable { } nextTag = tagReader.readTag(); } - throw new IOException("reached end of stream. last tag was "+nextTag); } private void acknowledgeStanzaUpTo(int serverCount) { @@ -711,42 +715,7 @@ public class XmppConnection implements Runnable { } else if (this.streamFeatures.hasChild("mechanisms") && shouldAuthenticate && (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS)) { - final List<String> mechanisms = extractMechanisms(streamFeatures - .findChild("mechanisms")); - final Element auth = new Element("auth"); - auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); - if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) { - saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG()); - } else if (mechanisms.contains("SCRAM-SHA-1")) { - saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG()); - } else if (mechanisms.contains("PLAIN")) { - saslMechanism = new Plain(tagWriter, account); - } else if (mechanisms.contains("DIGEST-MD5")) { - saslMechanism = new DigestMd5(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()) { - Logging.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) { - Logging.d(Config.LOGTAG, "Parse error while checking pinned auth mechanism"); - } - Logging.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism()); - auth.setAttribute("mechanism", saslMechanism.getMechanism()); - if (!saslMechanism.getClientFirstMessage().isEmpty()) { - auth.setContent(saslMechanism.getClientFirstMessage()); - } - tagWriter.writeElement(auth); - } else { - throw new IncompatibleServerException(); - } + authenticate(); } else if (this.streamFeatures.hasChild("sm", "urn:xmpp:sm:" + smVersion) && streamId != null) { if (Config.EXTENDED_SM_LOGGING) { Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": resuming after stanza #"+stanzasReceived); @@ -762,6 +731,45 @@ public class XmppConnection implements Runnable { } } + private void authenticate() throws IOException { + final List<String> mechanisms = extractMechanisms(streamFeatures + .findChild("mechanisms")); + final Element auth = new Element("auth"); + auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); + if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) { + saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG()); + } else if (mechanisms.contains("SCRAM-SHA-1")) { + saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG()); + } else if (mechanisms.contains("PLAIN")) { + saslMechanism = new Plain(tagWriter, account); + } else if (mechanisms.contains("DIGEST-MD5")) { + saslMechanism = new DigestMd5(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()) { + Logging.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) { + Logging.d(Config.LOGTAG, "Parse error while checking pinned auth mechanism"); + } + Logging.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism()); + auth.setAttribute("mechanism", saslMechanism.getMechanism()); + if (!saslMechanism.getClientFirstMessage().isEmpty()) { + auth.setContent(saslMechanism.getClientFirstMessage()); + } + tagWriter.writeElement(auth); + } else { + throw new IncompatibleServerException(); + } + } + private List<String> extractMechanisms(final Element stream) { final ArrayList<String> mechanisms = new ArrayList<>(stream .getChildren().size()); @@ -979,11 +987,12 @@ public class XmppConnection implements Runnable { synchronized (this.disco) { this.disco.clear(); } - mPendingServiceDiscoveries = mServerIdentity == Identity.NIMBUZZ ? 1 : 0; + mPendingServiceDiscoveries.set(0); + mIsServiceItemsDiscoveryPending.set(true); + mWaitForDisco = mServerIdentity != Identity.NIMBUZZ; lastDiscoStarted = SystemClock.elapsedRealtime(); Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": starting service discovery"); mXmppConnectionService.scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode()); - sendServiceDiscoveryItems(account.getServer()); Element caps = streamFeatures.findChild("c"); final String hash = caps == null ? null : caps.getAttribute("hash"); final String ver = caps == null ? null : caps.getAttribute("ver"); @@ -998,13 +1007,15 @@ public class XmppConnection implements Runnable { disco.put(account.getServer(), discoveryResult); } sendServiceDiscoveryInfo(account.getJid().toBareJid()); + sendServiceDiscoveryItems(account.getServer()); + if (!mWaitForDisco) { + finalizeBind(); + } this.lastSessionStarted = SystemClock.elapsedRealtime(); } private void sendServiceDiscoveryInfo(final Jid jid) { - if (mServerIdentity != Identity.NIMBUZZ) { - mPendingServiceDiscoveries++; - } + mPendingServiceDiscoveries.incrementAndGet(); final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(jid); iq.query("http://jabber.org/protocol/disco#info"); @@ -1048,14 +1059,10 @@ public class XmppConnection implements Runnable { Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco info for " + jid.toString()); } if (packet.getType() != IqPacket.TYPE.TIMEOUT) { - mPendingServiceDiscoveries--; - if (mPendingServiceDiscoveries == 0) { - Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": done with service discovery"); - Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": online with resource " + account.getResource()); - if (bindListener != null) { - bindListener.onBind(account); - } - changeStatus(Account.State.ONLINE); + if (mPendingServiceDiscoveries.decrementAndGet() == 0 + && !mIsServiceItemsDiscoveryPending.get() + && mWaitForDisco) { + finalizeBind(); } } } @@ -1065,6 +1072,14 @@ public class XmppConnection implements Runnable { } } + private void finalizeBind() { + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": online with resource " + account.getResource()); + if (bindListener != null) { + bindListener.onBind(account); + } + changeStatus(Account.State.ONLINE); + } + private void enableAdvancedStreamFeatures() { if (getFeatures().carbons() && !features.carbonsEnabled) { sendEnableCarbons(); @@ -1082,7 +1097,7 @@ public class XmppConnection implements Runnable { final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); iq.setTo(server.toDomainJid()); iq.query("http://jabber.org/protocol/disco#items"); - this.sendIqPacket(iq, new OnIqPacketReceived() { + String id = this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { @@ -1099,8 +1114,17 @@ public class XmppConnection implements Runnable { } else { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not query disco items of " + server); } + if (packet.getType() != IqPacket.TYPE.TIMEOUT) { + mIsServiceItemsDiscoveryPending.set(false); + if (mPendingServiceDiscoveries.get() == 0 && mWaitForDisco) { + finalizeBind(); + } + } } }); + synchronized (this.mPendingServiceDiscoveriesIds) { + this.mPendingServiceDiscoveriesIds.add(id); + } } private void sendEnableCarbons() { @@ -1481,13 +1505,15 @@ public class XmppConnection implements Runnable { public boolean pep() { synchronized (XmppConnection.this.disco) { - ServiceDiscoveryResult info = disco.get(account.getServer()); - if (info != null && info.hasIdentity("pubsub", "pep")) { - return true; - } else { - info = disco.get(account.getJid().toBareJid()); - return info != null && info.hasIdentity("pubsub", "pep"); - } + ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid()); + return info != null && info.hasIdentity("pubsub", "pep"); + } + } + + public boolean pepPersistent() { + synchronized (XmppConnection.this.disco) { + ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid()); + return info != null && info.getFeatures().contains("http://jabber.org/protocol/pubsub#persistent-items"); } } diff --git a/src/main/res/drawable-hdpi/ic_action_share.png b/src/main/res/drawable-hdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..a36464b8 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_action_share.png diff --git a/src/main/res/drawable-hdpi/ic_share_white_24dp.png b/src/main/res/drawable-hdpi/ic_share_white_24dp.png Binary files differnew file mode 100644 index 00000000..93b3c219 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_share_white_24dp.png diff --git a/src/main/res/drawable-mdpi/ic_action_share.png b/src/main/res/drawable-mdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..7362f0d7 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_action_share.png diff --git a/src/main/res/drawable-mdpi/ic_share_white_24dp.png b/src/main/res/drawable-mdpi/ic_share_white_24dp.png Binary files differnew file mode 100644 index 00000000..4d019722 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_share_white_24dp.png diff --git a/src/main/res/drawable-xhdpi/ic_action_share.png b/src/main/res/drawable-xhdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..40771e48 --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_action_share.png diff --git a/src/main/res/drawable-xhdpi/ic_share_white_24dp.png b/src/main/res/drawable-xhdpi/ic_share_white_24dp.png Binary files differnew file mode 100644 index 00000000..dd536bca --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_share_white_24dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_action_share.png b/src/main/res/drawable-xxhdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..22ed428f --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_action_share.png diff --git a/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png Binary files differnew file mode 100644 index 00000000..9963c6a0 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png diff --git a/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png Binary files differnew file mode 100644 index 00000000..bb521c14 --- /dev/null +++ b/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png diff --git a/src/main/res/menu/muc_details.xml b/src/main/res/menu/muc_details.xml index 51de4e75..ad79f577 100644 --- a/src/main/res/menu/muc_details.xml +++ b/src/main/res/menu/muc_details.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" > +<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_edit_subject" @@ -8,26 +8,33 @@ android:showAsAction="always" android:title="@string/action_edit_subject"/> <item + android:id="@+id/action_share" + android:icon="?attr/icon_share" + android:showAsAction="always" + android:orderInCategory="15" + android:title="@string/share_uri_with"/> + + <item android:id="@+id/action_show_qr_code" - android:title="@string/show_qr_code" - android:showAsAction="never" /> + android:showAsAction="never" + android:title="@string/show_qr_code"/> <item android:id="@+id/action_save_as_bookmark" - android:title="@string/save_as_bookmark" android:orderInCategory="80" - android:showAsAction="never" /> + android:showAsAction="never" + android:title="@string/save_as_bookmark"/> <item android:id="@+id/action_delete_bookmark" - android:title="@string/delete_bookmark" android:orderInCategory="80" - android:showAsAction="never" /> - <item - android:id="@+id/action_advanced_mode" - android:title="@string/advanced_mode" - android:checkable="true" - android:checked="false" - android:orderInCategory="85" - android:showAsAction="never" /> + android:showAsAction="never" + android:title="@string/delete_bookmark"/> + <item + android:id="@+id/action_advanced_mode" + android:checkable="true" + android:checked="false" + android:orderInCategory="85" + android:showAsAction="never" + android:title="@string/advanced_mode"/> <item android:id="@+id/action_accounts" android:orderInCategory="90" diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml index 60d6854e..eefb2c4f 100644 --- a/src/main/res/values-ar/strings.xml +++ b/src/main/res/values-ar/strings.xml @@ -96,9 +96,6 @@ <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_sound">التبيه الصوتي</string> - <string name="pref_sound_summary">سماع صوت عندما تصل رساله</string> <string name="pref_never_send_crash">لا ترسل تقارير أخطاء</string> <string name="pref_never_send_crash_summary">الغاء ارسال تقارير الأخطاء يقلل من فرص حل المشكلة سريعا فكن متعاون</string> <string name="pref_confirm_messages">تأكيد الرسالة</string> diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index 6b4d9240..28e21c52 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">доставянето се провали</string> <string name="send_rejected">отказано</string> <string name="preparing_image">Подготовка на изображението за изпращане</string> + <string name="preparing_images">Подготовка на изображенията за изпращане</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> @@ -106,9 +108,11 @@ <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_sound">Звук</string> - <string name="pref_sound_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_notification_grace_period">Продължителност на отсрочване на известията</string> <string name="pref_notification_grace_period_summary">Изключва известията за кратко, след като бъде получено копие на съобщение</string> <string name="pref_advanced_options">Разширени</string> @@ -352,6 +356,7 @@ <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> <string name="sending_file">изпращане (%1$d%% завършено)</string> @@ -539,6 +544,7 @@ </plurals> <string name="shared_file_with_x">Файлът е споделен с %s</string> <string name="shared_image_with_x">Изображението е споделено с %s</string> + <string name="shared_images_with_x">Изображения, споделени с %s</string> <string name="no_storage_permission">Conversations+ се нуждае от достъп до външно място за съхранение</string> <string name="sync_with_contacts">Синхронизиране с контактите</string> <string name="sync_with_contacts_long">Conversations+ иска да съчетае Вашия списък в XMPP с контактите Ви, за да показва пълните им имена и снимки..\n\nConversations+ единствено ще чете контактите Ви и ще ги използва вътрешно, без да ги качва на сървъра Ви.\n\nЩе бъдете помолен/а за позволение за достъп до контактите Ви.</string> @@ -566,4 +572,5 @@ <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> </resources> diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index 5b524419..401bf2df 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -97,9 +97,6 @@ <string name="pref_notifications">Notificacions</string> <string name="pref_notifications_summary">Notifica quan arriba un nou missatge</string> <string name="pref_vibrate">Vibra</string> - <string name="pref_vibrate_summary">Vibra quan arriba un nou missatge</string> - <string name="pref_sound">So</string> - <string name="pref_sound_summary">Reprodueix el to de trucada amb la notificació</string> <string name="pref_notification_grace_period">Notificació del període d\'espera</string> <string name="pref_notification_grace_period_summary">Desactiva les notificacions durant un breu termini després de rebre una còpia de missatges carbon</string> <string name="pref_never_send_crash">Mai enviïs informes d\'errors</string> diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index a53a0528..ab5395f6 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">doručení selhalo</string> <string name="send_rejected">zamítnuto</string> <string name="preparing_image">Připravuji obrázek na přenos</string> + <string name="preparing_images">Příprava obrázků pro přenos</string> + <string name="sharing_files_please_wait">Sdílení souborů. Chvíli strpení...</string> <string name="action_clear_history">Smazat historii</string> <string name="clear_conversation_history">Smaže historii konverzací</string> <string name="clear_histor_msg">Chcete smazat všechny zprávy v této konverzaci?\n\n<b>Varování:</b> Toto neovlivní zprávy uložené na jiných přístrojích nebo serverech.</string> @@ -313,6 +315,7 @@ <string name="checking_x">Ověřuji %s na HTTP hostiteli</string> <string name="not_connected_try_again">Bez připojení. Zkus znovu později</string> <string name="check_x_filesize">Ověřit %s velikost</string> + <string name="check_x_filesize_on_host">Kontrola %1$s velikosti na %2$s</string> <string name="message_options">Možnosti zpráv</string> <string name="copy_text">Zkopírovat text</string> <string name="copy_original_url">Kopírovat originální URL</string> @@ -351,6 +354,7 @@ <string name="choose_file">Vybrat soubor</string> <string name="receiving_x_file">Přijímám %1$s (%2$d%% dokončeno)</string> <string name="download_x_file">Stáhnout %s</string> + <string name="delete_x_file">Smazat %s</string> <string name="file">soubor</string> <string name="open_x_file">Otevřít %s</string> <string name="sending_file">odesílám (%1$d%% přeneseno)</string> @@ -507,6 +511,8 @@ <string name="pref_away_when_screen_off_summary">Při vypnuté obrazovce označí váš stav jako pryč</string> <string name="pref_xa_on_silent_mode">Nedostupný při vypnutém zvuku</string> <string name="pref_xa_on_silent_mode_summary">Při tichém módu označí váš stav jako nedostupný</string> + <string name="pref_treat_vibrate_as_silent">Vibrační mód brát stejně jako tichý</string> + <string name="pref_treat_vibrate_as_silent_summary">Označí vaše zdroje jako nedostupné při přepnutí do vibračního módu</string> <string name="pref_show_connection_options">Rozšířená nastavení připojení</string> <string name="pref_show_connection_options_summary">Zobrazovat nastavení hostname a port při vytváření účtu</string> <string name="hostname_example">xmpp.server.cz</string> @@ -539,6 +545,7 @@ </plurals> <string name="shared_file_with_x">Soubor sdílen s %s</string> <string name="shared_image_with_x">Obrázek sdílen s %s</string> + <string name="shared_images_with_x">Obrázky sdíleny s %s</string> <string name="no_storage_permission">Conversations+ vyžaduje přístup k externímu úložišti</string> <string name="sync_with_contacts">Synchronizovat s kontakty</string> <string name="sync_with_contacts_long">Aplikace Conversations+ by ráda porovnala váš XMPP seznam s vašimi kontakty, aby mohla zobrazit plná jména a avatary.\n\nConversations+ načte a porovná kontakty pouze lokálně, bez jejich nahrávání na server.\n\nNyní budete dotázáni na udělení práv pro přístup k seznamu kontaktů.</string> @@ -563,4 +570,7 @@ <string name="selection_too_large">Vybraný obsah je příliš dlouhý</string> <string name="no_accounts">(Žádné aktivované účty)</string> <string name="this_field_is_required">Toto pole je vyžadováno</string> + <string name="no_keys_just_confirm">Tomuto kontaktu již důvěřujete. Vybráním možnosti \'hotovo\' jen potvrzujete, že %s je součástí této konference.</string> + <string name="select_image_and_crop">Vybrat obrázek a oříznout</string> + <string name="this_account_is_disabled">Tento účet byl vypnut</string> </resources> diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index c578d738..0e3b388d 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -71,8 +71,8 @@ <string name="send_failed">Zustellung fehlgeschlagen</string> <string name="send_rejected">abgelehnt</string> <string name="preparing_image">Bild wird für Übertragung vorbereitet</string> - <string name="preparing_images">Bilder werden für die Übertragung vorbereitet</string> - <string name="sharing_files_please_wait">Teile Dateien. Bitte warten...</string> + <string name="preparing_images">Bilder werden für Übertragung vorbereitet</string> + <string name="sharing_files_please_wait">Teile Dateien. Bitte warten…</string> <string name="action_clear_history">Verlauf löschen</string> <string name="clear_conversation_history">Verlauf löschen</string> <string name="clear_histor_msg">Möchtest du alle Nachrichten in dieser Unterhaltung löschen?\n\n<b>Achtung:</b> Dies beeinflusst nicht Nachrichten, die auf anderen Geräten oder Servern gespeichert sind.</string> @@ -114,6 +114,8 @@ <string name="pref_notifications_summary">Benachrichtigen bei Erhalt einer neuen Nachricht</string> <string name="pref_vibrate">Vibrieren</string> <string name="pref_vibrate_summary">Vibrieren bei Erhalt einer neuen Nachricht</string> + <string name="pref_led">LED Benachrichtigung</string> + <string name="pref_led_summary">Blinke bei Erhalt einer neuen Nachricht</string> <string name="pref_sound">Benachrichtigungston</string> <string name="pref_sound_summary">Benachrichtigungston wiedergeben</string> <string name="pref_notification_grace_period">Gnadenfrist</string> @@ -172,7 +174,7 @@ <string name="mgmt_account_disable">Vorübergehend abschalten</string> <string name="mgmt_account_publish_avatar">Avatar veröffentlichen</string> <string name="mgmt_account_publish_pgp">Öffentlichen OpenPGP-Schlüssel veröffentlichen</string> - <string name="mgmt_account_enable">Aktivieren </string> + <string name="mgmt_account_enable">Konto aktivieren </string> <string name="mgmt_account_are_you_sure">Bist du dir sicher?</string> <string name="mgmt_account_delete_confirm_text">Wenn du dein Konto löschst, gehen alle Gesprächsverläufe verloren</string> <string name="attach_record_voice">Sprache aufzeichnen</string> @@ -629,7 +631,7 @@ <string name="retry_decryption">Entschlüsselung nochmal versuchen</string> <string name="pref_omemo_enabled_summary">OMEMO aktivieren?</string> <string name="pref_omemo_enabled_title">OMEMO aktivieren</string> - <string name="no_keys_just_confirm">Du vertraust diesem Kontakt bereits. In dem du \'Fertig\' auswählst bestätigst Du, dass %s Teil dieser Konferenz ist.</string> + <string name="no_keys_just_confirm">Du vertraust diesem Kontakt bereits. Durch Auswählen von \"Fertig\" bestätigst du, dass %s Teil dieser Konferenz ist.</string> <string name="select_image_and_crop">Bild auswählen und zuschneiden</string> <string name="this_account_is_disabled">Du hast diesen Account deaktiviert</string> </resources> diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 7d475d45..9e2667a1 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -97,9 +97,6 @@ <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_sound">Ήχος</string> - <string name="pref_sound_summary">Αναπαραγωγή ήχου κλήσης με την ειδοποίηση</string> <string name="pref_notification_grace_period">Περίοδος χάριτος ειδοποιήσεων</string> <string name="pref_notification_grace_period_summary">Απενεργοποίηση ειδοποιήσεων για λίγο χρόνο μετά από τη λήψη ακριβούς αντιγράφου</string> <string name="pref_never_send_crash">Να μην αποστέλλονται αναφορές λαθών</string> diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index ae5fe81a..c9aee945 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -617,6 +617,8 @@ <string name="notify_only_when_highlighted">Notificar sólo para mensajes destacados</string> <string name="notify_never">Notificaciones deshabilitadas</string> <string name="notify_paused">Notificaciones pausadas</string> + <string name="pref_picture_compression">Comprimir imágenes</string> + <string name="pref_picture_compression_summary">Redimensionar y comprimir las imágenes</string> <string name="always">Siempre</string> <string name="automatically">Automáticamente</string> <string name="battery_optimizations_enabled">Optimizaciones de uso de batería habilitadas</string> diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index 1d904331..1a7f2084 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">huts bidaltzerakoan</string> <string name="send_rejected">ukatua</string> <string name="preparing_image">Irudia transmisiorako prestatzen. Mesedez itxaron…</string> + <string name="preparing_images">Irudiak transmisiorako prestatzen</string> + <string name="sharing_files_please_wait">Fitxategiak partekatzen. Mesedez itxaron...</string> <string name="action_clear_history">Historia garbitu</string> <string name="clear_conversation_history">Elkarrizketa historia garbitu</string> <string name="clear_histor_msg">Elkarrizketa honetako mezu guztiak ezabatu nahi al dituzu?\n\n<b>Abisua:</b> Honek ez du beste gailu edo zerbitzarietan gordetako mezuetan eraginik izango.</string> @@ -106,9 +108,6 @@ <string name="pref_notifications">Jakinarazpenak</string> <string name="pref_notifications_summary">Mezu berri bat heltzerakoan jakinarazi</string> <string name="pref_vibrate">Dardaratu</string> - <string name="pref_vibrate_summary">Dardaratu ere mezu berri bat heltzerakoan</string> - <string name="pref_sound">Soinua</string> - <string name="pref_sound_summary">Dei-tonua jo jakinarazpenarekin</string> <string name="pref_notification_grace_period">Jakinarazpenen grazia epea</string> <string name="pref_notification_grace_period_summary">Jakinarazpenak denbora labur baterako ezgaitu ikatz-kopia bat jaso ondoren</string> <string name="pref_advanced_options">Aurreratua</string> @@ -352,6 +351,7 @@ <string name="choose_file">Fitxategia aukeratu</string> <string name="receiving_x_file">%1$s jasotzen (%2$d%% osatua)</string> <string name="download_x_file">%s deskargatu</string> + <string name="delete_x_file">Ezabatu %s</string> <string name="file">fitxategia</string> <string name="open_x_file">%s ireki</string> <string name="sending_file">bidaltzen (%1$d%% osatua)</string> @@ -539,6 +539,7 @@ </plurals> <string name="shared_file_with_x">Fitxategia %s(r)ekin partekatu da</string> <string name="shared_image_with_x">Irudia %s(r)ekin partekatu da</string> + <string name="shared_images_with_x">Irudiak %s(r)ekin partekatu dira</string> <string name="no_storage_permission">Conversationsek kanpoko biltegirako sarbidea behar du</string> <string name="sync_with_contacts">Kontaktuekin sinkronizatu</string> <string name="sync_with_contacts_long">Conversationsek zure XMPP zerrenda eta zure kontaktuak uztartu nahi ditu haien izenak eta argazkiak erakusteko.\n\nConversationsek zure kontaktuak modu lokalean soilik irakurri eta uztartuko ditu, zure zerbitzarira kargatu gabe.\n\nJarraian baimenak eskatuko zaizkizu zure kontaktuetara sartu ahal izateko.</string> diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index 70291aae..4fd2b160 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -76,7 +76,7 @@ <string name="clear_histor_msg">Voulez-vous supprimer tous les messages de cette conversation ?\n\n<b>Attention :</b> Les messages seront supprimés uniquement sur cet appareil.</string> <string name="delete_messages">Supprimer les messages</string> <string name="also_end_conversation">Fermer cette conversation ensuite</string> - <string name="choose_presence">Choisir le status de présence</string> + <string name="choose_presence">Choisir le statut de présence</string> <string name="send_unencrypted_message">Envoyer un message non chiffré</string> <string name="send_otr_message">Envoyer un message chiffré avec OTR</string> <string name="send_omemo_message">Envoyer un message chiffré avec OMEMO</string> @@ -86,7 +86,7 @@ <string name="send_unencrypted">Envoyer en clair</string> <string name="decryption_failed">Echec du déchiffrement. Avez-vous la bonne clef privée ?</string> <string name="openkeychain_required">OpenKeychain</string> - <string name="openkeychain_required_long">Conversations+ requiert une application tierce nommée <b>OpenKeychain</b> pour chiffrer et déchiffrer les messages.\n\nOpenKeychain est sous licence GPLv3 et est disponible sur F-Droid et Google Play.\n\n<small>(Veuillez redémarrer Conversations+ apres l\'installation de l\'app)</small></string> + <string name="openkeychain_required_long">Conversations+ requiert une application tierce nommée <b>OpenKeychain</b> pour chiffrer et déchiffrer les messages.\n\nOpenKeychain est sous licence GPLv3 et est disponible sur F-Droid et Google Play.\n\n<small>(Veuillez redémarrer Conversations+ après l\'installation de l\'app)</small></string> <string name="restart">Redémarrer</string> <string name="install">Installer</string> <string name="openkeychain_not_installed">Veuillez installer OpenKeychain</string> @@ -185,9 +185,9 @@ <string name="server_info_show_more">Infos sur le serveur</string> <string name="server_info_mam">XEP-0313 : MAM</string> <string name="server_info_carbon_messages">XEP-0280 : Copies carbone</string> - <string name="server_info_csi">XEP-0352 : Indication status client</string> + <string name="server_info_csi">XEP-0352 : Indication statut client</string> <string name="server_info_blocking">XEP-0191 : Commande de bloquage</string> - <string name="server_info_roster_version">XEP-0237 : Versionnement contacts</string> + <string name="server_info_roster_version">XEP-0237 : Révision contacts</string> <string name="server_info_stream_management">XEP-0198 : Gestion des flux</string> <string name="server_info_pep">XEP-0163 : PEP (Avatars / OMEMO)</string> <string name="server_info_http_upload">XEP-0363 : Envoi de fichiers via HTTP</string> @@ -272,7 +272,7 @@ <string name="request_presence_updates">Veuillez demander à votre contact de partager ses mises à jour de présence.\n\n<small>Elles seront utilisées pour déterminer son client.</small></string> <string name="request_now">Demander maintenant</string> <string name="delete_fingerprint">Supprimer l\'empreinte</string> - <string name="sure_delete_fingerprint">Etes-vous sûr de vouloir supprimer l\'empreinte ?</string> + <string name="sure_delete_fingerprint">Êtes-vous sûr de vouloir supprimer l\'empreinte ?</string> <string name="ignore">Ignorer</string> <string name="without_mutual_presence_updates"><b>Attention :</b> peut poser problème si l\'un des deux correspondants n\'a pas activé les mises à jour de présence.\n\n<small>Vérifiez dans les détails du contact que vous y avez bien souscrit.</small></string> <string name="pref_security_settings">Sécurité</string> @@ -285,7 +285,7 @@ <string name="pref_expert_options">Paramètres avancés</string> <string name="pref_expert_options_summary">À utiliser avec précaution.</string> <string name="title_activity_about">À propos</string> - <string name="pref_about_conversations_summary">Informations sur la version et les licenses</string> + <string name="pref_about_conversations_summary">Informations sur la version et les licences</string> <string name="title_pref_quiet_hours">Heures tranquilles</string> <string name="title_pref_quiet_hours_start_time">Heure de début</string> <string name="title_pref_quiet_hours_end_time">Heure de fin</string> @@ -298,7 +298,7 @@ <string name="pref_use_indicate_received_summary">Les messages reçus seront marqués d\'une coche verte (si supporté).</string> <string name="pref_use_send_button_to_indicate_status_summary">Le bouton Envoyer change de couleur pour indiquer le statut du contact.</string> <string name="pref_expert_options_other">Autres</string> - <string name="pref_conference_name">Nom de la conférence </string> + <string name="pref_conference_name">Nom de la conférence</string> <string name="pref_conference_name_summary">Identifier les conférences par leur sujet plutôt que leur JID.</string> <string name="pref_autojoin">Rejoindre automatiquement les conférences</string> <string name="pref_autojoin_summary">Respecter le paramètre de connexion automatique des favoris de conférence</string> @@ -323,7 +323,7 @@ <string name="url_copied_to_clipboard">URL copiée dans le presse-papier</string> <string name="message_copied_to_clipboard">Message copié dans le presse-papier</string> <string name="image_transmission_failed">Échec lors de l\'envoi de l\'image</string> - <string name="scan_qr_code">Scanner un QR code</string> + <string name="scan_qr_code">Scanner un code QR</string> <string name="show_qr_code">Afficher le code QR</string> <string name="show_block_list">Afficher la liste des contacts bloqués</string> <string name="account_details">Détails du compte</string> @@ -393,7 +393,7 @@ <string name="could_not_change_password">Impossible de changer le mot de passe</string> <string name="otr_session_not_started">Envoyez un message pour commencer la conversation chiffrée</string> <string name="ask_question">Poser une question</string> - <string name="smp_explain_question">Si vous et votre contact avez en commun un secret que personne d\'autre ne connait (comme une blague ou ce que vous avez mangé lors de votre dernière rencontre), vous pouvez utiliser ce secret pour vérifier vos empreintes respectives.\n\nVous donnez un indice ou posez votre question à votre contact, qui répondra en faisant attention à la casse.</string> + <string name="smp_explain_question">Si vous et votre contact avez en commun un secret que personne d\'autre ne connaît (comme une blague ou ce que vous avez mangé lors de votre dernière rencontre), vous pouvez utiliser ce secret pour vérifier vos empreintes respectives.\n\nVous donnez un indice ou posez votre question à votre contact, qui répondra en faisant attention à la casse.</string> <string name="smp_explain_answer">Votre contact souhaite confirmer votre identité grâce à un secret partagé. Il vous a envoyé le message/indice suivant concernant ce secret.</string> <string name="shared_secret_hint_should_not_be_empty">Votre indice ne doit pas être vide</string> <string name="shared_secret_can_not_be_empty">Votre secret partagé ne doit pas être vide</string> @@ -439,7 +439,7 @@ <string name="pref_enter_is_send">Touche Entrée pour envoyer</string> <string name="pref_enter_is_send_summary">Utiliser la touche Entrée pour envoyer un message.</string> <string name="pref_display_enter_key">Afficher la touche Entrée</string> - <string name="pref_display_enter_key_summary">Remplacer le bouton des Émoticônes par un bouton Entrée.</string> + <string name="pref_display_enter_key_summary">Remplacer la touche Émoticônes par une touche Entrée.</string> <string name="audio">audio</string> <string name="video">vidéo</string> <string name="image">image</string> @@ -452,7 +452,7 @@ <string name="avatar_has_been_published">L\'avatar a été publié !</string> <string name="sending_x_file">%s en cours d\'envoi</string> <string name="offering_x_file">En train de proposer un(e) %s</string> - <string name="hide_offline">Se cacher hors-ligne</string> + <string name="hide_offline">Cacher contacts hors-ligne</string> <string name="disable_account">Désactiver le compte</string> <string name="contact_is_typing">%s est en train d\'écrire</string> <string name="contact_has_stopped_typing">%s a arrêté d\'écrire</string> @@ -478,7 +478,7 @@ <item quantity="other">%d certificats supprimés</item> </plurals> <plurals name="select_contact"> - <item quantity="one">%d contact séléctionné</item> + <item quantity="one">%d contact sélectionné</item> <item quantity="other">%d contacts sélectionnés</item> </plurals> <string name="pref_quick_action_summary">Remplacer le bouton Envoyer par une action rapide.</string> @@ -494,7 +494,7 @@ <string name="username">Identifiant</string> <string name="username_hint">Identifiant</string> <string name="invalid_username">Cet identifiant n\'est pas valide</string> - <string name="conference_name">Nom de la conférence </string> + <string name="conference_name">Nom de la conférence</string> <string name="invalid_conference_name">Ce nom de conférence n\'est pas valide</string> <string name="download_failed_server_not_found">Échec du téléchargement : impossible de trouver le serveur</string> <string name="download_failed_file_not_found">Échec du téléchargement : impossible de trouver le fichier</string> @@ -508,7 +508,7 @@ <string name="pref_xa_on_silent_mode_summary">Marque cette ressource comme indisponible quand l\'appareil est en mode silencieux</string> <string name="pref_treat_vibrate_as_silent">Indisponible en mode vibreur</string> <string name="pref_treat_vibrate_as_silent_summary">Marque cette ressource comme indisponible quand l\'appareil est en mode vibreur</string> - <string name="pref_show_connection_options">Paramètres de connexioin avancés</string> + <string name="pref_show_connection_options">Paramètres de connexion avancés</string> <string name="pref_show_connection_options_summary">Montrer le nom d\'hôte et le port lors du paramétrage d\'un compte</string> <string name="hostname_example">xmpp.example.com</string> <string name="action_add_account_with_certificate">Ajouter un compte avec un certificat</string> @@ -541,7 +541,7 @@ <string name="shared_image_with_x">Image partagée avec %s</string> <string name="no_storage_permission">Conversations+ a besoin d\'accéder au stockage externe</string> <string name="sync_with_contacts">Synchroniser avec contacts</string> - <string name="sync_with_contacts_long">Conversations+ souhaite associer vos contacts XMPP avec les contacts de votre appareil, pour utiliser leur nom complet et leur avatar.\n\nConversations+ va uniquement lire vos contacts et les associer localement, sans les uploader sur le serveur XMPP.\n\nVotre appareil va maintenant vous demander la permission d\'accéder à vos contacts.</string> + <string name="sync_with_contacts_long">Conversations+ souhaite associer vos contacts XMPP avec les contacts de votre appareil, pour utiliser leur nom complet et leur avatar.\n\nConversations+ va uniquement lire vos contacts et les associer localement, sans les envoyer sur le serveur XMPP.\n\nVotre appareil va maintenant vous demander la permission d\'accéder à vos contacts.</string> <string name="certificate_information">Informations du certificat</string> <string name="certificate_subject">Sujet</string> <string name="certificate_issuer">Émetteur</string> diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 8b018839..ab3d4329 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -65,9 +65,6 @@ <string name="pref_notifications">Notificacións</string> <string name="pref_notifications_summary">Notifica cuando chega unha nova mensaxe</string> <string name="pref_vibrate">Tremer</string> - <string name="pref_vibrate_summary">Treme cando chega unha novo mensaxe</string> - <string name="pref_sound">Son</string> - <string name="pref_sound_summary">Reproduce un ton ca notificación</string> <string name="pref_notification_grace_period">Notificacións Carbons</string> <string name="pref_notification_grace_period_summary">Deshabilita as notificacións durante un corto periodo de tiempo despois de recibir a copia da mensaxe carbón</string> <string name="pref_never_send_crash">Nunca enviar informe de erros</string> diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml index 3c7f551e..87cffa6f 100644 --- a/src/main/res/values-id/strings.xml +++ b/src/main/res/values-id/strings.xml @@ -102,9 +102,6 @@ <string name="pref_notifications">Notifikasi</string> <string name="pref_notifications_summary">Notifikasikan jika pesan baru tiba</string> <string name="pref_vibrate">Getar</string> - <string name="pref_vibrate_summary">Juga aktifkan getaran bila pesan baru tiba</string> - <string name="pref_sound">Suara</string> - <string name="pref_sound_summary">mainkan suara saat menerima notifikasi</string> <string name="pref_notification_grace_period">Tenggang waktu pemberitahuan</string> <string name="pref_notification_grace_period_summary">Nonaktifkan pemberitahuan untuk waktu yang singkat setelah salinan diterima</string> <string name="pref_advanced_options">Lanjutan</string> diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 460b8b0b..7f5cd784 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -484,8 +484,6 @@ <string name="recently_used">Usati recentemente</string> <string name="choose_quick_action">Scegli azione rapida</string> <string name="search_for_contacts_or_groups">Cerca contatti o gruppi</string> - <!--%s = bare jid, %d = count of online resources--> - <string name="dlg_msg_details_msg_status_failed">Fallito</string> <string name="send_private_message">Invia messaggio privato</string> <string name="user_has_left_conference">%s ha abbandonato la conferenza!</string> <string name="username">Utente</string> @@ -503,6 +501,8 @@ <string name="pref_away_when_screen_off_summary">Imposta la tua risorsa come non disponibile quando lo schermo è spento</string> <string name="pref_xa_on_silent_mode">Non disponibile in modalità silenzioso</string> <string name="pref_xa_on_silent_mode_summary">Imposta la tua risorsa come non disponibile quando il dispositivo è in modalità silenziosa</string> + <string name="pref_treat_vibrate_as_silent">Tratta vibrazione come modalità silenziosa</string> + <string name="pref_treat_vibrate_as_silent_summary">Segna la tua risorsa come non disponibile quando il dispositivo ha solo la vibrazione</string> <string name="pref_show_connection_options">Impostazioni estese di connessione</string> <string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un account</string> <string name="hostname_example">xmpp.esempio.it</string> @@ -558,4 +558,7 @@ <string name="selection_too_large">L\'area selezionata è troppo grande</string> <string name="no_accounts">(Nessun account attivo)</string> <string name="this_field_is_required">Questo campo è obbligatorio</string> + <string name="no_keys_just_confirm">Ti fidi già di questo contatto. Selezionando \'fatto\' stai solo confermando che %s fa parte di questa conferenza.</string> + <string name="select_image_and_crop">Seleziona immagine e ritagliala</string> + <string name="this_account_is_disabled">Hai disabilitato questo account</string> </resources> diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml index 5feeec7a..21c3371f 100644 --- a/src/main/res/values-iw/strings.xml +++ b/src/main/res/values-iw/strings.xml @@ -103,9 +103,6 @@ <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_sound">צליל</string> - <string name="pref_sound_summary">נגן צלצול עם כל התראה</string> <string name="pref_notification_grace_period">משך תקופת ארכה</string> <string name="pref_notification_grace_period_summary">נטרל התראות לזמן קצר לאחר שהודעת Carbon Copy מתקבלת</string> <string name="pref_never_send_crash">לעולם אל תשלח דיווחי קריסה</string> diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml index 5b38ad2e..6e931508 100644 --- a/src/main/res/values-ja/strings.xml +++ b/src/main/res/values-ja/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">配信に失敗しました</string> <string name="send_rejected">拒否されました</string> <string name="preparing_image">転送用画像の準備中</string> + <string name="preparing_images">転送用画像の準備中</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> @@ -352,6 +354,7 @@ <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> <string name="sending_file">送信中 (%1$d%% 完了)</string> @@ -536,6 +539,7 @@ </plurals> <string name="shared_file_with_x">%s でファイルを共有</string> <string name="shared_image_with_x">%s で画像を共有</string> + <string name="shared_images_with_x">%s で画像を共有</string> <string name="no_storage_permission">Conversations+ は外部ストレージにアクセスが必要です</string> <string name="sync_with_contacts">連絡先と同期</string> <string name="sync_with_contacts_long">Conversations+ はフルネームやアバターを表示するために、連絡先と XMPP 名簿と一致するようにしたいです。\n\nConversations+ は、サーバーにアップロードすることはなく、ローカルで連絡先を読んで一致させるだけです。\n\n今、連絡先へのアクセス許可を付与するように求められます。</string> diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml index 510ad650..0e8e8715 100644 --- a/src/main/res/values-ko/strings.xml +++ b/src/main/res/values-ko/strings.xml @@ -105,9 +105,6 @@ <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_sound">소리 </string> - <string name="pref_sound_summary">알림과 동시에 벨소리 재생 </string> <string name="pref_notification_grace_period">알림 유예 </string> <string name="pref_notification_grace_period_summary">Carbon Copy 수신 후에 잠시동안 알림 해제</string> <string name="pref_never_send_crash">충돌 보고서 보내지 않음 </string> diff --git a/src/main/res/values-nb-rNO/strings.xml b/src/main/res/values-nb-rNO/strings.xml index 5fdaa81f..bcb85490 100644 --- a/src/main/res/values-nb-rNO/strings.xml +++ b/src/main/res/values-nb-rNO/strings.xml @@ -106,9 +106,6 @@ <string name="pref_notifications">Varslinger</string> <string name="pref_notifications_summary">Varsle når en ny melding ankommer</string> <string name="pref_vibrate">Vibrer</string> - <string name="pref_vibrate_summary">Vibrer også når ny melding ankommer</string> - <string name="pref_sound">Lyd</string> - <string name="pref_sound_summary">Spill av ringetone ved varsel</string> <string name="pref_notification_grace_period">Stilleperiode</string> <string name="pref_notification_grace_period_summary">Deaktiver varslinger for en kort periode etter at en kopi er mottatt</string> <string name="pref_advanced_options">Avanserte valg</string> diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 3e1b25b4..0b8265ae 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">afleveren mislukt</string> <string name="send_rejected">geweigerd</string> <string name="preparing_image">Bezig met voorbereiden van versturen van afbeelding</string> + <string name="preparing_images">Bezig met voorbereiden van versturen van afbeeldingen</string> + <string name="sharing_files_please_wait">Bestanden delen. Even geduld…</string> <string name="action_clear_history">Geschiedenis wissen</string> <string name="clear_conversation_history">Gespreksgeschiedenis wissen</string> <string name="clear_histor_msg">Wil je alle berichten in dit gesprek verwijderen?\n\n<b>Waarschuwing:</b> Dit zal geen invloed hebben op de berichten opgeslagen op andere apparaten of servers.</string> @@ -352,6 +354,7 @@ <string name="choose_file">Bestand kiezen</string> <string name="receiving_x_file">Ontvangen van %1$s (%2$d%% voltooid)</string> <string name="download_x_file">%s downloaden</string> + <string name="delete_x_file">%s verwijderen</string> <string name="file">bestand</string> <string name="open_x_file">%s openen</string> <string name="sending_file">versturen (%1$d%% voltooid)</string> @@ -539,6 +542,7 @@ </plurals> <string name="shared_file_with_x">Bestand gedeeld met %s</string> <string name="shared_image_with_x">Afbeelding gedeeld met %s</string> + <string name="shared_images_with_x">Afbeeldingen 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> diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 344ac009..6fc748d3 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -106,9 +106,6 @@ <string name="pref_notifications">Powiadomienia</string> <string name="pref_notifications_summary">Powiadamiaj, gdy nadejdzie wiadomość</string> <string name="pref_vibrate">Wibracje</string> - <string name="pref_vibrate_summary">Wibruj, gdy nadejdzie wiadomość</string> - <string name="pref_sound">Dźwięk</string> - <string name="pref_sound_summary">Odtwórz dźwięk z powiadomieniem</string> <string name="pref_notification_grace_period">Opóźnienie powiadomień</string> <string name="pref_notification_grace_period_summary">Wyłącz powiadomienia przez krótki czas po otrzymaniu kopii wiadomości</string> <string name="pref_advanced_options">Zaawansowane</string> diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml index b29c9f36..c5e95b09 100644 --- a/src/main/res/values-pt-rBR/strings.xml +++ b/src/main/res/values-pt-rBR/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">não foi entregue</string> <string name="send_rejected">rejeitada</string> <string name="preparing_image">Preparando a imagem para transmissão</string> + <string name="preparing_images">Preparando as imagens para o envio</string> + <string name="sharing_files_please_wait">Compartilhando arquivos. Por favor, aguarde...</string> <string name="action_clear_history">Limpar o histórico</string> <string name="clear_conversation_history">Limpa o histórico de conversas</string> <string name="clear_histor_msg">Deseja excluir todas as mensagens dessa conversa?\n\n<b>Atenção:</b> Isso não afetará mensagens armazenadas em outros dispositivos ou servidores.</string> @@ -97,18 +99,20 @@ <string name="no_pgp_keys">Não foi encontrada nenhuma chave OpenPGP</string> <string name="contacts_have_no_pgp_keys">O Conversations+ não conseguiu criptografar suas mensagens porque os seus contatos não estão anunciando a chave pública deles(as).\n\n<small>Por favor, solicite aos seus contatos que configurem o OpenPGP.</small></string> <string name="pref_general">Geral</string> - <string name="pref_xmpp_resource">Recurso XMPP</string> + <string name="pref_xmpp_resource">Identificação XMPP</string> <string name="pref_xmpp_resource_summary">O nome pelo qual esse cliente se identifica</string> <string name="pref_accept_files">Aceitar arquivos</string> <string name="pref_accept_files_summary">Aceitar automaticamente arquivos menores que...</string> <string name="pref_accept_files_size_summary">Aceitar automaticamente arquivos menores que...</string> <string name="pref_notification_settings">Notificação</string> <string name="pref_notifications">Notificações</string> - <string name="pref_notifications_summary">Notificar quando uma nova mensagem for recebida</string> + <string name="pref_notifications_summary">Notificar ao receber uma nova mensagem</string> <string name="pref_vibrate">Vibração</string> - <string name="pref_vibrate_summary">Vibrar quando uma nova mensagem for recebida</string> - <string name="pref_sound">Som</string> - <string name="pref_sound_summary">Som de notificação</string> + <string name="pref_vibrate_summary">Vibrar ao receber uma nova mensagem</string> + <string name="pref_led">Notificação via LED</string> + <string name="pref_led_summary">Piscar a luz de notificação ao receber uma nova mensagem</string> + <string name="pref_sound">Toque</string> + <string name="pref_sound_summary">Tocar um som ao receber uma nova mensagem</string> <string name="pref_notification_grace_period">Tempo de espera da notificação</string> <string name="pref_notification_grace_period_summary">Desativar notificações por um curto período após uma copia ser recebida</string> <string name="pref_advanced_options">Avançado</string> @@ -313,6 +317,7 @@ <string name="checking_x">Verificando %s no host HTTP</string> <string name="not_connected_try_again">Você não está conectado. Tente novamente mais tarde.</string> <string name="check_x_filesize">Verificar o tamanho de %s</string> + <string name="check_x_filesize_on_host">Verifique o tamanho de %1$s em %2$s</string> <string name="message_options">Opções da mensagem</string> <string name="copy_text">Copiar o texto</string> <string name="copy_original_url">Copiar a URL original</string> @@ -351,6 +356,7 @@ <string name="choose_file">Selecione o arquivo</string> <string name="receiving_x_file">Recebendo %1$s (completou %2$d%%)</string> <string name="download_x_file">Baixar %s</string> + <string name="delete_x_file">Excluir %s</string> <string name="file">arquivo</string> <string name="open_x_file">Abrir %s</string> <string name="sending_file">enviando (completou %1$d%%)</string> @@ -486,8 +492,6 @@ <string name="recently_used">Usada mais recentemente</string> <string name="choose_quick_action">Selecione a ação rápida</string> <string name="search_for_contacts_or_groups">Pesquisar por contatos ou grupos</string> - <!--%s = bare jid, %d = count of online resources--> - <string name="dlg_msg_details_msg_status_failed">Erro</string> <string name="send_private_message">Enviar mensagem privada</string> <string name="user_has_left_conference">%s deixou a conferência.</string> <string name="username">Nome de usuário</string> @@ -502,9 +506,11 @@ <string name="server_info_broken">Quebrado</string> <string name="pref_presence_settings">Presença</string> <string name="pref_away_when_screen_off">Afastado quando a tela estiver desligada</string> - <string name="pref_away_when_screen_off_summary">Marcar o seu status como afastado quando a tela estiver desligada</string> + <string name="pref_away_when_screen_off_summary">Definir o seu status como afastado quando a tela estiver desligada</string> <string name="pref_xa_on_silent_mode">Não disponível quando em modo silencioso</string> - <string name="pref_xa_on_silent_mode_summary">Marcar o seu status como não disponível quando o dispositivo estiver em modo silencioso</string> + <string name="pref_xa_on_silent_mode_summary">Definir o seu status como não disponível quando o dispositivo estiver em modo silencioso</string> + <string name="pref_treat_vibrate_as_silent">Considerar o modo de vibração como silencioso</string> + <string name="pref_treat_vibrate_as_silent_summary">Definir o seu status como indisponível quando o dispositivo estiver em modo de vibração</string> <string name="pref_show_connection_options">Configurações detalhadas da conexão</string> <string name="pref_show_connection_options_summary">Exibe o nome de host e configurações da porta ao configurar uma conta</string> <string name="hostname_example">xmpp.example.com</string> @@ -560,4 +566,8 @@ <string name="selection_too_large">A área selecionada é muito grande</string> <string name="no_accounts">(Nenhuma conta ativa)</string> <string name="this_field_is_required">Este campo é necessário</string> + <string name="no_keys_just_confirm">Você já confia nesse contato. Ao selecionar \'Concluído\', você está apenas confirmando que %s é parte dessa conferência.</string> + <string name="select_image_and_crop">Selecione e recorte a imagem</string> + <string name="this_account_is_disabled">Você desabilitou essa conta</string> + <string name="security_error_invalid_file_access">Erro de segurança: Acesso inválido ao arquivo</string> </resources> diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml index c79b12c9..9f130e12 100644 --- a/src/main/res/values-pt/strings.xml +++ b/src/main/res/values-pt/strings.xml @@ -1,27 +1,27 @@ <?xml version='1.0' encoding='UTF-8'?> <resources> - <string name="action_settings">Configurações</string> + <string name="action_settings">Definições</string> <string name="action_add">Nova conversa</string> <string name="action_accounts">Gerir contas</string> <string name="action_end_conversation">Finalizar essa conversa</string> - <string name="action_contact_details">Detalhes do contato</string> + <string name="action_contact_details">Detalhes do contacto</string> <string name="action_muc_details">Detalhes da conferência</string> <string name="action_secure">Conversa segura</string> <string name="action_add_account">Adicionar conta</string> <string name="action_edit_contact">Editar nome</string> <string name="action_add_phone_book">Adicionar ao livro de endereços</string> <string name="action_delete_contact">Apagar da lista</string> - <string name="action_block_contact">Bloquear contato</string> - <string name="action_unblock_contact">Desbloquear contato</string> + <string name="action_block_contact">Bloquear contacto</string> + <string name="action_unblock_contact">Desbloquear contacto</string> <string name="action_block_domain">Bloquear domínio</string> <string name="action_unblock_domain">Desbloquear domínio</string> <string name="title_activity_manage_accounts">Gerir contas</string> - <string name="title_activity_settings">Configurações</string> + <string name="title_activity_settings">Definições</string> <string name="title_activity_conference_details">Detalhes da conferência</string> - <string name="title_activity_contact_details">Detalhes do contato</string> + <string name="title_activity_contact_details">Detalhes do contacto</string> <string name="title_activity_sharewith">Compartilhar conversa</string> <string name="title_activity_start_conversation">Iniciar conversa</string> - <string name="title_activity_choose_contact">Escolher contato</string> + <string name="title_activity_choose_contact">Escolher contacto</string> <string name="title_activity_block_list">Bloquear lista</string> <string name="just_now">agora há pouco</string> <string name="minute_ago">1 minuto atrás</string> @@ -71,6 +71,8 @@ <string name="send_failed">a entrega falhou</string> <string name="send_rejected">rejeitado</string> <string name="preparing_image">Preparando a imagem para transmissão</string> + <string name="preparing_images">Preparando as imagens para a transmissão</string> + <string name="sharing_files_please_wait">Partilhando os ficheiros. Por favor aguarde...</string> <string name="action_clear_history">Limpar histórico</string> <string name="clear_conversation_history">Limpar o histórico de conversas</string> <string name="clear_histor_msg">Deseja remover todas as mensagens nesta conversa?\n\n<b>Aviso:<b> Isto não irá influenciar mensagens guardadas noutros dispositivos ou servidores.</string> @@ -268,7 +270,7 @@ <string name="enable">Ativar</string> <string name="conference_requires_password">Esta conferência requer uma palavra-passe</string> <string name="enter_password">Inserir palavra-passe</string> - <string name="missing_presence_updates">Atualizações de presença inexistente para o contato</string> + <string name="missing_presence_updates">Atualizações de presença inexistente para o contacto</string> <string name="request_presence_updates">Por favor peça atualizações de presença ao seu contacto primeiro.\n\n<small>Isto irá ser utilizado para determinar que cliente(s) o seu contacto está a utilizar.</small></string> <string name="request_now">Solicitar agora</string> <string name="delete_fingerprint">Remover impressão digital</string> @@ -352,6 +354,7 @@ <string name="choose_file">Escolher ficheiro</string> <string name="receiving_x_file">A receber %1$s (%2$d%% concluído)</string> <string name="download_x_file">Transferir %s</string> + <string name="delete_x_file">Remover %s</string> <string name="file">ficheiro</string> <string name="open_x_file">Abrir %s</string> <string name="sending_file">a enviar (%1$d%% concluído)</string> @@ -539,6 +542,7 @@ </plurals> <string name="shared_file_with_x">Ficheiro partilhado com %s</string> <string name="shared_image_with_x">Imagem partilhada com %s</string> + <string name="shared_images_with_x">Imagens partilhadas com %s</string> <string name="no_storage_permission">Conversations+ necessita de acesso ao armazenamento externo</string> <string name="sync_with_contacts">Sincronizar com contactos</string> <string name="sync_with_contacts_long">A aplicação Conversations+ deseja fazer a correspondência entre a sua lista de contactos XMPP e os seus contactos para mostrar os seus nomes completos e os seus avatares.\n\nA aplicação Conversations+ irá apenas ler os seus contactos e fazer a correspondência localmente sem enviar os dados para o seu servidor.\n\nIrá agora ser-lhe pedido para dar permissão para aceder aos seus contactos.</string> diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index f4954125..e05ffc83 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">trimitere esuata</string> <string name="send_rejected">respins</string> <string name="preparing_image">Pregatesc imaginea pentru transmisie</string> + <string name="preparing_images">Pregatesc imaginile pentru transmisie</string> + <string name="sharing_files_please_wait">Trimitere fisiere. Te rog asteapta...</string> <string name="action_clear_history">Sterge istoric</string> <string name="clear_conversation_history">Sterge istoricul conversatiei</string> <string name="clear_histor_msg">Doresti sa stergi toate mesajele din aceasta conversatie?\n\n<b>Atentie:</b> Aceasta actiune nu va influenta mesajele aflate pe alte telefoane/tabelete/servere.</string> @@ -352,6 +354,7 @@ <string name="choose_file">Alege un fisier</string> <string name="receiving_x_file">Primesc %1$s (%2$d%% complet)</string> <string name="download_x_file">Descarca %s</string> + <string name="delete_x_file">Sterge %s</string> <string name="file">fisier</string> <string name="open_x_file">Deschide %s</string> <string name="sending_file">trimit (%1$d%% complet)</string> @@ -542,6 +545,7 @@ </plurals> <string name="shared_file_with_x">Partajeaza fisierul cu %s...</string> <string name="shared_image_with_x">Partajeaza imaginea cu %s.</string> + <string name="shared_images_with_x">Partajeaza imaginile cu %s.</string> <string name="no_storage_permission">Conversations+ are nevoie de acces la stocarea externa</string> <string name="sync_with_contacts">Sincronizeaza cu contactele</string> <string name="sync_with_contacts_long">Conversations+ doreste sa potriveasta lista de contacte XMPP cu cea din dispozitiv pentru a putea afisa numule lor complete si avatarele.\n\nConversations+ doar v-a citi si potrivi local fara sa le incarce catre vreun server.\n\nUrmeaza sa fii intrebat daca doresti sa permiti accesul la contacte.</string> diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 5b005134..98e54769 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -106,9 +106,6 @@ <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_sound">Звуковой сигнал</string> - <string name="pref_sound_summary">Выберите звуковой сигнал для сообщений</string> <string name="pref_notification_grace_period">Отсрочка уведомлений</string> <string name="pref_notification_grace_period_summary">Не использовать уведомления, если вы прочитали сообщение на другом устройстве</string> <string name="pref_advanced_options">Дополнительно</string> diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml index d7814652..c05749a6 100644 --- a/src/main/res/values-sk/strings.xml +++ b/src/main/res/values-sk/strings.xml @@ -100,9 +100,6 @@ <string name="pref_notifications">Upozornenia</string> <string name="pref_notifications_summary">Upozorniť pri prijatí novej správy</string> <string name="pref_vibrate">Vibrovať</string> - <string name="pref_vibrate_summary">Vibrovať pri prijatí novej správy</string> - <string name="pref_sound">Zvuk</string> - <string name="pref_sound_summary">Prehrať zvuk spolu s upozornením</string> <string name="pref_notification_grace_period">Doba na prečítanie upozornenia</string> <string name="pref_notification_grace_period_summary">Neupozorňovať krátko po obdržaní kópie správy</string> <string name="pref_never_send_crash">Neodosielať detaily o zlyhaní aplikácie</string> diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index 544ab1b5..fe5b5f20 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">испорука није успела</string> <string name="send_rejected">одбијено</string> <string name="preparing_image">Припремам слику за пренос</string> + <string name="preparing_images">Припремам слике за пренос</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> @@ -106,9 +108,11 @@ <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_summary">Пуштање звука кад стигне нова порука</string> <string name="pref_notification_grace_period">Период одгоде обавештења</string> <string name="pref_notification_grace_period_summary">Искључи обавештења на кратко по примању карбон копије</string> <string name="pref_advanced_options">Напредно</string> @@ -350,6 +354,7 @@ <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> <string name="sending_file">шаљем (%1$d%% завршено)</string> @@ -540,6 +545,7 @@ </plurals> <string name="shared_file_with_x">Подељен фајл са %s</string> <string name="shared_image_with_x">Подељена слика са %s</string> + <string name="shared_images_with_x">Подељене слике са %s</string> <string name="no_storage_permission">Конверзацији је потребан приступ спољашњем складишту</string> <string name="sync_with_contacts">Синхронизуј са контактима</string> <string name="sync_with_contacts_long">Конверзација жели да поклапи ваш ИксМПП именик са контактима на вашем уређају да би приказала њихова пуна имена и аватаре.\n\nКонверзација ће само да очита ваше контакте и упореди их локално без отпремања на сервер.\n\nСада ћете бити упитани за дозволу приступа вашим контактима.</string> @@ -567,4 +573,5 @@ <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> </resources> diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index 7d94681c..1a2d4d38 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">sändning misslyckades</string> <string name="send_rejected">avvisad</string> <string name="preparing_image">Förbereder bild för sändning</string> + <string name="preparing_images">Förbereder bilder för överföring</string> + <string name="sharing_files_please_wait">Delar filer. Vänta...</string> <string name="action_clear_history">Rensa historik</string> <string name="clear_conversation_history">Rensa konversationshistorik</string> <string name="clear_histor_msg">Vill du ta bort alla meddelanden i denna konversation?\n\n<b>Varning:</b> Detta kommer inte påverka meddelanden lagrade på andra enheter eller servrar.</string> @@ -352,6 +354,7 @@ <string name="choose_file">Välj fil</string> <string name="receiving_x_file">Tar emot %1$s (%2$d%% klart)</string> <string name="download_x_file">Ladda ner %s</string> + <string name="delete_x_file">Ta bort %s</string> <string name="file">fil</string> <string name="open_x_file">Öppna %s</string> <string name="sending_file">skickar (%1$d%% klart)</string> @@ -539,6 +542,7 @@ </plurals> <string name="shared_file_with_x">Delade fil med %s</string> <string name="shared_image_with_x">Delade bild med %s</string> + <string name="shared_images_with_x">Delade bilder med %s</string> <string name="no_storage_permission">Conversations+ behöver access till extern lagring</string> <string name="sync_with_contacts">Synkronisera med kontakter</string> <string name="sync_with_contacts_long">Conversations+ vill matcha din XMPP-kontaktlista med dina kontakter för att visa deras namn och profilbild.\n\nConversations+ läser endast dina kontakter för att matcha dem lokalt utan att ladda upp dem till din server.\n\nDu kommer nu få frågan om tillåtelse för att använda kontakterna.</string> diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index 80fbb7b5..b1e6dd9b 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -106,9 +106,6 @@ <string name="pref_notifications">Bildirimler</string> <string name="pref_notifications_summary">Yeni ileti geldiğinde bildir</string> <string name="pref_vibrate">Titreşim</string> - <string name="pref_vibrate_summary">Yeni bir ileti geldiğinde aynı zamanda titreşsin</string> - <string name="pref_sound">Ses</string> - <string name="pref_sound_summary">Bildirimle birlikte zil çalsın</string> <string name="pref_notification_grace_period">Bildirim mühleti</string> <string name="pref_notification_grace_period_summary">Karbon kopya alındıktan sonra kısa bir süre için bildirimleri kapa</string> <string name="pref_advanced_options">Gelişmiş</string> diff --git a/src/main/res/values-v21/themes.xml b/src/main/res/values-v21/themes.xml index 1902832d..57cb9dc3 100644 --- a/src/main/res/values-v21/themes.xml +++ b/src/main/res/values-v21/themes.xml @@ -35,6 +35,7 @@ <item name="attr/icon_secure">@drawable/ic_lock_open_white_24dp</item> <item name="attr/icon_settings">@drawable/ic_settings_grey600_24dp</item> <item name="attr/icon_import_export">@drawable/ic_import_export_white_24dp</item> + <item name="attr/icon_share">@drawable/ic_share_white_24dp</item> </style> diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 6108286d..0db01a4d 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -105,9 +105,6 @@ <string name="pref_notifications">Thông báo</string> <string name="pref_notifications_summary">Thông báo khi có tin nhắn mới</string> <string name="pref_vibrate">Rung</string> - <string name="pref_vibrate_summary">Rung khi có tin nhắn mới</string> - <string name="pref_sound">Âm báo</string> - <string name="pref_sound_summary">Chơi nhạc chuông cùng với thông báo</string> <string name="pref_notification_grace_period">Thời gian gia hạn thông báo</string> <string name="pref_notification_grace_period_summary">Tắt thông báo trong một thời gian ngắn sau khi nhận được bản sao giấy than</string> <string name="pref_never_send_crash">Không bao giờ gửi báo cáo dừng chạy</string> diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 250f1a5d..76f73f06 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -71,6 +71,8 @@ <string name="send_failed">传递失败</string> <string name="send_rejected">拒绝</string> <string name="preparing_image">准备传输图像</string> + <string name="preparing_images">正在传输图像</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> @@ -352,6 +354,7 @@ <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> <string name="sending_file">发送中 (已完成 %1$d%%)</string> @@ -506,7 +509,7 @@ <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_show_connection_options">高级边接设置</string> + <string name="pref_show_connection_options">高级连接设置</string> <string name="pref_show_connection_options_summary">注册账户时显示主机名和端口</string> <string name="hostname_example">xmpp.example.com</string> <string name="action_add_account_with_certificate">使用证书添加账户</string> @@ -536,6 +539,7 @@ </plurals> <string name="shared_file_with_x">用 %s 分享文件</string> <string name="shared_image_with_x">用 %s 分享图片</string> + <string name="shared_images_with_x">图片分享自 %s</string> <string name="no_storage_permission">Conversations+ 需要访问外部存储</string> <string name="sync_with_contacts">与联系人同步</string> <string name="sync_with_contacts_long">Conversations+ 会匹配你的 XMPP 花名册与你的联系人,以显示他们的全名和头像。\n\nConversations+ 只会读取你的联系人并在本地匹配,不会上传到你的服务器。\n\n现在将要询问你是否给予访问你联系人的权限。</string> diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index 8dac03ff..8e9bac60 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -83,9 +83,6 @@ <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_sound">聲音</string> - <string name="pref_sound_summary">收到新訊息時播放鈴聲</string> <string name="pref_notification_grace_period">通知限期</string> <string name="pref_notification_grace_period_summary">收到副本後,關閉通知一小段時間</string> <string name="pref_never_send_crash">總是不發送故障報告</string> diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index 2cad436c..135301c0 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -27,6 +27,7 @@ <attr name="icon_search" format="reference"/> <attr name="icon_secure" format="reference"/> <attr name="icon_settings" format="reference"/> + <attr name="icon_share" format="reference"/> <attr name="icon_import_export" format="reference"/> <declare-styleable name="AmbilWarnaPreference"> <attr name="supportsAlpha" diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 3126572d..b6aa8899 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -104,6 +104,8 @@ <string name="pref_xmpp_resource_summary">The name this client identifies itself with</string> <string name="pref_accept_files">Accept files</string> <string name="pref_accept_files_summary">Automatically accept files smaller than…</string> + <string name="pref_return_to_previous">Quick Sharing</string> + <string name="pref_return_to_previous_summary">Immediately return to previous activity instead of opening the conversation after sharing something</string> <string name="pref_accept_files_size">Size</string> <string name="pref_accept_files_size_summary">Automatically accept files smaller than…</string> <string name="pref_accept_files_download">Wi-Fi only</string> @@ -114,9 +116,11 @@ <string name="pref_notifications">Notifications</string> <string name="pref_notifications_summary">Notify when a new message arrives</string> <string name="pref_vibrate">Vibrate</string> - <string name="pref_vibrate_summary">Also vibrate when a new message arrives</string> + <string name="pref_vibrate_summary">Vibrate when a new message arrives</string> + <string name="pref_led">LED Notification</string> + <string name="pref_led_summary">Blink notification light when a new message arrives</string> <string name="pref_sound">Sound</string> - <string name="pref_sound_summary">Play ringtone with notification</string> + <string name="pref_sound_summary">Play sound when a new message arrives</string> <string name="pref_notification_grace_period">Notification grace period</string> <string name="pref_notification_grace_period_summary">Disable notifications for a short time after a carbon copy was received</string> <string name="pref_advanced_options">Advanced</string> @@ -291,8 +295,6 @@ <string name="pref_security_settings">Security</string> <string name="pref_force_encryption">Force end-to-end encryption</string> <string name="pref_force_encryption_summary">Always send messages encrypted (except for conferences)</string> - <string name="pref_allow_message_correction">Allow message correction</string> - <string name="pref_allow_message_correction_summary">Allow your contacts to retroactively edit their messages</string> <string name="pref_dont_save_encrypted">Don’t save encrypted messages</string> <string name="pref_dont_save_encrypted_summary">Warning: This could lead to message loss</string> <string name="pref_expert_options">Expert settings</string> @@ -636,6 +638,7 @@ <string name="shared_file_with_x">Shared file with %s</string> <string name="shared_image_with_x">Shared image with %s</string> <string name="shared_images_with_x">Shared images with %s</string> + <string name="shared_text_with_x">Shared text with %s</string> <string name="no_storage_permission">Conversations+ need access to external storage</string> <string name="sync_with_contacts">Synchronize with contacts</string> <string name="sync_with_contacts_long">Conversations+ wants to match your XMPP roster with your contacts to show their full names and avatars.\n\nConversations+ will only read your contacts and match them locally without uploading them to your server.\n\nYou will now be asked to grant permission to access your contacts.</string> @@ -666,4 +669,8 @@ <string name="no_keys_just_confirm">You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference.</string> <string name="select_image_and_crop">Select image and crop</string> <string name="this_account_is_disabled">You have disabled this account</string> + <string name="cplus_copy_item">Copy item</string> + <string name="security_error_invalid_file_access">Security error: Invalid file access</string> + <string name="no_application_to_share_uri">No application found to share URI</string> + <string name="share_uri_with">Share URI with…</string> </resources> diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 142499f4..a157084f 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -33,6 +33,7 @@ <item name="attr/icon_secure">@drawable/ic_action_secure</item> <item name="attr/icon_settings">@drawable/ic_action_settings</item> <item name="attr/icon_import_export">@drawable/ic_stat_communication_import_export</item> + <item name="attr/icon_share">@drawable/ic_action_share</item> </style> <style name="ConversationsTheme.LargerText" parent="ConversationsTheme"> diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index 17c56bf7..44b66ab7 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -79,8 +79,15 @@ android:key="resize_picture" android:summary="@string/pref_resize_picture_summary" android:title="@string/pref_resize_picture"/> + <CheckBoxPreference + android:defaultValue="false" + android:key="return_to_previous" + android:title="@string/pref_return_to_previous" + android:summary="@string/pref_return_to_previous_summary"/> </PreferenceCategory> - <PreferenceCategory android:title="@string/pref_notification_settings" > + <PreferenceCategory + android:key="notifications" + android:title="@string/pref_notification_settings"> <PreferenceScreen android:summary="@string/pref_notification_settings" android:title="@string/pref_notifications" > @@ -117,15 +124,20 @@ android:dependency="show_notification" android:key="vibrate_on_notification" android:summary="@string/pref_vibrate_summary" - android:title="@string/pref_vibrate" /> - - <RingtonePreference - android:defaultValue="content://settings/system/notification_sound" + android:title="@string/pref_vibrate"/> + <CheckBoxPreference + android:defaultValue="true" android:dependency="show_notification" - android:key="notification_ringtone" - android:ringtoneType="notification" - android:summary="@string/pref_sound_summary" - android:title="@string/pref_sound" /> + android:key="led" + android:title="@string/pref_led" + android:summary="@string/pref_led_summary"/> + <RingtonePreference + android:defaultValue="content://settings/system/notification_sound" + android:dependency="show_notification" + android:key="notification_ringtone" + android:ringtoneType="notification" + android:summary="@string/pref_sound_summary" + android:title="@string/pref_sound"/> <yuku.ambilwarna.widget.AmbilWarnaPreference android:defaultValue="0xffffffff" @@ -185,7 +197,8 @@ android:title="@string/pref_dont_trust_system_cas_title"/> <Preference android:key="remove_trusted_certificates" - android:summary="@string/pref_remove_trusted_certificates_summary"/> + android:summary="@string/pref_remove_trusted_certificates_summary" + android:title="@string/pref_remove_trusted_certificates_title"/> </PreferenceCategory> <PreferenceCategory android:key="connection_options" |