feat(Zinnia): refactor and add like, a bunch of stuff
- refactor: move colour utilities to APCAUtil, for sharing with settings preview - feat: speaking of which, a nice preview in settings!! featuring hsv bars for all your previewing needs - feat: changed apca threshold to 45, I found this to be nicer than 75 - feat: added transparency option, alongside "unchanged" colour option which pairs nicely together for a translucent glass effect
This commit is contained in:
parent
bc4aa09fff
commit
e0b86e0fb4
3 changed files with 271 additions and 121 deletions
|
|
@ -0,0 +1,105 @@
|
||||||
|
package moe.lava.awoocord.zinnia
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.GradientDrawable
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.graphics.ColorUtils
|
||||||
|
import com.aliucord.utils.DimenUtils.dp
|
||||||
|
import com.discord.stores.StoreStream
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
internal object APCAUtil {
|
||||||
|
private val settings = ZinniaSettings
|
||||||
|
|
||||||
|
internal fun configureOn(view: TextView, colour: Int?) {
|
||||||
|
when (settings.mode) {
|
||||||
|
Mode.Block -> configureBlock(view, colour ?: Color.BLACK)
|
||||||
|
Mode.RoleDot -> configureRoleDot(view, colour ?: Color.BLACK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureRoleDot(view: TextView, colour: Int) { }
|
||||||
|
|
||||||
|
private fun configureBlock(view: TextView, colourP: Int) {
|
||||||
|
val isLight = StoreStream.getUserSettingsSystem().theme == "light"
|
||||||
|
var colour = colourP
|
||||||
|
val bcol = GradientDrawable()
|
||||||
|
bcol.cornerRadius = 4.dp.toFloat()
|
||||||
|
view.background = bcol
|
||||||
|
|
||||||
|
if (colour == Color.BLACK) {
|
||||||
|
if (settings.blockAlsoDefault) {
|
||||||
|
colour = if (isLight && !settings.blockInverted) Color.WHITE else Color.BLACK
|
||||||
|
} else {
|
||||||
|
view.background = null
|
||||||
|
view.setPadding(0, 0, 0, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.setPadding(4.dp, 0, 4.dp, 0)
|
||||||
|
|
||||||
|
var (preferred, other) = if (isLight) {
|
||||||
|
Color.WHITE to Color.BLACK
|
||||||
|
} else {
|
||||||
|
Color.BLACK to Color.WHITE
|
||||||
|
}
|
||||||
|
when (settings.blockMode) {
|
||||||
|
BlockMode.InvertedThemeOnly -> preferred = other
|
||||||
|
BlockMode.WhiteOnly -> preferred = Color.WHITE
|
||||||
|
BlockMode.BlackOnly -> preferred = Color.BLACK
|
||||||
|
BlockMode.Unchanged -> preferred = colourP
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
val colours = if (!settings.blockInverted) {
|
||||||
|
Colours(
|
||||||
|
fgP = preferred,
|
||||||
|
fgO = other,
|
||||||
|
bgP = colour,
|
||||||
|
bgO = colour,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Colours(
|
||||||
|
fgP = colour,
|
||||||
|
fgO = colour,
|
||||||
|
bgP = preferred,
|
||||||
|
bgO = other,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val usePreferred = when (settings.blockMode) {
|
||||||
|
BlockMode.ApcaOnly -> isApca(colours)
|
||||||
|
BlockMode.WcagOnly -> isWcag(colours)
|
||||||
|
BlockMode.ApcaLightWcagDark -> if (isLight) isApca(colours) else isWcag(colours)
|
||||||
|
BlockMode.WcagLightApcaDark -> if (isLight) isWcag(colours) else isApca(colours)
|
||||||
|
BlockMode.ThemeOnly,
|
||||||
|
BlockMode.InvertedThemeOnly,
|
||||||
|
BlockMode.WhiteOnly,
|
||||||
|
BlockMode.BlackOnly,
|
||||||
|
BlockMode.Unchanged -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usePreferred) {
|
||||||
|
view.setTextColor(colours.fgP)
|
||||||
|
bcol.setColor(ColorUtils.setAlphaComponent(colours.bgP, settings.alpha))
|
||||||
|
bcol.alpha = settings.alpha
|
||||||
|
} else {
|
||||||
|
view.setTextColor(colours.fgO)
|
||||||
|
bcol.setColor(ColorUtils.setAlphaComponent(colours.bgO, settings.alpha))
|
||||||
|
bcol.alpha = settings.alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isApca(c: Colours): Boolean {
|
||||||
|
val cPref = abs(APCA.contrast(c.fgP, c.bgP))
|
||||||
|
val cOth = abs(APCA.contrast(c.fgO, c.bgO))
|
||||||
|
return cPref > settings.blockApcaThreshold || cPref > cOth
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWcag(c: Colours): Boolean {
|
||||||
|
val cPref = ColorUtils.calculateContrast(c.fgP, c.bgP)
|
||||||
|
val cOth = ColorUtils.calculateContrast(c.fgO, c.bgO)
|
||||||
|
return cPref > settings.blockWcagThreshold || cPref > cOth
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
package moe.lava.awoocord.zinnia
|
package moe.lava.awoocord.zinnia
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.graphics.ColorUtils
|
|
||||||
import com.aliucord.annotations.AliucordPlugin
|
import com.aliucord.annotations.AliucordPlugin
|
||||||
import com.aliucord.entities.Plugin
|
import com.aliucord.entities.Plugin
|
||||||
import com.aliucord.patcher.*
|
import com.aliucord.patcher.after
|
||||||
|
import com.aliucord.patcher.component1
|
||||||
|
import com.aliucord.patcher.component2
|
||||||
|
import com.aliucord.patcher.component3
|
||||||
import com.aliucord.utils.DimenUtils.dp
|
import com.aliucord.utils.DimenUtils.dp
|
||||||
import com.aliucord.utils.ViewUtils.findViewById
|
import com.aliucord.utils.ViewUtils.findViewById
|
||||||
import com.aliucord.utils.accessField
|
import com.aliucord.utils.accessField
|
||||||
import com.discord.databinding.WidgetChannelMembersListItemUserBinding
|
import com.discord.databinding.WidgetChannelMembersListItemUserBinding
|
||||||
import com.discord.stores.StoreStream
|
|
||||||
import com.discord.widgets.channels.memberlist.adapter.ChannelMembersListAdapter
|
import com.discord.widgets.channels.memberlist.adapter.ChannelMembersListAdapter
|
||||||
import com.discord.widgets.channels.memberlist.adapter.ChannelMembersListViewHolderMember
|
import com.discord.widgets.channels.memberlist.adapter.ChannelMembersListViewHolderMember
|
||||||
import com.discord.widgets.chat.list.adapter.WidgetChatListAdapterItemMessage
|
import com.discord.widgets.chat.list.adapter.WidgetChatListAdapterItemMessage
|
||||||
import com.discord.widgets.chat.list.entries.ChatListEntry
|
import com.discord.widgets.chat.list.entries.ChatListEntry
|
||||||
import com.discord.widgets.chat.list.entries.MessageEntry
|
import com.discord.widgets.chat.list.entries.MessageEntry
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
private val ChannelMembersListViewHolderMember.binding
|
private val ChannelMembersListViewHolderMember.binding
|
||||||
by accessField<WidgetChannelMembersListItemUserBinding>()
|
by accessField<WidgetChannelMembersListItemUserBinding>()
|
||||||
|
|
@ -36,8 +34,6 @@ data class Colours(
|
||||||
class Zinnia : Plugin() {
|
class Zinnia : Plugin() {
|
||||||
companion object { const val NAME = "RoleBlocks" }
|
companion object { const val NAME = "RoleBlocks" }
|
||||||
|
|
||||||
private val localSettings = ZinniaSettings
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
settingsTab = SettingsTab(ZinniaSettings.Page::class.java, SettingsTab.Type.PAGE)
|
settingsTab = SettingsTab(ZinniaSettings.Page::class.java, SettingsTab.Type.PAGE)
|
||||||
}
|
}
|
||||||
|
|
@ -49,93 +45,6 @@ class Zinnia : Plugin() {
|
||||||
|
|
||||||
override fun stop(context: Context) { patcher.unpatchAll() }
|
override fun stop(context: Context) { patcher.unpatchAll() }
|
||||||
|
|
||||||
private fun configureOn(view: TextView, colour: Int?) {
|
|
||||||
when (localSettings.mode) {
|
|
||||||
Mode.Block -> configureBlock(view, colour ?: Color.BLACK)
|
|
||||||
Mode.RoleDot -> configureRoleDot(view, colour ?: Color.BLACK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun configureRoleDot(view: TextView, colour: Int) { }
|
|
||||||
|
|
||||||
private fun configureBlock(view: TextView, colourP: Int) {
|
|
||||||
val isLight = StoreStream.getUserSettingsSystem().theme == "light"
|
|
||||||
var colour = colourP
|
|
||||||
val bcol = GradientDrawable()
|
|
||||||
bcol.cornerRadius = 4.dp.toFloat()
|
|
||||||
view.background = bcol
|
|
||||||
|
|
||||||
if (colour == Color.BLACK) {
|
|
||||||
if (localSettings.blockAlsoDefault) {
|
|
||||||
colour = if (isLight && !localSettings.blockInverted) Color.WHITE else Color.BLACK
|
|
||||||
} else {
|
|
||||||
view.background = null
|
|
||||||
view.setPadding(0, 0, 0, 0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.setPadding(4.dp, 0, 4.dp, 0)
|
|
||||||
|
|
||||||
var (preferred, other) = if (isLight) {
|
|
||||||
Color.WHITE to Color.BLACK
|
|
||||||
} else {
|
|
||||||
Color.BLACK to Color.WHITE
|
|
||||||
}
|
|
||||||
when (localSettings.blockMode) {
|
|
||||||
BlockMode.InvertedThemeOnly -> preferred = other
|
|
||||||
BlockMode.WhiteOnly -> preferred = Color.WHITE
|
|
||||||
BlockMode.BlackOnly -> preferred = Color.BLACK
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
val colours = if (!localSettings.blockInverted) {
|
|
||||||
Colours(
|
|
||||||
fgP = preferred,
|
|
||||||
fgO = other,
|
|
||||||
bgP = colour,
|
|
||||||
bgO = colour,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Colours(
|
|
||||||
fgP = colour,
|
|
||||||
fgO = colour,
|
|
||||||
bgP = preferred,
|
|
||||||
bgO = other,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val usePreferred = when (localSettings.blockMode) {
|
|
||||||
BlockMode.ApcaOnly -> isApca(colours)
|
|
||||||
BlockMode.WcagOnly -> isWcag(colours)
|
|
||||||
BlockMode.ApcaLightWcagDark -> if (isLight) isApca(colours) else isWcag(colours)
|
|
||||||
BlockMode.WcagLightApcaDark -> if (isLight) isWcag(colours) else isApca(colours)
|
|
||||||
BlockMode.ThemeOnly,
|
|
||||||
BlockMode.InvertedThemeOnly,
|
|
||||||
BlockMode.WhiteOnly,
|
|
||||||
BlockMode.BlackOnly -> true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usePreferred) {
|
|
||||||
view.setTextColor(colours.fgP)
|
|
||||||
bcol.setColor(colours.bgP)
|
|
||||||
} else {
|
|
||||||
view.setTextColor(colours.fgO)
|
|
||||||
bcol.setColor(colours.bgO)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isApca(c: Colours): Boolean {
|
|
||||||
val cPref = abs(APCA.contrast(c.fgP, c.bgP))
|
|
||||||
val cOth = abs(APCA.contrast(c.fgO, c.bgO))
|
|
||||||
return cPref > localSettings.blockApcaThreshold || cPref > cOth
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isWcag(c: Colours): Boolean {
|
|
||||||
val cPref = ColorUtils.calculateContrast(c.fgP, c.bgP)
|
|
||||||
val cOth = ColorUtils.calculateContrast(c.fgO, c.bgO)
|
|
||||||
return cPref > localSettings.blockWcagThreshold || cPref > cOth
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun patchMemberList() {
|
private fun patchMemberList() {
|
||||||
// Patches the method that configures the username in members list
|
// Patches the method that configures the username in members list
|
||||||
patcher.after<ChannelMembersListViewHolderMember>(
|
patcher.after<ChannelMembersListViewHolderMember>(
|
||||||
|
|
@ -153,7 +62,7 @@ class Zinnia : Plugin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configureOn(usernameTextView, member.color)
|
APCAUtil.configureOn(usernameTextView, member.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,7 +75,7 @@ class Zinnia : Plugin() {
|
||||||
) { (_, _: Int, entry: MessageEntry) ->
|
) { (_, _: Int, entry: MessageEntry) ->
|
||||||
val username = itemView.findViewById<TextView?>("chat_list_adapter_item_text_name")
|
val username = itemView.findViewById<TextView?>("chat_list_adapter_item_text_name")
|
||||||
?: return@after
|
?: return@after
|
||||||
configureOn(username, entry.author?.color)
|
APCAUtil.configureOn(username, entry.author?.color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures for reply preview username
|
// Configures for reply preview username
|
||||||
|
|
@ -177,7 +86,7 @@ class Zinnia : Plugin() {
|
||||||
val referencedAuthor = entry.replyData?.messageEntry?.author
|
val referencedAuthor = entry.replyData?.messageEntry?.author
|
||||||
val replyUsername = itemView.findViewById<TextView?>("chat_list_adapter_item_text_decorator_reply_name")
|
val replyUsername = itemView.findViewById<TextView?>("chat_list_adapter_item_text_decorator_reply_name")
|
||||||
?: return@after
|
?: return@after
|
||||||
configureOn(replyUsername, referencedAuthor?.color)
|
APCAUtil.configureOn(replyUsername, referencedAuthor?.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,26 @@
|
||||||
package moe.lava.awoocord.zinnia
|
package moe.lava.awoocord.zinnia
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import com.aliucord.Constants
|
||||||
import com.aliucord.Utils
|
import com.aliucord.Utils
|
||||||
import com.aliucord.api.SettingsAPI
|
import com.aliucord.api.SettingsAPI
|
||||||
import com.aliucord.fragments.SettingsPage
|
import com.aliucord.fragments.SettingsPage
|
||||||
import com.aliucord.settings.delegate
|
import com.aliucord.settings.delegate
|
||||||
|
import com.aliucord.utils.DimenUtils.dp
|
||||||
|
import com.aliucord.wrappers.users.globalName
|
||||||
|
import com.discord.stores.StoreStream
|
||||||
|
import com.discord.utilities.color.ColorCompat
|
||||||
import com.discord.views.CheckedSetting
|
import com.discord.views.CheckedSetting
|
||||||
import com.discord.views.RadioManager
|
import com.discord.views.RadioManager
|
||||||
|
import com.lytefast.flexinput.R
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
|
@ -25,6 +38,7 @@ enum class BlockMode {
|
||||||
InvertedThemeOnly,
|
InvertedThemeOnly,
|
||||||
WhiteOnly,
|
WhiteOnly,
|
||||||
BlackOnly,
|
BlackOnly,
|
||||||
|
Unchanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsDelegateEnum<T : Enum<T>>(
|
class SettingsDelegateEnum<T : Enum<T>>(
|
||||||
|
|
@ -49,18 +63,47 @@ private inline fun <T : View> T.addTo(parent: ViewGroup, block: T.() -> Unit = {
|
||||||
parent.addView(this)
|
parent.addView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private typealias Delegate<Type> = ReadWriteProperty<Any, Type>
|
||||||
|
|
||||||
|
fun <T> basicDelegate(initial: T) = object : Delegate<T> {
|
||||||
|
private var current = initial
|
||||||
|
override fun getValue(self: Any?, prop: KProperty<*>): T = current
|
||||||
|
override fun setValue(self: Any?, prop: KProperty<*>, value: T) { current = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StateDelegate<T>(
|
||||||
|
private val inner: Delegate<T>,
|
||||||
|
private val update: (T) -> Unit,
|
||||||
|
) : Delegate<T> {
|
||||||
|
override fun getValue(self: Any?, prop: KProperty<*>): T = inner.getValue(self, prop)
|
||||||
|
|
||||||
|
override fun setValue(self: Any?, prop: KProperty<*>, value: T) {
|
||||||
|
inner.setValue(self, prop, value)
|
||||||
|
update(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object ZinniaSettings {
|
object ZinniaSettings {
|
||||||
private val api = SettingsAPI(Zinnia.NAME)
|
private val api = SettingsAPI(Zinnia.NAME)
|
||||||
|
|
||||||
var mode by api.delegateEnum(Mode.Block)
|
private var onStateUpdate = {}
|
||||||
|
|
||||||
var dotKeepNameColour by api.delegate(false)
|
private inline fun <T> reactive(backing: () -> Delegate<T>): StateDelegate<T> {
|
||||||
|
return StateDelegate(backing()) { onStateUpdate() }
|
||||||
|
}
|
||||||
|
|
||||||
var blockAlsoDefault by api.delegate(true)
|
var mode by reactive { api.delegateEnum(Mode.Block) }
|
||||||
var blockInverted by api.delegate(false)
|
|
||||||
var blockMode by api.delegateEnum(BlockMode.ApcaLightWcagDark)
|
var dotKeepNameColour by reactive { api.delegate(false) }
|
||||||
var blockApcaThreshold by api.delegate(75.0)
|
|
||||||
var blockWcagThreshold by api.delegate(4.5)
|
var blockAlsoDefault by reactive { api.delegate(true) }
|
||||||
|
var blockInverted by reactive { api.delegate(false) }
|
||||||
|
var blockMode by reactive { api.delegateEnum(BlockMode.ApcaLightWcagDark) }
|
||||||
|
var blockApcaThreshold by reactive { api.delegate(45.0f) }
|
||||||
|
var blockWcagThreshold by reactive { api.delegate(4.5f) }
|
||||||
|
|
||||||
|
private val _alpha = reactive { api.delegate("alpha", 255) }
|
||||||
|
var alpha by _alpha
|
||||||
|
|
||||||
class Page : SettingsPage() {
|
class Page : SettingsPage() {
|
||||||
private lateinit var manager: RadioManager
|
private lateinit var manager: RadioManager
|
||||||
|
|
@ -69,6 +112,13 @@ object ZinniaSettings {
|
||||||
|
|
||||||
private val checks = mutableListOf<CheckedSetting>()
|
private val checks = mutableListOf<CheckedSetting>()
|
||||||
|
|
||||||
|
private val _previewH = reactive { basicDelegate(0) }
|
||||||
|
private var previewH by _previewH
|
||||||
|
private val _previewS = reactive { basicDelegate(100) }
|
||||||
|
private var previewS by _previewS
|
||||||
|
private val _previewV = reactive { basicDelegate(100) }
|
||||||
|
private var previewV by _previewV
|
||||||
|
|
||||||
private fun createRadio(newMode: BlockMode, text: String, subtext: String? = null): CheckedSetting {
|
private fun createRadio(newMode: BlockMode, text: String, subtext: String? = null): CheckedSetting {
|
||||||
return Utils.createCheckedSetting(requireContext(), CheckedSetting.ViewType.RADIO, text, subtext).addTo(linearLayout) {
|
return Utils.createCheckedSetting(requireContext(), CheckedSetting.ViewType.RADIO, text, subtext).addTo(linearLayout) {
|
||||||
isChecked = blockMode == newMode
|
isChecked = blockMode == newMode
|
||||||
|
|
@ -81,6 +131,60 @@ object ZinniaSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createSlider(
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
initial: Int = min,
|
||||||
|
onChange: (value: Int, commit: Boolean) -> String
|
||||||
|
): LinearLayout {
|
||||||
|
var pendingValue = initial
|
||||||
|
return LinearLayout(requireContext(), null, 0, R.i.UiKit_Settings_Item).addTo(linearLayout) {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
val display = TextView(context, null, 0, R.i.UiKit_TextView).addTo(this) {
|
||||||
|
textSize = 16.0f
|
||||||
|
typeface = ResourcesCompat.getFont(context, Constants.Fonts.whitney_medium)
|
||||||
|
text = onChange(initial, false)
|
||||||
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
|
bottomMargin = 4.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SeekBar(context, null, 0, R.i.UiKit_SeekBar).addTo(this) {
|
||||||
|
this.max = max - min
|
||||||
|
progress = initial
|
||||||
|
setPadding(12.dp, 0, 12.dp, 0)
|
||||||
|
setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||||
|
override fun onProgressChanged(
|
||||||
|
seekBar: SeekBar,
|
||||||
|
progress: Int,
|
||||||
|
fromUser: Boolean,
|
||||||
|
) {
|
||||||
|
pendingValue = min + progress
|
||||||
|
display.text = onChange(pendingValue, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar) {}
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||||
|
onChange(pendingValue, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSlider(binding: Delegate<Int>, min: Int, max: Int, immediate: Boolean = false, label: (Int) -> String): LinearLayout {
|
||||||
|
var value by binding
|
||||||
|
return createSlider(min, max, value) { newValue, commit ->
|
||||||
|
@Suppress("AssignedValueIsNeverRead") // kt so dumb
|
||||||
|
if (immediate || commit) value = newValue
|
||||||
|
label(newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
onStateUpdate = {}
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
override fun onViewBound(view: View) {
|
||||||
super.onViewBound(view)
|
super.onViewBound(view)
|
||||||
setActionBarTitle(Zinnia.NAME)
|
setActionBarTitle(Zinnia.NAME)
|
||||||
|
|
@ -92,11 +196,12 @@ object ZinniaSettings {
|
||||||
val roleDotSettings = mutableListOf<CheckedSetting>()
|
val roleDotSettings = mutableListOf<CheckedSetting>()
|
||||||
|
|
||||||
addHeader(ctx, "Text colour")
|
addHeader(ctx, "Text colour")
|
||||||
createRadio(BlockMode.ApcaLightWcagDark, "Automatic", "Adjusts text colour based on role colour")
|
createRadio(BlockMode.ApcaLightWcagDark, "Automatic", "Adjusts text colour based on optimal contrast with role colour")
|
||||||
createRadio(BlockMode.ThemeOnly, "By theme", "Adjusts text colour based on theme")
|
createRadio(BlockMode.ThemeOnly, "By theme", "Adjusts text colour based on system theme (dark/light)")
|
||||||
createRadio(BlockMode.InvertedThemeOnly, "By theme (inverted)", "Same as above, but inverted")
|
createRadio(BlockMode.InvertedThemeOnly, "By theme (inverted)", "Same as above, but inverted")
|
||||||
createRadio(BlockMode.WhiteOnly, "White", "Force text colour to be white")
|
createRadio(BlockMode.WhiteOnly, "White", "Force text colour to be white")
|
||||||
createRadio(BlockMode.BlackOnly, "Black", "Force text colour to be black")
|
createRadio(BlockMode.BlackOnly, "Black", "Force text colour to be black")
|
||||||
|
createRadio(BlockMode.Unchanged, "Unchanged", "Keep text colour; ideal for using with a translucent block")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
addHeader(ctx, "Mode")
|
addHeader(ctx, "Mode")
|
||||||
|
|
@ -129,24 +234,12 @@ object ZinniaSettings {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addHeader(ctx, "Block Settings")
|
addHeader(ctx, "Block Settings")
|
||||||
Utils.createCheckedSetting(
|
|
||||||
ctx,
|
|
||||||
CheckedSetting.ViewType.SWITCH,
|
|
||||||
"Also block up default colours",
|
|
||||||
"Blocks up usernames that have no role colour",
|
|
||||||
).addTo(this) {
|
|
||||||
isChecked = blockAlsoDefault
|
|
||||||
setOnCheckedListener {
|
|
||||||
blockAlsoDefault = !blockAlsoDefault
|
|
||||||
}
|
|
||||||
blockSettings.add(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils.createCheckedSetting(
|
val invertSwitch = Utils.createCheckedSetting(
|
||||||
ctx,
|
ctx,
|
||||||
CheckedSetting.ViewType.SWITCH,
|
CheckedSetting.ViewType.SWITCH,
|
||||||
"Invert block colours",
|
"Invert block colours",
|
||||||
"By default, the role colour is applied as the block background. Turning this setting on instead makes the block black or white, and the text stays coloured.",
|
"By default, the role colour is applied as the block background. Turning this setting on inverts this.\nHas no effect with \"Unchanged\" colour option",
|
||||||
).addTo(this) {
|
).addTo(this) {
|
||||||
isChecked = blockInverted
|
isChecked = blockInverted
|
||||||
setOnCheckedListener {
|
setOnCheckedListener {
|
||||||
|
|
@ -154,7 +247,50 @@ object ZinniaSettings {
|
||||||
}
|
}
|
||||||
blockSettings.add(this)
|
blockSettings.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createSlider(_alpha, 0, 255, true) { "Alpha: ${(it / 2.55f).roundToInt()}%" }
|
||||||
|
|
||||||
|
// createSlider(0, 255, blockApcaThreshold.roundToInt()) { value, commit ->
|
||||||
|
// blockApcaThreshold = value.toFloat()
|
||||||
|
// "Apca Threshold: $value"
|
||||||
|
// }
|
||||||
|
|
||||||
|
addHeader(ctx, "Preview")
|
||||||
|
val preview = TextView(ctx, null, 0, R.i.UiKit_TextView_Large_SingleLine).addTo(this) {
|
||||||
|
val me = StoreStream.getUsers().me
|
||||||
|
text = me.globalName ?: me.username
|
||||||
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
|
marginStart = 16.dp
|
||||||
|
marginEnd = 16.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val hsv = floatArrayOf(0f, 0f, 0f)
|
||||||
|
Color.colorToHSV(ColorCompat.getThemedColor(this, R.b.color_brand), hsv)
|
||||||
|
previewH = hsv[0].roundToInt()
|
||||||
|
previewS = (hsv[1] * 100).roundToInt()
|
||||||
|
previewV = (hsv[2] * 100).roundToInt()
|
||||||
|
createSlider(_previewH, 0, 360, true) { "Hue: $it" }
|
||||||
|
createSlider(_previewS, 0, 100, true) { "Saturation: $it%" }
|
||||||
|
createSlider(_previewV, 0, 100, true) { "Value: $it%" }
|
||||||
|
|
||||||
|
onStateUpdate = {
|
||||||
|
updatePreview(preview)
|
||||||
|
if (blockMode != BlockMode.Unchanged) {
|
||||||
|
invertSwitch.l.b().isClickable = true
|
||||||
|
invertSwitch.alpha = 1f
|
||||||
|
} else {
|
||||||
|
invertSwitch.l.b().isClickable = false
|
||||||
|
invertSwitch.alpha = 0.3f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onStateUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updatePreview(preview: TextView) {
|
||||||
|
val colour = Color.HSVToColor(floatArrayOf(previewH.toFloat(), previewS / 100f, previewV / 100f))
|
||||||
|
APCAUtil.configureOn(preview, colour)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue