Day/night UI mode settings selector.

This commit is contained in:
Anton Chekulaev 2020-08-27 14:38:25 +10:00
parent 4f97989154
commit 3a6fe98f1f
4 changed files with 102 additions and 14 deletions

View File

@ -72,6 +72,7 @@ import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
import org.thoughtcrime.securesms.loki.protocol.SessionRequestMessageSendJob; import org.thoughtcrime.securesms.loki.protocol.SessionRequestMessageSendJob;
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation; import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
import org.thoughtcrime.securesms.loki.utilities.Broadcaster; 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.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
@ -215,6 +216,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
publicChatManager = new PublicChatManager(this); publicChatManager = new PublicChatManager(this);
updateOpenGroupProfilePicturesIfNeeded(); updateOpenGroupProfilePicturesIfNeeded();
registerForFCMIfNeeded(false); registerForFCMIfNeeded(false);
// Set application UI mode (day/night theme) to the user selected one.
UiModeUtilities.setupUiModeToUserSelected(this);
// ======== // ========
initializeJobManager(); initializeJobManager();
initializeMessageRetrieval(); initializeMessageRetrieval();

View File

@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.avatar.AvatarSelection
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory 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.ClearAllDataDialog
import org.thoughtcrime.securesms.loki.dialogs.SeedDialog import org.thoughtcrime.securesms.loki.dialogs.SeedDialog
import org.thoughtcrime.securesms.loki.utilities.fadeIn import org.thoughtcrime.securesms.loki.utilities.fadeIn
@ -100,11 +101,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.settings_general, menu) 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 return true
} }
@ -115,15 +111,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
true true
} }
R.id.action_change_theme -> { R.id.action_change_theme -> {
// A temporary demo code that manually switches between day/night themes. ChangeUiModeDialog().show(supportFragmentManager, ChangeUiModeDialog.TAG)
// 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()
true true
} }
else -> super.onOptionsItemSelected(item) else -> super.onOptionsItemSelected(item)

View File

@ -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()
}
}

View File

@ -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 <a href="https://developer.android.com/guide/topics/ui/look-and-feel/darktheme">Official Documentation</a>
*/
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);
}