From d9684a2010c1e4643ba7882b2616823814a45342 Mon Sep 17 00:00:00 2001
From: Charles Lombardo <clombardo169@gmail.com>
Date: Thu, 20 Apr 2023 18:01:09 -0400
Subject: [PATCH] android: Add theme mode picker

---
 .../features/settings/model/Settings.kt       |  1 +
 .../settings/ui/SettingsFragmentPresenter.kt  | 25 +++++++++++
 .../org/yuzu/yuzu_emu/utils/ThemeHelper.kt    | 44 ++++++++++++++-----
 .../app/src/main/res/values/arrays.xml        | 11 +++++
 .../app/src/main/res/values/strings.xml       |  6 +++
 5 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
index b00110e916..2cf9d704ee 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
@@ -136,6 +136,7 @@ class Settings {
 
         const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
         const val PREF_THEME = "Theme"
+        const val PREF_THEME_MODE = "ThemeMode"
 
         private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
 
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index b49a8bbec3..d8fa321ad1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -16,6 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
 import org.yuzu.yuzu_emu.features.settings.model.Settings
 import org.yuzu.yuzu_emu.features.settings.model.view.*
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
+import org.yuzu.yuzu_emu.utils.ThemeHelper
 
 class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) {
     private var menuTag: String? = null
@@ -355,6 +356,30 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     )
                 )
             }
+
+            val themeMode: AbstractIntSetting = object : AbstractIntSetting {
+                override var int: Int
+                    get() = preferences.getInt(Settings.PREF_THEME_MODE, -1)
+                    set(value) {
+                        preferences.edit().putInt(Settings.PREF_THEME_MODE, value).apply()
+                        ThemeHelper.setThemeMode(settingsActivity)
+                    }
+                override val key: String? = null
+                override val section: String? = null
+                override val isRuntimeEditable: Boolean = true
+                override val valueAsString: String
+                    get() = preferences.getInt(Settings.PREF_THEME_MODE, -1).toString()
+            }
+
+            add(
+                SingleChoiceSetting(
+                    themeMode,
+                    R.string.change_theme_mode,
+                    0,
+                    R.array.themeModeEntries,
+                    R.array.themeModeValues
+                )
+            )
         }
     }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ThemeHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ThemeHelper.kt
index 72e2fb75eb..467978e6de 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ThemeHelper.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ThemeHelper.kt
@@ -8,8 +8,10 @@ import android.content.res.Configuration
 import android.graphics.Color
 import androidx.annotation.ColorInt
 import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDelegate
 import androidx.core.content.ContextCompat
 import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsControllerCompat
 import androidx.preference.PreferenceManager
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.YuzuApplication
@@ -26,21 +28,11 @@ object ThemeHelper {
     @JvmStatic
     fun setTheme(activity: AppCompatActivity) {
         val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
+        setThemeMode(activity)
         when (preferences.getInt(Settings.PREF_THEME, 0)) {
             DEFAULT -> activity.setTheme(R.style.Theme_Yuzu_Main)
             MATERIAL_YOU -> activity.setTheme(R.style.Theme_Yuzu_Main_MaterialYou)
         }
-
-        val windowController = WindowCompat.getInsetsController(
-            activity.window,
-            activity.window.decorView
-        )
-        val isLightMode =
-            (activity.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO
-        windowController.isAppearanceLightStatusBars = isLightMode
-        windowController.isAppearanceLightNavigationBars = isLightMode
-
-        activity.window.statusBarColor = ContextCompat.getColor(activity, android.R.color.transparent)
     }
 
     @JvmStatic
@@ -80,4 +72,34 @@ object ThemeHelper {
             activity.recreate()
         }
     }
+
+    fun setThemeMode(activity: AppCompatActivity) {
+        val themeMode = PreferenceManager.getDefaultSharedPreferences(activity.applicationContext)
+            .getInt(Settings.PREF_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
+        activity.delegate.localNightMode = themeMode
+        val windowController = WindowCompat.getInsetsController(
+            activity.window,
+            activity.window.decorView
+        )
+        val systemReportedThemeMode =
+            activity.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
+        when (themeMode) {
+            AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> when (systemReportedThemeMode) {
+                Configuration.UI_MODE_NIGHT_NO -> setLightModeSystemBars(windowController)
+                Configuration.UI_MODE_NIGHT_YES -> setDarkModeSystemBars(windowController)
+            }
+            AppCompatDelegate.MODE_NIGHT_NO -> setLightModeSystemBars(windowController)
+            AppCompatDelegate.MODE_NIGHT_YES -> setDarkModeSystemBars(windowController)
+        }
+    }
+
+    private fun setLightModeSystemBars(windowController: WindowInsetsControllerCompat) {
+        windowController.isAppearanceLightStatusBars = true
+        windowController.isAppearanceLightNavigationBars = true
+    }
+
+    private fun setDarkModeSystemBars(windowController: WindowInsetsControllerCompat) {
+        windowController.isAppearanceLightStatusBars = false
+        windowController.isAppearanceLightNavigationBars = false
+    }
 }
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml
index a98ccd9857..ce9a576c2e 100644
--- a/src/android/app/src/main/res/values/arrays.xml
+++ b/src/android/app/src/main/res/values/arrays.xml
@@ -199,4 +199,15 @@
         <item>1</item>
     </integer-array>
 
+    <string-array name="themeModeEntries">
+        <item>@string/theme_mode_follow_system</item>
+        <item>@string/theme_mode_light</item>
+        <item>@string/theme_mode_dark</item>
+    </string-array>
+    <integer-array name="themeModeValues">
+        <item>-1</item>
+        <item>1</item>
+        <item>2</item>
+    </integer-array>
+
 </resources>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 90c94d67f4..28c9af7bd3 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -235,4 +235,10 @@
     <string name="theme_default">Default</string>
     <string name="theme_material_you">Material You</string>
 
+    <!-- Theme Modes -->
+    <string name="change_theme_mode">Change Theme Mode</string>
+    <string name="theme_mode_follow_system">Follow System</string>
+    <string name="theme_mode_light">Light</string>
+    <string name="theme_mode_dark">Dark</string>
+
 </resources>