Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android: Add static color theme option #350

Merged
merged 22 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3e4b6cf
[wip] android: Add static color theme support
kleidis Aug 10, 2024
f8ea10b
theme_util: Add a listener to recreate activity once color is changed
kleidis Aug 11, 2024
95a928d
theme_util: Recreate activity when MY is toggled too
kleidis Aug 11, 2024
236db9a
setup: Add new page for theme settings selection
kleidis Aug 12, 2024
25fde6a
[very wip] colors: Add more colors
kleidis Aug 12, 2024
4d9c993
setup: Completely rework the theme settings popup
kleidis Aug 12, 2024
f6c20c9
citra_colors: Fix the colors for all themes
kleidis Aug 13, 2024
d71603b
listener: Make it a global value && cleanup
kleidis Aug 16, 2024
be93b4d
setup: more code cleanup
kleidis Aug 16, 2024
c0a188a
Updated `PREF_STATIC_THEME_COLOR` string to follow convention
OpenSauce04 Aug 17, 2024
a7c5169
Comment spelling correction + Nitpick formatting
OpenSauce04 Aug 17, 2024
5fd8d3a
Nitpicky code formatting tweaks
OpenSauce04 Aug 17, 2024
d5f0733
Updated file license headers
OpenSauce04 Aug 17, 2024
b08d5c6
Cleanup strings
kleidis Aug 19, 2024
e4bbe0d
Revert SetupFragment.kt
kleidis Aug 19, 2024
8a189a8
strings: typo
kleidis Aug 19, 2024
e74a8ef
themeutil: Update listener comment
kleidis Aug 19, 2024
1dd9168
Fixed instant crash on Android 9
OpenSauce04 Aug 20, 2024
c442da0
Theme.Citra --> Theme.Lime
OpenSauce04 Aug 20, 2024
a27df41
Renamed all "citra_" color prefixes to "lime_"
OpenSauce04 Aug 20, 2024
43e5c64
Reverted unwarranted license header changes
OpenSauce04 Aug 20, 2024
215ab66
Removed Lime theme gave its values to the Green theme
OpenSauce04 Aug 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class Settings {
const val PREF_THEME_MODE = "ThemeMode"
const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"
const val PREF_SHOW_HOME_APPS = "ShowHomeApps"
const val PREF_STATIC_THEME_COLOR = "StaticThemeColor"

private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()

Expand All @@ -231,4 +232,4 @@ class Settings {
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,33 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
R.string.use_black_backgrounds_description
)
)

val staticThemeColor: AbstractIntSetting = object : AbstractIntSetting {
override var int: Int
get() = preferences.getInt(Settings.PREF_STATIC_THEME_COLOR, 0)
set(value) {
preferences.edit()
.putInt(Settings.PREF_STATIC_THEME_COLOR, value)
.apply()
settingsActivity.recreate()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getInt(Settings.PREF_STATIC_THEME_COLOR, 0).toString()
override val defaultValue: Any = 0
}

add(
SingleChoiceSetting(
staticThemeColor,
R.string.static_theme_color,
R.string.static_theme_color_description,
R.array.staticThemeNames,
R.array.staticThemeValues
)
)
kleidis marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
Expand All @@ -28,6 +33,7 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.preference.PreferenceManager
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialFadeThrough
import io.github.lime3ds.android.LimeApplication
Expand All @@ -42,9 +48,12 @@ import io.github.lime3ds.android.ui.main.MainActivity
import io.github.lime3ds.android.utils.CitraDirectoryHelper
import io.github.lime3ds.android.utils.GameHelper
import io.github.lime3ds.android.utils.PermissionsHandler
import io.github.lime3ds.android.utils.ThemeUtil
import io.github.lime3ds.android.utils.ViewUtils
import io.github.lime3ds.android.viewmodel.GamesViewModel
import io.github.lime3ds.android.viewmodel.HomeViewModel
import com.google.android.material.materialswitch.MaterialSwitch


class SetupFragment : Fragment() {
private var _binding: FragmentSetupBinding? = null
Expand Down Expand Up @@ -258,6 +267,30 @@ class SetupFragment : Fragment() {
R.string.add_games_warning_help
)
)
add(
SetupPage(
R.drawable.ic_palette,
R.string.set_up_theme_settings,
R.string.setup_theme_settings_description,
0,
true,
R.string.setup_set_theme,
{
ThemeUtil.isDuringSetup = true
showStaticThemeSelectionDialog()
},
false,
false,
{
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
if (preferences.getBoolean("ThemeSetupCompleted", false)) {
StepState.STEP_COMPLETE
} else {
StepState.STEP_INCOMPLETE
}
}
)
)
kleidis marked this conversation as resolved.
Show resolved Hide resolved
add(
SetupPage(
R.drawable.ic_check,
Expand Down Expand Up @@ -370,6 +403,71 @@ class SetupFragment : Fragment() {
private lateinit var microphoneCallback: SetupCallback
private lateinit var cameraCallback: SetupCallback

private fun showStaticThemeSelectionDialog() {
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val themeColors = resources.getStringArray(R.array.staticThemeNames)
val currentThemeColor = preferences.getInt(Settings.PREF_STATIC_THEME_COLOR, 0)

MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.set_up_theme_settings)
.setSingleChoiceItems(themeColors, currentThemeColor) { _, which ->
preferences.edit().putInt(Settings.PREF_STATIC_THEME_COLOR, which).apply()
}
.setPositiveButton(android.R.string.ok) { _, _ ->
showMaterialYouAndBlackThemeDialog()
}
.setNegativeButton(android.R.string.cancel, null)
.show()
}

private fun showMaterialYouAndBlackThemeDialog() {
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val switchContainer = LinearLayout(requireContext()).apply {
orientation = LinearLayout.VERTICAL
setPadding(64, 16, 64, 32)
}

val blackThemeSwitch = MaterialSwitch(requireContext()).apply {
text = getString(R.string.use_black_backgrounds)
isChecked = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false)
}
val blackThemeDescription = TextView(requireContext()).apply {
text = getString(R.string.use_black_backgrounds_description)
}
switchContainer.addView(blackThemeSwitch)
switchContainer.addView(blackThemeDescription)

val materialYouSwitch = MaterialSwitch(requireContext()).apply {
text = getString(R.string.material_you)
isChecked = preferences.getBoolean(Settings.PREF_MATERIAL_YOU, false)
}
val materialYouDescription = TextView(requireContext()).apply {
text = getString(R.string.material_you_description)
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
switchContainer.addView(materialYouSwitch)
switchContainer.addView(materialYouDescription)
}

MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.set_up_theme_settings)
.setView(switchContainer)
.setPositiveButton(android.R.string.ok) { _, _ ->
preferences.edit().apply {
putBoolean(Settings.PREF_BLACK_BACKGROUNDS, blackThemeSwitch.isChecked)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
putBoolean(Settings.PREF_MATERIAL_YOU, materialYouSwitch.isChecked)
}
apply()
}
preferences.edit().putBoolean("ThemeSetupCompleted", true).apply()
requireActivity().recreate()
}
.setNegativeButton(android.R.string.cancel, null)
.show()
}

