Skip to content

Commit cdbf075

Browse files
committed
Add support for custom secondary and tertiary colors (closes #45)
Available in Settings > 3 dot menu > Advanced
1 parent 40fc25e commit cdbf075

File tree

13 files changed

+319
-49
lines changed

13 files changed

+319
-49
lines changed

app/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,6 @@ dependencies {
9898
implementation(libs.recyclerview)
9999
implementation(libs.recyclerview.selection)
100100
implementation(libs.blurView)
101+
implementation(libs.lifecycle.common.jvm)
101102
annotationProcessor(libs.glide.compiler)
102103
}

app/src/main/java/com/drdisagree/colorblendr/common/Const.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ object Const {
2424
const val MONET_BACKGROUND_LIGHTNESS: String = "monetBackgroundLightnessValue"
2525
const val MONET_ACCURATE_SHADES: String = "monetAccurateShades"
2626
const val MONET_PITCH_BLACK_THEME: String = "monetPitchBlackTheme"
27-
const val MONET_SEED_COLOR: String = "monetSeedColor"
2827
const val MONET_SEED_COLOR_ENABLED: String = "monetSeedColorEnabled"
28+
const val MONET_SEED_COLOR: String = "monetSeedColor"
29+
const val MONET_SECONDARY_COLOR: String = "monetSecondaryColor"
30+
const val MONET_TERTIARY_COLOR: String = "monetTertiaryColor"
2931
const val MANUAL_OVERRIDE_COLORS: String = "manualOverrideColors"
3032
const val MONET_LAST_UPDATED: String = "monetLastUpdated"
3133
const val MONET_STYLE_ORIGINAL_NAME: String = "monetStyleOriginalName"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.drdisagree.colorblendr.ui.fragments
2+
3+
import android.graphics.Color
4+
import android.os.Bundle
5+
import android.view.LayoutInflater
6+
import android.view.MenuItem
7+
import android.view.View
8+
import android.view.ViewGroup
9+
import androidx.fragment.app.Fragment
10+
import androidx.lifecycle.ViewModelProvider
11+
import com.drdisagree.colorblendr.R
12+
import com.drdisagree.colorblendr.common.Const
13+
import com.drdisagree.colorblendr.common.Const.MONET_LAST_UPDATED
14+
import com.drdisagree.colorblendr.common.Const.MONET_SECONDARY_COLOR
15+
import com.drdisagree.colorblendr.common.Const.MONET_SEED_COLOR_ENABLED
16+
import com.drdisagree.colorblendr.common.Const.MONET_TERTIARY_COLOR
17+
import com.drdisagree.colorblendr.common.Const.workingMethod
18+
import com.drdisagree.colorblendr.config.RPrefs.getBoolean
19+
import com.drdisagree.colorblendr.config.RPrefs.getInt
20+
import com.drdisagree.colorblendr.config.RPrefs.putInt
21+
import com.drdisagree.colorblendr.config.RPrefs.putLong
22+
import com.drdisagree.colorblendr.databinding.FragmentSettingsAdvancedBinding
23+
import com.drdisagree.colorblendr.ui.viewmodels.SharedViewModel
24+
import com.drdisagree.colorblendr.utils.MiscUtil.setToolbarTitle
25+
import com.drdisagree.colorblendr.utils.OverlayManager.applyFabricatedColors
26+
import kotlinx.coroutines.CoroutineScope
27+
import kotlinx.coroutines.Dispatchers
28+
import kotlinx.coroutines.delay
29+
import kotlinx.coroutines.launch
30+
import kotlinx.coroutines.withContext
31+
import me.jfenn.colorpickerdialog.dialogs.ColorPickerDialog
32+
import me.jfenn.colorpickerdialog.views.picker.ImagePickerView
33+
34+
class SettingsAdvancedFragment : Fragment() {
35+
36+
private lateinit var binding: FragmentSettingsAdvancedBinding
37+
private var sharedViewModel: SharedViewModel? = null
38+
private val notShizukuMode: Boolean = workingMethod != Const.WorkMethod.SHIZUKU
39+
40+
override fun onCreate(savedInstanceState: Bundle?) {
41+
super.onCreate(savedInstanceState)
42+
43+
sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java]
44+
}
45+
46+
override fun onCreateView(
47+
inflater: LayoutInflater,
48+
container: ViewGroup?,
49+
savedInstanceState: Bundle?
50+
): View {
51+
binding = FragmentSettingsAdvancedBinding.inflate(inflater, container, false)
52+
53+
setToolbarTitle(requireContext(), R.string.advanced_settings, true, binding.header.toolbar)
54+
55+
// Secondary color
56+
var monetSecondaryColor = getInt(MONET_SECONDARY_COLOR, Color.WHITE)
57+
binding.secondaryColorPicker.isEnabled =
58+
getBoolean(MONET_SEED_COLOR_ENABLED, false) && notShizukuMode
59+
binding.secondaryColorPicker.previewColor =
60+
getInt(MONET_SECONDARY_COLOR, monetSecondaryColor)
61+
binding.secondaryColorPicker.setOnClickListener {
62+
ColorPickerDialog()
63+
.withCornerRadius(10f)
64+
.withColor(monetSecondaryColor)
65+
.withAlphaEnabled(false)
66+
.withPicker(ImagePickerView::class.java)
67+
.withListener { _: ColorPickerDialog?, color: Int ->
68+
if (monetSecondaryColor != color) {
69+
monetSecondaryColor = color
70+
binding.secondaryColorPicker.previewColor = color
71+
putInt(MONET_SECONDARY_COLOR, monetSecondaryColor)
72+
73+
applyFabricatedColors()
74+
}
75+
}
76+
.show(getChildFragmentManager(), "secondaryColorPicker")
77+
}
78+
79+
// Tertiary color
80+
var monetTertiaryColor = getInt(MONET_TERTIARY_COLOR, Color.WHITE)
81+
binding.tertiaryColorPicker.isEnabled =
82+
getBoolean(MONET_SEED_COLOR_ENABLED, false) && notShizukuMode
83+
binding.tertiaryColorPicker.previewColor = monetTertiaryColor
84+
binding.tertiaryColorPicker.setOnClickListener {
85+
ColorPickerDialog()
86+
.withCornerRadius(10f)
87+
.withColor(monetTertiaryColor)
88+
.withAlphaEnabled(false)
89+
.withPicker(ImagePickerView::class.java)
90+
.withListener { _: ColorPickerDialog?, color: Int ->
91+
if (monetTertiaryColor != color) {
92+
monetTertiaryColor = color
93+
binding.tertiaryColorPicker.previewColor = color
94+
putInt(MONET_TERTIARY_COLOR, monetTertiaryColor)
95+
96+
applyFabricatedColors()
97+
}
98+
}
99+
.show(getChildFragmentManager(), "tertiaryColorPicker")
100+
}
101+
102+
return binding.getRoot()
103+
}
104+
105+
@Suppress("DEPRECATION")
106+
@Deprecated("Deprecated in Java")
107+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
108+
if (item.itemId == android.R.id.home) {
109+
getParentFragmentManager().popBackStackImmediate()
110+
return true
111+
}
112+
return super.onOptionsItemSelected(item)
113+
}
114+
115+
private fun applyFabricatedColors() {
116+
CoroutineScope(Dispatchers.Main).launch {
117+
putLong(MONET_LAST_UPDATED, System.currentTimeMillis())
118+
delay(300)
119+
withContext(Dispatchers.IO) {
120+
try {
121+
applyFabricatedColors(requireContext())
122+
} catch (ignored: Exception) {
123+
}
124+
}
125+
}
126+
}
127+
128+
companion object {
129+
private val TAG: String = SettingsAdvancedFragment::class.java.simpleName
130+
}
131+
}

app/src/main/java/com/drdisagree/colorblendr/ui/fragments/SettingsFragment.kt

+40-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import android.content.Intent
88
import android.os.Bundle
99
import android.util.Log
1010
import android.view.LayoutInflater
11+
import android.view.Menu
12+
import android.view.MenuInflater
1113
import android.view.MenuItem
1214
import android.view.View
1315
import android.view.ViewGroup
@@ -16,7 +18,10 @@ import android.widget.Toast
1618
import androidx.activity.result.ActivityResult
1719
import androidx.activity.result.ActivityResultLauncher
1820
import androidx.activity.result.contract.ActivityResultContracts
21+
import androidx.core.view.MenuHost
22+
import androidx.core.view.MenuProvider
1923
import androidx.fragment.app.Fragment
24+
import androidx.lifecycle.Lifecycle
2025
import androidx.lifecycle.ViewModelProvider
2126
import com.drdisagree.colorblendr.ColorBlendr.Companion.appContext
2227
import com.drdisagree.colorblendr.R
@@ -108,6 +113,12 @@ class SettingsFragment : Fragment() {
108113
}
109114
}
110115

116+
override fun onCreate(savedInstanceState: Bundle?) {
117+
super.onCreate(savedInstanceState)
118+
119+
sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java]
120+
}
121+
111122
override fun onCreateView(
112123
inflater: LayoutInflater,
113124
container: ViewGroup?,
@@ -235,17 +246,38 @@ class SettingsFragment : Fragment() {
235246
return binding.getRoot()
236247
}
237248

238-
override fun onCreate(savedInstanceState: Bundle?) {
239-
super.onCreate(savedInstanceState)
249+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
250+
super.onViewCreated(view, savedInstanceState)
240251

241-
sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java]
252+
val menuHost: MenuHost = requireActivity()
253+
menuHost.addMenuProvider(object : MenuProvider {
254+
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
255+
menu.clear()
256+
menuInflater.inflate(R.menu.settings_menu, menu)
257+
}
258+
259+
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
260+
return when (menuItem.itemId) {
261+
R.id.advanced_settings -> {
262+
HomeFragment.replaceFragment(
263+
SettingsAdvancedFragment()
264+
)
265+
true
266+
}
267+
268+
else -> {
269+
false
270+
}
271+
}
272+
}
273+
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
242274
}
243275

