ui: feature section preview

This commit is contained in:
rhunk 2023-07-29 00:33:09 +02:00
parent d04ce42c7d
commit 5e41ccffd7
4 changed files with 137 additions and 20 deletions

View File

@ -27,9 +27,10 @@ class MainActivity : ComponentActivity() {
@SuppressLint("UnusedMaterialScaffoldPaddingParameter") @SuppressLint("UnusedMaterialScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val managerContext = ManagerContext(this)
setContent { setContent {
App(ManagerContext(this)) App(managerContext)
} }
} }
} }

View File

@ -8,9 +8,9 @@ import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper
class ManagerContext( class ManagerContext(
private val context: Context private val context: Context
) { ) {
private val config = ConfigWrapper() val config = ConfigWrapper()
private val translation = TranslationWrapper() val translation = TranslationWrapper()
private val mappings = MappingsWrapper(context) val mappings = MappingsWrapper(context)
init { init {
config.loadFromContext(context) config.loadFromContext(context)

View File

@ -1,25 +1,144 @@
package me.rhunk.snapenhance.manager.sections package me.rhunk.snapenhance.manager.sections
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column 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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn 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.material3.Text
import androidx.compose.runtime.Composable 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.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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 import me.rhunk.snapenhance.manager.Section
typealias ClickCallback = (Boolean) -> Unit
typealias AddClickCallback = (ClickCallback) -> ClickCallback
class FeaturesSection : Section() { 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 @Composable
@Preview @Preview
override fun Content() { override fun Content() {
val configItems = remember {
ConfigProperty.sortedByCategory()
}
Column { Column {
Text( Text(
text = "Features", text = "Features",
@ -31,20 +150,8 @@ class FeaturesSection : Section() {
.fillMaxSize(), .fillMaxSize(),
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
items(100) { index -> items(configItems) { item ->
OutlinedCard( PropertyCard(item)
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))
}
}
} }
} }
} }

View File

@ -5,6 +5,7 @@ import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.Logger
import me.rhunk.snapenhance.bridge.BridgeClient import me.rhunk.snapenhance.bridge.BridgeClient
import me.rhunk.snapenhance.config.ConfigProperty
import me.rhunk.snapenhance.data.LocalePair import me.rhunk.snapenhance.data.LocalePair
import java.util.Locale import java.util.Locale
@ -79,6 +80,14 @@ class TranslationWrapper {
return translationMap[key] ?: key.also { Logger.debug("Missing translation for $key") } 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 { fun format(key: String, vararg args: Pair<String, String>): String {
return args.fold(get(key)) { acc, pair -> return args.fold(get(key)) { acc, pair ->
acc.replace("{${pair.first}}", pair.second) acc.replace("{${pair.first}}", pair.second)