feat(IconOpts): icon background color selection

Fixes #42
This commit is contained in:
rushiiMachine 2025-03-29 21:42:32 -07:00
parent b8cf2176c6
commit 9f036879a0
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
5 changed files with 142 additions and 13 deletions

View file

@ -133,6 +133,7 @@ android {
kotlin { kotlin {
sourceSets.all { sourceSets.all {
languageSettings.enableLanguageFeature("ExplicitBackingFields") languageSettings.enableLanguageFeature("ExplicitBackingFields")
languageSettings.enableLanguageFeature("WhenGuards")
} }
} }

View file

@ -8,21 +8,56 @@ import com.aliucord.manager.ui.screens.patchopts.PatchOptions.IconReplacement
class IconOptionsModel( class IconOptionsModel(
prefilledOptions: IconReplacement, prefilledOptions: IconReplacement,
) : ScreenModel { ) : ScreenModel {
var selectedColor by mutableStateOf<Color>(((prefilledOptions as? IconReplacement.CustomColor) ?: IconReplacement.Discord).color) // ---------- Icon patching mode ---------- //
var mode by mutableStateOf(IconOptionsMode.Original)
private set private set
fun changeMode(mode: IconOptionsMode) {
this.mode = mode
}
// ---------- Replacement color ---------- //
var selectedColorValue by mutableLongStateOf(0)
val selectedColor: Color
inline get() = Color(selectedColorValue.toULong())
fun changeSelectedColor(color: Color) { fun changeSelectedColor(color: Color) {
this.selectedColor = color selectedColorValue = color.value.toLong()
} }
fun generateConfig(): IconReplacement { // ---------- Other ---------- //
// TODO: other branches init {
return IconReplacement.CustomColor(color = selectedColor) when (prefilledOptions) {
is IconReplacement.CustomColor if prefilledOptions.color == IconReplacement.Aliucord.color -> {
changeMode(IconOptionsMode.Aliucord)
changeSelectedColor(IconReplacement.Aliucord.color)
}
is IconReplacement.CustomColor -> {
changeMode(IconOptionsMode.CustomColor)
changeSelectedColor(prefilledOptions.color)
}
is IconReplacement.CustomImage -> {
changeMode(IconOptionsMode.CustomImage)
TODO()
}
IconReplacement.Original -> changeMode(IconOptionsMode.Original)
}
} }
enum class Mode { fun generateConfig(): IconReplacement = when (mode) {
Original, IconOptionsMode.Original -> IconReplacement.Original
ReplaceColor, IconOptionsMode.Aliucord -> IconReplacement.Aliucord
ReplaceForeground, IconOptionsMode.CustomColor -> IconReplacement.CustomColor(color = selectedColor)
IconOptionsMode.CustomImage -> TODO()
} }
} }
enum class IconOptionsMode {
Original,
Aliucord,
CustomColor,
CustomImage,
}

View file

