commit 5e41ccffd7d15351597959c3f5e253b4c67ff81d
parent d04ce42c7dd6618fcd7efff86196fdec6742da20
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat, 29 Jul 2023 00:33:09 +0200

ui: feature section preview

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/manager/MainActivity.kt | 3++-
Mapp/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt | 6+++---
Mapp/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt | 139++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mcore/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt | 9+++++++++
4 files changed, 137 insertions(+), 20 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/MainActivity.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/MainActivity.kt @@ -27,9 +27,10 @@ class MainActivity : ComponentActivity() { @SuppressLint("UnusedMaterialScaffoldPaddingParameter") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val managerContext = ManagerContext(this) setContent { - App(ManagerContext(this)) + App(managerContext) } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt @@ -8,9 +8,9 @@ import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper class ManagerContext( private val context: Context ) { - private val config = ConfigWrapper() - private val translation = TranslationWrapper() - private val mappings = MappingsWrapper(context) + val config = ConfigWrapper() + val translation = TranslationWrapper() + val mappings = MappingsWrapper(context) init { config.loadFromContext(context) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt @@ -1,25 +1,144 @@ package me.rhunk.snapenhance.manager.sections +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.OutlinedCard +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.OpenInNew +import androidx.compose.material3.Card +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import me.rhunk.snapenhance.config.ConfigProperty +import me.rhunk.snapenhance.config.impl.ConfigIntegerValue +import me.rhunk.snapenhance.config.impl.ConfigStateListValue +import me.rhunk.snapenhance.config.impl.ConfigStateSelection +import me.rhunk.snapenhance.config.impl.ConfigStateValue +import me.rhunk.snapenhance.config.impl.ConfigStringValue import me.rhunk.snapenhance.manager.Section +typealias ClickCallback = (Boolean) -> Unit +typealias AddClickCallback = (ClickCallback) -> ClickCallback + class FeaturesSection : Section() { @Composable + private fun PropertyAction(item: ConfigProperty, clickCallback: AddClickCallback) { + when (val configValueContainer = remember { item.valueContainer }) { + is ConfigStateValue -> { + val state = remember { + mutableStateOf(configValueContainer.value()) + } + + Switch( + checked = state.value, + onCheckedChange = clickCallback { + state.value = !state.value + configValueContainer.writeFrom(state.value.toString()) + } + ) + } + + is ConfigStateSelection -> { + Text( + text = configValueContainer.value().let { + it.substring(0, it.length.coerceAtMost(20)) + } + ) + } + + is ConfigStateListValue -> { + IconButton(onClick = { }) { + Icon(Icons.Filled.OpenInNew, contentDescription = null) + } + } + + is ConfigIntegerValue -> { + FilledIconButton(onClick = { }) { + Text(text = configValueContainer.value().toString()) + } + } + + is ConfigStringValue -> { + Text( + text = configValueContainer.value().let { + it.substring(0, it.length.coerceAtMost(20)) + } + ) + } + } + } + + @OptIn(ExperimentalLayoutApi::class) + @Composable + private fun PropertyCard(item: ConfigProperty) { + val clickCallback = remember { mutableStateOf<ClickCallback?>(null) } + Card( + modifier = Modifier + .fillMaxWidth() + .clickable { + clickCallback.value?.invoke(true) + } + .padding(start = 10.dp, end = 10.dp, top = 5.dp, bottom = 5.dp) + ) { + FlowRow( + modifier = Modifier + .fillMaxSize() + .padding(all = 10.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .weight(1f, fill = true) + .padding(all = 10.dp) + ) { + Text(text = manager.translation.propertyName(item), fontSize = 16.sp) + Text( + text = manager.translation.propertyDescription(item), + fontSize = 12.sp, + lineHeight = 15.sp + ) + } + + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(all = 10.dp) + ) { + PropertyAction(item, clickCallback = { callback -> + clickCallback.value = callback + callback + }) + } + } + } + } + + + + @Composable @Preview override fun Content() { + val configItems = remember { + ConfigProperty.sortedByCategory() + } Column { Text( text = "Features", @@ -31,20 +150,8 @@ class FeaturesSection : Section() { .fillMaxSize(), verticalArrangement = Arrangement.Center ) { - items(100) { index -> - OutlinedCard( - modifier = Modifier - .fillMaxWidth() - .padding(all = 10.dp) - .height(70.dp) - ) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center - ) { - Text(text = "Feature $index", modifier = Modifier.padding(all = 15.dp)) - } - } + items(configItems) { item -> + PropertyCard(item) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt @@ -5,6 +5,7 @@ import com.google.gson.JsonObject import com.google.gson.JsonParser import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.bridge.BridgeClient +import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.LocalePair import java.util.Locale @@ -79,6 +80,14 @@ class TranslationWrapper { return translationMap[key] ?: key.also { Logger.debug("Missing translation for $key") } } + fun propertyName(property: ConfigProperty): String { + return get("property.${property.translationKey}.name") + } + + fun propertyDescription(property: ConfigProperty): String { + return get("property.${property.translationKey}.description") + } + fun format(key: String, vararg args: Pair<String, String>): String { return args.fold(get(key)) { acc, pair -> acc.replace("{${pair.first}}", pair.second)