Completely refactor accents
Completely refactor the accent system to be much more understandable.
This commit is contained in:
parent
2889e6fdfd
commit
c4bc86cb05
15 changed files with 181 additions and 184 deletions
|
@ -11,7 +11,7 @@ import androidx.databinding.DataBindingUtil
|
|||
import org.oxycblt.auxio.databinding.ActivityMainBinding
|
||||
import org.oxycblt.auxio.playback.PlaybackService
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.isEdgeOn
|
||||
|
||||
/**
|
||||
|
@ -30,10 +30,10 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
AppCompatDelegate.setDefaultNightMode(settingsManager.theme)
|
||||
|
||||
accent = settingsManager.accent
|
||||
val accent = Accent.set(settingsManager.accent)
|
||||
|
||||
// Apply the theme
|
||||
setTheme(accent.second)
|
||||
setTheme(accent.theme)
|
||||
|
||||
if (isEdgeOn()) {
|
||||
doEdgeToEdgeSetup(binding)
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.NavController
|
||||
|
@ -17,8 +18,7 @@ import org.oxycblt.auxio.detail.DetailViewModel
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.getTransparentAccent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.isLandscape
|
||||
import org.oxycblt.auxio.ui.toColor
|
||||
|
||||
|
@ -45,10 +45,8 @@ class MainFragment : Fragment() {
|
|||
return null
|
||||
}
|
||||
|
||||
val colorActive = accent.first.toColor(requireContext())
|
||||
val colorInactive = getTransparentAccent(
|
||||
requireContext(), accent.first, 150
|
||||
)
|
||||
val colorActive = Accent.get().color.toColor(requireContext())
|
||||
val colorInactive = ColorUtils.setAlphaComponent(colorActive, 150)
|
||||
|
||||
// Set up the tints for the navigation icons + text
|
||||
val navTints = ColorStateList(
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.Highlightable
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.applyAccents
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setTextColorResource
|
||||
|
@ -138,8 +138,10 @@ class AlbumDetailAdapter(
|
|||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
if (isHighlighted) {
|
||||
binding.songName.setTextColorResource(accent.first)
|
||||
binding.songTrack.setTextColorResource(accent.first)
|
||||
val accent = Accent.get()
|
||||
|
||||
binding.songName.setTextColorResource(accent.color)
|
||||
binding.songTrack.setTextColorResource(accent.color)
|
||||
} else {
|
||||
binding.songName.setTextColor(normalTextColor)
|
||||
binding.songTrack.setTextColor(inactiveTextColor)
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.Highlightable
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.applyAccents
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setTextColorResource
|
||||
|
@ -137,7 +137,7 @@ class ArtistDetailAdapter(
|
|||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
if (isHighlighted) {
|
||||
binding.albumName.setTextColorResource(accent.first)
|
||||
binding.albumName.setTextColorResource(Accent.get().color)
|
||||
} else {
|
||||
binding.albumName.setTextColor(normalTextColor)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.Highlightable
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.applyAccents
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setTextColorResource
|
||||
|
@ -138,7 +138,7 @@ class GenreDetailAdapter(
|
|||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
if (isHighlighted) {
|
||||
binding.songName.setTextColorResource(accent.first)
|
||||
binding.songName.setTextColorResource(Accent.get().color)
|
||||
} else {
|
||||
binding.songName.setTextColor(normalTextColor)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
|
|||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.memberBinding
|
||||
import org.oxycblt.auxio.ui.toColor
|
||||
|
||||
|
@ -36,7 +36,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
|
||||
// Colors
|
||||
private val accentColor: ColorStateList by lazy {
|
||||
ColorStateList.valueOf(accent.first.toColor(requireContext()))
|
||||
Accent.get().getStateList(requireContext())
|
||||
}
|
||||
|
||||
private val controlColor: ColorStateList by lazy {
|
||||
|
|
|
@ -22,7 +22,7 @@ import androidx.dynamicanimation.animation.SpringForce
|
|||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
||||
import com.reddit.indicatorfastscroll.FastScrollerView
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.toColor
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,7 @@ class NoLeakThumbView @JvmOverloads constructor(
|
|||
) : ConstraintLayout(context, attrs, defStyleAttr),
|
||||
FastScrollerView.ItemIndicatorSelectedCallback {
|
||||
|
||||
private val thumbColor = ColorStateList.valueOf(accent.first.toColor(context))
|
||||
private val thumbColor = Accent.get().getStateList(context)
|
||||
private val iconColor = R.color.background.toColor(context)
|
||||
private val textAppearanceRes = R.style.TextAppearance_ThumbIndicator
|
||||
private val textColor = R.color.background.toColor(context)
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.toColor
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
|
@ -23,8 +22,8 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.ActionMenu
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.fixAnimationInfoMemoryLeak
|
||||
import org.oxycblt.auxio.ui.getLandscapeSpans
|
||||
import org.oxycblt.auxio.ui.isLandscape
|
||||
|
@ -51,7 +50,7 @@ class SearchFragment : Fragment() {
|
|||
|
||||
// Apply the accents manually. Not going through the mess of converting my app's
|
||||
// styling to Material given all the second-and-third-order effects it has.
|
||||
val accent = accent.first.toColor(requireContext())
|
||||
val accent = Accent.get().color.toColor(requireContext())
|
||||
|
||||
val searchAdapter = SearchAdapter(::onItemSelection) { view, data ->
|
||||
ActionMenu(requireCompatActivity(), view, data, ActionMenu.FLAG_NONE)
|
||||
|
|
|
@ -20,9 +20,8 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.settings.ui.AccentAdapter
|
||||
import org.oxycblt.auxio.ui.ACCENTS
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.createToast
|
||||
import org.oxycblt.auxio.ui.getDetailedAccentSummary
|
||||
|
||||
/**
|
||||
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].
|
||||
|
@ -84,7 +83,7 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
|||
true
|
||||
}
|
||||
|
||||
summary = getDetailedAccentSummary(requireActivity(), accent)
|
||||
summary = Accent.get().getDetailedSummary(context)
|
||||
}
|
||||
|
||||
SettingsManager.Keys.KEY_EDGE_TO_EDGE -> {
|
||||
|
@ -153,7 +152,7 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
|||
// This is why I hate using third party libraries.
|
||||
val recycler = RecyclerView(requireContext()).apply {
|
||||
adapter = AccentAdapter {
|
||||
if (it.first != accent.first) {
|
||||
if (it != Accent.get()) {
|
||||
SettingsManager.getInstance().accent = it
|
||||
|
||||
requireActivity().recreate()
|
||||
|
@ -169,7 +168,7 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
|||
|
||||
(layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(
|
||||
ACCENTS.indexOf(accent),
|
||||
ACCENTS.indexOf(Accent.get()),
|
||||
(width / 2) - childWidth
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
|||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.ui.ACCENTS
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
|
||||
/**
|
||||
* Wrapper around the [SharedPreferences] class that writes & reads values without a context.
|
||||
|
@ -31,12 +32,10 @@ class SettingsManager private constructor(context: Context) :
|
|||
/**
|
||||
* The current accent.
|
||||
*/
|
||||
var accent: Pair<Int, Int>
|
||||
var accent: Accent
|
||||
get() {
|
||||
val accentIndex = sharedPrefs.getInt(Keys.KEY_ACCENT, 5)
|
||||
|
||||
// Accent is stored as an index [to be efficient], so retrieve it when done.
|
||||
return ACCENTS[accentIndex]
|
||||
return ACCENTS[sharedPrefs.getInt(Keys.KEY_ACCENT, 5)]
|
||||
}
|
||||
set(value) {
|
||||
val accentIndex = ACCENTS.indexOf(value)
|
||||
|
@ -200,14 +199,14 @@ class SettingsManager private constructor(context: Context) :
|
|||
|
||||
companion object {
|
||||
@Volatile
|
||||
private lateinit var INSTANCE: SettingsManager
|
||||
private var INSTANCE: SettingsManager? = null
|
||||
|
||||
/**
|
||||
* Init the single instance of [SettingsManager]. Done so that every object
|
||||
* can have access to it regardless of if it has a context.
|
||||
*/
|
||||
fun init(context: Context): SettingsManager {
|
||||
if (!::INSTANCE.isInitialized) {
|
||||
if (INSTANCE == null) {
|
||||
synchronized(this) {
|
||||
INSTANCE = SettingsManager(context)
|
||||
}
|
||||
|
@ -220,10 +219,13 @@ class SettingsManager private constructor(context: Context) :
|
|||
* Get the single instance of [SettingsManager].
|
||||
*/
|
||||
fun getInstance(): SettingsManager {
|
||||
check(::INSTANCE.isInitialized) {
|
||||
"SettingsManager must be initialized with init() before getting its instance."
|
||||
val instance = INSTANCE
|
||||
|
||||
if (instance != null) {
|
||||
return instance
|
||||
}
|
||||
return INSTANCE
|
||||
|
||||
error("SettingsManager must be initialized with init() before getting its instance.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ItemAccentBinding
|
||||
import org.oxycblt.auxio.ui.ACCENTS
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.getAccentItemSummary
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.toColor
|
||||
|
||||
/**
|
||||
|
@ -17,7 +16,7 @@ import org.oxycblt.auxio.ui.toColor
|
|||
* @param doOnAccentConfirm What to do when an accent is confirmed.
|
||||
*/
|
||||
class AccentAdapter(
|
||||
private val doOnAccentConfirm: (accent: Pair<Int, Int>) -> Unit
|
||||
private val doOnAccentConfirm: (accent: Accent) -> Unit
|
||||
) : RecyclerView.Adapter<AccentAdapter.ViewHolder>() {
|
||||
override fun getItemCount(): Int = ACCENTS.size
|
||||
|
||||
|
@ -33,31 +32,25 @@ class AccentAdapter(
|
|||
private val binding: ItemAccentBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(accentData: Pair<Int, Int>) {
|
||||
fun bind(accent: Accent) {
|
||||
binding.accent.apply {
|
||||
contentDescription = getAccentItemSummary(context, accentData)
|
||||
contentDescription = accent.getDetailedSummary(context)
|
||||
|
||||
setOnClickListener {
|
||||
doOnAccentConfirm(accentData)
|
||||
doOnAccentConfirm(accent)
|
||||
}
|
||||
|
||||
imageTintList = if (accentData.first == accent.first) {
|
||||
imageTintList = if (accent == Accent.get()) {
|
||||
isEnabled = false
|
||||
|
||||
ColorStateList.valueOf(
|
||||
R.color.background.toColor(context)
|
||||
)
|
||||
ColorStateList.valueOf(R.color.background.toColor(context))
|
||||
} else {
|
||||
isEnabled = true
|
||||
|
||||
ColorStateList.valueOf(
|
||||
android.R.color.transparent.toColor(context)
|
||||
)
|
||||
ColorStateList.valueOf(android.R.color.transparent.toColor(context))
|
||||
}
|
||||
|
||||
backgroundTintList = ColorStateList.valueOf(
|
||||
accentData.first.toColor(context)
|
||||
)
|
||||
backgroundTintList = accent.getStateList(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.oxycblt.auxio.songs
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
|
@ -18,12 +17,11 @@ import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
|||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.Accent
|
||||
import org.oxycblt.auxio.ui.ActionMenu
|
||||
import org.oxycblt.auxio.ui.accent
|
||||
import org.oxycblt.auxio.ui.getLandscapeSpans
|
||||
import org.oxycblt.auxio.ui.isLandscape
|
||||
import org.oxycblt.auxio.ui.requireCompatActivity
|
||||
import org.oxycblt.auxio.ui.toColor
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
|
@ -109,7 +107,7 @@ class SongsFragment : Fragment() {
|
|||
|
||||
// API 22 and below don't support the state color, so just use the accent.
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
|
||||
textColor = ColorStateList.valueOf(accent.first.toColor(requireContext()))
|
||||
textColor = Accent.get().getStateList(requireContext())
|
||||
}
|
||||
|
||||
setupWithRecyclerView(
|
||||
|
|
111
app/src/main/java/org/oxycblt/auxio/ui/Accent.kt
Normal file
111
app/src/main/java/org/oxycblt/auxio/ui/Accent.kt
Normal file
|
@ -0,0 +1,111 @@
|
|||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.text.Spanned
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.core.text.toSpanned
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* A list of all possible accents.
|
||||
* TODO: Add custom accents
|
||||
*/
|
||||
val ACCENTS = arrayOf(
|
||||
Accent(R.color.red, R.style.Theme_Red, R.string.color_label_red),
|
||||
Accent(R.color.pink, R.style.Theme_Pink, R.string.color_label_pink),
|
||||
Accent(R.color.purple, R.style.Theme_Purple, R.string.color_label_purple),
|
||||
Accent(R.color.deep_purple, R.style.Theme_DeepPurple, R.string.color_label_deep_purple),
|
||||
Accent(R.color.indigo, R.style.Theme_Indigo, R.string.color_label_indigo),
|
||||
Accent(R.color.blue, R.style.Theme_Blue, R.string.color_label_blue),
|
||||
Accent(R.color.light_blue, R.style.Theme_LightBlue, R.string.color_label_light_blue),
|
||||
Accent(R.color.cyan, R.style.Theme_Cyan, R.string.color_label_cyan),
|
||||
Accent(R.color.teal, R.style.Theme_Teal, R.string.color_label_teal),
|
||||
Accent(R.color.green, R.style.Theme_Green, R.string.color_label_green),
|
||||
Accent(R.color.light_green, R.style.Theme_LightGreen, R.string.color_label_light_green),
|
||||
Accent(R.color.lime, R.style.Theme_Lime, R.string.color_label_lime),
|
||||
Accent(R.color.yellow, R.style.Theme_Yellow, R.string.color_label_yellow),
|
||||
Accent(R.color.amber, R.style.Theme_Amber, R.string.color_label_amber),
|
||||
Accent(R.color.orange, R.style.Theme_Orange, R.string.color_label_orange),
|
||||
Accent(R.color.deep_orange, R.style.Theme_DeepOrange, R.string.color_label_deep_orange),
|
||||
Accent(R.color.brown, R.style.Theme_Brown, R.string.color_label_brown),
|
||||
Accent(R.color.grey, R.style.Theme_Gray, R.string.color_label_grey),
|
||||
Accent(R.color.blue_grey, R.style.Theme_BlueGrey, R.string.color_label_blue_grey),
|
||||
Accent(R.color.control_color, R.style.Theme_Neutral, R.string.color_label_neutral)
|
||||
)
|
||||
|
||||
/**
|
||||
* The data object for an accent.
|
||||
* @property color The color resource for this accent
|
||||
* @property theme The theme resource for this accent
|
||||
* @property name The name of this accent
|
||||
*/
|
||||
data class Accent(
|
||||
@ColorRes val color: Int,
|
||||
@StyleRes val theme: Int,
|
||||
@StringRes val name: Int
|
||||
) {
|
||||
/**
|
||||
* Get a [ColorStateList] of the accent
|
||||
*/
|
||||
fun getStateList(context: Context): ColorStateList {
|
||||
return ColorStateList.valueOf(color.toColor(context))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name (in bold) and the hex value of a accent.
|
||||
* @param context [Context] required
|
||||
* @return A rendered span with the name in bold + the hex value of the accent.
|
||||
*/
|
||||
@SuppressLint("ResourceType")
|
||||
fun getDetailedSummary(context: Context): Spanned {
|
||||
val name = context.getString(name)
|
||||
val hex = context.getString(color).toUpperCase(Locale.getDefault())
|
||||
|
||||
return context.getString(
|
||||
R.string.format_accent_summary,
|
||||
name, hex
|
||||
).toSpanned().render()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var current: Accent? = null
|
||||
|
||||
/**
|
||||
* Get the current accent, will default to whatever is stored in [SettingsManager]
|
||||
* if there isnt one.
|
||||
* @return The current accent
|
||||
*/
|
||||
fun get(): Accent {
|
||||
val cur = current
|
||||
|
||||
if (cur != null) {
|
||||
return cur
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
val newCur = SettingsManager.getInstance().accent
|
||||
current = newCur
|
||||
return newCur
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current accent.
|
||||
* @return The new accent
|
||||
*/
|
||||
fun set(accent: Accent): Accent {
|
||||
synchronized(this) {
|
||||
current = accent
|
||||
}
|
||||
|
||||
return accent
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,9 +14,11 @@ import android.view.WindowManager
|
|||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
|
@ -51,7 +53,7 @@ fun TextView.setTextColorResource(@ColorRes color: Int) {
|
|||
* Required because you cant determine a style of a view before API 29
|
||||
*/
|
||||
fun MaterialButton.applyAccents(highlighted: Boolean) {
|
||||
val accent = accent.first.toColor(context)
|
||||
val accent = Accent.get().color.toColor(context)
|
||||
|
||||
if (highlighted) {
|
||||
backgroundTintList = ColorStateList.valueOf(accent)
|
||||
|
@ -103,6 +105,23 @@ fun Spanned.render(): Spanned {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a color.
|
||||
* @param context [Context] required
|
||||
* @return The resolved color, black if the resolving process failed.
|
||||
*/
|
||||
@ColorInt
|
||||
fun Int.toColor(context: Context): Int {
|
||||
return try {
|
||||
ContextCompat.getColor(context, this)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
logE("Attempted color load failed.")
|
||||
|
||||
// Default to the emergency color [Black] if the loading fails.
|
||||
ContextCompat.getColor(context, android.R.color.black)
|
||||
}
|
||||
}
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
|
||||
/**
|
||||
|
@ -177,8 +196,9 @@ private fun isSystemBarOnBottom(activity: Activity): Boolean {
|
|||
// --- HACKY NIGHTMARES ---
|
||||
|
||||
/**
|
||||
* Use R E F L E C T I O N to fix a memory leak where mAnimationInfo will keep a reference to
|
||||
* Use ***R E F L E C T I O N*** to fix a memory leak where mAnimationInfo will keep a reference to
|
||||
* its focused view.
|
||||
*
|
||||
* I can't believe I have to do this.
|
||||
*/
|
||||
fun Fragment.fixAnimationInfoMemoryLeak() {
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.text.Spanned
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.text.toSpanned
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.logE
|
||||
import java.util.Locale
|
||||
|
||||
// Functions for managing colors/accents.
|
||||
|
||||
/**
|
||||
* An array of the base accents and their respective themes.
|
||||
*/
|
||||
val ACCENTS = arrayOf(
|
||||
Pair(R.color.red, R.style.Theme_Red), // 0
|
||||
Pair(R.color.pink, R.style.Theme_Pink), // 1
|
||||
Pair(R.color.purple, R.style.Theme_Purple), // 2
|
||||
Pair(R.color.deep_purple, R.style.Theme_DeepPurple), // 3
|
||||
Pair(R.color.indigo, R.style.Theme_Indigo), // 4
|
||||
Pair(R.color.blue, R.style.Theme_Blue), // 5 - Default!
|
||||
Pair(R.color.light_blue, R.style.Theme_LightBlue), // 6
|
||||
Pair(R.color.cyan, R.style.Theme_Cyan), // 7
|
||||
Pair(R.color.teal, R.style.Theme_Teal), // 8
|
||||
Pair(R.color.green, R.style.Theme_Green), // 9
|
||||
Pair(R.color.light_green, R.style.Theme_LightGreen), // 10
|
||||
Pair(R.color.lime, R.style.Theme_Lime), // 11
|
||||
Pair(R.color.yellow, R.style.Theme_Yellow), // 12
|
||||
Pair(R.color.amber, R.style.Theme_Amber), // 13
|
||||
Pair(R.color.orange, R.style.Theme_Orange), // 14
|
||||
Pair(R.color.deep_orange, R.style.Theme_DeepOrange), // 15
|
||||
Pair(R.color.brown, R.style.Theme_Brown), // 16
|
||||
Pair(R.color.grey, R.style.Theme_Gray), // 17
|
||||
Pair(R.color.blue_grey, R.style.Theme_BlueGrey), // 18
|
||||
Pair(R.color.control_color, R.style.Theme_Neutral)
|
||||
)
|
||||
|
||||
/**
|
||||
* An array of strings for each accent, use these instead of [Resources.getResourceName] so that
|
||||
* the accent names are translated.
|
||||
*/
|
||||
private val ACCENT_NAMES = arrayOf(
|
||||
R.string.color_label_red, R.string.color_label_pink,
|
||||
R.string.color_label_purple, R.string.color_label_deep_purple,
|
||||
R.string.color_label_indigo, R.string.color_label_blue,
|
||||
R.string.color_label_light_blue, R.string.color_label_cyan,
|
||||
R.string.color_label_teal, R.string.color_label_green,
|
||||
R.string.color_label_light_green, R.string.color_label_lime,
|
||||
R.string.color_label_yellow, R.string.color_label_amber,
|
||||
R.string.color_label_orange, R.string.color_label_deep_orange,
|
||||
R.string.color_label_brown, R.string.color_label_grey,
|
||||
R.string.color_label_blue_grey, R.string.color_label_neutral
|
||||
)
|
||||
|
||||
/**
|
||||
* The programmatically accessible accent, reflects the currently set accent.
|
||||
*/
|
||||
lateinit var accent: Pair<Int, Int>
|
||||
|
||||
/**
|
||||
* Gets the transparent form of a color.
|
||||
* @param context [Context] required to create the color
|
||||
* @param color The RESOURCE ID for the color
|
||||
* @param alpha The new alpha that wants to be applied
|
||||
* @return The new, resolved transparent color
|
||||
*/
|
||||
@ColorInt
|
||||
fun getTransparentAccent(context: Context, @ColorRes color: Int, alpha: Int): Int {
|
||||
return ColorUtils.setAlphaComponent(
|
||||
color.toColor(context),
|
||||
alpha
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a color.
|
||||
* @param context [Context] required
|
||||
* @return The resolved color, black if the resolving process failed.
|
||||
*/
|
||||
@ColorInt
|
||||
fun Int.toColor(context: Context): Int {
|
||||
return try {
|
||||
ContextCompat.getColor(context, this)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
logE("Attempted color load failed.")
|
||||
|
||||
// Default to the emergency color [Black] if the loading fails.
|
||||
ContextCompat.getColor(context, android.R.color.black)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of an accent.
|
||||
* @param context [Context] required
|
||||
* @param newAccent The accent the name should be given for.
|
||||
* @return The accent name according to the strings for this specific locale.
|
||||
*/
|
||||
fun getAccentItemSummary(context: Context, newAccent: Pair<Int, Int>): String {
|
||||
val accentIndex = ACCENTS.indexOf(newAccent)
|
||||
|
||||
check(accentIndex != -1) { "Invalid accent given" }
|
||||
|
||||
return context.getString(ACCENT_NAMES[accentIndex])
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name (in bold) and the hex value of a accent.
|
||||
* @param context [Context] required
|
||||
* @param newAccent Accent to get the information for
|
||||
* @return A rendered span with the name in bold + the hex value of the accent.
|
||||
*/
|
||||
fun getDetailedAccentSummary(context: Context, newAccent: Pair<Int, Int>): Spanned {
|
||||
val name = getAccentItemSummary(context, newAccent)
|
||||
val hex = context.getString(accent.first).toUpperCase(Locale.getDefault())
|
||||
|
||||
return context.getString(
|
||||
R.string.format_accent_summary,
|
||||
name, hex
|
||||
).toSpanned().render()
|
||||
}
|
Loading…
Reference in a new issue