diff --git a/build.gradle b/build.gradle index 2540a7836f94d5606604e5bedc4f7a43b5b5f98a..3f6c3ec6b8168a28d8f3294299c8e1c1951a29e4 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 d09005593636963d8d94eab1c91e2f812e467589..9228a5170a8c053f005c9b9a33517fd043dab5e2 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 5a301f769886ca4d7992e90f94e9693e4768e0a7..b6d4d452ee6fa28bfa281f12058d5e87d490bf78 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 1a04210dd4c99bc05f14c79b944bc3aa00199cc3..2f4c81671ca459553156fe6a8736f276c1bc0be3 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 cbdd21b36caef09dcbc709823c60dca0016de307..f96a17ffced3786548a097a167656cb76813dd2e 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 66ed355c41a16b658322d45733823f735fdfc3a9..0b20e26c58fae988e68775d920737bba49f88307 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 24528fc164de65be189fec3420563f40b4ce9c94..b2a40976c503c4b744f83e0562092bf85dbb2f62 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 f0d9825613d3202131b691b956cd0b4943b1ab65..fa89034ae25f7d3afd3e0a1f61e0cc77f86180c3 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 d57737f61453d595f8997e000dc71a36e450ab55..2aa9421fd69c83543fa97a156f6e811ba37ebe20 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 9c88711316b564281e65a64979887fcd27340306..cea58c15ecef8e1fbff19b263b4b9980c243fde0 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 cf48a125961d7971eac93746448bf5e1557ca044..fba273b0aa2efb49e8cdf085c61053bef54187ae 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 8d780d0d7380456d09bacb58ceb3e7850e71b306..5a9c31d20a06f181881876cc2c2bd82603ef86ab 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 41a8944034aa712c6f013a2d69984bc94007da24..71662589ca3739f9a6a86ad83cefb828488fc6d5 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 2aacf89273c721882f38b5b222398d0e685e347b..b9ebb413dd4f11344d2f04fc774861690e634fa3 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 6d0bc7928376a1dfb05e81e77c5cfe46c85543da..5ed83219d19bb5bd41e6e1157cc281431c5e14cb 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 24dd3cafd0e190cae5d78216ca3d7e221a7f6dd6..dc038ce377e1e4e3254a5da8c2b476f4ce2e9165 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 92329c6663ca9c065a2ba3a72711c2b091003d37..7d3846ebeae6ff2d378221b8b97a5fe034e0e807 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 be8caa9869264e3a51417cd1f88a0c3713ffbb0f..bc4fab2cc62b5ae7bfcd704c874d53bd933297dd 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 f8d60d55775bd28dd4a4387b319c58e4c489d3d5..ac5b07e77dcb543a5a511de2b81c3605834dd280 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 56913b2a1a4602cd22979db3bdddcbaafd1e884c..bfce03860ba8813adef062284f0993b8a996c6fe 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 f6eae81cfd6ed139bb724d2010f4d61dad552438..72cad4cd0088777b4129f6b6f5f415efb4717692 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 aaef099789b1adc9a9c1ecc506533298b74922f6..8d686c36fc45ffbb35ce4a0cf035c8425d96166a 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 75c9468f996257591292790f39949938aae6783e..7a2bb09385d5a036da2a1182d6fc3bd4c54c7aaa 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 d49d7d23d24cdfdba6b3d3f5e62795f6f2e798e8..5803a20e5876d694ae37c56453b9ce1f21bbe549 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 0e80fa1d5baf1a18e6d5f5563fe66b334314370e..0000000000000000000000000000000000000000 --- 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 9378d82b7393b4735c998dea1ce7d5a314563697..0000000000000000000000000000000000000000 --- 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 0f1cb4f68ed02f0f67f5f77891ab734b082e0fb1..c33c3e6bd7ba2c7c23ba57b6dd4609fcbb2afb58 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 c7302ae2e2f0cb134519da72a603e624a7d8180d..b9b09d0e0789cb403bb66401b398bcc44f5c0b1b 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 0000000000000000000000000000000000000000..7ac85553412b16b427a0923c1e132213fa9a62ef --- /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 0000000000000000000000000000000000000000..b58a7f3982eee98cf9782a2caada0344e10cfd32 --- /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 2ecf230d9624f7fa534332025ea0ccd1b69fb028..a30d25c00ac0fe060220ebfba40702264927b806 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 0000000000000000000000000000000000000000..6b05c18c5b6630f3fe04ac3af15ed62f3a0f5ce0 --- /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 0000000000000000000000000000000000000000..26bb27dc9a7bcac52f5c891997a3a8c51ba17efb --- /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 0000000000000000000000000000000000000000..59ca1484eda06c8e3b5872eec4192031f8a3de99 --- /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 0000000000000000000000000000000000000000..045275f95b9450dd43f6f5224f557df2f731d264 --- /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 0000000000000000000000000000000000000000..81df3da184de0d0e0a2cf12837c8e0168b0f639c --- /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 0000000000000000000000000000000000000000..6f0c4f56c815585d58b80fb52fbd433958d8fa80 --- /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 0000000000000000000000000000000000000000..ba64c5fc340f29322922ccd86a61ab7aaf1fc6d2 --- /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 0000000000000000000000000000000000000000..3470e98c3c9b302fe296acf4e32f67ac9cc2078d --- /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 0000000000000000000000000000000000000000..631ecb6c4eca711d3d19bc1b0a9605f0e5656af4 --- /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 ae99e094335798a7e3d7af52558e660dc0ce7b37..7d194ba9581c2626ac9760d002cdf9a4454dc7b4 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 6d3ba6224121f0d7e19361f853a6fd6bdf0d280f..a6e91593ea2bf4df491f0dca173ece4d933b69b9 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 0000000000000000000000000000000000000000..8ed427d746450d6cc19001989a629a06b47820f1 --- /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 0000000000000000000000000000000000000000..c508dbe3513e09caef6a483dfc8ebb7eafc4c561 --- /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 0000000000000000000000000000000000000000..25fed9d253a603514a848291298019d6c37a20ef --- /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 0000000000000000000000000000000000000000..2c7ffc3ace85545ce2ab8b030c7222f810f7b967 --- /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 0000000000000000000000000000000000000000..c87b654c9debe3b3ef9616996c28df92ae65795f --- /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 0000000000000000000000000000000000000000..9e3255316fd158523a10970b2c427abfb3a255d0 --- /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 0000000000000000000000000000000000000000..50a7239ac617eccb2458ad4cc8937f9a0908d2ff --- /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 0000000000000000000000000000000000000000..849d7b1c23e3d9ec9945a961da4b761d08f0bb62 --- /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 0000000000000000000000000000000000000000..63a35fe6456e7db5f0fc708bc0be08166791c29a --- /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 0a16f16352991b1c58d3857bd6b9b3282c8cda13..ae280360902695905ebd669e804f4c72e11935c5 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 0000000000000000000000000000000000000000..2406aac48a08abe99e8132f7c5a0c79d1f80bdc0 --- /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 0000000000000000000000000000000000000000..c543e3f643ff76193791fa414c04e159c53213bf --- /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 0000000000000000000000000000000000000000..51e84c112c4a8773e7b9d08ec14eece0ff9216ae --- /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 0000000000000000000000000000000000000000..3ce75f00f52249acbcac6ffde7468bb8996fb77f --- /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 0000000000000000000000000000000000000000..915537e464806e6409e25e49046dc7cbc780861d --- /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 0000000000000000000000000000000000000000..267173b5e2fec24b15c39d9c0701f1802dd74c36 --- /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 0000000000000000000000000000000000000000..db78749e513feb672cfe153822ec66acc8fe998f --- /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 ddc83227b4ce2d30f1bfb0e2e8f20754b039a73f..098f18274f1bf2d7a5a1746e21999b18e818b6f8 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 0000000000000000000000000000000000000000..326fb50b875c70ca84eeef125ee9934053a9b160 --- /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 0000000000000000000000000000000000000000..4f9fd480e10412b3ddc38550848b29afdf47dad0 --- /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 0000000000000000000000000000000000000000..c13176ba2dda3f3f4046927e4025391627122532 --- /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 0000000000000000000000000000000000000000..00d17f2cca3402dee48283a00a54285e487ee893 --- /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 0000000000000000000000000000000000000000..72c1549150d139d6ba33a67ff4c18ad12f7f164d --- /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 0000000000000000000000000000000000000000..f7f199198034d86e89f179dad99479d20b24e71e --- /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 0000000000000000000000000000000000000000..be4bb2924920252e980cb80b36ad72afd94d2c50 --- /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 0000000000000000000000000000000000000000..f434507bfaa0788e4a9dff6b12091c2848dd7ee9 --- /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 0000000000000000000000000000000000000000..e9449cf1b13af212ebf82315f79313b3e6b0a07d --- /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 0000000000000000000000000000000000000000..fad20c2fe6658d35991fad074cac6f04227fcaab --- /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 0000000000000000000000000000000000000000..45d230a8399dc3d690fc8c5f696873afdcb846c8 --- /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 0e7c701d40d0aa722f7d03862ce41edbb53db17d..7b697eb44c3397cf9c172d198fda3bc0d1a775a7 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 0000000000000000000000000000000000000000..1535646f2b85e4c6e468980d9c1585defe1095f2 --- /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 0000000000000000000000000000000000000000..bdde86c2b6f1cc5eb7f05e43966476e9a2096e97 --- /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 e02f1d19120a9916a6a738ae5b65ac6705324154..ddcefe0533ab24e0e6fe94005b8d11c180136ff5 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 a5865f2fa007d56cc65cad4c78c226db25a668a5..53d84da4fbb799d07cfca0916de96014181ff36b 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 87ddfcbcf5d5a7454b5c51b12704c4e8f5215101..eda500ac63267b3566fe293a863128041d908dad 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 95b3b85e49a535a419d2b8306e0f6e3b39512240..6b831f7888df724e63d27e5030b8f68161057e13 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 3944bd33d8daab26547e67c38bd097b4809032d4..cffaa14aec4736d0fbf9e0f7a4b7092895d3645b 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 ade65234e98abeb3b77df3444189328917559cbd..3ec310f8521df3c23f0a1bb19a3a10dd4a3d92c7 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 d1e7487bb25a2ef7e00055988183f215ab65b355..090ea644e668f6aeaa6be559f4b1235963480bd2 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 02b250f1fa82927a9f7cec95382a7434754a8fbb..f23495dad15e996fc34196e232f9ef0e64523ce2 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 aa1811da04ce36ffede9daf443906509312ba43f..a97cd7176f58a5550d37a03d193e4e356d2ce335 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 b7701fa26ce216145807d16a4b676bdc8b549115..f6aeb830d0436efce54e42ad5ca9d27732b26657 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 8dfe057e8072670a12c849e15426abcca1047a14..8074162237824aec70145120ebc21c62f54f5805 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 e2d7eb8526564f21a081aced998aea2b0507a5af..5cf081f34b8d76cbe3c42db3545df6d841b935ab 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 f8a682dd9dfbb430e6d0c896b01d03ae0eff1701..dc163cc9ee1579e9d383e3eea015de2e4ef24117 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 fbf1efce11efa56b74d071f9d3218e575a797b88..c614a8ffe152a1edfb986711464350080dfe7fbe 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 ba31ba5ef3d85279b1dcac107531eae8c8bda975..dfd6ee54fa0239bac679b9633323117bd38f6feb 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 4eb5eabe7b10e5157a6f31efa3dea1160911e2fc..76d9332a44a49804824b96bef43e38bd229c4196 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 2850a67ffa8047bf285d9e431beaade57a2dd0a4..9ba1876ee0d70d2ffe207617437272474db5fe4c 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 06c08abda83d2cfa0cf00a9cca9cc3411e132bb7..e0a2c0a540a20031657aad773533c6926ef65fab 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 8f03a6f56543289eeb78870b307c9268bd8fb2a6..8b3489761c8b5c879a1455569b3244c2367e6ffe 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 15aa6fb83222b730dacb032d7283ce324b350002..5d1ed7b0c3b07468e510b9b2e7de4d36c9d7d3be 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 4ac5f82214c849ae02a08222d6a58b0ec4b5246e..0299f1fdbbed446cdf477f045cd2bc05d15f7c04 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 b051797cbad2a2e4196c479140472a17275de6f2..b7d4e483eeac4eb30f761362ab0e27e9e2b63f9e 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 b966f88ca8cd773d940bf3a779d8fed090ccaa9c..cb93885b5c8a47b0fda305b87a7e49afe32857be 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 7427815e709bab298f47b0fe066671f9b58d892f..055e98fe1a621f4d1bb47b1d410550b6b6fd75c2 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 bad9c7fabf331ba7210717c3df5e688c430d1c12..ddbd66fd7a6254a1d99f0025c2866a3ad95d25b2 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 dbe3faebe82e9b830f0b98e0a5945226e0cf137d..1a7c2fc8c232c77d9b660e25ac4349c8d81a205b 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 aede07bfcc1c59568c488e75ce351f75b47757f1..9240999bb8ac9973d8dcd0ef0e193bb0b47a48c8 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 4f76633e1319dee85d5c0b4a3523380e1561a89b..e6fa1eb144df89176a9a7a516c4bf3699a3a202d 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 6f5a78be37ebbdc0e1f19130fef3163696d57651..0c86d9651da740c8ed39f2cfaeec9c12f4323308 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 9dee496549c3982bac4bec7dce587cadfda253f4..ae8d7851ffcd7c446fd8c54c97d22c6e236cbd36 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 d9e13fe18b2f641787b26e48bd820a7d318d4379..13bba3c14e4fdf2e5a8f1ff8b5b4a3abad849bb1 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 6adc1a99e98a534c46631709388d83d166ae14d0..54d172a326b83950b1210d2aa9e463ab6d0673b1 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 0399e3ef31d289bf06df71707fcd20a17daf554a..fc36b94dbbadc80091e8cc51e195fc0a0924d771 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 04f0ee8176cf594eccac25ec51a795b68db711cf..c72acebe45135c8987fc08cb38491d216f645a13 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 4a99e5a4a5b32335ed17476b7d3a5cea2bab8398..64e9558c1bf5f4c2bdc68428d5cc1fbfca15f702 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 5fa2be1f9b719e86385fe14c47bf096bf2350880..d6a6b84e31f586ae5ba6c7b10a81713cf58018c2 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 74e127750dbde247cd01239ab636202b4a380cce..7f94e1f6c641bdff3daa414a10537a2e901d5e6c 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 319a79f6e25bbec37f56f16b47de5028a2815695..96c3e9f087355e345104f6668804a811377c841b 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 7364f343a6327d2039c4e6379b4585bcb79aabbf..2c3344076dec969ebb809a7e84b44b9afa38af71 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 a7d2031924ab2dbd51aa77c16353b8238b3788de..cc09d04bf7453003f0cee77237e85cac7f870f26 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 288e4ae74a600311822a3f23eac149e5de74ff1e..929aee1a3856f91fe3c461c267eb71f9db8b49ab 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 0405599fdb6dc773cf3b56e15d16be64dd2fb13a..290b54404ccde6cda923fb9bd0d93b37b58ec679 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 cde8240a26af7aa249c00bb56d79ad6488dd6b2c..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..7577fb2eaf99c8417ea94f73665f96425cf5c599 --- /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 0000000000000000000000000000000000000000..3ac78e4be73ecb5d238ba97198cf0094b0769eac --- /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 0000000000000000000000000000000000000000..390e1e591c4140109017bbdda17a0edfcd1411a2 --- /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 0000000000000000000000000000000000000000..2de980c40f94446a1b1420b0dd3d11427ddefecb --- /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 0000000000000000000000000000000000000000..82e74efc907bd52ce2ae49d462f131af626bd87e --- /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 0000000000000000000000000000000000000000..b425c35cd724c268b2ad785c5e41aad1128f1d96 --- /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 0000000000000000000000000000000000000000..86bd6c87ea9e47b0371cadd44fff21dfa89ec1b7 --- /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 0000000000000000000000000000000000000000..de07d7016d8df0060bd8a72dd6a5ed3cc73a7e81 --- /dev/null +++ b/src/main/res/xml/preferences_up.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file