private val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
Expand Down Expand Up @@ -434,6 +532,7 @@ class SetupFragment : Fragment() {
preferences.edit()
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
.apply()
ThemeUtil.isDuringSetup = false
mainActivity.finishSetup(binding.root.findNavController())
}

Expand Down Expand Up @@ -478,4 +577,4 @@ class SetupFragment : Fragment() {
}
windowInsets
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
settingsViewModel.settings.loadSettings()
}

ThemeUtil.ThemeChangeListener(this)
ThemeUtil.setTheme(this)
super.onCreate(savedInstanceState)

Expand Down Expand Up @@ -340,4 +341,4 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
.build()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.preference.PreferenceManager
import io.github.lime3ds.android.LimeApplication
import io.github.lime3ds.android.R
Expand All @@ -25,12 +28,29 @@ object ThemeUtil {
private val preferences: SharedPreferences get() =
PreferenceManager.getDefaultSharedPreferences(LimeApplication.appContext)

private fun getSelectedStaticThemeColor(): Int {
val themeIndex = preferences.getInt(Settings.PREF_STATIC_THEME_COLOR, 0)
val themes = arrayOf(
R.style.Theme_Citra_Blue,
R.style.Theme_Citra_Cyan,
R.style.Theme_Citra_Red,
R.style.Theme_Citra_Green,
R.style.Theme_Citra_LimeGreen,
R.style.Theme_Citra_Yellow,
R.style.Theme_Citra_Orange,
R.style.Theme_Citra_Violet,
R.style.Theme_Citra_Pink,
R.style.Theme_Citra_Gray
)
return themes[themeIndex]
}

fun setTheme(activity: AppCompatActivity) {
setThemeMode(activity)
if (preferences.getBoolean(Settings.PREF_MATERIAL_YOU, false)) {
activity.setTheme(R.style.Theme_Lime_Main_MaterialYou)
} else {
activity.setTheme(R.style.Theme_Lime_Main)
activity.setTheme(getSelectedStaticThemeColor())
}

// Using a specific night mode check because this could apply incorrectly when using the
Expand Down Expand Up @@ -96,4 +116,23 @@ object ThemeUtil {
Color.blue(color)
)
}
}



// Track setup status in order to enable / disable listener
var isDuringSetup = false

// Listener that detects if the theme is being changed from the initial setup or from normal settings
// Without this the dual popup on the setup was getting cut off becuase the activity was being recreated
private var listener: SharedPreferences.OnSharedPreferenceChangeListener? = null

fun ThemeChangeListener(activity: AppCompatActivity) {
listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
val relevantKeys = listOf(Settings.PREF_STATIC_THEME_COLOR, Settings.PREF_MATERIAL_YOU, Settings.PREF_BLACK_BACKGROUNDS)
if (key in relevantKeys && !isDuringSetup) {
activity.recreate()
}
}
preferences.registerOnSharedPreferenceChangeListener(listener)
}
}
Loading
Loading