SettingsActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.FragmentManager;
  4import android.content.Context;
  5import android.content.DialogInterface;
  6import android.content.Intent;
  7import android.content.SharedPreferences;
  8import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
  9import android.content.pm.PackageManager;
 10import android.net.Uri;
 11import android.os.Build;
 12import android.os.Bundle;
 13import android.os.storage.StorageManager;
 14import android.preference.CheckBoxPreference;
 15import android.preference.ListPreference;
 16import android.preference.Preference;
 17import android.preference.PreferenceCategory;
 18import android.preference.PreferenceManager;
 19import android.preference.PreferenceScreen;
 20import android.provider.MediaStore;
 21import android.util.Log;
 22import android.widget.Toast;
 23
 24import androidx.annotation.NonNull;
 25import androidx.appcompat.app.AlertDialog;
 26import androidx.core.content.ContextCompat;
 27
 28import com.cheogram.android.DownloadDefaultStickers;
 29
 30import com.google.common.base.Strings;
 31import com.google.common.collect.ImmutableList;
 32import com.google.common.collect.Lists;
 33
 34import java.io.File;
 35import java.security.KeyStoreException;
 36import java.util.ArrayList;
 37import java.util.Arrays;
 38import java.util.Collections;
 39import java.util.List;
 40
 41import eu.siacs.conversations.Config;
 42import eu.siacs.conversations.R;
 43import eu.siacs.conversations.crypto.OmemoSetting;
 44import eu.siacs.conversations.entities.Account;
 45import eu.siacs.conversations.entities.Contact;
 46import eu.siacs.conversations.persistance.FileBackend;
 47import eu.siacs.conversations.services.ExportBackupService;
 48import eu.siacs.conversations.services.MemorizingTrustManager;
 49import eu.siacs.conversations.services.QuickConversationsService;
 50import eu.siacs.conversations.services.UnifiedPushDistributor;
 51import eu.siacs.conversations.ui.util.SettingsUtils;
 52import eu.siacs.conversations.ui.util.StyledAttributes;
 53import eu.siacs.conversations.utils.GeoHelper;
 54import eu.siacs.conversations.utils.ThemeHelper;
 55import eu.siacs.conversations.utils.TimeFrameUtils;
 56import eu.siacs.conversations.xmpp.Jid;
 57
 58public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener {
 59
 60    public static final String KEEP_FOREGROUND_SERVICE = "enable_foreground_service";
 61    public static final String AWAY_WHEN_SCREEN_IS_OFF = "away_when_screen_off";
 62    public static final String TREAT_VIBRATE_AS_SILENT = "treat_vibrate_as_silent";
 63    public static final String DND_ON_SILENT_MODE = "dnd_on_silent_mode";
 64    public static final String MANUALLY_CHANGE_PRESENCE = "manually_change_presence";
 65    public static final String BLIND_TRUST_BEFORE_VERIFICATION = "btbv";
 66    public static final String AUTOMATIC_MESSAGE_DELETION = "automatic_message_deletion";
 67    public static final String BROADCAST_LAST_ACTIVITY = "last_activity";
 68    public static final String THEME = "theme";
 69    public static final String SHOW_DYNAMIC_TAGS = "show_dynamic_tags";
 70    public static final String OMEMO_SETTING = "omemo";
 71    public static final String PREVENT_SCREENSHOTS = "prevent_screenshots";
 72
 73    public static final int REQUEST_CREATE_BACKUP = 0xbf8701;
 74    public static final int REQUEST_DOWNLOAD_STICKERS = 0xbf8702;
 75
 76    private SettingsFragment mSettingsFragment;
 77
 78    @Override
 79    protected void onCreate(Bundle savedInstanceState) {
 80        super.onCreate(savedInstanceState);
 81        setContentView(R.layout.activity_settings);
 82        FragmentManager fm = getFragmentManager();
 83        mSettingsFragment = (SettingsFragment) fm.findFragmentById(R.id.settings_content);
 84        if (mSettingsFragment == null
 85                || !mSettingsFragment.getClass().equals(SettingsFragment.class)) {
 86            mSettingsFragment = new SettingsFragment();
 87            fm.beginTransaction().replace(R.id.settings_content, mSettingsFragment).commit();
 88        }
 89        mSettingsFragment.setActivityIntent(getIntent());
 90        this.mTheme = findTheme();
 91        setTheme(this.mTheme);
 92        ThemeHelper.applyCustomColors(this);
 93        getWindow()
 94                .getDecorView()
 95                .setBackgroundColor(
 96                        StyledAttributes.getColor(this, R.attr.color_background_primary));
 97        setSupportActionBar(findViewById(R.id.toolbar));
 98        configureActionBar(getSupportActionBar());
 99    }
100
101    @Override
102    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
103        if (data == null || data.getData() == null) return;
104
105        SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
106        p.edit().putString("sticker_directory", data.getData().toString()).commit();
107    }
108
109    @Override
110    void onBackendConnected() {
111        boolean diallerIntegrationPossible = false;
112
113        if (Build.VERSION.SDK_INT >= 23) {
114            outer:
115            for (Account account : xmppConnectionService.getAccounts()) {
116                for (Contact contact : account.getRoster().getContacts()) {
117                    if (contact.getPresences().anyIdentity("gateway", "pstn")) {
118                        diallerIntegrationPossible = true;
119                        break outer;
120                    }
121                }
122            }
123        }
124        if (!diallerIntegrationPossible) {
125            PreferenceCategory cat = (PreferenceCategory) mSettingsFragment.findPreference("notification_category");
126            Preference pref = mSettingsFragment.findPreference("dialler_integration_incoming");
127            if (cat != null && pref != null) cat.removePreference(pref);
128        }
129        if (xmppConnectionService.getAccounts().size() > 1) {
130            PreferenceCategory cat = (PreferenceCategory) mSettingsFragment.findPreference("notification_category");
131            Preference pref = mSettingsFragment.findPreference("quiet_hours");
132            if (cat != null && pref != null) cat.removePreference(pref);
133        }
134        final Preference accountPreference =
135                mSettingsFragment.findPreference(UnifiedPushDistributor.PREFERENCE_ACCOUNT);
136        reconfigureUpAccountPreference(accountPreference);
137    }
138
139    private void reconfigureUpAccountPreference(final Preference preference) {
140        final ListPreference listPreference;
141        if (preference instanceof ListPreference) {
142            listPreference = (ListPreference) preference;
143        } else {
144            return;
145        }
146        final List<CharSequence> accounts =
147                ImmutableList.copyOf(
148                        Lists.transform(
149                                xmppConnectionService.getAccounts(),
150                                a -> a.getJid().asBareJid().toEscapedString()));
151        final ImmutableList.Builder<CharSequence> entries = new ImmutableList.Builder<>();
152        final ImmutableList.Builder<CharSequence> entryValues = new ImmutableList.Builder<>();
153        entries.add(getString(R.string.no_account_deactivated));
154        entryValues.add("none");
155        entries.addAll(accounts);
156        entryValues.addAll(accounts);
157        listPreference.setEntries(entries.build().toArray(new CharSequence[0]));
158        listPreference.setEntryValues(entryValues.build().toArray(new CharSequence[0]));
159        if (!accounts.contains(listPreference.getValue())) {
160            listPreference.setValue("none");
161        }
162    }
163
164    @Override
165    public void onStart() {
166        super.onStart();
167        PreferenceManager.getDefaultSharedPreferences(this)
168                .registerOnSharedPreferenceChangeListener(this);
169
170        changeOmemoSettingSummary();
171
172        if (QuickConversationsService.isQuicksy()
173                || Strings.isNullOrEmpty(Config.CHANNEL_DISCOVERY)) {
174            final PreferenceCategory groupChats =
175                    (PreferenceCategory) mSettingsFragment.findPreference("group_chats");
176            final Preference channelDiscoveryMethod =
177                    mSettingsFragment.findPreference("channel_discovery_method");
178            if (groupChats != null && channelDiscoveryMethod != null) {
179                groupChats.removePreference(channelDiscoveryMethod);
180            }
181        }
182
183        if (QuickConversationsService.isQuicksy()) {
184            final PreferenceCategory connectionOptions =
185                    (PreferenceCategory) mSettingsFragment.findPreference("connection_options");
186            PreferenceScreen expert = (PreferenceScreen) mSettingsFragment.findPreference("expert");
187            if (connectionOptions != null) {
188                expert.removePreference(connectionOptions);
189            }
190        }
191
192        PreferenceScreen mainPreferenceScreen =
193                (PreferenceScreen) mSettingsFragment.findPreference("main_screen");
194
195        PreferenceCategory attachmentsCategory =
196                (PreferenceCategory) mSettingsFragment.findPreference("attachments");
197        CheckBoxPreference locationPlugin =
198                (CheckBoxPreference) mSettingsFragment.findPreference("use_share_location_plugin");
199        if (attachmentsCategory != null && locationPlugin != null) {
200            if (!GeoHelper.isLocationPluginInstalled(this)) {
201                attachmentsCategory.removePreference(locationPlugin);
202            }
203        }
204
205        // this feature is only available on Huawei Android 6.
206        PreferenceScreen huaweiPreferenceScreen =
207                (PreferenceScreen) mSettingsFragment.findPreference("huawei");
208        if (huaweiPreferenceScreen != null) {
209            Intent intent = huaweiPreferenceScreen.getIntent();
210            // remove when Api version is above M (Version 6.0) or if the intent is not callable
211            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || !isCallable(intent)) {
212                PreferenceCategory generalCategory =
213                        (PreferenceCategory) mSettingsFragment.findPreference("general");
214                generalCategory.removePreference(huaweiPreferenceScreen);
215                if (generalCategory.getPreferenceCount() == 0) {
216                    if (mainPreferenceScreen != null) {
217                        mainPreferenceScreen.removePreference(generalCategory);
218                    }
219                }
220            }
221        }
222
223        ListPreference automaticMessageDeletionList =
224                (ListPreference) mSettingsFragment.findPreference(AUTOMATIC_MESSAGE_DELETION);
225        if (automaticMessageDeletionList != null) {
226            final int[] choices =
227                    getResources().getIntArray(R.array.automatic_message_deletion_values);
228            CharSequence[] entries = new CharSequence[choices.length];
229            CharSequence[] entryValues = new CharSequence[choices.length];
230            for (int i = 0; i < choices.length; ++i) {
231                entryValues[i] = String.valueOf(choices[i]);
232                if (choices[i] == 0) {
233                    entries[i] = getString(R.string.never);
234                } else {
235                    entries[i] = TimeFrameUtils.resolve(this, 1000L * choices[i]);
236                }
237            }
238            automaticMessageDeletionList.setEntries(entries);
239            automaticMessageDeletionList.setEntryValues(entryValues);
240        }
241
242        boolean removeLocation =
243                new Intent("eu.siacs.conversations.location.request")
244                                .resolveActivity(getPackageManager())
245                        == null;
246        boolean removeVoice =
247                new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
248                                .resolveActivity(getPackageManager())
249                        == null;
250
251        ListPreference quickAction =
252                (ListPreference) mSettingsFragment.findPreference("quick_action");
253        if (quickAction != null && (removeLocation || removeVoice)) {
254            ArrayList<CharSequence> entries =
255                    new ArrayList<>(Arrays.asList(quickAction.getEntries()));
256            ArrayList<CharSequence> entryValues =
257                    new ArrayList<>(Arrays.asList(quickAction.getEntryValues()));
258            int index = entryValues.indexOf("location");
259            if (index > 0 && removeLocation) {
260                entries.remove(index);
261                entryValues.remove(index);
262            }
263            index = entryValues.indexOf("voice");
264            if (index > 0 && removeVoice) {
265                entries.remove(index);
266                entryValues.remove(index);
267            }
268            quickAction.setEntries(entries.toArray(new CharSequence[entries.size()]));
269            quickAction.setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()]));
270        }
271
272        final Preference removeCertsPreference =
273                mSettingsFragment.findPreference("remove_trusted_certificates");
274        if (removeCertsPreference != null) {
275            removeCertsPreference.setOnPreferenceClickListener(
276                    preference -> {
277                        final MemorizingTrustManager mtm =
278                                xmppConnectionService.getMemorizingTrustManager();
279                        final ArrayList<String> aliases = Collections.list(mtm.getCertificates());
280                        if (aliases.size() == 0) {
281                            displayToast(getString(R.string.toast_no_trusted_certs));
282                            return true;
283                        }
284                        final ArrayList<Integer> selectedItems = new ArrayList<>();
285                        final AlertDialog.Builder dialogBuilder =
286                                new AlertDialog.Builder(SettingsActivity.this);
287                        dialogBuilder.setTitle(
288                                getResources().getString(R.string.dialog_manage_certs_title));
289                        dialogBuilder.setMultiChoiceItems(
290                                aliases.toArray(new CharSequence[aliases.size()]),
291                                null,
292                                (dialog, indexSelected, isChecked) -> {
293                                    if (isChecked) {
294                                        selectedItems.add(indexSelected);
295                                    } else if (selectedItems.contains(indexSelected)) {
296                                        selectedItems.remove(Integer.valueOf(indexSelected));
297                                    }
298                                    ((AlertDialog) dialog)
299                                            .getButton(DialogInterface.BUTTON_POSITIVE)
300                                            .setEnabled(selectedItems.size() > 0);
301                                });
302
303                        dialogBuilder.setPositiveButton(
304                                getResources()
305                                        .getString(R.string.dialog_manage_certs_positivebutton),
306                                (dialog, which) -> {
307                                    int count = selectedItems.size();
308                                    if (count > 0) {
309                                        for (int i = 0; i < count; i++) {
310                                            try {
311                                                Integer item =
312                                                        Integer.valueOf(
313                                                                selectedItems.get(i).toString());
314                                                String alias = aliases.get(item);
315                                                mtm.deleteCertificate(alias);
316                                            } catch (KeyStoreException e) {
317                                                e.printStackTrace();
318                                                displayToast("Error: " + e.getLocalizedMessage());
319                                            }
320                                        }
321                                        if (xmppConnectionServiceBound) {
322                                            reconnectAccounts();
323                                        }
324                                        displayToast(
325                                                getResources()
326                                                        .getQuantityString(
327                                                                R.plurals.toast_delete_certificates,
328                                                                count,
329                                                                count));
330                                    }
331                                });
332                        dialogBuilder.setNegativeButton(
333                                getResources()
334                                        .getString(R.string.dialog_manage_certs_negativebutton),
335                                null);
336                        AlertDialog removeCertsDialog = dialogBuilder.create();
337                        removeCertsDialog.show();
338                        removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
339                        return true;
340                    });
341        }
342
343        final Preference createBackupPreference = mSettingsFragment.findPreference("create_backup");
344        if (createBackupPreference != null) {
345            createBackupPreference.setSummary(
346                    getString(
347                            R.string.pref_create_backup_summary,
348                            FileBackend.getBackupDirectory(this).getAbsolutePath()));
349            createBackupPreference.setOnPreferenceClickListener(
350                    preference -> {
351                        if (hasStoragePermission(REQUEST_CREATE_BACKUP)) {
352                            createBackup();
353                        }
354                        return true;
355                    });
356        }
357
358        if (Config.ONLY_INTERNAL_STORAGE) {
359            final Preference cleanCachePreference = mSettingsFragment.findPreference("clean_cache");
360            if (cleanCachePreference != null) {
361                cleanCachePreference.setOnPreferenceClickListener(preference -> cleanCache());
362            }
363
364            final Preference cleanPrivateStoragePreference =
365                    mSettingsFragment.findPreference("clean_private_storage");
366            if (cleanPrivateStoragePreference != null) {
367                cleanPrivateStoragePreference.setOnPreferenceClickListener(
368                        preference -> cleanPrivateStorage());
369            }
370        }
371
372        final Preference deleteOmemoPreference =
373                mSettingsFragment.findPreference("delete_omemo_identities");
374        if (deleteOmemoPreference != null) {
375            deleteOmemoPreference.setOnPreferenceClickListener(
376                    preference -> deleteOmemoIdentities());
377        }
378        if (Config.omemoOnly()) {
379            final PreferenceCategory privacyCategory =
380                    (PreferenceCategory) mSettingsFragment.findPreference("privacy");
381            final Preference omemoPreference =mSettingsFragment.findPreference(OMEMO_SETTING);
382            if (omemoPreference != null) {
383                privacyCategory.removePreference(omemoPreference);
384            }
385        }
386
387        final Preference stickerDir = mSettingsFragment.findPreference("sticker_directory");
388        if (stickerDir != null) {
389            if (Build.VERSION.SDK_INT >= 24) {
390                stickerDir.setOnPreferenceClickListener((p) -> {
391                    Intent intent = ((StorageManager) getSystemService(Context.STORAGE_SERVICE)).getPrimaryStorageVolume().createOpenDocumentTreeIntent();
392                    startActivityForResult(Intent.createChooser(intent, "Choose sticker location"), 0);
393                    return true;
394                });
395            } else {
396                PreferenceCategory expertMedia = (PreferenceCategory) mSettingsFragment.findPreference("expert_media");
397                expertMedia.removePreference(stickerDir);
398            }
399        }
400
401        final Preference downloadDefaultStickers = mSettingsFragment.findPreference("download_default_stickers");
402        if (downloadDefaultStickers != null) {
403            downloadDefaultStickers.setOnPreferenceClickListener(
404                    preference -> {
405                        if (hasStoragePermission(REQUEST_DOWNLOAD_STICKERS)) {
406                            downloadStickers();
407                        }
408                        return true;
409                    });
410        }
411
412        final Preference clearBlockedMedia = mSettingsFragment.findPreference("clear_blocked_media");
413        if (clearBlockedMedia != null) {
414            clearBlockedMedia.setOnPreferenceClickListener((p) -> {
415                xmppConnectionService.clearBlockedMedia();
416                displayToast("Blocked media will be displayed again.");
417                return true;
418            });
419        }
420
421        final String theTheme = PreferenceManager.getDefaultSharedPreferences(this).getString(THEME, "");
422        if (Build.VERSION.SDK_INT < 30 || !theTheme.equals("custom")) {
423            final PreferenceCategory uiCategory = (PreferenceCategory) mSettingsFragment.findPreference("ui");
424            final Preference customTheme = mSettingsFragment.findPreference("custom_theme");
425            if (customTheme != null) uiCategory.removePreference(customTheme);
426        }
427    }
428
429    private void changeOmemoSettingSummary() {
430        final ListPreference omemoPreference =
431                (ListPreference) mSettingsFragment.findPreference(OMEMO_SETTING);
432        if (omemoPreference == null) {
433            return;
434        }
435        final String value = omemoPreference.getValue();
436        switch (value) {
437            case "always":
438                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_always);
439                break;
440            case "default_on":
441                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_on);
442                break;
443            case "default_off":
444                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_off);
445                break;
446        }
447    }
448
449    private boolean isCallable(final Intent i) {
450        return i != null
451                && getPackageManager()
452                                .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY)
453                                .size()
454                        > 0;
455    }
456
457    private boolean cleanCache() {
458        Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
459        intent.setData(Uri.parse("package:" + getPackageName()));
460        startActivity(intent);
461        return true;
462    }
463
464    private boolean cleanPrivateStorage() {
465        for (String type : Arrays.asList("Images", "Videos", "Files", "Recordings")) {
466            cleanPrivateFiles(type);
467        }
468        return true;
469    }
470
471    private void cleanPrivateFiles(final String type) {
472        try {
473            File dir = new File(getFilesDir().getAbsolutePath(), "/" + type + "/");
474            File[] array = dir.listFiles();
475            if (array != null) {
476                for (int b = 0; b < array.length; b++) {
477                    String name = array[b].getName().toLowerCase();
478                    if (name.equals(".nomedia")) {
479                        continue;
480                    }
481                    if (array[b].isFile()) {
482                        array[b].delete();
483                    }
484                }
485            }
486        } catch (Throwable e) {
487            Log.e("CleanCache", e.toString());
488        }
489    }
490
491    private boolean deleteOmemoIdentities() {
492        AlertDialog.Builder builder = new AlertDialog.Builder(this);
493        builder.setTitle(R.string.pref_delete_omemo_identities);
494        final List<CharSequence> accounts = new ArrayList<>();
495        for (Account account : xmppConnectionService.getAccounts()) {
496            if (account.isEnabled()) {
497                accounts.add(account.getJid().asBareJid().toString());
498            }
499        }
500        final boolean[] checkedItems = new boolean[accounts.size()];
501        builder.setMultiChoiceItems(
502                accounts.toArray(new CharSequence[accounts.size()]),
503                checkedItems,
504                (dialog, which, isChecked) -> {
505                    checkedItems[which] = isChecked;
506                    final AlertDialog alertDialog = (AlertDialog) dialog;
507                    for (boolean item : checkedItems) {
508                        if (item) {
509                            alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
510                            return;
511                        }
512                    }
513                    alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
514                });
515        builder.setNegativeButton(R.string.cancel, null);
516        builder.setPositiveButton(
517                R.string.delete_selected_keys,
518                (dialog, which) -> {
519                    for (int i = 0; i < checkedItems.length; ++i) {
520                        if (checkedItems[i]) {
521                            try {
522                                Jid jid = Jid.of(accounts.get(i).toString());
523                                Account account = xmppConnectionService.findAccountByJid(jid);
524                                if (account != null) {
525                                    account.getAxolotlService().regenerateKeys(true);
526                                }
527                            } catch (IllegalArgumentException e) {
528                                //
529                            }
530                        }
531                    }
532                });
533        AlertDialog dialog = builder.create();
534        dialog.show();
535        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
536        return true;
537    }
538
539    @Override
540    public void onStop() {
541        super.onStop();
542        PreferenceManager.getDefaultSharedPreferences(this)
543                .unregisterOnSharedPreferenceChangeListener(this);
544    }
545
546    @Override
547    public void onSharedPreferenceChanged(SharedPreferences preferences, String name) {
548        final List<String> resendPresence =
549                Arrays.asList(
550                        "confirm_messages",
551                        DND_ON_SILENT_MODE,
552                        AWAY_WHEN_SCREEN_IS_OFF,
553                        "allow_message_correction",
554                        TREAT_VIBRATE_AS_SILENT,
555                        MANUALLY_CHANGE_PRESENCE,
556                        BROADCAST_LAST_ACTIVITY);
557        if (name.equals(OMEMO_SETTING)) {
558            OmemoSetting.load(this, preferences);
559            changeOmemoSettingSummary();
560        } else if (name.equals(KEEP_FOREGROUND_SERVICE)) {
561            xmppConnectionService.toggleForegroundService();
562        } else if (resendPresence.contains(name)) {
563            if (xmppConnectionServiceBound) {
564                if (name.equals(AWAY_WHEN_SCREEN_IS_OFF) || name.equals(MANUALLY_CHANGE_PRESENCE)) {
565                    xmppConnectionService.toggleScreenEventReceiver();
566                }
567                xmppConnectionService.refreshAllPresences();
568            }
569        } else if (name.equals("dont_trust_system_cas")) {
570            xmppConnectionService.updateMemorizingTrustmanager();
571            reconnectAccounts();
572        } else if (name.equals("use_tor")) {
573            if (preferences.getBoolean(name, false)) {
574                displayToast(getString(R.string.audio_video_disabled_tor));
575            }
576            reconnectAccounts();
577            xmppConnectionService.reinitializeMuclumbusService();
578        } else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) {
579            xmppConnectionService.expireOldMessages(true);
580        } else if (name.equals(THEME) || name.equals("custom_theme_primary") || name.equals("custom_theme_primary_dark") || name.equals("custom_theme_accent") || name.equals("custom_theme_dark")) {
581            final int theme = findTheme();
582            xmppConnectionService.setTheme(theme);
583            ThemeHelper.applyCustomColors(xmppConnectionService);
584            recreate();
585        } else if (name.equals(PREVENT_SCREENSHOTS)) {
586            SettingsUtils.applyScreenshotPreventionSetting(this);
587        } else if (UnifiedPushDistributor.PREFERENCES.contains(name)) {
588            if (xmppConnectionService.reconfigurePushDistributor()) {
589                xmppConnectionService.renewUnifiedPushEndpoints();
590            }
591        }
592    }
593
594    @Override
595    public void onResume() {
596        super.onResume();
597        SettingsUtils.applyScreenshotPreventionSetting(this);
598    }
599
600    @Override
601    public void onRequestPermissionsResult(
602            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
603        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
604        if (grantResults.length > 0)
605            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
606                if (requestCode == REQUEST_CREATE_BACKUP) {
607                    createBackup();
608                }
609                if (requestCode == REQUEST_DOWNLOAD_STICKERS) {
610                    downloadStickers();
611                }
612            } else {
613                Toast.makeText(
614                                this,
615                                getString(
616                                        R.string.no_storage_permission,
617                                        getString(R.string.app_name)),
618                                Toast.LENGTH_SHORT)
619                        .show();
620            }
621    }
622
623    private void createBackup() {
624        new AlertDialog.Builder(this)
625            .setTitle("Create Backup")
626            .setMessage("Export extra Cheogram-only data (backup will not import into other apps then)?")
627            .setPositiveButton(R.string.yes, (dialog, whichButton) -> {
628                createBackup(true);
629            })
630            .setNegativeButton(R.string.no, (dialog, whichButton) -> {
631                createBackup(false);
632            }).show();
633    }
634
635    private void createBackup(boolean withCheogramDb) {
636        Intent intent = new Intent(this, ExportBackupService.class);
637        intent.putExtra("cheogram_db", withCheogramDb);
638        ContextCompat.startForegroundService(this, intent);
639        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
640        builder.setMessage(R.string.backup_started_message);
641        builder.setPositiveButton(R.string.ok, null);
642        builder.create().show();
643    }
644
645    private void downloadStickers() {
646        Intent intent = new Intent(this, DownloadDefaultStickers.class);
647        intent.putExtra("tor", xmppConnectionService.useTorToConnect());
648        ContextCompat.startForegroundService(this, intent);
649        displayToast("Sticker download started");
650    }
651
652    private void displayToast(final String msg) {
653        runOnUiThread(() -> Toast.makeText(SettingsActivity.this, msg, Toast.LENGTH_LONG).show());
654    }
655
656    private void reconnectAccounts() {
657        for (Account account : xmppConnectionService.getAccounts()) {
658            if (account.isEnabled()) {
659                xmppConnectionService.reconnectAccountInBackground(account);
660            }
661        }
662    }
663
664    public void refreshUiReal() {
665        // nothing to do. This Activity doesn't implement any listeners
666    }
667}