244276
private fun crossfade(view: View) {
245277
try {
246278
val animTime: Int = resources.getInteger(android.R.integer.config_mediumAnimTime)
247279
if (view.visibility == View.GONE) {
248-
view.setAlpha(0f)
280+
view.alpha = 0f
249281
view.visibility = View.VISIBLE
250282
view.animate()
251283
.alpha(1f)
@@ -259,7 +291,7 @@ class SettingsFragment : Fragment() {
259291
override fun onAnimationEnd(animation: Animator) {
260292
super.onAnimationEnd(animation)
261293
try {
262-
view.setAlpha(0f)
294+
view.alpha = 0f
263295
view.visibility = View.GONE
264296
} catch (ignored: Exception) {
265297
}
@@ -272,8 +304,8 @@ class SettingsFragment : Fragment() {
272304

273305
private fun backupRestoreSettings(isBackingUp: Boolean) {
274306
val fileIntent = Intent().apply {
275-
setAction(if (isBackingUp) Intent.ACTION_CREATE_DOCUMENT else Intent.ACTION_GET_CONTENT)
276-
setType("*/*")
307+
action = if (isBackingUp) Intent.ACTION_CREATE_DOCUMENT else Intent.ACTION_GET_CONTENT
308+
type = "*/*"
277309
putExtra(Intent.EXTRA_TITLE, "theme_config" + ".colorblendr")
278310
}
279311
if (isBackingUp) {
@@ -416,7 +448,7 @@ class SettingsFragment : Fragment() {
416448
}
417449

418450
companion object {
419-
private val TAG: String = SettingsFragment::class.java.getSimpleName()
451+
private val TAG: String = SettingsFragment::class.java.simpleName
420452
private val colorNames: Array<Array<String>> = ColorUtil.colorNames
421453

422454
fun clearCustomColors() {

app/src/main/java/com/drdisagree/colorblendr/ui/widgets/ColorPickerWidget.kt

+28-24
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class ColorPickerWidget : RelativeLayout {
7070
}
7171

7272
if (!iconSpaceReserved) {
73-
iconImageView!!.setVisibility(GONE)
73+
iconImageView!!.visibility = GONE
7474
}
7575

7676
if (colorResId != Int.MIN_VALUE) {
@@ -88,24 +88,28 @@ class ColorPickerWidget : RelativeLayout {
8888

8989
fun setSummary(summaryResId: Int) {
9090
summaryTextView!!.setText(summaryResId)
91+
92+
summaryTextView!!.visibility = if (summaryResId == 0) GONE else VISIBLE
9193
}
9294

9395
fun setSummary(summary: String?) {
9496
summaryTextView!!.text = summary
97+
98+
summaryTextView!!.visibility = if (summary == null) GONE else VISIBLE
9599
}
96100

97101
fun setIcon(icon: Int) {
98102
iconImageView!!.setImageResource(icon)
99-
iconImageView!!.setVisibility(VISIBLE)
103+
iconImageView!!.visibility = VISIBLE
100104
}
101105

102106
fun setIcon(drawable: Drawable?) {
103107
iconImageView!!.setImageDrawable(drawable)
104-
iconImageView!!.setVisibility(VISIBLE)
108+
iconImageView!!.visibility = VISIBLE
105109
}
106110

107111
fun setIconVisibility(visibility: Int) {
108-
iconImageView!!.setVisibility(visibility)
112+
iconImageView!!.visibility = visibility
109113
}
110114

111115
@get:ColorInt
@@ -129,7 +133,7 @@ class ColorPickerWidget : RelativeLayout {
129133
GradientDrawable.Orientation.LEFT_RIGHT,
130134
intArrayOf(colorTemp, colorTemp)
131135
)
132-
drawable.setShape(GradientDrawable.OVAL)
136+
drawable.shape = GradientDrawable.OVAL
133137
colorView!!.background = drawable
134138
}
135139

@@ -145,25 +149,25 @@ class ColorPickerWidget : RelativeLayout {
145149
val color: Int = a.getColor(0, 0)
146150
a.recycle()
147151

148-
iconImageView!!.setImageTintList(ColorStateList.valueOf(color))
152+
iconImageView!!.imageTintList = ColorStateList.valueOf(color)
149153

150-
titleTextView!!.setAlpha(1.0f)
151-
summaryTextView!!.setAlpha(0.8f)
154+
titleTextView!!.alpha = 1.0f
155+
summaryTextView!!.alpha = 0.8f
152156
} else {
153157
if (isDarkMode) {
154-
iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.DKGRAY))
158+
iconImageView!!.imageTintList = ColorStateList.valueOf(Color.DKGRAY)
155159
} else {
156-
iconImageView!!.setImageTintList(ColorStateList.valueOf(Color.LTGRAY))
160+
iconImageView!!.imageTintList = ColorStateList.valueOf(Color.LTGRAY)
157161
}
158162

159-
titleTextView!!.setAlpha(0.6f)
160-
summaryTextView!!.setAlpha(0.4f)
163+
titleTextView!!.alpha = 0.6f
164+
summaryTextView!!.alpha = 0.4f
161165
}
162166

163-
container!!.setEnabled(enabled)
164-
titleTextView!!.setEnabled(enabled)
165-
summaryTextView!!.setEnabled(enabled)
166-
iconImageView!!.setEnabled(enabled)
167+
container!!.isEnabled = enabled
168+
titleTextView!!.isEnabled = enabled
169+
summaryTextView!!.isEnabled = enabled
170+
iconImageView!!.isEnabled = enabled
167171
previewColor = if (enabled) previewColor else Color.GRAY
168172
}
169173

@@ -175,17 +179,17 @@ class ColorPickerWidget : RelativeLayout {
175179
summaryTextView = findViewById(R.id.summary)
176180
colorView = findViewById(R.id.color_widget)
177181

178-
container!!.setId(generateViewId())
179-
iconImageView!!.setId(generateViewId())
180-
titleTextView!!.setId(generateViewId())
181-
summaryTextView!!.setId(generateViewId())
182-
colorView!!.setId(generateViewId())
182+
container!!.id = generateViewId()
183+
iconImageView!!.id = generateViewId()
184+
titleTextView!!.id = generateViewId()
185+
summaryTextView!!.id = generateViewId()
186+
colorView!!.id = generateViewId()
183187

184-
val layoutParams: LayoutParams =
185-
findViewById<View>(R.id.text_container).layoutParams as LayoutParams
188+
val textContainer = findViewById<View>(R.id.text_container)
189+
val layoutParams: LayoutParams = textContainer.layoutParams as LayoutParams
186190
layoutParams.addRule(START_OF, colorView!!.id)
187191
layoutParams.addRule(END_OF, iconImageView!!.id)
188-
findViewById<View>(R.id.text_container).setLayoutParams(layoutParams)
192+
textContainer.layoutParams = layoutParams
189193
}
190194

191195
override fun setOnClickListener(l: OnClickListener?) {

0 commit comments

Comments
 (0)