mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-13 13:47:47 +02:00
ui(features): dialogs & translations
This commit is contained in:
@ -22,8 +22,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = rootProject.ext["applicationId"].toString()
|
applicationId = rootProject.ext["applicationId"].toString()
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
//noinspection OldTargetApi
|
targetSdk = 34
|
||||||
targetSdk = 33
|
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,11 +36,12 @@ android {
|
|||||||
flavorDimensions += "abi"
|
flavorDimensions += "abi"
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
|
|
||||||
|
|
||||||
create("armv8") {
|
create("armv8") {
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters.add("arm64-v8a")
|
abiFilters.add("arm64-v8a")
|
||||||
}
|
}
|
||||||
|
|
||||||
dimension = "abi"
|
dimension = "abi"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,13 +81,13 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":core"))
|
implementation(project(":core"))
|
||||||
implementation(libs.androidx.material.icons.extended)
|
implementation(libs.androidx.material.icons.extended)
|
||||||
implementation(libs.androidx.navigation.compose)
|
|
||||||
implementation(libs.androidx.activity.ktx)
|
|
||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.material)
|
implementation(libs.androidx.material)
|
||||||
|
implementation(libs.androidx.activity.ktx)
|
||||||
|
implementation(libs.androidx.navigation.compose)
|
||||||
|
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling:1.4.3")
|
debugImplementation("androidx.compose.ui:ui-tooling:1.4.3")
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview:1.4.3")
|
debugImplementation("androidx.compose.ui:ui-tooling-preview:1.4.3")
|
||||||
implementation(kotlin("reflect"))
|
implementation(kotlin("reflect"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,159 +18,173 @@ import androidx.compose.material3.Switch
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
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.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.text.TextRange
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import me.rhunk.snapenhance.config.ConfigProperty
|
import me.rhunk.snapenhance.config.ConfigProperty
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigIntegerValue
|
import me.rhunk.snapenhance.config.impl.ConfigIntegerValue
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigStateListValue
|
import me.rhunk.snapenhance.config.impl.ConfigStateListValue
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigStateSelection
|
import me.rhunk.snapenhance.config.impl.ConfigStateSelection
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigStringValue
|
import me.rhunk.snapenhance.manager.data.ManagerContext
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
class Dialogs(
|
||||||
@Preview
|
private val context: ManagerContext
|
||||||
fun TestPreview() {
|
) {
|
||||||
KeyboardInputDialog(config = ConfigProperty.SAVE_FOLDER)
|
@Composable
|
||||||
}
|
fun DefaultDialogCard(content: @Composable ColumnScope.() -> Unit) {
|
||||||
|
Card(
|
||||||
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp, 5.dp, 10.dp, 10.dp),
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp, 10.dp, 10.dp, 10.dp)
|
||||||
|
.verticalScroll(ScrollState(0)),
|
||||||
|
) { content() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DefaultDialogCard(content: @Composable ColumnScope.() -> Unit) {
|
fun DefaultEntryText(text: String, modifier: Modifier = Modifier) {
|
||||||
Card(
|
Text(
|
||||||
shape = MaterialTheme.shapes.medium,
|
text = text,
|
||||||
modifier = Modifier
|
|
||||||
.padding(10.dp, 5.dp, 10.dp, 10.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(10.dp, 10.dp, 10.dp, 10.dp)
|
.padding(10.dp, 10.dp, 10.dp, 10.dp)
|
||||||
.verticalScroll(ScrollState(0)),
|
.then(modifier)
|
||||||
) { content() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun DefaultEntryText(text: String, modifier: Modifier = Modifier) {
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(10.dp, 10.dp, 10.dp, 10.dp)
|
|
||||||
.then(modifier)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun StateSelectionDialog(config: ConfigProperty) {
|
|
||||||
assert(config.valueContainer is ConfigStateSelection)
|
|
||||||
val keys = (config.valueContainer as ConfigStateSelection).keys()
|
|
||||||
val selectedValue = remember {
|
|
||||||
mutableStateOf(config.valueContainer.value())
|
|
||||||
}
|
|
||||||
DefaultDialogCard {
|
|
||||||
keys.forEach { item ->
|
|
||||||
fun select() {
|
|
||||||
selectedValue.value = item
|
|
||||||
config.valueContainer.writeFrom(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.clickable { select() },
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
DefaultEntryText(
|
|
||||||
text = item,
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
RadioButton(
|
|
||||||
selected = selectedValue.value == item,
|
|
||||||
onClick = { select() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun KeyboardInputDialog(config: ConfigProperty, dismiss: () -> Unit = {}) {
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
|
||||||
|
|
||||||
DefaultDialogCard {
|
|
||||||
val fieldValue = remember { mutableStateOf(config.valueContainer.read()) }
|
|
||||||
TextField(
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(all = 10.dp).focusRequester(focusRequester),
|
|
||||||
value = fieldValue.value, onValueChange = {
|
|
||||||
fieldValue.value = it
|
|
||||||
},
|
|
||||||
keyboardOptions = when (config.valueContainer) {
|
|
||||||
is ConfigIntegerValue -> {
|
|
||||||
KeyboardOptions(keyboardType = KeyboardType.Number)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
KeyboardOptions(keyboardType = KeyboardType.Text)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
singleLine = true
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
@Composable
|
||||||
modifier = Modifier.padding(top = 10.dp).fillMaxWidth(),
|
fun StateSelectionDialog(config: ConfigProperty) {
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
assert(config.valueContainer is ConfigStateSelection)
|
||||||
) {
|
val keys = (config.valueContainer as ConfigStateSelection).keys()
|
||||||
Button(onClick = { dismiss() }) {
|
val selectedValue = remember {
|
||||||
Text(text = "Cancel")
|
mutableStateOf(config.valueContainer.value())
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
DefaultDialogCard {
|
||||||
config.valueContainer.writeFrom(fieldValue.value)
|
keys.forEach { item ->
|
||||||
dismiss()
|
fun select() {
|
||||||
}) {
|
selectedValue.value = item
|
||||||
Text(text = "Ok")
|
config.valueContainer.writeFrom(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.clickable { select() },
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
DefaultEntryText(
|
||||||
|
text = if (config.disableValueLocalization)
|
||||||
|
item
|
||||||
|
else context.translation.propertyOption(config, item),
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
RadioButton(
|
||||||
|
selected = selectedValue.value == item,
|
||||||
|
onClick = { select() }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
@Composable
|
||||||
focusRequester.requestFocus()
|
fun KeyboardInputDialog(config: ConfigProperty, dismiss: () -> Unit = {}) {
|
||||||
}
|
val focusRequester = remember { FocusRequester() }
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
DefaultDialogCard {
|
||||||
fun StateListDialog(config: ConfigProperty) {
|
val fieldValue = remember {
|
||||||
assert(config.valueContainer is ConfigStateListValue)
|
mutableStateOf(config.valueContainer.read().let {
|
||||||
val stateList = (config.valueContainer as ConfigStateListValue).value()
|
TextFieldValue(
|
||||||
DefaultDialogCard {
|
text = it,
|
||||||
stateList.keys.forEach { key ->
|
selection = TextRange(it.length)
|
||||||
val state = remember {
|
)
|
||||||
mutableStateOf(stateList[key] ?: false)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggle(value: Boolean? = null) {
|
TextField(
|
||||||
state.value = value ?: !state.value
|
modifier = Modifier
|
||||||
stateList[key] = state.value
|
.fillMaxWidth()
|
||||||
}
|
.padding(all = 10.dp)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
.focusRequester(focusRequester),
|
||||||
|
value = fieldValue.value,
|
||||||
|
onValueChange = {
|
||||||
|
fieldValue.value = it
|
||||||
|
},
|
||||||
|
keyboardOptions = when (config.valueContainer) {
|
||||||
|
is ConfigIntegerValue -> {
|
||||||
|
KeyboardOptions(keyboardType = KeyboardType.Number)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
KeyboardOptions(keyboardType = KeyboardType.Text)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.clickable { toggle() },
|
modifier = Modifier.padding(top = 10.dp).fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
) {
|
) {
|
||||||
DefaultEntryText(
|
Button(onClick = { dismiss() }) {
|
||||||
text = key,
|
Text(text = "Cancel")
|
||||||
modifier = Modifier
|
}
|
||||||
.weight(1f)
|
Button(onClick = {
|
||||||
)
|
config.valueContainer.writeFrom(fieldValue.value.text)
|
||||||
Switch(
|
dismiss()
|
||||||
checked = state.value,
|
}) {
|
||||||
onCheckedChange = {
|
Text(text = "Ok")
|
||||||
toggle(it)
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Composable
|
||||||
|
fun StateListDialog(config: ConfigProperty) {
|
||||||
|
assert(config.valueContainer is ConfigStateListValue)
|
||||||
|
val stateList = (config.valueContainer as ConfigStateListValue).value()
|
||||||
|
DefaultDialogCard {
|
||||||
|
stateList.keys.forEach { key ->
|
||||||
|
val state = remember {
|
||||||
|
mutableStateOf(stateList[key] ?: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggle(value: Boolean? = null) {
|
||||||
|
state.value = value ?: !state.value
|
||||||
|
stateList[key] = state.value
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.clickable { toggle() },
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
DefaultEntryText(
|
||||||
|
text = if (config.disableValueLocalization)
|
||||||
|
key
|
||||||
|
else context.translation.propertyOption(config, key),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
Switch(
|
||||||
|
checked = state.value,
|
||||||
|
onCheckedChange = {
|
||||||
|
toggle(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,22 +4,8 @@ import android.annotation.SuppressLint
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Settings
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.navigation.compose.NavHost
|
|
||||||
import androidx.navigation.compose.composable
|
|
||||||
import androidx.navigation.compose.navigation
|
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import me.rhunk.snapenhance.manager.data.ManagerContext
|
import me.rhunk.snapenhance.manager.data.ManagerContext
|
||||||
|
|
||||||
@ -27,26 +13,20 @@ class MainActivity : ComponentActivity() {
|
|||||||
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
|
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
val startDestination = intent.getStringExtra("route")?.let { EnumSection.fromRoute(it) } ?: EnumSection.HOME
|
||||||
val managerContext = ManagerContext(this)
|
val managerContext = ManagerContext(this)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
App(managerContext)
|
val navController = rememberNavController()
|
||||||
|
val navigation = Navigation(managerContext)
|
||||||
|
AppMaterialTheme {
|
||||||
|
Scaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.background,
|
||||||
|
bottomBar = { navigation.NavBar(navController = navController) }
|
||||||
|
) { innerPadding ->
|
||||||
|
navigation.NavigationHost(navController = navController, innerPadding = innerPadding, startDestination = startDestination)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun App(
|
|
||||||
context: ManagerContext
|
|
||||||
) {
|
|
||||||
val navController = rememberNavController()
|
|
||||||
val navigation = Navigation(context)
|
|
||||||
AppMaterialTheme {
|
|
||||||
Scaffold(
|
|
||||||
containerColor = MaterialTheme.colorScheme.background,
|
|
||||||
bottomBar = { navigation.NavBar(navController = navController) }
|
|
||||||
) { innerPadding ->
|
|
||||||
navigation.NavigationHost(navController = navController, innerPadding = innerPadding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,6 +30,7 @@ class Navigation(
|
|||||||
) {
|
) {
|
||||||
@Composable
|
@Composable
|
||||||
fun NavigationHost(
|
fun NavigationHost(
|
||||||
|
startDestination: EnumSection,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
innerPadding: PaddingValues
|
innerPadding: PaddingValues
|
||||||
) {
|
) {
|
||||||
@ -40,7 +41,7 @@ class Navigation(
|
|||||||
instance.navController = navController
|
instance.navController = navController
|
||||||
} }
|
} }
|
||||||
|
|
||||||
NavHost(navController, startDestination = EnumSection.FEATURES.route, Modifier.padding(innerPadding)) {
|
NavHost(navController, startDestination = startDestination.route, Modifier.padding(innerPadding)) {
|
||||||
sections.forEach { (section, instance) ->
|
sections.forEach { (section, instance) ->
|
||||||
composable(section.route) {
|
composable(section.route) {
|
||||||
instance.Content()
|
instance.Content()
|
||||||
|
@ -48,6 +48,12 @@ enum class EnumSection(
|
|||||||
title = "Debug",
|
title = "Debug",
|
||||||
icon = Icons.Filled.BugReport
|
icon = Icons.Filled.BugReport
|
||||||
);
|
);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromRoute(route: String): EnumSection {
|
||||||
|
return values().first { it.route == route }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,9 +4,12 @@ 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.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
@ -31,6 +34,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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
|
||||||
@ -43,15 +47,15 @@ import me.rhunk.snapenhance.config.impl.ConfigStateListValue
|
|||||||
import me.rhunk.snapenhance.config.impl.ConfigStateSelection
|
import me.rhunk.snapenhance.config.impl.ConfigStateSelection
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigStateValue
|
import me.rhunk.snapenhance.config.impl.ConfigStateValue
|
||||||
import me.rhunk.snapenhance.config.impl.ConfigStringValue
|
import me.rhunk.snapenhance.config.impl.ConfigStringValue
|
||||||
import me.rhunk.snapenhance.manager.StateListDialog
|
import me.rhunk.snapenhance.manager.Dialogs
|
||||||
import me.rhunk.snapenhance.manager.Section
|
import me.rhunk.snapenhance.manager.Section
|
||||||
import me.rhunk.snapenhance.manager.StateSelectionDialog
|
|
||||||
import me.rhunk.snapenhance.manager.KeyboardInputDialog
|
|
||||||
|
|
||||||
typealias ClickCallback = (Boolean) -> Unit
|
typealias ClickCallback = (Boolean) -> Unit
|
||||||
typealias RegisterClickCallback = (ClickCallback) -> ClickCallback
|
typealias RegisterClickCallback = (ClickCallback) -> ClickCallback
|
||||||
|
|
||||||
class FeaturesSection : Section() {
|
class FeaturesSection : Section() {
|
||||||
|
private val dialogs by lazy { Dialogs(manager) }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PropertyAction(item: ConfigProperty, registerClickCallback: RegisterClickCallback) {
|
private fun PropertyAction(item: ConfigProperty, registerClickCallback: RegisterClickCallback) {
|
||||||
val showDialog = remember { mutableStateOf(false) }
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
@ -82,12 +86,15 @@ class FeaturesSection : Section() {
|
|||||||
is ConfigStateSelection -> {
|
is ConfigStateSelection -> {
|
||||||
registerDialogOnClickCallback()
|
registerDialogOnClickCallback()
|
||||||
dialogComposable.value = {
|
dialogComposable.value = {
|
||||||
StateSelectionDialog(item)
|
dialogs.StateSelectionDialog(item)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = container.value().let {
|
overflow = TextOverflow.Ellipsis,
|
||||||
it.substring(0, it.length.coerceAtMost(20))
|
maxLines = 1,
|
||||||
}
|
modifier = Modifier.widthIn(0.dp, 120.dp),
|
||||||
|
text = if (item.disableValueLocalization) container.value() else {
|
||||||
|
manager.translation.propertyOption(item, container.value())
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,10 +102,10 @@ class FeaturesSection : Section() {
|
|||||||
dialogComposable.value = {
|
dialogComposable.value = {
|
||||||
when (container) {
|
when (container) {
|
||||||
is ConfigStateListValue -> {
|
is ConfigStateListValue -> {
|
||||||
StateListDialog(item)
|
dialogs.StateListDialog(item)
|
||||||
}
|
}
|
||||||
is ConfigStringValue, is ConfigIntegerValue -> {
|
is ConfigStringValue, is ConfigIntegerValue -> {
|
||||||
KeyboardInputDialog(item) { showDialog.value = false }
|
dialogs.KeyboardInputDialog(item) { showDialog.value = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +113,7 @@ class FeaturesSection : Section() {
|
|||||||
registerDialogOnClickCallback().let { { it.invoke(true) } }.also {
|
registerDialogOnClickCallback().let { { it.invoke(true) } }.also {
|
||||||
if (container is ConfigIntegerValue) {
|
if (container is ConfigIntegerValue) {
|
||||||
FilledIconButton(onClick = it) {
|
FilledIconButton(onClick = it) {
|
||||||
Text(text = container.value().toString())
|
Text(text = container.value().toString(), modifier = Modifier.wrapContentWidth(), overflow = TextOverflow.Ellipsis)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IconButton(onClick = it) {
|
IconButton(onClick = it) {
|
||||||
@ -132,7 +139,7 @@ class FeaturesSection : Section() {
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(all = 10.dp),
|
.padding(all = 4.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -206,10 +213,11 @@ class FeaturesSection : Section() {
|
|||||||
)
|
)
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxHeight(),
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
items(configItems) { item ->
|
items(configItems) { item ->
|
||||||
|
if (item.shouldAppearInSettings.not()) return@items
|
||||||
PropertyCard(item)
|
PropertyCard(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package me.rhunk.snapenhance.manager.sections
|
package me.rhunk.snapenhance.manager.sections
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import me.rhunk.snapenhance.manager.Section
|
import me.rhunk.snapenhance.manager.Section
|
||||||
|
|
||||||
class NotImplemented : Section() {
|
class NotImplemented : Section() {
|
||||||
|
@ -88,6 +88,10 @@ class TranslationWrapper {
|
|||||||
return get("property.${property.translationKey}.description")
|
return get("property.${property.translationKey}.description")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun propertyOption(property: ConfigProperty, item: String): String {
|
||||||
|
return get(property.getOptionTranslationKey(item))
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -48,9 +48,10 @@ class SettingsGearInjector : AbstractMenu() {
|
|||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
val intent = Intent().apply {
|
val intent = Intent().apply {
|
||||||
setClassName(BuildConfig.APPLICATION_ID, ConfigActivity::class.java.name)
|
setClassName(BuildConfig.APPLICATION_ID, "me.rhunk.snapenhance.manager.MainActivity")
|
||||||
|
putExtra("route", "features")
|
||||||
|
putExtra("lspatched", File(context.cacheDir, "lspatch/origin").exists())
|
||||||
}
|
}
|
||||||
intent.putExtra("lspatched", File(context.cacheDir, "lspatch/origin").exists())
|
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user