@ -1,17 +1,23 @@
package com.aliucord.manager.ui.screens.iconopts package com.aliucord.manager.ui.screens.iconopts
import android.os.Parcelable import android.os.Parcelable
import androidx.compose.animation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import com.aliucord.manager.R
import com.aliucord.manager.ui.screens.iconopts.components.IconOptionsAppBar import com.aliucord.manager.ui.screens.iconopts.components.IconOptionsAppBar
import com.aliucord.manager.ui.screens.iconopts.components.RadioSelectorItem
import dev.zt64.compose.pipette.CircularColorPicker import dev.zt64.compose.pipette.CircularColorPicker
import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -37,6 +43,8 @@ class IconOptionsScreen(
val model = parent.getIconModel() val model = parent.getIconModel()
IconOptionsScreenContent( IconOptionsScreenContent(
mode = model.mode,
setMode = model::changeMode,
selectedColor = model.selectedColor, selectedColor = model.selectedColor,
setSelectedColor = model::changeSelectedColor, setSelectedColor = model::changeSelectedColor,
) )
@ -45,6 +53,8 @@ class IconOptionsScreen(
@Composable @Composable
fun IconOptionsScreenContent( fun IconOptionsScreenContent(
mode: IconOptionsMode,
setMode: (IconOptionsMode) -> Unit,
selectedColor: Color, selectedColor: Color,
setSelectedColor: (Color) -> Unit, setSelectedColor: (Color) -> Unit,
) { ) {
@ -60,11 +70,42 @@ fun IconOptionsScreenContent(
.padding(paddingValues) .padding(paddingValues)
.padding(horizontal = 20.dp, vertical = 20.dp) .padding(horizontal = 20.dp, vertical = 20.dp)
) { ) {
CircularColorPicker( // TODO: live icon preview
color = selectedColor,
onColorChange = setSelectedColor, HorizontalDivider(Modifier.padding(vertical = 16.dp))
modifier = Modifier.size(250.dp)
RadioSelectorItem(
name = stringResource(R.string.discord),
description = stringResource(R.string.iconopts_variant_desc_discord),
selected = mode == IconOptionsMode.Original,
onClick = remember { { setMode(IconOptionsMode.Original) } },
) )
RadioSelectorItem(
name = stringResource(R.string.aliucord),
description = stringResource(R.string.iconopts_variant_desc_aliucord),
selected = mode == IconOptionsMode.Aliucord,
onClick = remember { { setMode(IconOptionsMode.Aliucord) } },
)
RadioSelectorItem(
name = stringResource(R.string.iconopts_variant_title_color),
description = stringResource(R.string.iconopts_variant_desc_color),
selected = mode == IconOptionsMode.CustomColor,
onClick = remember { { setMode(IconOptionsMode.CustomColor) } },
)
HorizontalDivider(Modifier.padding(vertical = 16.dp))
AnimatedVisibility(
visible = mode == IconOptionsMode.CustomColor,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically { -it / 10 },
) {
CircularColorPicker(
color = selectedColor,
onColorChange = setSelectedColor,
modifier = Modifier.size(230.dp),
)
}
} }
} }
} }

View file

@ -0,0 +1,48 @@
package com.aliucord.manager.ui.screens.iconopts.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp
import com.aliucord.manager.ui.screens.patchopts.components.options.PatchOption
@Composable
fun RadioSelectorItem(
name: String,
description: String,
selected: Boolean,
modifier: Modifier = Modifier.Companion,
onClick: () -> Unit,
) {
val interactionSource = remember(::MutableInteractionSource)
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
modifier = modifier
.fillMaxWidth()
.padding(end = 12.dp)
.clickable(
onClick = onClick,
interactionSource = interactionSource,
indication = null,
role = Role.Companion.Switch,
),
) {
RadioButton(
selected = selected,
onClick = onClick,
interactionSource = interactionSource,
)
PatchOption(
name = name,
description = description,
content = {},
)
}
}

View file

@ -165,6 +165,10 @@
<string name="patchopts_divider_advanced">Advanced</string> <string name="patchopts_divider_advanced">Advanced</string>
<string name="iconopts_screen_title">Icon Replacement</string> <string name="iconopts_screen_title">Icon Replacement</string>
<string name="iconopts_variant_title_color">Custom Color</string>
<string name="iconopts_variant_desc_discord">Does not alter the original icon, instead only adding the missing monochrome icon to the APK.</string>
<string name="iconopts_variant_desc_aliucord">Changes the original icon color to Aliucord\'s branding.</string>
<string name="iconopts_variant_desc_color">Select a custom icon background color.</string>
<string name="notif_group_install_title">Active installation</string> <string name="notif_group_install_title">Active installation</string>
<string name="notif_group_install_desc">Progress notifications sent during a minimized installation</string> <string name="notif_group_install_desc">Progress notifications sent during a minimized installation</string>