Developer quick setting for theming
Closes https://github.com/SchildiChat/SchildiChat-android/issues/117 Change-Id: Ie8fab9b7842e695b9e59a65d2cbf09c7edfd1dd8
This commit is contained in:
parent
226428e0ba
commit
3e58f2c254
|
@ -0,0 +1,62 @@
|
|||
package de.spiritcroc.menu
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
||||
object ArrayOptionsMenuHelper {
|
||||
private data class OptionsMenuMetadata(
|
||||
val menuId: Int,
|
||||
val entriesId: Int,
|
||||
val valuesId: Int,
|
||||
val values: HashMap<Int, String> = HashMap(),
|
||||
var action: (String) -> Boolean = { false }
|
||||
)
|
||||
|
||||
private val menuLookup = HashMap<Int, OptionsMenuMetadata>()
|
||||
|
||||
fun createSubmenu(resources: Resources,
|
||||
menuItem: MenuItem,
|
||||
groupId: Int,
|
||||
entriesId: Int,
|
||||
valuesId: Int,
|
||||
initialValue: String,
|
||||
sortFunction: (List<Pair<String, String>>) -> List<Pair<String, String>> = { it },
|
||||
action: (String) -> Boolean) {
|
||||
val menuId = menuItem.itemId
|
||||
var metadata = menuLookup[menuId]
|
||||
if (metadata == null || metadata.entriesId != entriesId || metadata.valuesId != valuesId) {
|
||||
metadata = OptionsMenuMetadata(menuId, entriesId, valuesId)
|
||||
menuLookup[menuId] = metadata
|
||||
}
|
||||
metadata.action = action
|
||||
|
||||
menuItem.subMenu.apply {
|
||||
clear()
|
||||
val themeEntries = resources.getStringArray(entriesId)
|
||||
val themeValues = resources.getStringArray(valuesId)
|
||||
sortFunction(themeEntries.zip(themeValues)).forEach { theme ->
|
||||
val itemId = View.generateViewId()
|
||||
val item = add(groupId, itemId, Menu.NONE, theme.first).apply {
|
||||
isCheckable = true
|
||||
}
|
||||
metadata.values[itemId] = theme.second
|
||||
if (initialValue == theme.second) {
|
||||
item.isChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleSubmenu(item: MenuItem, vararg menuIds: Int): Boolean {
|
||||
menuIds.forEach { menuId ->
|
||||
val metadata = menuLookup[menuId] ?: return@forEach
|
||||
val value = metadata.values[item.itemId] ?: return@forEach
|
||||
if (metadata.action(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -35,12 +35,14 @@ import com.airbnb.mvrx.Mavericks
|
|||
import com.airbnb.mvrx.viewModel
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import de.spiritcroc.menu.ArrayOptionsMenuHelper
|
||||
import im.vector.app.AppStateHandler
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.replaceFragment
|
||||
import im.vector.app.core.extensions.restart
|
||||
import im.vector.app.core.extensions.validateBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.pushers.PushersManager
|
||||
|
@ -536,6 +538,38 @@ class HomeActivity :
|
|||
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||
menu.findItem(R.id.menu_home_init_sync_legacy)?.isVisible = vectorPreferences.developerMode()
|
||||
menu.findItem(R.id.menu_home_init_sync_optimized)?.isVisible = vectorPreferences.developerMode()
|
||||
menu.findItem(R.id.dev_theming)?.isVisible = vectorPreferences.developerMode()
|
||||
|
||||
// Base theme setting
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_base_theme),
|
||||
R.id.dev_base_theme_group,
|
||||
R.array.theme_entries,
|
||||
R.array.theme_values,
|
||||
ThemeUtils.getCurrentActiveTheme(this)
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveTheme(this, value)
|
||||
restart()
|
||||
true
|
||||
}
|
||||
|
||||
// Accent color theme setting
|
||||
val isLightTheme = ThemeUtils.isLightTheme(this)
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_theme_accent),
|
||||
R.id.dev_theme_accent_group,
|
||||
if (isLightTheme) R.array.sc_accent_color_light_entries else R.array.sc_accent_color_dark_entries,
|
||||
if (isLightTheme) R.array.sc_accent_color_light_values else R.array.sc_accent_color_dark_values,
|
||||
ThemeUtils.getCurrentActiveThemeAccent(this),
|
||||
sortFunction = { list -> list.sortedBy { it.first } }
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveThemeAccent(this, value)
|
||||
restart()
|
||||
true
|
||||
}
|
||||
|
||||
return super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
|
@ -575,7 +609,10 @@ class HomeActivity :
|
|||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
return ArrayOptionsMenuHelper.handleSubmenu(item,
|
||||
R.id.dev_base_theme,
|
||||
R.id.dev_theme_accent
|
||||
) || super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
|
|
|
@ -73,6 +73,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import com.vanniktech.emoji.EmojiPopup
|
||||
import de.spiritcroc.matrixsdk.util.DbgUtil
|
||||
import de.spiritcroc.matrixsdk.util.Dimber
|
||||
import de.spiritcroc.menu.ArrayOptionsMenuHelper
|
||||
import de.spiritcroc.recyclerview.StickyHeaderItemDecoration
|
||||
import de.spiritcroc.recyclerview.widget.BetterLinearLayoutManager
|
||||
import de.spiritcroc.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -85,6 +86,7 @@ import im.vector.app.core.epoxy.LayoutManagerStateRestorer
|
|||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.registerStartForActivityResult
|
||||
import im.vector.app.core.extensions.restart
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.core.extensions.showKeyboard
|
||||
import im.vector.app.core.extensions.trackItemsVisibilityChange
|
||||
|
@ -1165,18 +1167,68 @@ class TimelineFragment @Inject constructor(
|
|||
updateMenuThreadNotificationBadge(menu, state)
|
||||
}
|
||||
|
||||
// Selected bubble style
|
||||
val selectedBubbleStyle = when (bubbleThemeUtils.getBubbleStyle()) {
|
||||
BubbleThemeUtils.BUBBLE_STYLE_NONE -> R.id.dev_bubble_style_none
|
||||
BubbleThemeUtils.BUBBLE_STYLE_START -> R.id.dev_bubble_style_start
|
||||
BubbleThemeUtils.BUBBLE_STYLE_BOTH -> R.id.dev_bubble_style_both
|
||||
BubbleThemeUtils.BUBBLE_STYLE_ELEMENT -> R.id.dev_bubble_style_element
|
||||
else -> R.id.dev_bubble_style_both
|
||||
}
|
||||
menu.findItem(selectedBubbleStyle).isChecked = true
|
||||
|
||||
// Hidden events
|
||||
menu.findItem(R.id.dev_hidden_events).isChecked = vectorPreferences.shouldShowHiddenEvents()
|
||||
|
||||
// Bubble style
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_bubble_style),
|
||||
R.id.dev_bubble_style_group,
|
||||
R.array.bubble_style_entries,
|
||||
R.array.bubble_style_values,
|
||||
bubbleThemeUtils.getBubbleStyle()
|
||||
) { value ->
|
||||
if (value != bubbleThemeUtils.getBubbleStyle()) {
|
||||
bubbleThemeUtils.setBubbleStyle(value)
|
||||
requireActivity().restart()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// Base theme setting
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_base_theme),
|
||||
R.id.dev_base_theme_group,
|
||||
R.array.theme_entries,
|
||||
R.array.theme_values,
|
||||
ThemeUtils.getCurrentActiveTheme(requireContext())
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveTheme(requireContext(), value)
|
||||
requireActivity().restart()
|
||||
true
|
||||
}
|
||||
|
||||
// Accent color theme setting
|
||||
val isLightTheme = ThemeUtils.isLightTheme(requireContext())
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_theme_accent),
|
||||
R.id.dev_theme_accent_group,
|
||||
if (isLightTheme) R.array.sc_accent_color_light_entries else R.array.sc_accent_color_dark_entries,
|
||||
if (isLightTheme) R.array.sc_accent_color_light_values else R.array.sc_accent_color_dark_values,
|
||||
ThemeUtils.getCurrentActiveThemeAccent(requireContext()),
|
||||
sortFunction = { list -> list.sortedBy { it.first } }
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveThemeAccent(requireContext(), value)
|
||||
requireActivity().restart()
|
||||
true
|
||||
}
|
||||
|
||||
// Bubble corner radius
|
||||
ArrayOptionsMenuHelper.createSubmenu(
|
||||
resources,
|
||||
menu.findItem(R.id.dev_bubble_rounded_corners),
|
||||
R.id.dev_bubble_rounded_corners_group,
|
||||
R.array.bubble_appearance_roundness_entries,
|
||||
R.array.bubble_appearance_roundness_values,
|
||||
bubbleThemeUtils.getBubbleRoundnessSetting()
|
||||
) { value ->
|
||||
bubbleThemeUtils.setBubbleRoundnessSetting(value)
|
||||
reloadTimeline()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
@ -1209,22 +1261,6 @@ class TimelineFragment @Inject constructor(
|
|||
navigator.openRoomProfile(requireActivity(), timelineArgs.roomId)
|
||||
true
|
||||
}
|
||||
R.id.dev_bubble_style_none -> {
|
||||
handleSetBubbleStyle(BubbleThemeUtils.BUBBLE_STYLE_NONE)
|
||||
true
|
||||
}
|
||||
R.id.dev_bubble_style_start -> {
|
||||
handleSetBubbleStyle(BubbleThemeUtils.BUBBLE_STYLE_START)
|
||||
true
|
||||
}
|
||||
R.id.dev_bubble_style_both -> {
|
||||
handleSetBubbleStyle(BubbleThemeUtils.BUBBLE_STYLE_BOTH)
|
||||
true
|
||||
}
|
||||
R.id.dev_bubble_style_element -> {
|
||||
handleSetBubbleStyle(BubbleThemeUtils.BUBBLE_STYLE_ELEMENT)
|
||||
true
|
||||
}
|
||||
R.id.dev_hidden_events -> {
|
||||
val shouldShow = !item.isChecked
|
||||
vectorPreferences.setShouldShowHiddenEvents(shouldShow)
|
||||
|
@ -1263,7 +1299,12 @@ class TimelineFragment @Inject constructor(
|
|||
}
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
else -> ArrayOptionsMenuHelper.handleSubmenu(item,
|
||||
R.id.dev_base_theme,
|
||||
R.id.dev_bubble_style,
|
||||
R.id.dev_theme_accent,
|
||||
R.id.dev_bubble_rounded_corners
|
||||
) || super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2851,13 +2892,6 @@ class TimelineFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleSetBubbleStyle(bubbleStyle: String) {
|
||||
if (bubbleStyle != bubbleThemeUtils.getBubbleStyle()) {
|
||||
bubbleThemeUtils.setBubbleStyle(bubbleStyle)
|
||||
requireActivity().recreate()
|
||||
}
|
||||
}
|
||||
|
||||
// AttachmentsHelper.Callback
|
||||
override fun onContentAttachmentsReady(attachments: List<ContentAttachmentData>) {
|
||||
val grouped = attachments.toGroupedContentAttachmentData()
|
||||
|
|
|
@ -785,6 +785,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
R.id.show_participants -> true // SC
|
||||
R.id.dev_bubble_style, // SC
|
||||
R.id.dev_hidden_events, // SC
|
||||
R.id.dev_theming, // SC
|
||||
R.id.dev_tools -> vectorPreferences.developerMode()
|
||||
else -> false
|
||||
}
|
||||
|
|
|
@ -72,9 +72,18 @@ class BubbleThemeUtils @Inject constructor(private val context: Context) {
|
|||
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(BUBBLE_STYLE_KEY, value).apply()
|
||||
}
|
||||
|
||||
fun getBubbleRoundnessSetting(): String {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getString(BUBBLE_ROUNDNESS_KEY, BUBBLE_ROUNDNESS_DEFAULT) ?: BUBBLE_ROUNDNESS_DEFAULT
|
||||
}
|
||||
|
||||
fun setBubbleRoundnessSetting(value: String) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(BUBBLE_ROUNDNESS_KEY, value).apply()
|
||||
}
|
||||
|
||||
fun getBubbleAppearance(): ScBubbleAppearance {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val baseAppearance = when (prefs.getString(BUBBLE_ROUNDNESS_KEY, BUBBLE_ROUNDNESS_DEFAULT)) {
|
||||
val baseAppearance = when (getBubbleRoundnessSetting()) {
|
||||
BUBBLE_ROUNDNESS_R1 -> r1ScBubbleAppearance
|
||||
BUBBLE_ROUNDNESS_R2 -> r2ScBubbleAppearance
|
||||
else -> defaultScBubbleAppearance
|
||||
|
|
|
@ -273,6 +273,52 @@ object ThemeUtils {
|
|||
mColorByAttr.clear()
|
||||
}
|
||||
|
||||
// For developer quick options
|
||||
fun setCurrentActiveTheme(context: Context, theme: String) {
|
||||
var darkTheme = getApplicationDarkTheme(context)
|
||||
var lightTheme = getApplicationLightTheme(context)
|
||||
val darkAccent = getApplicationDarkThemeAccent(context)
|
||||
val lightAccent = getApplicationLightThemeAccent(context)
|
||||
if (useDarkTheme(context)) {
|
||||
darkTheme = theme
|
||||
} else {
|
||||
lightTheme = theme
|
||||
}
|
||||
setApplicationTheme(context, lightTheme, darkTheme, lightAccent, darkAccent)
|
||||
}
|
||||
|
||||
// For developer quick options
|
||||
fun getCurrentActiveTheme(context: Context): String {
|
||||
return if (useDarkTheme(context)) {
|
||||
getApplicationDarkTheme(context)
|
||||
} else {
|
||||
getApplicationLightTheme(context)
|
||||
}
|
||||
}
|
||||
|
||||
// For developer quick options
|
||||
fun setCurrentActiveThemeAccent(context: Context, accent: String) {
|
||||
val darkTheme = getApplicationDarkTheme(context)
|
||||
val lightTheme = getApplicationLightTheme(context)
|
||||
var darkAccent = getApplicationDarkThemeAccent(context)
|
||||
var lightAccent = getApplicationLightThemeAccent(context)
|
||||
if (useDarkTheme(context)) {
|
||||
darkAccent = accent
|
||||
} else {
|
||||
lightAccent = accent
|
||||
}
|
||||
setApplicationTheme(context, lightTheme, darkTheme, lightAccent, darkAccent)
|
||||
}
|
||||
|
||||
// For developer quick options
|
||||
fun getCurrentActiveThemeAccent(context: Context): String {
|
||||
return if (useDarkTheme(context)) {
|
||||
getApplicationDarkThemeAccent(context)
|
||||
} else {
|
||||
getApplicationLightThemeAccent(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun setApplicationLightTheme(context: Context, theme: String) {
|
||||
setApplicationTheme(context, theme, getApplicationDarkTheme(context),
|
||||
getApplicationLightThemeAccent(context), getApplicationDarkThemeAccent(context))
|
||||
|
|
|
@ -38,4 +38,36 @@
|
|||
app:iconTint="?vctr_content_secondary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/dev_theming"
|
||||
android:title="@string/settings_theme"
|
||||
android:visible="false"
|
||||
tools:visible="true"
|
||||
app:showAsAction="never">
|
||||
<menu>
|
||||
<group>
|
||||
<item
|
||||
android:id="@+id/dev_base_theme"
|
||||
android:title="@string/settings_theme">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/dev_base_theme_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/dev_theme_accent"
|
||||
android:title="@string/setting_sc_accent_color">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/dev_theme_accent_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -90,22 +90,52 @@
|
|||
android:visible="false"
|
||||
app:showAsAction="never"
|
||||
tools:visible="true">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:checkableBehavior="single">
|
||||
android:id="@+id/dev_bubble_style_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/dev_theming"
|
||||
android:title="@string/settings_theme"
|
||||
android:visible="false"
|
||||
tools:visible="true"
|
||||
app:showAsAction="never">
|
||||
<menu>
|
||||
<group>
|
||||
<item
|
||||
android:id="@+id/dev_bubble_style_both"
|
||||
android:title="@string/bubble_style_both"
|
||||
android:checked="true" />
|
||||
android:id="@+id/dev_base_theme"
|
||||
android:title="@string/settings_theme">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/dev_base_theme_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/dev_bubble_style_start"
|
||||
android:title="@string/bubble_style_start" />
|
||||
android:id="@+id/dev_theme_accent"
|
||||
android:title="@string/setting_sc_accent_color">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/dev_theme_accent_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/dev_bubble_style_element"
|
||||
android:title="@string/bubble_style_element" />
|
||||
<item
|
||||
android:id="@+id/dev_bubble_style_none"
|
||||
android:title="@string/bubble_style_none" />
|
||||
android:id="@+id/dev_bubble_rounded_corners"
|
||||
android:title="@string/bubble_rounded_corners">
|
||||
<!-- Programmatically inflated menu -->
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/dev_bubble_rounded_corners_group"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
</item>
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
<string name="settings_advanced_theme_settings">Advanced theme settings</string>
|
||||
<string name="settings_user_colors">User colors</string>
|
||||
<string name="settings_theme_colors">Theme colors</string>
|
||||
<string name="setting_sc_accent_color">Accent color</string>
|
||||
<string name="setting_sc_accent_color_light">Accent color for light themes</string>
|
||||
<string name="setting_sc_accent_color_dark">Accent color for dark themes</string>
|
||||
<string name="settings_sc_accent_disclaimer">Note that these color settings only apply to SC themes, and not Element themes.</string>
|
||||
|
|
Loading…
Reference in New Issue