feat(IconOpts): colored icon preview
This commit is contained in:
parent
b89a529afa
commit
910be40d79
4 changed files with 151 additions and 3 deletions
|
|
@ -0,0 +1,82 @@
|
|||
package com.aliucord.manager.ui.components
|
||||
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.widget.ImageView
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.applyCanvas
|
||||
import androidx.core.graphics.createBitmap
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import com.aliucord.manager.R
|
||||
|
||||
@Composable
|
||||
fun discordIconDrawable(
|
||||
backgroundColor: Color,
|
||||
size: Dp = 24.dp,
|
||||
): Drawable {
|
||||
val density = LocalDensity.current
|
||||
val context = LocalContext.current
|
||||
val size = with(density) { size.roundToPx() }
|
||||
|
||||
val bitmap = remember(size) { createBitmap(size, size) }
|
||||
val drawable = remember(context) {
|
||||
InsetDrawable(
|
||||
/* drawable = */ ContextCompat.getDrawable(context, R.drawable.ic_discord)!!,
|
||||
/* inset = */ (size * .17f).toInt(),
|
||||
)
|
||||
}
|
||||
|
||||
DisposableEffect(size) {
|
||||
onDispose {
|
||||
bitmap.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(backgroundColor, bitmap, drawable) {
|
||||
bitmap.applyCanvas {
|
||||
val paint = Paint().apply {
|
||||
style = Paint.Style.FILL
|
||||
setColor(backgroundColor.toArgb())
|
||||
}
|
||||
|
||||
drawRect(Rect(0, 0, width, height), paint)
|
||||
drawable.setBounds(0, 0, width, height)
|
||||
drawable.draw(this)
|
||||
}
|
||||
|
||||
onDispose {}
|
||||
}
|
||||
|
||||
return remember(context, bitmap) {
|
||||
RoundedBitmapDrawableFactory.create(context.resources, bitmap).apply {
|
||||
isCircular = true
|
||||
setAntiAlias(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ColoredDiscordAppIcon(
|
||||
drawable: Drawable,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
ImageView(context).apply {
|
||||
setImageDrawable(drawable)
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -31,8 +31,10 @@ import coil3.compose.AsyncImage
|
|||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.ui.components.*
|
||||
import com.aliucord.manager.ui.screens.iconopts.components.*
|
||||
import com.aliucord.manager.ui.screens.patchopts.PatchOptions
|
||||
import com.aliucord.manager.ui.screens.patchopts.PatchOptionsScreen
|
||||
import com.aliucord.manager.ui.util.ColorSaver
|
||||
import com.aliucord.manager.ui.util.throttledState
|
||||
import dev.zt64.compose.pipette.CircularColorPicker
|
||||
import dev.zt64.compose.pipette.HsvColor
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
|
|
@ -88,7 +90,37 @@ fun IconOptionsScreenContent(
|
|||
.padding(paddingValues)
|
||||
.padding(horizontal = 20.dp, vertical = 20.dp)
|
||||
) {
|
||||
// TODO: live icon preview
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterHorizontally),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
val color = when (mode) {
|
||||
IconOptionsMode.Original -> PatchOptions.IconReplacement.Blurple.color // TODO: old vs new discord color?
|
||||
IconOptionsMode.Aliucord -> PatchOptions.IconReplacement.Aliucord.color
|
||||
IconOptionsMode.CustomColor -> selectedColor.toColor()
|
||||
IconOptionsMode.CustomImage -> Color.Black // TODO: custom image icon preview
|
||||
}
|
||||
val throttledColor by throttledState(value = color, throttleMs = 75)
|
||||
|
||||
val drawable = discordIconDrawable(
|
||||
backgroundColor = throttledColor,
|
||||
size = 72.dp,
|
||||
)
|
||||
|
||||
ColoredDiscordAppIcon(
|
||||
drawable = drawable,
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
ColoredDiscordAppIcon(
|
||||
drawable = drawable,
|
||||
modifier = Modifier.size(48.dp),
|
||||
)
|
||||
ColoredDiscordAppIcon(
|
||||
drawable = drawable,
|
||||
modifier = Modifier.size(72.dp),
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(Modifier.padding(vertical = 16.dp))
|
||||
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ data class PatchOptions(
|
|||
val Aliucord = CustomColor(Color(0xFF00C853))
|
||||
|
||||
/**
|
||||
* The Discord icon color.
|
||||
* The new Discord blurple.
|
||||
*/
|
||||
val Discord = CustomColor(Color(0xFF7289DA))
|
||||
val Blurple = CustomColor(Color(0xFF5865F2))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package com.aliucord.manager.ui.util
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
@Composable
|
||||
fun <T> throttledState(
|
||||
value: T,
|
||||
throttleMs: Long,
|
||||
): State<T> {
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = remember { mutableStateOf(value) }
|
||||
var lastEmitTime by remember { mutableLongStateOf(0L) }
|
||||
var trailingJob by remember { mutableStateOf<Job?>(null) }
|
||||
|
||||
LaunchedEffect(value) {
|
||||
val now = System.currentTimeMillis()
|
||||
val sinceLastEmit = now - lastEmitTime
|
||||
|
||||
if (sinceLastEmit >= throttleMs) {
|
||||
lastEmitTime = now
|
||||
state.value = value
|
||||
} else {
|
||||
trailingJob?.cancel()
|
||||
trailingJob = scope.launch {
|
||||
delay(throttleMs - sinceLastEmit)
|
||||
lastEmitTime = System.currentTimeMillis()
|
||||
state.value = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue