refactor: compose icon deprecation

- refactor script interface
This commit is contained in:
rhunk
2023-10-07 11:30:56 +02:00
parent f3cc14f405
commit bc67308df8
9 changed files with 170 additions and 138 deletions

View File

@@ -6,7 +6,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -80,7 +80,7 @@ class Navigation(
IconButton(
onClick = { navHostController.popBackStack() }
) {
Icon(Icons.Filled.ArrowBack, contentDescription = null)
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null)
}
}
}, actions = {

View File

@@ -8,9 +8,9 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.FilterList
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -218,7 +218,7 @@ class DownloadsSection : Section() {
context.androidContext.startActivity(intent)
}) {
Icon(
imageVector = Icons.Default.OpenInNew,
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
contentDescription = null
)
}

View File

@@ -12,10 +12,10 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.FolderOpen
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.rounded.Save
import androidx.compose.material3.*
@@ -224,7 +224,7 @@ class FeaturesSection : Section() {
}
} else {
IconButton(onClick = it) {
Icon(Icons.Filled.OpenInNew, contentDescription = null)
Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null)
}
}
}

View File

@@ -7,6 +7,7 @@ import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
@@ -155,7 +156,7 @@ class HomeSection : Section() {
Button(onClick = {
context.checkForRequirements(Requirements.LANGUAGE)
}, modifier = Modifier.height(40.dp)) {
Icon(Icons.Filled.OpenInNew, contentDescription = null)
Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null)
}
}
}

View File

@@ -5,7 +5,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
@@ -73,7 +73,7 @@ class SettingsSection : Section() {
Text(text = title, modifier = Modifier.padding(start = 26.dp))
IconButton(onClick = { takeAction() }) {
Icon(
imageVector = Icons.Filled.OpenInNew,
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
contentDescription = null,
modifier = Modifier.size(24.dp)
)

View File

@@ -0,0 +1,154 @@
package me.rhunk.snapenhance.ui.manager.sections.scripting
import androidx.compose.foundation.layout.*
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import me.rhunk.snapenhance.core.Logger
import me.rhunk.snapenhance.scripting.impl.ui.InterfaceBuilder
import me.rhunk.snapenhance.scripting.impl.ui.components.Node
import me.rhunk.snapenhance.scripting.impl.ui.components.NodeType
import kotlin.math.abs
@Composable
@Suppress("UNCHECKED_CAST")
private fun DrawNode(node: Node) {
val coroutineScope = rememberCoroutineScope()
val cachedAttributes = remember { mutableStateMapOf(*node.attributes.toList().toTypedArray()) }
node.uiChangeDetection = { key, value ->
coroutineScope.launch {
cachedAttributes[key] = value
}
}
DisposableEffect(Unit) {
onDispose {
node.uiChangeDetection = { _, _ -> }
}
}
val arrangement = cachedAttributes["arrangement"]
val alignment = cachedAttributes["alignment"]
val spacing = cachedAttributes["spacing"]?.toString()?.toInt()?.let { abs(it) }
val rowColumnModifier = Modifier
.then(if (cachedAttributes["fillMaxWidth"] as? Boolean == true) Modifier.fillMaxWidth() else Modifier)
.then(if (cachedAttributes["fillMaxHeight"] as? Boolean == true) Modifier.fillMaxHeight() else Modifier)
.padding(
(cachedAttributes["padding"]
?.toString()
?.toInt()
?.let { abs(it) } ?: 2).dp)
fun runCallbackSafe(callback: () -> Unit) {
runCatching {
callback()
}.onFailure {
Logger.directError("Error running callback", it)
}
}
@Composable
fun NodeLabel() {
Text(
text = cachedAttributes["label"] as String,
fontSize = (cachedAttributes["fontSize"]?.toString()?.toInt() ?: 14).sp,
color = (cachedAttributes["color"] as? Long)?.let { Color(it) } ?: Color.Unspecified
)
}
when (node.type) {
NodeType.COLUMN -> {
Column(
verticalArrangement = arrangement as? Arrangement.Vertical ?: spacing?.let { Arrangement.spacedBy(it.dp) } ?: Arrangement.Top,
horizontalAlignment = alignment as? Alignment.Horizontal ?: Alignment.Start,
modifier = rowColumnModifier
) {
node.children.forEach { child ->
DrawNode(child)
}
}
}
NodeType.ROW -> {
Row(
horizontalArrangement = arrangement as? Arrangement.Horizontal ?: spacing?.let { Arrangement.spacedBy(it.dp) } ?: Arrangement.SpaceBetween,
verticalAlignment = alignment as? Alignment.Vertical ?: Alignment.CenterVertically,
modifier = rowColumnModifier
) {
node.children.forEach { child ->
DrawNode(child)
}
}
}
NodeType.TEXT -> NodeLabel()
NodeType.SWITCH -> {
var switchState by remember {
mutableStateOf(cachedAttributes["state"] as Boolean)
}
Switch(
checked = switchState,
onCheckedChange = { state ->
runCallbackSafe {
switchState = state
node.setAttribute("state", state)
(cachedAttributes["callback"] as? (Boolean) -> Unit)?.let { it(state) }
}
}
)
}
NodeType.SLIDER -> {
var sliderValue by remember {
mutableFloatStateOf((cachedAttributes["value"] as Int).toFloat())
}
Slider(
value = sliderValue,
onValueChange = { value ->
runCallbackSafe {
sliderValue = value
node.setAttribute("value", value.toInt())
(cachedAttributes["callback"] as? (Int) -> Unit)?.let { it(value.toInt()) }
}
},
valueRange = (cachedAttributes["min"] as Int).toFloat()..(cachedAttributes["max"] as Int).toFloat(),
steps = cachedAttributes["step"] as Int,
)
}
NodeType.BUTTON -> {
OutlinedButton(onClick = {
runCallbackSafe {
(cachedAttributes["callback"] as? () -> Unit)?.let { it() }
}
}) {
NodeLabel()
}
}
else -> {}
}
}
@Composable
fun ScriptInterface(interfaceBuilder: InterfaceBuilder) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
interfaceBuilder.nodes.forEach { node ->
DrawNode(node)
}
LaunchedEffect(interfaceBuilder) {
interfaceBuilder.onLaunchedCallback?.invoke()
}
}
}

