diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 3e4ea39fcb..685894dcd9 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -72,6 +72,7 @@ import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionRequestMessageSendJob; import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation; import org.thoughtcrime.securesms.loki.utilities.Broadcaster; +import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities; import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.NotificationChannels; @@ -215,6 +216,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc publicChatManager = new PublicChatManager(this); updateOpenGroupProfilePicturesIfNeeded(); registerForFCMIfNeeded(false); + // Set application UI mode (day/night theme) to the user selected one. + UiModeUtilities.setupUiModeToUserSelected(this); // ======== initializeJobManager(); initializeMessageRetrieval(); diff --git a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index c6ff62f814..dc2d75345c 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.avatar.AvatarSelection import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.loki.dialogs.ChangeUiModeDialog import org.thoughtcrime.securesms.loki.dialogs.ClearAllDataDialog import org.thoughtcrime.securesms.loki.dialogs.SeedDialog import org.thoughtcrime.securesms.loki.utilities.fadeIn @@ -100,11 +101,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.settings_general, menu) - -// // Day/night themes are only available since Android 10 -// menu.findItem(R.id.action_change_theme) -// .setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - return true } @@ -115,15 +111,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { true } R.id.action_change_theme -> { - // A temporary demo code that manually switches between day/night themes. - // The effect is reset after the app restart. - val currentUiMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK - val nightMode: Int = when(currentUiMode) { - Configuration.UI_MODE_NIGHT_YES -> AppCompatDelegate.MODE_NIGHT_NO - else -> AppCompatDelegate.MODE_NIGHT_YES - } - AppCompatDelegate.setDefaultNightMode(nightMode) - recreate() + ChangeUiModeDialog().show(supportFragmentManager, ChangeUiModeDialog.TAG) true } else -> super.onOptionsItemSelected(item) diff --git a/src/org/thoughtcrime/securesms/loki/dialogs/ChangeUiModeDialog.kt b/src/org/thoughtcrime/securesms/loki/dialogs/ChangeUiModeDialog.kt new file mode 100644 index 0000000000..b9e2127fd9 --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/dialogs/ChangeUiModeDialog.kt @@ -0,0 +1,35 @@ +package org.thoughtcrime.securesms.loki.dialogs + +import android.app.Dialog +import android.os.Bundle +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import org.thoughtcrime.securesms.loki.utilities.UiMode +import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities + +//TODO Use localized string resources. +class ChangeUiModeDialog : DialogFragment() { + + companion object { + public const val TAG = "ChangeUiModeDialog" + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val context = requireContext() + + val displayNameList = UiMode.values().map { it.displayName }.toTypedArray() + val activeUiMode = UiModeUtilities.getUserSelectedUiMode(context) + + return AlertDialog.Builder(context) + .setSingleChoiceItems(displayNameList, activeUiMode.ordinal) { _, selectedItemIdx: Int -> + val uiMode = UiMode.values()[selectedItemIdx] + UiModeUtilities.setUserSelectedUiMode(context, uiMode) + dismiss() + requireActivity().recreate() + } + .setTitle("Application theme") + .setNegativeButton("Cancel") { _, _ -> dismiss() } + .create() + + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/utilities/UiModeUtilities.kt b/src/org/thoughtcrime/securesms/loki/utilities/UiModeUtilities.kt new file mode 100644 index 0000000000..0a24e5777a --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/utilities/UiModeUtilities.kt @@ -0,0 +1,62 @@ +package org.thoughtcrime.securesms.loki.utilities + +import android.content.Context +import android.content.res.Configuration +import androidx.appcompat.app.AppCompatDelegate + +/** + * Day/night UI mode related utilities. + * @see Official Documentation + */ +object UiModeUtilities { + private const val PREF_FILE_NAME = "UiModeUtilities" + private const val PREF_KEY_SELECTED_UI_MODE = "SELECTED_UI_MODE" + + @JvmStatic + public fun setUserSelectedUiMode(context: Context, uiMode: UiMode) { + val prefs = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE) + prefs.edit() + .putString(PREF_KEY_SELECTED_UI_MODE, uiMode.name) + .apply() + AppCompatDelegate.setDefaultNightMode(uiMode.nightModeValue) + } + + @JvmStatic + public fun getUserSelectedUiMode(context: Context): UiMode { + val prefs = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE) + val selectedUiModeName = prefs.getString(PREF_KEY_SELECTED_UI_MODE, UiMode.SYSTEM_DEFAULT.name)!! + var selectedUiMode: UiMode + try { + selectedUiMode = UiMode.valueOf(selectedUiModeName) + } catch (e: IllegalArgumentException) { + // Cannot recognize UiMode constant from the given string. + selectedUiMode = UiMode.SYSTEM_DEFAULT + } + return selectedUiMode + } + + @JvmStatic + public fun setupUiModeToUserSelected(context: Context) { + val selectedUiMode = getUserSelectedUiMode(context) + setUserSelectedUiMode(context, selectedUiMode) + } +} + +//TODO Use localized string resources. +enum class UiMode( + val displayName: String, + val uiModeNightFlag: Int, + val nightModeValue: Int) { + + DAY ("Day", + Configuration.UI_MODE_NIGHT_NO, + AppCompatDelegate.MODE_NIGHT_NO), + + NIGHT ("Night", + Configuration.UI_MODE_NIGHT_YES, + AppCompatDelegate.MODE_NIGHT_YES), + + SYSTEM_DEFAULT ("System default", + Configuration.UI_MODE_NIGHT_UNDEFINED, + AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); +} \ No newline at end of file