diff --git a/build.gradle b/build.gradle
index 2540a7836..3f6c3ec6b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,6 +47,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.exifinterface:exifinterface:1.3.7'
implementation 'androidx.cardview:cardview:1.0.0'
+ implementation "androidx.preference:preference:1.2.1"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.google.android.material:material:1.11.0'
diff --git a/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java b/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
index d09005593..9228a5170 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
@@ -147,7 +147,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (easyOnboardingInvite != null) {
return;
}
diff --git a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
index 5a301f769..b6d4d452e 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
@@ -35,7 +35,7 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
protected void refreshUiReal() {}
@Override
- void onBackendConnected() {}
+ protected void onBackendConnected() {}
@Override
protected void onCreate(final Bundle savedInstanceState) {
diff --git a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
index 1a04210dd..2f4c81671 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -137,7 +137,7 @@ public class ManageAccountActivity extends XmppActivity
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (selectedAccountJid != null) {
this.selectedAccount = xmppConnectionService.findAccountByJid(selectedAccountJid);
}
diff --git a/src/conversations/java/eu/siacs/conversations/ui/PickServerActivity.java b/src/conversations/java/eu/siacs/conversations/ui/PickServerActivity.java
index cbdd21b36..f96a17ffc 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/PickServerActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/PickServerActivity.java
@@ -22,7 +22,7 @@ public class PickServerActivity extends XmppActivity {
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
}
diff --git a/src/conversations/java/eu/siacs/conversations/ui/ShareViaAccountActivity.java b/src/conversations/java/eu/siacs/conversations/ui/ShareViaAccountActivity.java
index 66ed355c4..0b20e26c5 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/ShareViaAccountActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/ShareViaAccountActivity.java
@@ -57,7 +57,7 @@ public class ShareViaAccountActivity extends XmppActivity {
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
final int numAccounts = xmppConnectionService.getAccounts().size();
if (numAccounts == 1) {
diff --git a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
index 24528fc16..b2a40976c 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
@@ -88,7 +88,7 @@ public class WelcomeActivity extends XmppActivity
protected void refreshUiReal() {}
@Override
- void onBackendConnected() {}
+ protected void onBackendConnected() {}
@Override
public void onStart() {
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index f0d982561..fa89034ae 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -255,7 +255,7 @@
@@ -265,10 +265,10 @@
+ android:label="@string/title_activity_choose_contact" />
+ android:label="@string/title_activity_block_list" />
@@ -353,7 +353,7 @@
+ android:label="@string/media_browser" />
+ android:label="@string/group_chat_members" />
+ android:label="@string/discover_channels" />
= Build.VERSION_CODES.M) {
- scheduleNextIdlePing();
- }
+ scheduleNextIdlePing();
break;
case ACTION_FCM_MESSAGE_RECEIVED:
Log.d(Config.LOGTAG, "push message arrived in service. account");
@@ -1119,19 +1117,19 @@ public class XmppConnectionService extends Service {
}
private boolean dndOnSilentMode() {
- return getBooleanPreference(SettingsActivity.DND_ON_SILENT_MODE, R.bool.dnd_on_silent_mode);
+ return getBooleanPreference(AppSettings.DND_ON_SILENT_MODE, R.bool.dnd_on_silent_mode);
}
private boolean manuallyChangePresence() {
- return getBooleanPreference(SettingsActivity.MANUALLY_CHANGE_PRESENCE, R.bool.manually_change_presence);
+ return getBooleanPreference(AppSettings.MANUALLY_CHANGE_PRESENCE, R.bool.manually_change_presence);
}
private boolean treatVibrateAsSilent() {
- return getBooleanPreference(SettingsActivity.TREAT_VIBRATE_AS_SILENT, R.bool.treat_vibrate_as_silent);
+ return getBooleanPreference(AppSettings.TREAT_VIBRATE_AS_SILENT, R.bool.treat_vibrate_as_silent);
}
private boolean awayWhenScreenLocked() {
- return getBooleanPreference(SettingsActivity.AWAY_WHEN_SCREEN_IS_OFF, R.bool.away_when_screen_off);
+ return getBooleanPreference(AppSettings.AWAY_WHEN_SCREEN_IS_OFF, R.bool.away_when_screen_off);
}
private String getCompressPicturesPreference() {
@@ -1287,10 +1285,6 @@ public class XmppConnectionService extends Service {
Log.d(Config.LOGTAG, "restoring accounts...");
this.accounts = databaseBackend.getAccounts();
final SharedPreferences.Editor editor = getPreferences().edit();
- if (this.accounts.size() == 0 && Arrays.asList("Sony", "Sony Ericsson").contains(Build.MANUFACTURER)) {
- editor.putBoolean(SettingsActivity.KEEP_FOREGROUND_SERVICE, true);
- Log.d(Config.LOGTAG, Build.MANUFACTURER + " is on blacklist. enabling foreground service");
- }
final boolean hasEnabledAccounts = hasEnabledAccounts();
editor.putBoolean(EventReceiver.SETTING_ENABLED_ACCOUNTS, hasEnabledAccounts).apply();
editor.apply();
@@ -1334,20 +1328,18 @@ public class XmppConnectionService extends Service {
this.pgpServiceConnection.bindToService();
}
- final PowerManager pm = ContextCompat.getSystemService(this, PowerManager.class);
- this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Conversations:Service");
+ final PowerManager powerManager = getSystemService(PowerManager.class);
+ this.wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Conversations:Service");
toggleForegroundService();
updateUnreadCountBadge();
toggleScreenEventReceiver();
final IntentFilter systemBroadcastFilter = new IntentFilter();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- scheduleNextIdlePing();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- systemBroadcastFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- }
- systemBroadcastFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ scheduleNextIdlePing();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ systemBroadcastFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
}
+ systemBroadcastFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
ContextCompat.registerReceiver(
this,
this.mInternalEventReceiver,
@@ -1363,6 +1355,17 @@ public class XmppConnectionService extends Service {
mForceDuringOnCreate.set(false);
toggleForegroundService();
internalPingExecutor.scheduleAtFixedRate(this::manageAccountConnectionStatesInternal,10,10,TimeUnit.SECONDS);
+ final SharedPreferences sharedPreferences =
+ androidx.preference.PreferenceManager.getDefaultSharedPreferences(this);
+ sharedPreferences.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
+ Log.d(Config.LOGTAG,"preference '"+key+"' has changed");
+ if (AppSettings.KEEP_FOREGROUND_SERVICE.equals(key)) {
+ toggleForegroundService();
+ }
+ }
+ });
}
@@ -4421,7 +4424,7 @@ public class XmppConnectionService extends Service {
}
public long getAutomaticMessageDeletionDate() {
- final long timeout = getLongPreference(SettingsActivity.AUTOMATIC_MESSAGE_DELETION, R.integer.automatic_message_deletion);
+ final long timeout = getLongPreference(AppSettings.AUTOMATIC_MESSAGE_DELETION, R.integer.automatic_message_deletion);
return timeout == 0 ? timeout : (System.currentTimeMillis() - (timeout * 1000));
}
@@ -4459,11 +4462,11 @@ public class XmppConnectionService extends Service {
}
public boolean showExtendedConnectionOptions() {
- return QuickConversationsService.isConversations() && getBooleanPreference("show_connection_options", R.bool.show_connection_options);
+ return QuickConversationsService.isConversations() && getBooleanPreference(AppSettings.SHOW_CONNECTION_OPTIONS, R.bool.show_connection_options);
}
public boolean broadcastLastActivity() {
- return getBooleanPreference(SettingsActivity.BROADCAST_LAST_ACTIVITY, R.bool.last_activity);
+ return getBooleanPreference(AppSettings.BROADCAST_LAST_ACTIVITY, R.bool.last_activity);
}
public int unreadCount() {
@@ -4477,7 +4480,7 @@ public class XmppConnectionService extends Service {
private List threadSafeList(Set set) {
synchronized (LISTENER_LOCK) {
- return set.size() == 0 ? Collections.emptyList() : new ArrayList<>(set);
+ return set.isEmpty() ? Collections.emptyList() : new ArrayList<>(set);
}
}
@@ -5208,7 +5211,7 @@ public class XmppConnectionService extends Service {
}
public boolean blindTrustBeforeVerification() {
- return getBooleanPreference(SettingsActivity.BLIND_TRUST_BEFORE_VERIFICATION, R.bool.btbv);
+ return getBooleanPreference(AppSettings.BLIND_TRUST_BEFORE_VERIFICATION, R.bool.btbv);
}
public ShortcutService getShortcutService() {
diff --git a/src/main/java/eu/siacs/conversations/ui/AbstractSearchableListItemActivity.java b/src/main/java/eu/siacs/conversations/ui/AbstractSearchableListItemActivity.java
index d57737f61..2aa9421fd 100644
--- a/src/main/java/eu/siacs/conversations/ui/AbstractSearchableListItemActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/AbstractSearchableListItemActivity.java
@@ -126,7 +126,7 @@ public abstract class AbstractSearchableListItemActivity extends XmppActivity im
protected abstract void filterContacts(final String needle);
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
filterContacts();
}
diff --git a/src/main/java/eu/siacs/conversations/ui/BaseActivity.java b/src/main/java/eu/siacs/conversations/ui/BaseActivity.java
index 9c8871131..cea58c15e 100644
--- a/src/main/java/eu/siacs/conversations/ui/BaseActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/BaseActivity.java
@@ -25,7 +25,7 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onResume(){
super.onResume();
- SettingsUtils.applyScreenshotPreventionSetting(this);
+ SettingsUtils.applyScreenshotSetting(this);
}
public void setDynamicColors(final boolean isDynamicColors) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
index cf48a1259..fba273b0a 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
@@ -51,7 +51,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti
private Account mAccount;
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
this.mAccount = extractAccount(getIntent());
if (this.mAccount != null && this.mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
this.binding.currentPasswordLayout.setVisibility(View.GONE);
diff --git a/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java b/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
index 8d780d0d7..5a9c31d20 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
@@ -65,7 +65,7 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (optedIn || method == ChannelDiscoveryService.Method.LOCAL_SERVER) {
final String query;
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
index 41a894403..71662589c 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
@@ -47,7 +47,7 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
loadEnabledAccounts();
if (accountList.size() == 1) {
goToProfilePictureActivity(accountList.get(0));
diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
index 2aacf8927..b9ebb413d 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
@@ -362,7 +362,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
filterContacts();
this.mActivatedAccounts.clear();
for (final Account account : xmppConnectionService.getAccounts()) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index 6d0bc7928..5ed83219d 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -396,7 +396,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (mPendingConferenceInvite != null) {
mPendingConferenceInvite.execute(this);
mPendingConferenceInvite = null;
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index 24dd3cafd..dc038ce37 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -39,6 +39,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@@ -243,7 +244,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
public void onStart() {
super.onStart();
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
- this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, false);
+ this.showDynamicTags = preferences.getBoolean(AppSettings.SHOW_DYNAMIC_TAGS, false);
this.showLastSeen = preferences.getBoolean("last_activity", false);
binding.mediaWrapper.setVisibility(Compatibility.hasStoragePermission(this) ? View.VISIBLE : View.GONE);
mMediaAdapter.setAttachments(Collections.emptyList());
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java
index 92329c666..7d3846ebe 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java
@@ -144,7 +144,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (performRedirectIfNecessary(true)) {
return;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index be8caa986..bc4fab2cc 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -47,6 +47,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@@ -938,7 +939,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
private void changePresence() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- boolean manualStatus = sharedPreferences.getBoolean(SettingsActivity.MANUALLY_CHANGE_PRESENCE, getResources().getBoolean(R.bool.manually_change_presence));
+ boolean manualStatus = sharedPreferences.getBoolean(AppSettings.MANUALLY_CHANGE_PRESENCE, getResources().getBoolean(R.bool.manually_change_presence));
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
final DialogPresenceBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.dialog_presence, null, false);
String current = mAccount.getPresenceStatusMessage();
diff --git a/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java b/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
index f8d60d557..ac5b07e77 100644
--- a/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
@@ -44,7 +44,7 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
Intent intent = getIntent();
String account = intent == null ? null : intent.getStringExtra("account");
String jid = intent == null ? null : intent.getStringExtra("jid");
diff --git a/src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java b/src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java
index 56913b2a1..bfce03860 100644
--- a/src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java
@@ -60,7 +60,7 @@ public class MemorizingActivity extends AppCompatActivity implements OnClickList
@Override
public void onResume() {
super.onResume();
- SettingsUtils.applyScreenshotPreventionSetting(this);
+ SettingsUtils.applyScreenshotSetting(this);
Intent i = getIntent();
decisionId = i.getIntExtra(MemorizingTrustManager.DECISION_INTENT_ID, MTMDecision.DECISION_INVALID);
diff --git a/src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java b/src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java
index f6eae81cf..72cad4cd0 100644
--- a/src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java
@@ -49,7 +49,7 @@ public class MucUsersActivity extends XmppActivity implements XmppConnectionServ
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
final Intent intent = getIntent();
final String uuid = intent == null ? null : intent.getStringExtra("uuid");
if (uuid != null) {
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java
index aaef09978..8d686c36f 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java
@@ -63,7 +63,7 @@ public class PublishGroupChatProfilePictureActivity extends XmppActivity impleme
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
String uuid = pendingConversationUuid.pop();
if (uuid != null) {
this.conversation = xmppConnectionService.findConversationByUuid(uuid);
diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
index 75c9468f9..7a2bb0938 100644
--- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
@@ -475,7 +475,7 @@ public class RtpSessionActivity extends XmppActivity
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
final var intent = getIntent();
if (intent == null) {
return;
diff --git a/src/main/java/eu/siacs/conversations/ui/SearchActivity.java b/src/main/java/eu/siacs/conversations/ui/SearchActivity.java
index d49d7d23d..5803a20e5 100644
--- a/src/main/java/eu/siacs/conversations/ui/SearchActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/SearchActivity.java
@@ -215,7 +215,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
final List searchTerm = pendingSearch.pop();
if (searchTerm != null && currentSearch.watch(searchTerm)) {
xmppConnectionService.search(searchTerm, uuid,this);
diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
deleted file mode 100644
index 0e80fa1d5..000000000
--- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
+++ /dev/null
@@ -1,568 +0,0 @@
-package eu.siacs.conversations.ui;
-
-import android.app.FragmentManager;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceCategory;
-import android.preference.PreferenceManager;
-import android.preference.PreferenceScreen;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.core.content.ContextCompat;
-import androidx.databinding.DataBindingUtil;
-
-import com.google.android.material.color.DynamicColors;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.KeyStoreException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.Conversations;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.crypto.OmemoSetting;
-import eu.siacs.conversations.databinding.ActivitySettingsBinding;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.services.ExportBackupService;
-import eu.siacs.conversations.services.MemorizingTrustManager;
-import eu.siacs.conversations.services.QuickConversationsService;
-import eu.siacs.conversations.services.UnifiedPushDistributor;
-import eu.siacs.conversations.ui.util.SettingsUtils;
-import eu.siacs.conversations.utils.GeoHelper;
-import eu.siacs.conversations.utils.TimeFrameUtils;
-import eu.siacs.conversations.xmpp.Jid;
-
-public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener {
-
- public static final String KEEP_FOREGROUND_SERVICE = "enable_foreground_service";
- public static final String AWAY_WHEN_SCREEN_IS_OFF = "away_when_screen_off";
- public static final String TREAT_VIBRATE_AS_SILENT = "treat_vibrate_as_silent";
- public static final String DND_ON_SILENT_MODE = "dnd_on_silent_mode";
- public static final String MANUALLY_CHANGE_PRESENCE = "manually_change_presence";
- public static final String BLIND_TRUST_BEFORE_VERIFICATION = "btbv";
- public static final String AUTOMATIC_MESSAGE_DELETION = "automatic_message_deletion";
- public static final String BROADCAST_LAST_ACTIVITY = "last_activity";
- public static final String THEME = "theme";
- public static final String SHOW_DYNAMIC_TAGS = "show_dynamic_tags";
- public static final String OMEMO_SETTING = "omemo";
- public static final String PREVENT_SCREENSHOTS = "prevent_screenshots";
-
- public static final int REQUEST_CREATE_BACKUP = 0xbf8701;
-
- private SettingsFragment mSettingsFragment;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- final ActivitySettingsBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_settings);
- FragmentManager fm = getFragmentManager();
- mSettingsFragment = (SettingsFragment) fm.findFragmentById(R.id.settings_content);
- if (mSettingsFragment == null
- || !mSettingsFragment.getClass().equals(SettingsFragment.class)) {
- mSettingsFragment = new SettingsFragment();
- fm.beginTransaction().replace(R.id.settings_content, mSettingsFragment).commit();
- }
- mSettingsFragment.setActivityIntent(getIntent());
- Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
- setSupportActionBar(binding.toolbar);
- configureActionBar(getSupportActionBar());
- }
-
- @Override
- void onBackendConnected() {
- final Preference accountPreference =
- mSettingsFragment.findPreference(UnifiedPushDistributor.PREFERENCE_ACCOUNT);
- reconfigureUpAccountPreference(accountPreference);
- }
-
- private void reconfigureUpAccountPreference(final Preference preference) {
- final ListPreference listPreference;
- if (preference instanceof ListPreference) {
- listPreference = (ListPreference) preference;
- } else {
- return;
- }
- final List accounts =
- ImmutableList.copyOf(
- Lists.transform(
- xmppConnectionService.getAccounts(),
- a -> a.getJid().asBareJid().toEscapedString()));
- final ImmutableList.Builder entries = new ImmutableList.Builder<>();
- final ImmutableList.Builder entryValues = new ImmutableList.Builder<>();
- entries.add(getString(R.string.no_account_deactivated));
- entryValues.add("none");
- entries.addAll(accounts);
- entryValues.addAll(accounts);
- listPreference.setEntries(entries.build().toArray(new CharSequence[0]));
- listPreference.setEntryValues(entryValues.build().toArray(new CharSequence[0]));
- if (!accounts.contains(listPreference.getValue())) {
- listPreference.setValue("none");
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(this);
-
- changeOmemoSettingSummary();
-
- if (QuickConversationsService.isQuicksy()
- || QuickConversationsService.isPlayStoreFlavor()
- || Strings.isNullOrEmpty(Config.CHANNEL_DISCOVERY)) {
- final PreferenceCategory groupChats =
- (PreferenceCategory) mSettingsFragment.findPreference("group_chats");
- final Preference channelDiscoveryMethod =
- mSettingsFragment.findPreference("channel_discovery_method");
- if (groupChats != null && channelDiscoveryMethod != null) {
- groupChats.removePreference(channelDiscoveryMethod);
- }
- }
-
- if (QuickConversationsService.isQuicksy()) {
- final PreferenceCategory connectionOptions =
- (PreferenceCategory) mSettingsFragment.findPreference("connection_options");
- PreferenceScreen expert = (PreferenceScreen) mSettingsFragment.findPreference("expert");
- if (connectionOptions != null) {
- expert.removePreference(connectionOptions);
- }
- }
-
- PreferenceScreen mainPreferenceScreen =
- (PreferenceScreen) mSettingsFragment.findPreference("main_screen");
-
- PreferenceCategory attachmentsCategory =
- (PreferenceCategory) mSettingsFragment.findPreference("attachments");
- CheckBoxPreference locationPlugin =
- (CheckBoxPreference) mSettingsFragment.findPreference("use_share_location_plugin");
- if (attachmentsCategory != null && locationPlugin != null) {
- if (!GeoHelper.isLocationPluginInstalled(this)) {
- attachmentsCategory.removePreference(locationPlugin);
- }
- }
-
- // this feature is only available on Huawei Android 6.
- PreferenceScreen huaweiPreferenceScreen =
- (PreferenceScreen) mSettingsFragment.findPreference("huawei");
- if (huaweiPreferenceScreen != null) {
- Intent intent = huaweiPreferenceScreen.getIntent();
- // remove when Api version is above M (Version 6.0) or if the intent is not callable
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || !isCallable(intent)) {
- PreferenceCategory generalCategory =
- (PreferenceCategory) mSettingsFragment.findPreference("general");
- generalCategory.removePreference(huaweiPreferenceScreen);
- if (generalCategory.getPreferenceCount() == 0) {
- if (mainPreferenceScreen != null) {
- mainPreferenceScreen.removePreference(generalCategory);
- }
- }
- }
- }
-
- final PreferenceCategory uiPreferenceCategory = (PreferenceCategory) mSettingsFragment.findPreference("ui");
- final Preference dynamicColorsPreference = mSettingsFragment.findPreference("dynamic_colors");
- if (dynamicColorsPreference != null && !DynamicColors.isDynamicColorAvailable()) {
- uiPreferenceCategory.removePreference(dynamicColorsPreference);
- }
-
- ListPreference automaticMessageDeletionList =
- (ListPreference) mSettingsFragment.findPreference(AUTOMATIC_MESSAGE_DELETION);
- if (automaticMessageDeletionList != null) {
- final int[] choices =
- getResources().getIntArray(R.array.automatic_message_deletion_values);
- CharSequence[] entries = new CharSequence[choices.length];
- CharSequence[] entryValues = new CharSequence[choices.length];
- for (int i = 0; i < choices.length; ++i) {
- entryValues[i] = String.valueOf(choices[i]);
- if (choices[i] == 0) {
- entries[i] = getString(R.string.never);
- } else {
- entries[i] = TimeFrameUtils.resolve(this, 1000L * choices[i]);
- }
- }
- automaticMessageDeletionList.setEntries(entries);
- automaticMessageDeletionList.setEntryValues(entryValues);
- }
-
- final Preference removeCertsPreference =
- mSettingsFragment.findPreference("remove_trusted_certificates");
- if (removeCertsPreference != null) {
- removeCertsPreference.setOnPreferenceClickListener(
- preference -> {
- final MemorizingTrustManager mtm =
- xmppConnectionService.getMemorizingTrustManager();
- final ArrayList aliases = Collections.list(mtm.getCertificates());
- if (aliases.isEmpty()) {
- displayToast(getString(R.string.toast_no_trusted_certs));
- return true;
- }
- final ArrayList selectedItems = new ArrayList<>();
- final MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(SettingsActivity.this);
- dialogBuilder.setTitle(
- getResources().getString(R.string.dialog_manage_certs_title));
- dialogBuilder.setMultiChoiceItems(
- aliases.toArray(new CharSequence[0]),
- null,
- (dialog, indexSelected, isChecked) -> {
- if (isChecked) {
- selectedItems.add(indexSelected);
- } else if (selectedItems.contains(indexSelected)) {
- selectedItems.remove(Integer.valueOf(indexSelected));
- }
- ((AlertDialog) dialog)
- .getButton(DialogInterface.BUTTON_POSITIVE)
- .setEnabled(!selectedItems.isEmpty());
- });
-
- dialogBuilder.setPositiveButton(
- getResources()
- .getString(R.string.dialog_manage_certs_positivebutton),
- (dialog, which) -> {
- int count = selectedItems.size();
- if (count > 0) {
- for (int i = 0; i < count; i++) {
- try {
- final int item =
- Integer.parseInt(
- selectedItems.get(i).toString());
- String alias = aliases.get(item);
- mtm.deleteCertificate(alias);
- } catch (final KeyStoreException e) {
- displayToast("Error: " + e.getLocalizedMessage());
- }
- }
- if (xmppConnectionServiceBound) {
- reconnectAccounts();
- }
- displayToast(
- getResources()
- .getQuantityString(
- R.plurals.toast_delete_certificates,
- count,
- count));
- }
- });
- dialogBuilder.setNegativeButton(
- getResources()
- .getString(R.string.dialog_manage_certs_negativebutton),
- null);
- AlertDialog removeCertsDialog = dialogBuilder.create();
- removeCertsDialog.show();
- removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
- return true;
- });
- }
-
- final Preference createBackupPreference = mSettingsFragment.findPreference("create_backup");
- if (createBackupPreference != null) {
- createBackupPreference.setSummary(
- getString(
- R.string.pref_create_backup_summary,
- FileBackend.getBackupDirectory(this).getAbsolutePath()));
- createBackupPreference.setOnPreferenceClickListener(
- preference -> {
- if (hasStoragePermission(REQUEST_CREATE_BACKUP)) {
- createBackup();
- }
- return true;
- });
- }
-
- if (Config.ONLY_INTERNAL_STORAGE) {
- final Preference cleanCachePreference = mSettingsFragment.findPreference("clean_cache");
- if (cleanCachePreference != null) {
- cleanCachePreference.setOnPreferenceClickListener(preference -> cleanCache());
- }
-
- final Preference cleanPrivateStoragePreference =
- mSettingsFragment.findPreference("clean_private_storage");
- if (cleanPrivateStoragePreference != null) {
- cleanPrivateStoragePreference.setOnPreferenceClickListener(
- preference -> cleanPrivateStorage());
- }
- }
-
- final Preference deleteOmemoPreference =
- mSettingsFragment.findPreference("delete_omemo_identities");
- if (deleteOmemoPreference != null) {
- deleteOmemoPreference.setOnPreferenceClickListener(
- preference -> deleteOmemoIdentities());
- }
- if (Config.omemoOnly()) {
- final PreferenceCategory privacyCategory =
- (PreferenceCategory) mSettingsFragment.findPreference("privacy");
- final Preference omemoPreference =mSettingsFragment.findPreference(OMEMO_SETTING);
- if (omemoPreference != null) {
- privacyCategory.removePreference(omemoPreference);
- }
- }
- }
-
- private void changeOmemoSettingSummary() {
- final ListPreference omemoPreference =
- (ListPreference) mSettingsFragment.findPreference(OMEMO_SETTING);
- if (omemoPreference == null) {
- return;
- }
- final String value = omemoPreference.getValue();
- switch (value) {
- case "always":
- omemoPreference.setSummary(R.string.pref_omemo_setting_summary_always);
- break;
- case "default_on":
- omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_on);
- break;
- case "default_off":
- omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_off);
- break;
- }
- }
-
- private boolean isCallable(final Intent i) {
- return i != null
- && !getPackageManager()
- .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY).isEmpty();
- }
-
- private boolean cleanCache() {
- Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.setData(Uri.parse("package:" + getPackageName()));
- startActivity(intent);
- return true;
- }
-
- private boolean cleanPrivateStorage() {
- for (String type : Arrays.asList("Images", "Videos", "Files", "Recordings")) {
- cleanPrivateFiles(type);
- }
- return true;
- }
-
- private void cleanPrivateFiles(final String type) {
- try {
- File dir = new File(getFilesDir().getAbsolutePath(), "/" + type + "/");
- File[] array = dir.listFiles();
- if (array != null) {
- for (int b = 0; b < array.length; b++) {
- String name = array[b].getName().toLowerCase();
- if (name.equals(".nomedia")) {
- continue;
- }
- if (array[b].isFile()) {
- array[b].delete();
- }
- }
- }
- } catch (Throwable e) {
- Log.e("CleanCache", e.toString());
- }
- }
-
- private boolean deleteOmemoIdentities() {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setTitle(R.string.pref_delete_omemo_identities);
- final List accounts = new ArrayList<>();
- for (Account account : xmppConnectionService.getAccounts()) {
- if (account.isEnabled()) {
- accounts.add(account.getJid().asBareJid().toString());
- }
- }
- final boolean[] checkedItems = new boolean[accounts.size()];
- builder.setMultiChoiceItems(
- accounts.toArray(new CharSequence[accounts.size()]),
- checkedItems,
- (dialog, which, isChecked) -> {
- checkedItems[which] = isChecked;
- final AlertDialog alertDialog = (AlertDialog) dialog;
- for (boolean item : checkedItems) {
- if (item) {
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
- return;
- }
- }
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
- });
- builder.setNegativeButton(R.string.cancel, null);
- builder.setPositiveButton(
- R.string.delete_selected_keys,
- (dialog, which) -> {
- for (int i = 0; i < checkedItems.length; ++i) {
- if (checkedItems[i]) {
- try {
- Jid jid = Jid.of(accounts.get(i).toString());
- Account account = xmppConnectionService.findAccountByJid(jid);
- if (account != null) {
- account.getAxolotlService().regenerateKeys(true);
- }
- } catch (IllegalArgumentException e) {
- //
- }
- }
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
- return true;
- }
-
- @Override
- public void onStop() {
- super.onStop();
- PreferenceManager.getDefaultSharedPreferences(this)
- .unregisterOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences preferences, String name) {
- final List resendPresence =
- Arrays.asList(
- "confirm_messages",
- DND_ON_SILENT_MODE,
- AWAY_WHEN_SCREEN_IS_OFF,
- "allow_message_correction",
- TREAT_VIBRATE_AS_SILENT,
- MANUALLY_CHANGE_PRESENCE,
- BROADCAST_LAST_ACTIVITY);
- if (name.equals(OMEMO_SETTING)) {
- OmemoSetting.load(this, preferences);
- changeOmemoSettingSummary();
- } else if (name.equals(KEEP_FOREGROUND_SERVICE)) {
- xmppConnectionService.toggleForegroundService();
- } else if (resendPresence.contains(name)) {
- if (xmppConnectionServiceBound) {
- if (name.equals(AWAY_WHEN_SCREEN_IS_OFF) || name.equals(MANUALLY_CHANGE_PRESENCE)) {
- xmppConnectionService.toggleScreenEventReceiver();
- }
- xmppConnectionService.refreshAllPresences();
- }
- } else if (name.equals("dont_trust_system_cas")) {
- xmppConnectionService.updateMemorizingTrustmanager();
- reconnectAccounts();
- } else if (name.equals("use_tor")) {
- if (preferences.getBoolean(name, false)) {
- displayToast(getString(R.string.audio_video_disabled_tor));
- }
- reconnectAccounts();
- xmppConnectionService.reinitializeMuclumbusService();
- } else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) {
- xmppConnectionService.expireOldMessages(true);
- } else if (name.equals(THEME)) {
- final var value = preferences.getString(THEME,getString(R.string.theme));
- final int desiredNightMode = Conversations.getDesiredNightMode(value);
- setDesiredNightMode(desiredNightMode);
- } else if (name.equals("dynamic_colors")) {
- final var value = preferences.getBoolean("dynamic_colors",false);
- setDynamicColors(value);
- } else if (name.equals(PREVENT_SCREENSHOTS)) {
- SettingsUtils.applyScreenshotPreventionSetting(this);
- } else if (UnifiedPushDistributor.PREFERENCES.contains(name)) {
- final String pushServerPreference =
- Strings.nullToEmpty(preferences.getString(
- UnifiedPushDistributor.PREFERENCE_PUSH_SERVER,
- getString(R.string.default_push_server))).trim();
- if (isJidInvalid(pushServerPreference) || isHttpUri(pushServerPreference)) {
- Toast.makeText(this,R.string.invalid_jid,Toast.LENGTH_LONG).show();
- }
- if (xmppConnectionService.reconfigurePushDistributor()) {
- xmppConnectionService.renewUnifiedPushEndpoints();
- }
- }
- }
-
- private static boolean isJidInvalid(final String input) {
- if (Strings.isNullOrEmpty(input)) {
- return true;
- }
- try {
- Jid.ofEscaped(input);
- return false;
- } catch (final IllegalArgumentException e) {
- return true;
- }
- }
-
- private static boolean isHttpUri(final String input) {
- final URI uri;
- try {
- uri = new URI(input);
- } catch (final URISyntaxException e) {
- return false;
- }
- return Arrays.asList("http","https").contains(uri.getScheme());
- }
-
- @Override
- public void onResume() {
- super.onResume();
- SettingsUtils.applyScreenshotPreventionSetting(this);
- }
-
- @Override
- public void onRequestPermissionsResult(
- int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (grantResults.length > 0)
- if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (requestCode == REQUEST_CREATE_BACKUP) {
- createBackup();
- }
- } else {
- Toast.makeText(
- this,
- getString(
- R.string.no_storage_permission,
- getString(R.string.app_name)),
- Toast.LENGTH_SHORT)
- .show();
- }
- }
-
- private void createBackup() {
- ContextCompat.startForegroundService(this, new Intent(this, ExportBackupService.class));
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setMessage(R.string.backup_started_message);
- builder.setPositiveButton(R.string.ok, null);
- builder.create().show();
- }
-
- private void displayToast(final String msg) {
- runOnUiThread(() -> Toast.makeText(SettingsActivity.this, msg, Toast.LENGTH_LONG).show());
- }
-
- private void reconnectAccounts() {
- for (Account account : xmppConnectionService.getAccounts()) {
- if (account.isEnabled()) {
- xmppConnectionService.reconnectAccountInBackground(account);
- }
- }
- }
-
- public void refreshUiReal() {
- // nothing to do. This Activity doesn't implement any listeners
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java
deleted file mode 100644
index 9378d82b7..000000000
--- a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package eu.siacs.conversations.ui;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceCategory;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
-import android.text.TextUtils;
-import android.widget.ListView;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.utils.Compatibility;
-
-public class SettingsFragment extends PreferenceFragment {
-
- private String page = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preferences);
-
- // Remove from standard preferences if the flag ONLY_INTERNAL_STORAGE is false
- if (!Config.ONLY_INTERNAL_STORAGE) {
- PreferenceCategory mCategory = (PreferenceCategory) findPreference("security_options");
- if (mCategory != null) {
- Preference cleanCache = findPreference("clean_cache");
- Preference cleanPrivateStorage = findPreference("clean_private_storage");
- mCategory.removePreference(cleanCache);
- mCategory.removePreference(cleanPrivateStorage);
- }
- }
- Compatibility.removeUnusedPreferences(this);
-
- if (!TextUtils.isEmpty(page)) {
- openPreferenceScreen(page);
- }
-
- }
-
- @Override
- public void onActivityCreated(Bundle bundle) {
- super.onActivityCreated(bundle);
-
- final ListView listView = getActivity().findViewById(android.R.id.list);
- if (listView != null) {
- listView.setDivider(null);
- }
- }
-
- public void setActivityIntent(final Intent intent) {
- boolean wasEmpty = TextUtils.isEmpty(page);
- if (intent != null) {
- if (Intent.ACTION_VIEW.equals(intent.getAction())) {
- if (intent.getExtras() != null) {
- this.page = intent.getExtras().getString("page");
- if (wasEmpty) {
- openPreferenceScreen(page);
- }
- }
- }
- }
- }
-
- private void openPreferenceScreen(final String screenName) {
- final Preference pref = findPreference(screenName);
- if (pref instanceof PreferenceScreen) {
- final PreferenceScreen preferenceScreen = (PreferenceScreen) pref;
- getActivity().setTitle(preferenceScreen.getTitle());
- preferenceScreen.setDependency("");
- setPreferenceScreen((PreferenceScreen) pref);
- }
- }
-}
diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
index 0f1cb4f68..c33c3e6bd 100644
--- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -172,7 +172,7 @@ public class ShareWithActivity extends XmppActivity
}
@Override
- void onBackendConnected() {
+ protected void onBackendConnected() {
if (xmppConnectionServiceBound
&& share != null
&& ((share.contact != null && share.account != null))) {
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index c7302ae2e..b9b09d0e0 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -18,7 +18,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
@@ -56,6 +55,7 @@ import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.common.base.Strings;
+import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -348,7 +348,7 @@ public abstract class XmppActivity extends ActionBarActivity {
dialog.show();
}
- abstract void onBackendConnected();
+ protected abstract void onBackendConnected();
protected void registerListeners() {
if (this instanceof XmppConnectionService.OnConversationUpdate) {
@@ -414,7 +414,7 @@ public abstract class XmppActivity extends ActionBarActivity {
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
- startActivity(new Intent(this, SettingsActivity.class));
+ startActivity(new Intent(this, eu.siacs.conversations.ui.activity.SettingsActivity.class));
break;
case R.id.action_privacy_policy:
openPrivacyPolicy();
@@ -832,7 +832,7 @@ public abstract class XmppActivity extends ActionBarActivity {
}
protected boolean manuallyChangePresence() {
- return getBooleanPreference(SettingsActivity.MANUALLY_CHANGE_PRESENCE, R.bool.manually_change_presence);
+ return getBooleanPreference(AppSettings.MANUALLY_CHANGE_PRESENCE, R.bool.manually_change_presence);
}
protected String getShareableUri() {
@@ -873,7 +873,7 @@ public abstract class XmppActivity extends ActionBarActivity {
@Override
protected void onResume(){
super.onResume();
- SettingsUtils.applyScreenshotPreventionSetting(this);
+ SettingsUtils.applyScreenshotSetting(this);
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/activity/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/activity/SettingsActivity.java
new file mode 100644
index 000000000..7ac855534
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/activity/SettingsActivity.java
@@ -0,0 +1,70 @@
+package eu.siacs.conversations.ui.activity;
+
+import android.app.Notification;
+import android.os.Bundle;
+
+import androidx.databinding.DataBindingUtil;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.google.common.collect.ImmutableSet;
+
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.databinding.ActivitySettingsBinding;
+import eu.siacs.conversations.ui.Activities;
+import eu.siacs.conversations.ui.XmppActivity;
+import eu.siacs.conversations.ui.fragment.settings.MainSettingsFragment;
+import eu.siacs.conversations.ui.fragment.settings.NotificationsSettingsFragment;
+import eu.siacs.conversations.ui.fragment.settings.XmppPreferenceFragment;
+
+import java.util.Collections;
+
+public class SettingsActivity extends XmppActivity {
+
+ @Override
+ protected void refreshUiReal() {}
+
+ @Override
+ protected void onBackendConnected() {
+ final var fragmentManager = getSupportFragmentManager();
+ final var currentFragment = fragmentManager.findFragmentById(R.id.fragment_container);
+ if (currentFragment instanceof XmppPreferenceFragment xmppPreferenceFragment) {
+ xmppPreferenceFragment.onBackendConnected();
+ }
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final ActivitySettingsBinding binding =
+ DataBindingUtil.setContentView(this, R.layout.activity_settings);
+ setSupportActionBar(binding.materialToolbar);
+ Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
+
+ final var intent = getIntent();
+ final var categories = intent == null ? Collections.emptySet() : intent.getCategories();
+ final PreferenceFragmentCompat preferenceFragment;
+ if (ImmutableSet.of(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+ .equals(categories)) {
+ preferenceFragment = new NotificationsSettingsFragment();
+ } else {
+ preferenceFragment = new MainSettingsFragment();
+ }
+
+ final var fragmentManager = getSupportFragmentManager();
+ final var currentFragment = fragmentManager.findFragmentById(R.id.fragment_container);
+ if (currentFragment == null) {
+ fragmentManager
+ .beginTransaction()
+ .replace(R.id.fragment_container, preferenceFragment)
+ .commit();
+ }
+ binding.materialToolbar.setNavigationOnClickListener(
+ view -> {
+ if (fragmentManager.getBackStackEntryCount() == 0) {
+ finish();
+ } else {
+ fragmentManager.popBackStack();
+ }
+ });
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/activity/result/PickRingtone.java b/src/main/java/eu/siacs/conversations/ui/activity/result/PickRingtone.java
new file mode 100644
index 000000000..b58a7f398
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/activity/result/PickRingtone.java
@@ -0,0 +1,47 @@
+package eu.siacs.conversations.ui.activity.result;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import androidx.activity.result.contract.ActivityResultContract;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class PickRingtone extends ActivityResultContract {
+
+ private static final Uri NONE = Uri.parse("about:blank");
+
+ private final int ringToneType;
+
+ public PickRingtone(final int ringToneType) {
+ this.ringToneType = ringToneType;
+ }
+
+ @NonNull
+ @Override
+ public Intent createIntent(@NonNull final Context context, final Uri existing) {
+ final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, ringToneType);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
+ if (existing != null) {
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existing);
+ }
+ return intent;
+ }
+
+ @Override
+ public Uri parseResult(int resultCode, @Nullable Intent data) {
+ if (resultCode != Activity.RESULT_OK || data == null) {
+ return null;
+ }
+ final Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+ return pickedUri == null ? NONE : pickedUri;
+ }
+
+ public static Uri noneToNull(final Uri uri) {
+ return uri == null || NONE.equals(uri) ? null : uri;
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
index 2ecf230d9..a30d25c00 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
@@ -15,11 +15,11 @@ import androidx.databinding.DataBindingUtil;
import com.wefika.flowlayout.FlowLayout;
+import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ItemContactBinding;
import eu.siacs.conversations.entities.ListItem;
-import eu.siacs.conversations.ui.SettingsActivity;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
@@ -47,7 +47,7 @@ public class ListItemAdapter extends ArrayAdapter {
public void refreshSettings() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
- this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, false);
+ this.showDynamicTags = preferences.getBoolean(AppSettings.SHOW_DYNAMIC_TAGS, false);
}
@NonNull
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/AttachmentsSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/AttachmentsSettingsFragment.java
new file mode 100644
index 000000000..6b05c18c5
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/AttachmentsSettingsFragment.java
@@ -0,0 +1,22 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceFragmentCompat;
+
+import eu.siacs.conversations.R;
+
+public class AttachmentsSettingsFragment extends PreferenceFragmentCompat {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_attachments, rootKey);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.pref_attachments);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/ConnectionSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/ConnectionSettingsFragment.java
new file mode 100644
index 000000000..26bb27dc9
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/ConnectionSettingsFragment.java
@@ -0,0 +1,69 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.common.base.Strings;
+
+import eu.siacs.conversations.AppSettings;
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.services.QuickConversationsService;
+
+public class ConnectionSettingsFragment extends XmppPreferenceFragment {
+
+ private static final String GROUPS_AND_CONFERENCES = "groups_and_conferences";
+
+ public static boolean hideChannelDiscovery() {
+ return QuickConversationsService.isQuicksy()
+ || QuickConversationsService.isPlayStoreFlavor()
+ || Strings.isNullOrEmpty(Config.CHANNEL_DISCOVERY);
+ }
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_connection, rootKey);
+ final var channelDiscovery = findPreference(AppSettings.CHANNEL_DISCOVERY_METHOD);
+ final var groupsAndConferences = findPreference(GROUPS_AND_CONFERENCES);
+ if (channelDiscovery == null || groupsAndConferences == null) {
+ throw new IllegalStateException();
+ }
+ if (hideChannelDiscovery()) {
+ groupsAndConferences.setVisible(false);
+ channelDiscovery.setVisible(false);
+ }
+ }
+
+ @Override
+ protected void onSharedPreferenceChanged(@NonNull String key) {
+ super.onSharedPreferenceChanged(key);
+ switch (key) {
+ case AppSettings.USE_TOR -> {
+ final var appSettings = new AppSettings(requireContext());
+ if (appSettings.isUseTor()) {
+ runOnUiThread(
+ () ->
+ Toast.makeText(
+ requireActivity(),
+ R.string.audio_video_disabled_tor,
+ Toast.LENGTH_LONG)
+ .show());
+ }
+ reconnectAccounts();
+ requireService().reinitializeMuclumbusService();
+ }
+ case AppSettings.SHOW_CONNECTION_OPTIONS -> {
+ reconnectAccounts();
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.pref_connection_options);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/InterfaceSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/InterfaceSettingsFragment.java
new file mode 100644
index 000000000..59ca1484e
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/InterfaceSettingsFragment.java
@@ -0,0 +1,67 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.android.material.color.DynamicColors;
+
+import eu.siacs.conversations.AppSettings;
+import eu.siacs.conversations.Conversations;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.ui.activity.SettingsActivity;
+import eu.siacs.conversations.ui.util.SettingsUtils;
+
+public class InterfaceSettingsFragment extends XmppPreferenceFragment {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_interface, rootKey);
+ final var themePreference = findPreference("theme");
+ final var dynamicColors = findPreference("dynamic_colors");
+ if (themePreference == null || dynamicColors == null) {
+ throw new IllegalStateException(
+ "The preference resource file did not contain theme or color preferences");
+ }
+ themePreference.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof final String theme) {
+ final int desiredNightMode = Conversations.getDesiredNightMode(theme);
+ requireSettingsActivity().setDesiredNightMode(desiredNightMode);
+ }
+ return true;
+ });
+ dynamicColors.setVisible(DynamicColors.isDynamicColorAvailable());
+ dynamicColors.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ requireSettingsActivity().setDynamicColors(Boolean.TRUE.equals(newValue));
+ return true;
+ });
+ }
+
+ @Override
+ protected void onSharedPreferenceChanged(@NonNull String key) {
+ super.onSharedPreferenceChanged(key);
+ if (key.equals(AppSettings.ALLOW_SCREENSHOTS)) {
+ SettingsUtils.applyScreenshotSetting(requireActivity());
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.pref_title_interface);
+ }
+
+ public SettingsActivity requireSettingsActivity() {
+ final var activity = requireActivity();
+ if (activity instanceof SettingsActivity settingsActivity) {
+ return settingsActivity;
+ }
+ throw new IllegalStateException(
+ String.format(
+ "%s is not %s",
+ activity.getClass().getName(), SettingsActivity.class.getName()));
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/MainSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/MainSettingsFragment.java
new file mode 100644
index 000000000..045275f95
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/MainSettingsFragment.java
@@ -0,0 +1,36 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Build;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.google.common.base.Strings;
+
+import eu.siacs.conversations.BuildConfig;
+import eu.siacs.conversations.R;
+
+public class MainSettingsFragment extends PreferenceFragmentCompat {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_main, rootKey);
+ final var about = findPreference("about");
+ final var connection = findPreference("connection");
+ if (about == null || connection == null) {
+ throw new IllegalStateException("The preference resource file is missing some preferences");
+ }
+ about.setTitle(getString(R.string.title_activity_about_x, BuildConfig.APP_NAME));
+ about.setSummary(String.format("%s %s %s (%s)", BuildConfig.APP_NAME, BuildConfig.VERSION_NAME, im.conversations.webrtc.BuildConfig.WEBRTC_VERSION, Strings.nullToEmpty(Build.DEVICE)));
+ if (ConnectionSettingsFragment.hideChannelDiscovery()) {
+ connection.setSummary(R.string.pref_connection_summary);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.title_activity_settings);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/NotificationsSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/NotificationsSettingsFragment.java
new file mode 100644
index 000000000..81df3da18
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/NotificationsSettingsFragment.java
@@ -0,0 +1,102 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.content.SharedPreferences;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
+import eu.siacs.conversations.AppSettings;
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.ui.activity.result.PickRingtone;
+import eu.siacs.conversations.utils.Compatibility;
+
+public class NotificationsSettingsFragment extends XmppPreferenceFragment {
+
+ private final ActivityResultLauncher pickRingtoneLauncher =
+ registerForActivityResult(
+ new PickRingtone(RingtoneManager.TYPE_RINGTONE),
+ result -> {
+ if (result == null) {
+ // do nothing. user aborted
+ return;
+ }
+ final Uri uri = PickRingtone.noneToNull(result);
+ setRingtone(uri);
+ Log.i(Config.LOGTAG, "User set ringtone to " + uri);
+ });
+
+ @Override
+ public void onCreatePreferences(
+ @Nullable final Bundle savedInstanceState, final @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_notifications, rootKey);
+ final var messageNotificationSettings = findPreference("message_notification_settings");
+ final var notificationRingtone = findPreference(AppSettings.NOTIFICATION_RINGTONE);
+ final var notificationHeadsUp = findPreference(AppSettings.NOTIFICATION_HEADS_UP);
+ final var notificationVibrate = findPreference(AppSettings.NOTIFICATION_VIBRATE);
+ final var notificationLed = findPreference(AppSettings.NOTIFICATION_LED);
+ final var foregroundService = findPreference(AppSettings.KEEP_FOREGROUND_SERVICE);
+ if (messageNotificationSettings == null
+ || notificationRingtone == null
+ || notificationHeadsUp == null
+ || notificationVibrate == null
+ || notificationLed == null
+ || foregroundService == null) {
+ throw new IllegalStateException("The preference resource file is missing preferences");
+ }
+ if (Compatibility.runsTwentySix()) {
+ notificationRingtone.setVisible(false);
+ notificationHeadsUp.setVisible(false);
+ notificationVibrate.setVisible(false);
+ notificationLed.setVisible(false);
+ foregroundService.setVisible(false);
+ } else {
+ messageNotificationSettings.setVisible(false);
+ }
+ }
+
+ @Override
+ protected void onSharedPreferenceChanged(@NonNull String key) {
+ super.onSharedPreferenceChanged(key);
+ if (key.equals(AppSettings.KEEP_FOREGROUND_SERVICE)) {
+ requireService().toggleForegroundService();
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.notifications);
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(final Preference preference) {
+ if (AppSettings.RINGTONE.equals(preference.getKey())) {
+ pickRingtone();
+ return true;
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
+ private void pickRingtone() {
+ final Uri uri = appSettings().getRingtone();
+ Log.i(Config.LOGTAG, "current ringtone: " + uri);
+ this.pickRingtoneLauncher.launch(uri);
+ }
+
+ private void setRingtone(final Uri uri) {
+ appSettings().setRingtone(uri);
+ }
+
+ private AppSettings appSettings() {
+ return new AppSettings(requireContext());
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/PrivacySettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/PrivacySettingsFragment.java
new file mode 100644
index 000000000..6f0c4f56c
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/PrivacySettingsFragment.java
@@ -0,0 +1,41 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import eu.siacs.conversations.AppSettings;
+import eu.siacs.conversations.R;
+
+public class PrivacySettingsFragment extends XmppPreferenceFragment {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_privacy, rootKey);
+ }
+
+ @Override
+ protected void onSharedPreferenceChanged(@NonNull String key) {
+ super.onSharedPreferenceChanged(key);
+ switch (key) {
+ case AppSettings.AWAY_WHEN_SCREEN_IS_OFF, AppSettings.MANUALLY_CHANGE_PRESENCE -> {
+ requireService().toggleScreenEventReceiver();
+ requireService().refreshAllPresences();
+ }
+ case AppSettings.CONFIRM_MESSAGES,
+ AppSettings.BROADCAST_LAST_ACTIVITY,
+ AppSettings.ALLOW_MESSAGE_CORRECTION,
+ AppSettings.DND_ON_SILENT_MODE,
+ AppSettings.TREAT_VIBRATE_AS_SILENT -> {
+ requireService().refreshAllPresences();
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.pref_privacy);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/SecuritySettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/SecuritySettingsFragment.java
new file mode 100644
index 000000000..ba64c5fc3
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/SecuritySettingsFragment.java
@@ -0,0 +1,195 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.common.base.Strings;
+import com.google.common.primitives.Ints;
+
+import eu.siacs.conversations.AppSettings;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.crypto.OmemoSetting;
+import eu.siacs.conversations.services.MemorizingTrustManager;
+import eu.siacs.conversations.utils.TimeFrameUtils;
+
+import java.security.KeyStoreException;
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class SecuritySettingsFragment extends XmppPreferenceFragment {
+
+ private static final String REMOVE_TRUSTED_CERTIFICATES = "remove_trusted_certificates";
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_security, rootKey);
+ final ListPreference omemo = findPreference(AppSettings.OMEMO);
+ final ListPreference automaticMessageDeletion =
+ findPreference(AppSettings.AUTOMATIC_MESSAGE_DELETION);
+ if (omemo == null || automaticMessageDeletion == null) {
+ throw new IllegalStateException("The preference resource file is missing preferences");
+ }
+ omemo.setSummaryProvider(new OmemoSummaryProvider());
+ final int[] choices = getResources().getIntArray(R.array.automatic_message_deletion_values);
+ final CharSequence[] entries = new CharSequence[choices.length];
+ final CharSequence[] entryValues = new CharSequence[choices.length];
+ for (int i = 0; i < choices.length; ++i) {
+ entryValues[i] = String.valueOf(choices[i]);
+ entries[i] = messageDeletionValueToName(requireContext(), choices[i]);
+ }
+ automaticMessageDeletion.setEntries(entries);
+ automaticMessageDeletion.setEntryValues(entryValues);
+ automaticMessageDeletion.setSummaryProvider(new MessageDeletionSummaryProvider());
+ }
+
+ private static String messageDeletionValueToName(final Context context, final int value) {
+ if (value == 0) {
+ return context.getString(R.string.never);
+ } else {
+ return TimeFrameUtils.resolve(context, 1000L * value);
+ }
+ }
+
+ @Override
+ protected void onSharedPreferenceChanged(@NonNull String key) {
+ super.onSharedPreferenceChanged(key);
+ switch (key) {
+ case AppSettings.OMEMO -> {
+ OmemoSetting.load(requireContext());
+ }
+ case AppSettings.TRUST_SYSTEM_CA_STORE -> {
+ requireService().updateMemorizingTrustmanager();
+ reconnectAccounts();
+ }
+ case AppSettings.REQUIRE_CHANNEL_BINDING -> {}
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.pref_title_security);
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(final Preference preference) {
+ if (REMOVE_TRUSTED_CERTIFICATES.equals(preference.getKey())) {
+ showRemoveCertificatesDialog();
+ return true;
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
+ private void showRemoveCertificatesDialog() {
+ final MemorizingTrustManager mtm = requireService().getMemorizingTrustManager();
+ final ArrayList aliases = Collections.list(mtm.getCertificates());
+ if (aliases.isEmpty()) {
+ Toast.makeText(requireActivity(), R.string.toast_no_trusted_certs, Toast.LENGTH_LONG)
+ .show();
+ return;
+ }
+ final ArrayList selectedItems = new ArrayList<>();
+ final MaterialAlertDialogBuilder dialogBuilder =
+ new MaterialAlertDialogBuilder(requireActivity());
+ dialogBuilder.setTitle(getString(R.string.dialog_manage_certs_title));
+ dialogBuilder.setMultiChoiceItems(
+ aliases.toArray(new CharSequence[0]),
+ null,
+ (dialog, indexSelected, isChecked) -> {
+ if (isChecked) {
+ selectedItems.add(indexSelected);
+ } else if (selectedItems.contains(indexSelected)) {
+ selectedItems.remove(Integer.valueOf(indexSelected));
+ }
+ if (dialog instanceof AlertDialog alertDialog) {
+ alertDialog
+ .getButton(DialogInterface.BUTTON_POSITIVE)
+ .setEnabled(!selectedItems.isEmpty());
+ }
+ });
+
+ dialogBuilder.setPositiveButton(
+ getString(R.string.dialog_manage_certs_positivebutton),
+ (dialog, which) -> confirmCertificateDeletion(aliases, selectedItems));
+ dialogBuilder.setNegativeButton(R.string.cancel, null);
+ final AlertDialog removeCertsDialog = dialogBuilder.create();
+ removeCertsDialog.show();
+ removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
+ }
+
+ private void confirmCertificateDeletion(
+ final ArrayList aliases, final ArrayList selectedItems) {
+ final int count = selectedItems.size();
+ if (count == 0) {
+ return;
+ }
+ final MemorizingTrustManager mtm = requireService().getMemorizingTrustManager();
+ for (int i = 0; i < count; i++) {
+ try {
+ final int item = Integer.parseInt(selectedItems.get(i).toString());
+ final String alias = aliases.get(item);
+ mtm.deleteCertificate(alias);
+ } catch (final KeyStoreException e) {
+ Toast.makeText(
+ requireActivity(),
+ "Error: " + e.getLocalizedMessage(),
+ Toast.LENGTH_LONG)
+ .show();
+ }
+ }
+ reconnectAccounts();
+ Toast.makeText(
+ requireActivity(),
+ getResources()
+ .getQuantityString(
+ R.plurals.toast_delete_certificates, count, count),
+ Toast.LENGTH_LONG)
+ .show();
+ }
+
+ private static class MessageDeletionSummaryProvider
+ implements Preference.SummaryProvider {
+
+ @Nullable
+ @Override
+ public CharSequence provideSummary(@NonNull ListPreference preference) {
+ final Integer value = Ints.tryParse(Strings.nullToEmpty(preference.getValue()));
+ return messageDeletionValueToName(preference.getContext(), value == null ? 0 : value);
+ }
+ }
+
+ private static class OmemoSummaryProvider
+ implements Preference.SummaryProvider {
+
+ @Nullable
+ @Override
+ public CharSequence provideSummary(@NonNull ListPreference preference) {
+ final var context = preference.getContext();
+ final var sharedPreferences = preference.getSharedPreferences();
+ final String value;
+ if (sharedPreferences == null) {
+ value = null;
+ } else {
+ value =
+ sharedPreferences.getString(
+ preference.getKey(),
+ context.getString(R.string.omemo_setting_default));
+ }
+ return switch (Strings.nullToEmpty(value)) {
+ case "always" -> context.getString(R.string.pref_omemo_setting_summary_always);
+ case "default_off" -> context.getString(
+ R.string.pref_omemo_setting_summary_default_off);
+ default -> context.getString(R.string.pref_omemo_setting_summary_default_on);
+ };
+ }
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/UpSettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/UpSettingsFragment.java
new file mode 100644
index 000000000..3470e98c3
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/UpSettingsFragment.java
@@ -0,0 +1,99 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.EditTextPreference;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.services.UnifiedPushDistributor;
+import eu.siacs.conversations.xmpp.Jid;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.List;
+
+public class UpSettingsFragment extends XmppPreferenceFragment {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.preferences_up, rootKey);
+ }
+
+ @Override
+ public void onBackendConnected() {
+ final ListPreference upAccounts = findPreference(UnifiedPushDistributor.PREFERENCE_ACCOUNT);
+ final EditTextPreference pushServer = findPreference(UnifiedPushDistributor.PREFERENCE_PUSH_SERVER);
+ if (upAccounts == null || pushServer == null) {
+ throw new IllegalStateException();
+ }
+ pushServer.setOnPreferenceChangeListener((preference, newValue) -> {
+ if (newValue instanceof String string) {
+ if (Strings.isNullOrEmpty(string) || isJidInvalid(string) || isHttpUri(string)) {
+ Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
+ return false;
+ }
+ });
+ reconfigureUpAccountPreference(upAccounts);
+ }
+
+ private static boolean isJidInvalid(final String input) {
+ try {
+ final var jid = Jid.ofEscaped(input);
+ return !jid.isBareJid();
+ } catch (final IllegalArgumentException e) {
+ return true;
+ }
+ }
+
+ private static boolean isHttpUri(final String input) {
+ final URI uri;
+ try {
+ uri = new URI(input);
+ } catch (final URISyntaxException e) {
+ return false;
+ }
+ return Arrays.asList("http","https").contains(uri.getScheme());
+ }
+
+
+ private void reconfigureUpAccountPreference(final ListPreference listPreference) {
+ final List accounts =
+ ImmutableList.copyOf(
+ Lists.transform(
+ requireService().getAccounts(),
+ a -> a.getJid().asBareJid().toEscapedString()));
+ final ImmutableList.Builder entries = new ImmutableList.Builder<>();
+ final ImmutableList.Builder entryValues = new ImmutableList.Builder<>();
+ entries.add(getString(R.string.no_account_deactivated));
+ entryValues.add("none");
+ entries.addAll(accounts);
+ entryValues.addAll(accounts);
+ listPreference.setEntries(entries.build().toArray(new CharSequence[0]));
+ listPreference.setEntryValues(entryValues.build().toArray(new CharSequence[0]));
+ if (!accounts.contains(listPreference.getValue())) {
+ listPreference.setValue("none");
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ requireActivity().setTitle(R.string.unified_push_distributor);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/fragment/settings/XmppPreferenceFragment.java b/src/main/java/eu/siacs/conversations/ui/fragment/settings/XmppPreferenceFragment.java
new file mode 100644
index 000000000..631ecb6c4
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/fragment/settings/XmppPreferenceFragment.java
@@ -0,0 +1,80 @@
+package eu.siacs.conversations.ui.fragment.settings;
+
+import android.content.SharedPreferences;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceFragmentCompat;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.ui.XmppActivity;
+
+public abstract class XmppPreferenceFragment extends PreferenceFragmentCompat {
+
+ private final SharedPreferences.OnSharedPreferenceChangeListener
+ sharedPreferenceChangeListener =
+ (sharedPreferences, key) -> {
+ if (key == null) {
+ return;
+ }
+ onSharedPreferenceChanged(key);
+ };
+
+ protected void onSharedPreferenceChanged(@NonNull String key) {}
+
+ public void onBackendConnected() {}
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ final var sharedPreferences = getPreferenceManager().getSharedPreferences();
+ if (sharedPreferences != null) {
+ sharedPreferences.registerOnSharedPreferenceChangeListener(
+ this.sharedPreferenceChangeListener);
+ }
+ final var xmppActivity = requireXmppActivity();
+ if (xmppActivity.xmppConnectionService != null) {
+ this.onBackendConnected();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ final var sharedPreferences = getPreferenceManager().getSharedPreferences();
+ if (sharedPreferences != null) {
+ sharedPreferences.registerOnSharedPreferenceChangeListener(
+ this.sharedPreferenceChangeListener);
+ }
+ }
+
+ protected void reconnectAccounts() {
+ final var service = requireService();
+ for (final Account account : service.getAccounts()) {
+ if (account.isEnabled()) {
+ service.reconnectAccountInBackground(account);
+ }
+ }
+ }
+
+ protected XmppActivity requireXmppActivity() {
+ final var activity = requireActivity();
+ if (activity instanceof XmppActivity xmppActivity) {
+ return xmppActivity;
+ }
+ throw new IllegalStateException();
+ }
+
+ protected XmppConnectionService requireService() {
+ final var xmppActivity = requireXmppActivity();
+ final var service = xmppActivity.xmppConnectionService;
+ if (service != null) {
+ return service;
+ }
+ throw new IllegalStateException();
+ }
+
+ protected void runOnUiThread(final Runnable runnable) {
+ requireActivity().runOnUiThread(runnable);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java b/src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java
index ae99e0943..7d194ba95 100644
--- a/src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java
+++ b/src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java
@@ -1,20 +1,19 @@
package eu.siacs.conversations.ui.util;
import android.app.Activity;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
import android.view.Window;
import android.view.WindowManager;
+import eu.siacs.conversations.AppSettings;
+
public class SettingsUtils {
- public static void applyScreenshotPreventionSetting(Activity activity){
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
- boolean preventScreenshots = preferences.getBoolean("prevent_screenshots", false);
- Window activityWindow = activity.getWindow();
- if(preventScreenshots){
- activityWindow.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
- } else {
+ public static void applyScreenshotSetting(final Activity activity) {
+ final var appSettings = new AppSettings(activity);
+ final Window activityWindow = activity.getWindow();
+ if (appSettings.isAllowScreenshots()) {
activityWindow.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ } else {
+ activityWindow.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
}
diff --git a/src/main/java/eu/siacs/conversations/utils/Compatibility.java b/src/main/java/eu/siacs/conversations/utils/Compatibility.java
index 6d3ba6224..a6e91593e 100644
--- a/src/main/java/eu/siacs/conversations/utils/Compatibility.java
+++ b/src/main/java/eu/siacs/conversations/utils/Compatibility.java
@@ -22,10 +22,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
+import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
-import eu.siacs.conversations.ui.SettingsActivity;
-import eu.siacs.conversations.ui.SettingsFragment;
import java.util.Arrays;
import java.util.Collections;
@@ -33,15 +32,6 @@ import java.util.List;
public class Compatibility {
- private static final List UNUSED_SETTINGS_POST_TWENTYSIX =
- Arrays.asList(
- "led",
- "notification_ringtone",
- "notification_headsup",
- "vibrate_on_notification");
- private static final List UNUSED_SETTINGS_PRE_TWENTYSIX =
- Collections.singletonList("message_notification_settings");
-
public static boolean hasStoragePermission(final Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU || ContextCompat.checkSelfPermission(
context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
@@ -76,7 +66,7 @@ public class Compatibility {
final PackageManager packageManager = context.getPackageManager();
final ApplicationInfo applicationInfo =
packageManager.getApplicationInfo(context.getPackageName(), 0);
- return applicationInfo == null || applicationInfo.targetSdkVersion >= 26;
+ return applicationInfo.targetSdkVersion >= 26;
} catch (PackageManager.NameNotFoundException | RuntimeException e) {
return true; // when in doubt…
}
@@ -87,7 +77,7 @@ public class Compatibility {
final PackageManager packageManager = context.getPackageManager();
final ApplicationInfo applicationInfo =
packageManager.getApplicationInfo(context.getPackageName(), 0);
- return applicationInfo == null || applicationInfo.targetSdkVersion >= 24;
+ return applicationInfo.targetSdkVersion >= 24;
} catch (PackageManager.NameNotFoundException | RuntimeException e) {
return true; // when in doubt…
}
@@ -105,43 +95,10 @@ public class Compatibility {
return runsAndTargetsTwentySix(context)
|| getBooleanPreference(
context,
- SettingsActivity.KEEP_FOREGROUND_SERVICE,
+ AppSettings.KEEP_FOREGROUND_SERVICE,
R.bool.enable_foreground_service);
}
- public static void removeUnusedPreferences(SettingsFragment settingsFragment) {
- List categories =
- Arrays.asList(
- (PreferenceCategory)
- settingsFragment.findPreference("notification_category"),
- (PreferenceCategory) settingsFragment.findPreference("advanced"));
- for (String key :
- (runsTwentySix()
- ? UNUSED_SETTINGS_POST_TWENTYSIX
- : UNUSED_SETTINGS_PRE_TWENTYSIX)) {
- Preference preference = settingsFragment.findPreference(key);
- if (preference != null) {
- for (PreferenceCategory category : categories) {
- if (category != null) {
- category.removePreference(preference);
- }
- }
- }
- }
- if (Compatibility.runsTwentySix()) {
- if (targetsTwentySix(settingsFragment.getContext())) {
- Preference preference =
- settingsFragment.findPreference(SettingsActivity.KEEP_FOREGROUND_SERVICE);
- if (preference != null) {
- for (PreferenceCategory category : categories) {
- if (category != null) {
- category.removePreference(preference);
- }
- }
- }
- }
- }
- }
public static void startService(Context context, Intent intent) {
try {
diff --git a/src/main/res/drawable/ic_arrow_back_24dp.xml b/src/main/res/drawable/ic_arrow_back_24dp.xml
new file mode 100644
index 000000000..8ed427d74
--- /dev/null
+++ b/src/main/res/drawable/ic_arrow_back_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_assured_workload_24dp.xml b/src/main/res/drawable/ic_assured_workload_24dp.xml
new file mode 100644
index 000000000..c508dbe35
--- /dev/null
+++ b/src/main/res/drawable/ic_assured_workload_24dp.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_attachment_24dp.xml b/src/main/res/drawable/ic_attachment_24dp.xml
new file mode 100644
index 000000000..25fed9d25
--- /dev/null
+++ b/src/main/res/drawable/ic_attachment_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_auto_delete_24dp.xml b/src/main/res/drawable/ic_auto_delete_24dp.xml
new file mode 100644
index 000000000..2c7ffc3ac
--- /dev/null
+++ b/src/main/res/drawable/ic_auto_delete_24dp.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_cloud_sync_24dp.xml b/src/main/res/drawable/ic_cloud_sync_24dp.xml
new file mode 100644
index 000000000..c87b654c9
--- /dev/null
+++ b/src/main/res/drawable/ic_cloud_sync_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_dark_mode_24dp.xml b/src/main/res/drawable/ic_dark_mode_24dp.xml
new file mode 100644
index 000000000..9e3255316
--- /dev/null
+++ b/src/main/res/drawable/ic_dark_mode_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_do_not_disturb_on_24dp.xml b/src/main/res/drawable/ic_do_not_disturb_on_24dp.xml
new file mode 100644
index 000000000..50a7239ac
--- /dev/null
+++ b/src/main/res/drawable/ic_do_not_disturb_on_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_domino_mask_24dp.xml b/src/main/res/drawable/ic_domino_mask_24dp.xml
new file mode 100644
index 000000000..849d7b1c2
--- /dev/null
+++ b/src/main/res/drawable/ic_domino_mask_24dp.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/src/main/res/drawable/ic_done_all_24dp.xml b/src/main/res/drawable/ic_done_all_24dp.xml
new file mode 100644
index 000000000..63a35fe64
--- /dev/null
+++ b/src/main/res/drawable/ic_done_all_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_download_24dp.xml b/src/main/res/drawable/ic_download_24dp.xml
index 0a16f1635..ae2803609 100644
--- a/src/main/res/drawable/ic_download_24dp.xml
+++ b/src/main/res/drawable/ic_download_24dp.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/src/main/res/drawable/ic_keyboard_24dp.xml b/src/main/res/drawable/ic_keyboard_24dp.xml
new file mode 100644
index 000000000..2406aac48
--- /dev/null
+++ b/src/main/res/drawable/ic_keyboard_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_keyboard_return_24dp.xml b/src/main/res/drawable/ic_keyboard_return_24dp.xml
new file mode 100644
index 000000000..c543e3f64
--- /dev/null
+++ b/src/main/res/drawable/ic_keyboard_return_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_label_24dp.xml b/src/main/res/drawable/ic_label_24dp.xml
new file mode 100644
index 000000000..51e84c112
--- /dev/null
+++ b/src/main/res/drawable/ic_label_24dp.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_mediation_24dp.xml b/src/main/res/drawable/ic_mediation_24dp.xml
new file mode 100644
index 000000000..3ce75f00f
--- /dev/null
+++ b/src/main/res/drawable/ic_mediation_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_movie_24dp.xml b/src/main/res/drawable/ic_movie_24dp.xml
new file mode 100644
index 000000000..915537e46
--- /dev/null
+++ b/src/main/res/drawable/ic_movie_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_network_node_24dp.xml b/src/main/res/drawable/ic_network_node_24dp.xml
new file mode 100644
index 000000000..267173b5e
--- /dev/null
+++ b/src/main/res/drawable/ic_network_node_24dp.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/src/main/res/drawable/ic_palette_24dp.xml b/src/main/res/drawable/ic_palette_24dp.xml
new file mode 100644
index 000000000..db78749e5
--- /dev/null
+++ b/src/main/res/drawable/ic_palette_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_person_24dp.xml b/src/main/res/drawable/ic_person_24dp.xml
index ddc83227b..098f18274 100644
--- a/src/main/res/drawable/ic_person_24dp.xml
+++ b/src/main/res/drawable/ic_person_24dp.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/src/main/res/drawable/ic_phone_24dp.xml b/src/main/res/drawable/ic_phone_24dp.xml
new file mode 100644
index 000000000..326fb50b8
--- /dev/null
+++ b/src/main/res/drawable/ic_phone_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_photo_24dp.xml b/src/main/res/drawable/ic_photo_24dp.xml
new file mode 100644
index 000000000..4f9fd480e
--- /dev/null
+++ b/src/main/res/drawable/ic_photo_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_privacy_tip_24dp.xml b/src/main/res/drawable/ic_privacy_tip_24dp.xml
new file mode 100644
index 000000000..c13176ba2
--- /dev/null
+++ b/src/main/res/drawable/ic_privacy_tip_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_private_connectivity_24dp.xml b/src/main/res/drawable/ic_private_connectivity_24dp.xml
new file mode 100644
index 000000000..00d17f2cc
--- /dev/null
+++ b/src/main/res/drawable/ic_private_connectivity_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_report_24dp.xml b/src/main/res/drawable/ic_report_24dp.xml
new file mode 100644
index 000000000..72c154915
--- /dev/null
+++ b/src/main/res/drawable/ic_report_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml b/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml
new file mode 100644
index 000000000..f7f199198
--- /dev/null
+++ b/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_screenshot_24dp.xml b/src/main/res/drawable/ic_screenshot_24dp.xml
new file mode 100644
index 000000000..be4bb2924
--- /dev/null
+++ b/src/main/res/drawable/ic_screenshot_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_security_24dp.xml b/src/main/res/drawable/ic_security_24dp.xml
new file mode 100644
index 000000000..f434507bf
--- /dev/null
+++ b/src/main/res/drawable/ic_security_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_send_time_extension_24dp.xml b/src/main/res/drawable/ic_send_time_extension_24dp.xml
new file mode 100644
index 000000000..e9449cf1b
--- /dev/null
+++ b/src/main/res/drawable/ic_send_time_extension_24dp.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_settings_ethernet_24dp.xml b/src/main/res/drawable/ic_settings_ethernet_24dp.xml
new file mode 100644
index 000000000..fad20c2fe
--- /dev/null
+++ b/src/main/res/drawable/ic_settings_ethernet_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_touch_app_24dp.xml b/src/main/res/drawable/ic_touch_app_24dp.xml
new file mode 100644
index 000000000..45d230a83
--- /dev/null
+++ b/src/main/res/drawable/ic_touch_app_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_travel_explore_24dp.xml b/src/main/res/drawable/ic_travel_explore_24dp.xml
index 0e7c701d4..7b697eb44 100644
--- a/src/main/res/drawable/ic_travel_explore_24dp.xml
+++ b/src/main/res/drawable/ic_travel_explore_24dp.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/src/main/res/drawable/ic_vertical_align_bottom_24dp.xml b/src/main/res/drawable/ic_vertical_align_bottom_24dp.xml
new file mode 100644
index 000000000..1535646f2
--- /dev/null
+++ b/src/main/res/drawable/ic_vertical_align_bottom_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_vibration_24dp.xml b/src/main/res/drawable/ic_vibration_24dp.xml
new file mode 100644
index 000000000..bdde86c2b
--- /dev/null
+++ b/src/main/res/drawable/ic_vibration_24dp.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/main/res/drawable/ic_visibility.xml b/src/main/res/drawable/ic_visibility_24dp.xml
similarity index 61%
rename from src/main/res/drawable/ic_visibility.xml
rename to src/main/res/drawable/ic_visibility_24dp.xml
index e02f1d191..ddcefe053 100644
--- a/src/main/res/drawable/ic_visibility.xml
+++ b/src/main/res/drawable/ic_visibility_24dp.xml
@@ -1,9 +1,12 @@
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?colorControlNormal"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ android:fillColor="@android:color/white"
+ android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" />
+
diff --git a/src/main/res/layout/activity_settings.xml b/src/main/res/layout/activity_settings.xml
index a5865f2fa..53d84da4f 100644
--- a/src/main/res/layout/activity_settings.xml
+++ b/src/main/res/layout/activity_settings.xml
@@ -1,26 +1,29 @@
-
+
-
+ android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ app:liftOnScroll="false">
-
+ android:layout_height="?attr/actionBarSize"
+ app:navigationIcon="@drawable/ic_arrow_back_24dp" />
-
-
+ android:layout_height="match_parent"
+ android:fillViewport="true"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
\ No newline at end of file
diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml
index 87ddfcbcf..eda500ac6 100644
--- a/src/main/res/values-ar/strings.xml
+++ b/src/main/res/values-ar/strings.xml
@@ -344,7 +344,6 @@
إحذف الشهادات التي تقبلتها يدويا
إحذف الشهادات
قم بحذف المختارة
- الغاء
حركة سريعة
لا شيء
التي تم استعمالها كثيرا مؤخرا
diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml
index 95b3b85e4..6b831f788 100644
--- a/src/main/res/values-bg/strings.xml
+++ b/src/main/res/values-bg/strings.xml
@@ -430,7 +430,6 @@
Няма сертификати, одобрени на ръка
Премахване на сертификатите
Изтриване на избраните
- Отказ
- %d сертификат е изтрит
- %d сертификата са изтрити
diff --git a/src/main/res/values-bn-rIN/strings.xml b/src/main/res/values-bn-rIN/strings.xml
index 3944bd33d..cffaa14ae 100644
--- a/src/main/res/values-bn-rIN/strings.xml
+++ b/src/main/res/values-bn-rIN/strings.xml
@@ -99,7 +99,6 @@
এই ব্যক্তিকে ব্লক্ করা যাক
ব্লকটা সরিয়ে ফেলা যাক
পরিচিত ব্যক্তি
- না, থাক।
পরিচিত ব্যক্তিদের মধ্যে খোঁজা যাক
বার্তাগুলির মধ্যে খোঁজা যাক
সরাসরিভাবেই খোঁজা যাক
diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml
index ade65234e..3ec310f85 100644
--- a/src/main/res/values-ca/strings.xml
+++ b/src/main/res/values-ca/strings.xml
@@ -429,7 +429,6 @@
No hi ha certificats aprovats manualment
Esborrar certificats
Esborrar selecció
- Cancel·lar
- %d certificat esborrat
- %d certificats esborrats
diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml
index d1e7487bb..090ea644e 100644
--- a/src/main/res/values-cs/strings.xml
+++ b/src/main/res/values-cs/strings.xml
@@ -432,7 +432,6 @@
Žádné ručně povolené certifikáty
Odstranit certifikáty
Smazat výběr
- Zrušit
- %d certifikát smazán
- %d certifikáty smazány
diff --git a/src/main/res/values-da-rDK/strings.xml b/src/main/res/values-da-rDK/strings.xml
index 02b250f1f..f23495dad 100644
--- a/src/main/res/values-da-rDK/strings.xml
+++ b/src/main/res/values-da-rDK/strings.xml
@@ -438,7 +438,6 @@
Ingen manuelt godkendt certifikater
Fjern certifikater
Slet valgt
- Annuller
- %d certifikat slettet
- %d certifikater slettet
@@ -990,5 +989,4 @@
Udgående opkald (%s) · %s
Indkommende opkald (%s) · %s
Fjern konto fra server
- En brugervalgt push-server til at videresende push-meddelelser via XMPP til din enhed.
\ No newline at end of file
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index aa1811da0..a97cd7176 100644
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -440,7 +440,6 @@
Keine manuell bestätigten Zertifikate
Zertifikate löschen
Auswahl löschen
- Abbrechen
- %d Zertifikat gelöscht
- %d Zertifikate gelöscht
@@ -982,7 +981,6 @@
Umschalten auf Video ablehnen
XMPP-Konto
Push-Server
- Ein selbst gewählter Push-Server, der Push-Nachrichten über XMPP an dein Gerät weiterleitet.
Kein (deaktiviert)
UnifiedPush Verteiler
Das Konto, über das Push-Nachrichten empfangen werden sollen.
@@ -1018,7 +1016,6 @@
Möchtest du das Lesezeichen für %s entfernen und die Unterhaltung schließen?
Löschen & Schließen
Willst du das Lesezeichen für %s entfernen?
- Die Channelsuche verwendet einen Drittanbieterservice namens <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Wenn du diese Funktion verwendest, werden deine IP-Adresse und deine Suchbegriffe an diesen Dienst übertragen. Weitere Informationen findest du in der <a href=https://search.jabber.network/privacy>Datenschutzerklärung</a>.
Teilen mit…
Farbige Chatblasen helfen, gesendete und empfangene Nachrichten zu unterscheiden
Farbige Chatblasen
diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml
index b7701fa26..f6aeb830d 100644
--- a/src/main/res/values-el/strings.xml
+++ b/src/main/res/values-el/strings.xml
@@ -431,7 +431,6 @@
Δεν υπάρχουν χειροκίνητα επιβεβαιωμένα πιστοποιητικα
Αφαίρεση πιστοποιητικών
Διαγραφή επιλογής
- Ακύρωση
- %d πιστοποιητικό διαγράφηκε
- %d πιστοποιητικά διαγράφηκαν
diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml
index 8dfe057e8..807416223 100644
--- a/src/main/res/values-es/strings.xml
+++ b/src/main/res/values-es/strings.xml
@@ -441,7 +441,6 @@
No aceptar certificados manualmente
Eliminar certificados
Eliminar seleccionados
- Cancelar
- %d certificado eliminado
- %d certificados eliminados
@@ -998,7 +997,6 @@
Cuenta XMPP
La cuenta a través de la cual se recibirán los mensajes push.
Servidor push
- Un servidor push elegido por el usuario para transmitir mensajes push a través de XMPP a su dispositivo.
Ninguno (desactivado)
Llamada entrante (%s) · %s
Llamada saliente (%s) · %s
diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml
index e2d7eb852..5cf081f34 100644
--- a/src/main/res/values-eu/strings.xml
+++ b/src/main/res/values-eu/strings.xml
@@ -362,7 +362,6 @@
Ez dago eskuz onartutako ziurtagiririk
Ziurtagiriak kendu
Aukeratutakoak ezabatu
- Utzi
- Ziurtagiri %d ezabatua
- %d ziurtagiri ezabatuak
diff --git a/src/main/res/values-fa-rIR/strings.xml b/src/main/res/values-fa-rIR/strings.xml
index f8a682dd9..dc163cc9e 100644
--- a/src/main/res/values-fa-rIR/strings.xml
+++ b/src/main/res/values-fa-rIR/strings.xml
@@ -139,7 +139,6 @@
آفلاین
مخاطب
نمایش موقعیت مکانی
- لغو
آنلاین
متوسط
تأییدیهٔ امنیتی ناشناخته پذیرفته شود؟
@@ -157,7 +156,6 @@
دیدن گفتگو
اثر انگشت OMEMO کپی شد
نمایش مسدودسازیها
- سرور push دلخواه کاربر برای رساندن اعلانهای push از راه XMPP به دستگاه شما.
وصل شدن
ورود
شما وصل نیستید. بعداً دوباره تلاش کنید
diff --git a/src/main/res/values-fi/strings.xml b/src/main/res/values-fi/strings.xml
index fbf1efce1..c614a8ffe 100644
--- a/src/main/res/values-fi/strings.xml
+++ b/src/main/res/values-fi/strings.xml
@@ -423,7 +423,6 @@
Poista käsin hyväksytyt varmenteet
Ei käsin hyväksyttyjä varmenteita
Poista varmenteet
- Peruuta
- %d varmenne poistettiin
- %d varmennetta poistettiin
diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml
index ba31ba5ef..dfd6ee54f 100644
--- a/src/main/res/values-fr/strings.xml
+++ b/src/main/res/values-fr/strings.xml
@@ -437,7 +437,6 @@
Aucun certificat approuvé manuellement
Retirer les certificats
Supprimer la sélection
- Annuler
- %d certificat supprimé
- %d certificats supprimés
@@ -990,7 +989,6 @@
Compte XMPP
Le compte par lequel les messages push seront reçus.
Serveur Push
- Un serveur push choisi par l\'utilisateur pour relayer les messages push via XMPP vers votre appareil.
Aucun (désactivé)
- %1$d appels manqués de %2$d contact
diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml
index 4eb5eabe7..76d9332a4 100644
--- a/src/main/res/values-gl/strings.xml
+++ b/src/main/res/values-gl/strings.xml
@@ -440,7 +440,6 @@
Sen certificados aprobados manualmente
Eliminar certificados
Borrar seleción
- Cancelar
- %d certificado eliminado
- %d certificados eleminados
@@ -984,7 +983,6 @@
Conta XMPP
A conta a través da cal se recibirán as mensaxes push.
Servidor Push
- O servidor elexido pola usuaria para obter as mensaxes push a través de XMPP.
Ningún (desactivado)
Rexeitar
Chamada entrante (%s) · %s
diff --git a/src/main/res/values-hu/strings.xml b/src/main/res/values-hu/strings.xml
index 2850a67ff..9ba1876ee 100644
--- a/src/main/res/values-hu/strings.xml
+++ b/src/main/res/values-hu/strings.xml
@@ -422,7 +422,6 @@
Nincsenek kézzel jóváhagyott tanúsítványok
Tanúsítványok eltávolítása
Kijelölés törlése
- Mégse
- %d tanúsítvány törölve
- %d tanúsítvány törölve
diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml
index 06c08abda..e0a2c0a54 100644
--- a/src/main/res/values-id/strings.xml
+++ b/src/main/res/values-id/strings.xml
@@ -357,7 +357,6 @@
Tidak ada sertifikat yang disahkan secara manual
Hapus sertifikat
Hapus seleksi
- Batal
- %d sertifikat dihapus
diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml
index 8f03a6f56..8b3489761 100644
--- a/src/main/res/values-it/strings.xml
+++ b/src/main/res/values-it/strings.xml
@@ -441,7 +441,6 @@
Non sono presenti certificati accettati manualmente
Elimina i certificati
Cancella la selezione
- Annulla
- Cancellato il %d certificato
- Cancellati %d certificati
@@ -999,7 +998,6 @@
Profilo XMPP
Il profilo attraverso cui verranno ricevuti i messaggi push.
Server push
- Un server scelto dall\'utente per inoltrare i messaggi push via XMPP al tuo dispositivo.
Nessuno (disattivato)
Rifiuta
Chiamata in arrivo (%s) · %s
diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml
index 15aa6fb83..5d1ed7b0c 100644
--- a/src/main/res/values-iw/strings.xml
+++ b/src/main/res/values-iw/strings.xml
@@ -240,7 +240,6 @@
אין חתימות דיגטליות שאושרו ידנית
מחק חתימות דיגטליות
מחק פריטים שנבחרו
- ביטול
- %d חתימה נמחקה
- %d חתימות נמחקו
diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml
index 4ac5f8221..0299f1fdb 100644
--- a/src/main/res/values-ja/strings.xml
+++ b/src/main/res/values-ja/strings.xml
@@ -436,7 +436,6 @@
手動で承認した証明書がありません
証明書を削除
選択したものを削除
- 中止
- %d個の証明書を削除しました
@@ -973,7 +972,6 @@
発信通話 · %s
オーディオブック
自分で保存したバックアップしか復元しないでください!
- XMPP経由でPushメッセージを端末に転送するユーザー指定のPushサーバー。
ログイン
通知を表示しない
アカウントをサーバーから削除
diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml
index b051797cb..b7d4e483e 100644
--- a/src/main/res/values-ko/strings.xml
+++ b/src/main/res/values-ko/strings.xml
@@ -279,7 +279,6 @@
수동으로 승인된 인증서 없음
인증서 삭제
선택 삭제
- 취소
- %d 인증서 삭제됨
diff --git a/src/main/res/values-ml/strings.xml b/src/main/res/values-ml/strings.xml
index b966f88ca..cb93885b5 100644
--- a/src/main/res/values-ml/strings.xml
+++ b/src/main/res/values-ml/strings.xml
@@ -225,7 +225,6 @@
ലൊക്കേഷൻ അയയ്ക്കുക
ലൊക്കേഷൻ കാണിക്കൂ
ലൊക്കേഷൻ
- റദ്ദാക്കൂ
സമീപകാലത്ത് ഉപയോഗിച്ചത്
കോൺടാക്റ്റുകൾ തിരയുക
സ്വകാര്യ സന്ദേശം അയയ്ക്കൂ
diff --git a/src/main/res/values-nb-rNO/strings.xml b/src/main/res/values-nb-rNO/strings.xml
index 7427815e7..055e98fe1 100644
--- a/src/main/res/values-nb-rNO/strings.xml
+++ b/src/main/res/values-nb-rNO/strings.xml
@@ -306,7 +306,6 @@
Ingen manuelt godkjente sertifikater
Fjern sertifikater
Slett innhold i merket område
- Avbryt
- %d sertifikat slettet
- %d sertifikater slettet
diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml
index bad9c7fab..ddbd66fd7 100644
--- a/src/main/res/values-nl/strings.xml
+++ b/src/main/res/values-nl/strings.xml
@@ -399,7 +399,6 @@
Geen handmatig goedgekeurde certificaten
Certificaten verwijderen
Selectie verwijderen
- Annuleren
- %d certificaat verwijderd
- %d certificaten verwijderd
diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml
index dbe3faebe..1a7c2fc8c 100644
--- a/src/main/res/values-pl/strings.xml
+++ b/src/main/res/values-pl/strings.xml
@@ -444,7 +444,6 @@
Brak ręcznie zaufanych certyfikatów
Usuń certyfikaty
Usuń zaznaczone
- Anuluj
- Usunięto %d certyfikat
- Usunięto %d certyfikaty
@@ -1016,7 +1015,6 @@
Konto XMPP
Konto, poprzez które będą odbierane powiadomienia push.
Serwer push
- Dowolnie wybrany serwer push do przekazywania wiadomości push przez XMPP na Twoje urządzenie.
Brak (nieaktywne)
Odrzuć
Połączenie przychodzące (%s) · %s
diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml
index aede07bfc..9240999bb 100644
--- a/src/main/res/values-pt-rBR/strings.xml
+++ b/src/main/res/values-pt-rBR/strings.xml
@@ -437,7 +437,6 @@
Nenhum certificado aprovado manualmente
Remover certificados
Excluir a seleção
- Cancelar
- %d certificado cancelado
- %d certificados cancelados
diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml
index 4f76633e1..e6fa1eb14 100644
--- a/src/main/res/values-pt/strings.xml
+++ b/src/main/res/values-pt/strings.xml
@@ -299,7 +299,6 @@
Não existem certificados aprovados manualmente
Remover certificados
Apagar seleção
- Cancelar
- %d certificado apagado
- %d certificados apagados
diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml
index 6f5a78be3..0c86d9651 100644
--- a/src/main/res/values-ro-rRO/strings.xml
+++ b/src/main/res/values-ro-rRO/strings.xml
@@ -443,7 +443,6 @@
Nici un certificat aprobat manual
Înlătură certificatele
Șterge selecția
- Anuleaza
- %d certificat sters
- %d certificate sterse
@@ -1001,7 +1000,6 @@
Respinge solicitarea de comutare la video
Cont XMPP
Server Push
- Un server ales de utilizator pentru a intermedia mesajele push către dispozitivul vostru prin XMPP.
Nici unul (dezactivat)
Distribuitor UnifiedPush
Contul prin care vor fi primite notificările push.
diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml
index 9dee49654..ae8d7851f 100644
--- a/src/main/res/values-ru/strings.xml
+++ b/src/main/res/values-ru/strings.xml
@@ -435,7 +435,6 @@
Не найдено сертификатов, подтверждённых вручную
Удалить сертификаты
Удалить отмеченные
- Отмена
- Удалён %d сертификат
- Удалено %d сертификата
@@ -1009,7 +1008,6 @@
Регистрации учётных записей не поддерживаются
Звонки выключены, пока используется Tor
Учётная запись для получения пуш-уведомлений.
- Выбираемый пользователем сервер для перенаправления уведомлений на Ваше устройство.
Нет (неактивно)
Вы собираетесь проверить ключи OMEMO своей учетной записи. Это безопасно только в том случае, если вы перешли по этой ссылке из надежного источника, где только вы могли опубликовать эту ссылку.
Не пытайтесь восстановить резервные копии, которые не были созданы вами!
diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml
index d9e13fe18..13bba3c14 100644
--- a/src/main/res/values-sk/strings.xml
+++ b/src/main/res/values-sk/strings.xml
@@ -387,7 +387,6 @@
Žiadne ručne schválené certifikáty
Odstrániť certifikáty
Vymazať výber
- Zrušiť
- %d certifikátu vymazaných
- %d certifikátu vymazaných
diff --git a/src/main/res/values-sq-rAL/strings.xml b/src/main/res/values-sq-rAL/strings.xml
index 6adc1a99e..54d172a32 100644
--- a/src/main/res/values-sq-rAL/strings.xml
+++ b/src/main/res/values-sq-rAL/strings.xml
@@ -354,7 +354,6 @@
S’u dhanë dëshmi dorazi
Hiqi dëshmitë
Fshije përzgjedhjen
- Anuloje
Veprim i Shpejtë
Asnjë
Më të përdorur së fundi
@@ -968,7 +967,6 @@
Thirrjet janë të çaktivizuara, kur përdoret Tor-i
Llogaria përmes së cilës do të merren mesazhet push.
Shërbyes Push
- Një shërbyes push i zgjedhur nga përdoruesi, përmes të cilit të kalohen te pajisja juaj mesazhet push përmes XMPP-je.
Ka të hartuar një udhërrëfyes mbi krijim llogarish te conversations.im.
\nKu zgjidhet conversations.im si shërbim, do të jeni në gjendje të komunikoni me përdorues prej shërbimesh të tjera duke u dhënë atyre adresën tuaj të plotë XMPP.
@@ -1027,7 +1025,6 @@
Doni të hiqet faqerojtësi për %s dhe të mbyllet biseda?
Fshije & Mbylle
Doni të hiqet faqerojtësi për %s?
- Pikasja e kanaleve përdor një shërbim palë të tretë të quajtur <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Përdorimi i kësaj veçorie do t’i transmetojë atij shërbimi adresën tuaj IP dhe terma kërkimesh. Për më tepër hollësi, shihni <a href=https://search.jabber.network/privacy>Rregullat e tyre mbi Privatësinë</a>.
Flluska të ngjyrosura fjalosjeje ndihmojnë të dalloni mesazhe të dërguar dhe të marrë
Ngjyra dinamike
Ngjyra Sistemi (Material You)
diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml
index 0399e3ef3..fc36b94db 100644
--- a/src/main/res/values-sr/strings.xml
+++ b/src/main/res/values-sr/strings.xml
@@ -424,7 +424,6 @@
Нема ручно одобрених сертификата
Уклањање сертификата
Обриши изабрано
- Одустани
- %d сертификат обрисан
- %d сертификата обрисана
diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml
index 04f0ee817..c72acebe4 100644
--- a/src/main/res/values-sv/strings.xml
+++ b/src/main/res/values-sv/strings.xml
@@ -447,7 +447,6 @@
Inga manuellt godkända certifikat
Ta bort certifikaten
Ta bort val
- Avbryt
- %d certifikat borttaget
- %d certifikat borttagna
@@ -974,7 +973,6 @@
XMPP-konto
Kontot genom vilket push-meddelanden tas emot.
Push-server
- En användarvald push-server för att vidarebefordra push-meddelanden via XMPP till din enhet.
Ingen (inaktiverad)
Det här telefonnumret är för närvarande inloggat med en annan enhet.
Var god ange ditt namn för att låta personer som inte har dig i sina adressböcker, veta vem du är.
diff --git a/src/main/res/values-szl/strings.xml b/src/main/res/values-szl/strings.xml
index 4a99e5a4a..64e9558c1 100644
--- a/src/main/res/values-szl/strings.xml
+++ b/src/main/res/values-szl/strings.xml
@@ -451,7 +451,6 @@
Brak ryncznie zadufanych certyfikatōw
Wymaż certyfikaty
Wymaż zaznaczōne
- Pociep
- Wymazany %d certyfikat
- Wymazane %d certyfikaty
diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml
index 5fa2be1f9..d6a6b84e3 100644
--- a/src/main/res/values-tr-rTR/strings.xml
+++ b/src/main/res/values-tr-rTR/strings.xml
@@ -442,7 +442,6 @@
Bizzat onaylanmış sertifika yok
Sertifikaları kaldır
Seçilenleri sil
- İptal
- %d sertifikaları silindi
- %d sertifikaları silindi
diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml
index 74e127750..7f94e1f6c 100644
--- a/src/main/res/values-uk/strings.xml
+++ b/src/main/res/values-uk/strings.xml
@@ -435,7 +435,6 @@
Немає сертифікатів, підтверджених вручну
Вилучити сертифікати
Вилучити вибране
- Скасувати
- %d сертифікат вилучено
- %d сертифікати вилучено
@@ -969,7 +968,6 @@
- Деякі повідомлення не вдалося надіслати
- Деякі повідомлення не вдалося надіслати
- Оберіть сервер для доставки push-повідомлень через XMPP на Ваш пристрій.
Застосунок для передачі зображення не надав достатніх дозволів.
Виклики вимкнені при використанні Tor
%1$s обробляє Ваш список контактів локально, на Вашому пристрої, щоб показати імена та зображення профілю для відповідних контактів у XMPP.
diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml
index 319a79f6e..96c3e9f08 100644
--- a/src/main/res/values-vi/strings.xml
+++ b/src/main/res/values-vi/strings.xml
@@ -434,7 +434,6 @@
Không có chứng nhận được phê duyệt thủ công
Xoá các chứng nhận
Xoá lựa chọn
- Huỷ
- Đã xoá %d chứng nhận
@@ -959,7 +958,6 @@
Tài khoản sẽ nhận được tin nhắn đã đẩy đi.
Tài khoản XMPP
Máy chủ đẩy
- Một máy chủ đẩy do người dùng chọn để phát lại tin nhắn đẩy qua XMPP đến thiết bị của bạn.
Không tồn tại (đã vô hiệu hóa)
Từ chối
Lưu thành nhóm trò chuyện
diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml
index 7364f343a..2c3344076 100644
--- a/src/main/res/values-zh-rCN/strings.xml
+++ b/src/main/res/values-zh-rCN/strings.xml
@@ -454,7 +454,6 @@
没有手动批准的证书
移除证书
删除所选
- 取消
- %d 个证书已删除
@@ -991,7 +990,6 @@
无 (已停用)
UnifiedPush 分发程序
接收推送消息的账号。
- 用户选择的推送服务器,通过 XMPP 将推送消息转送至设备。
拒绝
来电 (%s) · %s
去电 (%s) · %s
@@ -1024,7 +1022,6 @@
是否移除 %s 的书签并关闭对话?
是否移除 %s 的书签?
删除 & 关闭
- 频道发现使用称为 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服务。<br><br>使用此功能会将您的 IP 地址和搜索词传输到此服务。请参阅其 <a href=https://search.jabber.network/privacy>隐私政策</a> 以获取更多信息。
开始聊天
分享至…
彩色聊天气泡有助于区分发送和接收的信息
diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml
index a7d203192..cc09d04bf 100644
--- a/src/main/res/values-zh-rTW/strings.xml
+++ b/src/main/res/values-zh-rTW/strings.xml
@@ -414,7 +414,6 @@
沒有手動核准的憑證
移除憑證
刪除選取項目
- 取消
- %d 個憑證已刪除
@@ -964,7 +963,6 @@
UnifiedPush 散發者
XMPP 帳戶
推送伺服器
- 使用者選擇的推送伺服器,透過 XMPP 將訊息推送至您的裝置。
無 (已停用)
接收推送訊息的帳戶。
拒絕
diff --git a/src/main/res/values/defaults.xml b/src/main/res/values/defaults.xml
index 288e4ae74..929aee1a3 100644
--- a/src/main/res/values/defaults.xml
+++ b/src/main/res/values/defaults.xml
@@ -24,6 +24,7 @@
true
0
false
+ true
true
false
false
@@ -44,7 +45,7 @@
false
360
JABBER_NETWORK
- false
+ true
up.conversations.im
none
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 0405599fd..290b54404 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -282,7 +282,7 @@
Ignore
Warning: Sending this without mutual presence updates could cause unexpected problems.\n\nGo to “Contact details” to verify your presence subscriptions.
Security
- Allow message correction
+ Message correction
Allow your contacts to retroactively edit their messages
Expert settings
Please be careful with these
@@ -446,7 +446,6 @@
No manually approved certificates
Remove certificates
Delete selection
- Cancel
- %d certificate deleted
- %d certificates deleted
@@ -479,8 +478,8 @@
Show as Busy when device is in silent mode
Treat vibrate as silent mode
Show as Busy when device is on vibrate
- Extended connection settings
- Show hostname and port settings when setting up an account
+ Hostname & Port
+ Show extended connection settings when setting up an account
xmpp.example.com
Login with certificate
Could not parse certificate
@@ -571,8 +570,8 @@
Short
Medium
Long
- Broadcast use
- Lets your contacts know when you use Conversations
+ Last seen
+ Let your contacts see when you last used the app
Privacy
Theme
Select the color palette
@@ -749,7 +748,7 @@
Copy XMPP address
HTTP File Sharing for S3
Direct Search
- At ‘Start chat’ screen open keyboard and place cursor in search field
+ At ‘New chat’ screen open keyboard and place cursor in search field
Group chat avatar
Host does not support group chat avatars
Only the owner can change group chat avatar
@@ -1009,7 +1008,6 @@
XMPP Account
The account through which push messages will be received.
Push Server
- A user-chosen push server to relay push messages via XMPP to your device.
None (deactivated)
Decline
Remove account from server
@@ -1027,4 +1025,39 @@
Delete & Archive chat
Start chat
No client certificate selected!
+
+
+
+ Interface
+ Theme, Colors, Screenshots, Input
+ Security
+ E2E Encryption, Blind Trust Before Verification, MIM Detection
+ Notification relay for UnifiedPush compatible third party apps
+ Notifications
+ File size, Image compression, Video quality
+ Grace period, Ringtone, Vibration, Strangers
+ Sending
+ Receiving
+ Automatic download
+ Appearance
+ Light/dark mode
+ Allow screenshots
+ Show app content in app switcher and allow screenshots to be taken
+ End-to-end encryption
+ Certificate authorities
+ Trust the system’s CA certificates
+ Require channel binding
+ Channel binding can detect some machine-in-the-middle attacks
+ Server connection
+ Operating System
+ Typing notifications, Last Seen, Availability
+ Hostname & Port, Tor
+ Hostname & Port, Tor, Channel Discovery
+ Keyboard
+ Engagement notifications
+ Application
+ Interaction
+ On device
+ When acting as a UnifiedPush Distributor the persistent, reliably and battery-friendly XMPP connection will be utilized to wake up other UnifiedPush compatible app such as Tusky, Ltt.rs, FluffyChat and more.
+
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
deleted file mode 100644
index cde8240a2..000000000
--- a/src/main/res/xml/preferences.xml
+++ /dev/null
@@ -1,376 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/res/xml/preferences_attachments.xml b/src/main/res/xml/preferences_attachments.xml
new file mode 100644
index 000000000..7577fb2ea
--- /dev/null
+++ b/src/main/res/xml/preferences_attachments.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_connection.xml b/src/main/res/xml/preferences_connection.xml
new file mode 100644
index 000000000..3ac78e4be
--- /dev/null
+++ b/src/main/res/xml/preferences_connection.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_interface.xml b/src/main/res/xml/preferences_interface.xml
new file mode 100644
index 000000000..390e1e591
--- /dev/null
+++ b/src/main/res/xml/preferences_interface.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_main.xml b/src/main/res/xml/preferences_main.xml
new file mode 100644
index 000000000..2de980c40
--- /dev/null
+++ b/src/main/res/xml/preferences_main.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_notifications.xml b/src/main/res/xml/preferences_notifications.xml
new file mode 100644
index 000000000..82e74efc9
--- /dev/null
+++ b/src/main/res/xml/preferences_notifications.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_privacy.xml b/src/main/res/xml/preferences_privacy.xml
new file mode 100644
index 000000000..b425c35cd
--- /dev/null
+++ b/src/main/res/xml/preferences_privacy.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_security.xml b/src/main/res/xml/preferences_security.xml
new file mode 100644
index 000000000..86bd6c87e
--- /dev/null
+++ b/src/main/res/xml/preferences_security.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/xml/preferences_up.xml b/src/main/res/xml/preferences_up.xml
new file mode 100644
index 000000000..de07d7016
--- /dev/null
+++ b/src/main/res/xml/preferences_up.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file