View File

@@ -9,19 +9,15 @@ import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.rhunk.snapenhance.scripting.impl.ui.components.Node
import me.rhunk.snapenhance.scripting.impl.ui.components.NodeType
import me.rhunk.snapenhance.scripting.type.ModuleInfo
import me.rhunk.snapenhance.ui.manager.Section
import me.rhunk.snapenhance.ui.util.pullrefresh.PullRefreshIndicator
import me.rhunk.snapenhance.ui.util.pullrefresh.pullRefresh
import me.rhunk.snapenhance.ui.util.pullrefresh.rememberPullRefreshState
import kotlin.math.abs
class ScriptsSection : Section() {
@Composable
@@ -88,115 +84,6 @@ class ScriptsSection : Section() {
}
}
@Composable
private fun DrawNode(node: Node) {
val coroutineScope = rememberCoroutineScope()
val cachedAttributes = remember { mutableStateMapOf(*node.attributes.toList().toTypedArray()) }
node.uiChangeDetection = { key, value ->
coroutineScope.launch {
cachedAttributes[key] = value
}
}
val arrangement = cachedAttributes["arrangement"]
val alignment = cachedAttributes["alignment"]
val spacing = cachedAttributes["spacing"]?.toString()?.toInt()?.let { abs(it) }
val rowColumnModifier = Modifier
.then(if (cachedAttributes["fillMaxWidth"] as? Boolean == true) Modifier.fillMaxWidth() else Modifier)
.then(if (cachedAttributes["fillMaxHeight"] as? Boolean == true) Modifier.fillMaxHeight() else Modifier)
.padding(
(cachedAttributes["padding"]
?.toString()
?.toInt()
?.let { abs(it) } ?: 2).dp)
fun runCallbackSafe(callback: () -> Unit) {
runCatching {
callback()
}.onFailure {
context.log.error("Error running callback", it)
}
}
@Composable
fun NodeLabel() {
Text(
text = cachedAttributes["label"] as String,
fontSize = (cachedAttributes["fontSize"]?.toString()?.toInt() ?: 14).sp,
color = (cachedAttributes["color"] as? Long)?.let { Color(it) } ?: Color.Unspecified
)
}
when (node.type) {
NodeType.COLUMN -> {
Column(
verticalArrangement = arrangement as? Arrangement.Vertical ?: spacing?.let { Arrangement.spacedBy(it.dp) } ?: Arrangement.Top,
horizontalAlignment = alignment as? Alignment.Horizontal ?: Alignment.Start,
modifier = rowColumnModifier
) {
node.children.forEach { child ->
DrawNode(child)
}
}
}
NodeType.ROW -> {
Row(
horizontalArrangement = arrangement as? Arrangement.Horizontal ?: spacing?.let { Arrangement.spacedBy(it.dp) } ?: Arrangement.SpaceBetween,
verticalAlignment = alignment as? Alignment.Vertical ?: Alignment.CenterVertically,
modifier = rowColumnModifier
) {
node.children.forEach { child ->
DrawNode(child)
}
}
}
NodeType.TEXT -> NodeLabel()
NodeType.SWITCH -> {
var switchState by remember {
mutableStateOf(cachedAttributes["state"] as Boolean)
}
Switch(
checked = switchState,
onCheckedChange = { state ->
runCallbackSafe {
switchState = state
node.setAttribute("state", state)
(cachedAttributes["callback"] as? (Boolean) -> Unit)?.let { it(state) }
}
}
)
}
NodeType.SLIDER -> {
var sliderValue by remember {
mutableFloatStateOf((cachedAttributes["value"] as Int).toFloat())
}
Slider(
value = sliderValue,
onValueChange = { value ->
runCallbackSafe {
sliderValue = value
node.setAttribute("value", value.toInt())
(cachedAttributes["callback"] as? (Int) -> Unit)?.let { it(value.toInt()) }
}
},
valueRange = (cachedAttributes["min"] as Int).toFloat()..(cachedAttributes["max"] as Int).toFloat(),
steps = cachedAttributes["step"] as Int,
)
}
NodeType.BUTTON -> {
OutlinedButton(onClick = {
runCallbackSafe {
(cachedAttributes["callback"] as? () -> Unit)?.let { it() }
}
}) {
NodeLabel()
}
}
else -> {}
}
}
@Composable
fun ScriptSettings(script: ModuleInfo) {
@@ -211,19 +98,7 @@ class ScriptsSection : Section() {
return
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
settingsInterface.nodes.forEach { node ->
DrawNode(node)
}
LaunchedEffect(settingsInterface) {
settingsInterface.onLaunchedCallback?.invoke()
}
}
ScriptInterface(interfaceBuilder = settingsInterface)
}
@@ -259,13 +134,14 @@ class ScriptsSection : Section() {
modifier = Modifier
.fillMaxSize()
.pullRefresh(pullRefreshState),
horizontalAlignment = Alignment.CenterHorizontally
) {
item {
if (scriptModules.isEmpty()) {
Text(
text = "No scripts found",
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(8.dp).align(Alignment.Center)
modifier = Modifier.padding(8.dp)
)
}
}

View File

@@ -9,7 +9,7 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowForwardIos
import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
@@ -122,7 +122,7 @@ class SetupActivity : ComponentActivity() {
imageVector = if (requiredScreens.size <= 1 && canGoNext) {
Icons.Default.Check
} else {
Icons.Default.ArrowForwardIos
Icons.AutoMirrored.Default.ArrowForwardIos
},
contentDescription = null
)

View File

@@ -7,6 +7,7 @@ import me.rhunk.snapenhance.ui.menu.AbstractMenu
class SettingsMenu : AbstractMenu() {
//TODO: quick settings
@SuppressLint("SetTextI18n")
@Suppress("UNUSED_PARAMETER")
fun inject(viewModel: View, addView: (View) -> Unit) {
/*val actions = context.actionManager.getActions().map {
Pair(it) {