@@ -4,28 +4,39 @@ import android.content.Intent
44import android.widget.Toast
55import androidx.compose.foundation.layout.Box
66import androidx.compose.foundation.layout.Column
7+ import androidx.compose.foundation.layout.Row
8+ import androidx.compose.foundation.layout.fillMaxSize
9+ import androidx.compose.foundation.layout.fillMaxWidth
710import androidx.compose.foundation.layout.padding
11+ import androidx.compose.foundation.rememberScrollState
12+ import androidx.compose.foundation.verticalScroll
813import androidx.compose.material3.Button
14+ import androidx.compose.material3.Card
915import androidx.compose.material3.DrawerValue
1016import androidx.compose.material3.MaterialTheme
1117import androidx.compose.material3.Text
1218import androidx.compose.material3.TextField
1319import androidx.compose.material3.rememberDrawerState
1420import androidx.compose.runtime.Composable
21+ import androidx.compose.runtime.LaunchedEffect
22+ import androidx.compose.runtime.collectAsState
1523import androidx.compose.runtime.getValue
24+ import androidx.compose.runtime.mutableIntStateOf
1625import androidx.compose.runtime.mutableStateMapOf
1726import androidx.compose.runtime.mutableStateOf
1827import androidx.compose.runtime.remember
1928import androidx.compose.runtime.rememberCoroutineScope
2029import androidx.compose.runtime.setValue
2130import androidx.compose.runtime.snapshots.SnapshotStateMap
2231import androidx.compose.ui.Modifier
32+ import androidx.compose.ui.platform.LocalLifecycleOwner
2333import androidx.compose.ui.res.stringResource
2434import androidx.compose.ui.tooling.preview.Preview
35+ import androidx.compose.ui.unit.dp
36+ import androidx.lifecycle.Lifecycle
2537import androidx.navigation.compose.rememberNavController
2638import org.andbootmgr.app.util.ConfigFile
2739import java.io.File
28- import java.util.Random
2940
3041/*
3142 uint32_t win_bg_color;
@@ -42,7 +53,8 @@ import java.util.Random
4253 uint32_t button_unselected_text_color;
4354 uint32_t button_selected_color;
4455 uint32_t button_selected_text_color;
45- uint8_t button_radius;
56+ uint8_t button_unselected_radius;
57+ uint8_t button_selected_radius;
4658 bool button_grow_default;
4759 uint8_t button_border_unselected_size;
4860 uint32_t button_border_unselected_color;
@@ -65,34 +77,37 @@ fun Themes(vm: MainActivityState) {
6577 }
6678 }
6779 }
68- val e = remember { mutableStateMapOf<Long , Boolean >() }
69- val col = { it: String -> it.startsWith(" 0x" ) && (it.toIntOrNull(16 ) ? : - 1 ) in 0 .. 0xffffff }
70- Column {
71- ConfigTextField (c, e, stringResource(id = R .string.win_bg_color), " win_bg_color" , validate = col)
72- ConfigTextField (c, e, stringResource(id = R .string.win_radius), " win_radius" ) { it.toShortOrNull() != null }
73- ConfigTextField (c, e, stringResource(id = R .string.win_border_size), " win_border_size" ) { it.toShortOrNull() != null }
74- ConfigTextField (c, e, stringResource(id = R .string.win_border_color), " win_border_color" , validate = col)
75- ConfigTextField (c, e, stringResource(id = R .string.list_bg_color), " list_bg_color" , validate = col)
76- ConfigTextField (c, e, stringResource(id = R .string.list_radius), " list_radius" ) { it.toShortOrNull() != null }
77- ConfigTextField (c, e, stringResource(id = R .string.list_border_size), " list_border_size" ) { it.toShortOrNull() != null }
78- ConfigTextField (c, e, stringResource(id = R .string.list_border_color), " list_border_color" , validate = col)
79- ConfigTextField (c, e, stringResource(id = R .string.global_font_size), " global_font_size" ) { it.toIntOrNull() != null }
80- ConfigTextField (c, e, stringResource(id = R .string.global_font_name), " global_font_name" ) { true /* should check if exists later */ }
81- ConfigTextField (c, e, stringResource(id = R .string.button_unselected_color), " button_unselected_color" , validate = col)
82- ConfigTextField (c, e, stringResource(id = R .string.button_unselected_text_color), " button_unselected_text_color" , validate = col)
83- ConfigTextField (c, e, stringResource(id = R .string.button_unselected_size), " button_unselected_size" ) { it.toIntOrNull() != null }
84- ConfigTextField (c, e, stringResource(id = R .string.button_selected_color), " button_selected_color" , validate = col)
85- ConfigTextField (c, e, stringResource(id = R .string.button_selected_text_color), " button_selected_text_color" , validate = col)
86- ConfigTextField (c, e, stringResource(id = R .string.button_selected_size), " button_selected_size" ) { it.toIntOrNull() != null }
87- ConfigTextField (c, e, stringResource(id = R .string.button_radius), " button_radius" ) { it.toShortOrNull() != null }
88- ConfigTextField (c, e, stringResource(id = R .string.button_grow_default), " button_grow_default" ) { it.toBooleanStrictOrNull() != null } // TODO checkbox
89- ConfigTextField (c, e, stringResource(id = R .string.button_border_unselected_color), " button_border_unselected_color" , validate = col)
90- ConfigTextField (c, e, stringResource(id = R .string.button_border_unselected_size), " button_border_unselected_size" ) { it.toIntOrNull() != null }
91- ConfigTextField (c, e, stringResource(id = R .string.button_border_selected_color), " button_border_selected_color" , validate = col)
92- ConfigTextField (c, e, stringResource(id = R .string.button_border_selected_size), " button_border_selected_size" ) { it.toIntOrNull() != null }
93-
94-
95- Button (onClick = {
80+ val e = remember { mutableStateMapOf<String , Boolean >() }
81+ var resetCounter by remember { mutableIntStateOf(0 ) }
82+ val col = { it: String -> it.startsWith(" 0x" ) && it.length == 8 && (it.substring(2 ).toIntOrNull(16 ) ? : - 1 ) in 0 .. 0xffffff }
83+ val configs = listOf (
84+ Config (stringResource(id = R .string.win_bg_color), " win_bg_color" , " 0x000000" , col),
85+ Config (stringResource(id = R .string.win_radius), " win_radius" , " 0" ) { it.toShortOrNull() != null },
86+ Config (stringResource(id = R .string.win_border_size), " win_border_size" , " 0" ) { it.toShortOrNull() != null },
87+ Config (stringResource(id = R .string.win_border_color), " win_border_color" , " 0xffffff" , col),
88+ Config (stringResource(id = R .string.list_bg_color), " list_bg_color" , " 0x000000" , col),
89+ Config (stringResource(id = R .string.list_radius), " list_radius" , " 0" ) { it.toShortOrNull() != null },
90+ Config (stringResource(id = R .string.list_border_size), " list_border_size" , " 0" ) { it.toShortOrNull() != null },
91+ Config (stringResource(id = R .string.list_border_color), " list_border_color" , " 0xffffff" , col),
92+ Config (stringResource(id = R .string.global_font_size), " global_font_size" , " 0" ) { it.toIntOrNull() != null },
93+ Config (stringResource(id = R .string.global_font_name), " global_font_name" , " " ) { true /* should check if exists later */ },
94+ Config (stringResource(id = R .string.button_unselected_color), " button_unselected_color" , " 0x000000" , col),
95+ Config (stringResource(id = R .string.button_unselected_text_color), " button_unselected_text_color" ," 0xffffff" , col),
96+ Config (stringResource(id = R .string.button_unselected_radius), " button_unselected_radius" , " 0" ) { it.toShortOrNull() != null },
97+ Config (stringResource(id = R .string.button_selected_color), " button_selected_color" , " 0xff9800" , col),
98+ Config (stringResource(id = R .string.button_selected_text_color), " button_selected_text_color" , " 0x000000" , col),
99+ Config (stringResource(id = R .string.button_selected_radius), " button_selected_radius" , " 0" ) { it.toShortOrNull() != null },
100+ Config (stringResource(id = R .string.button_grow_default), " button_grow_default" , " true" ) { it.toBooleanStrictOrNull() != null }, // TODO checkbox
101+ Config (stringResource(id = R .string.button_border_unselected_color), " button_border_unselected_color" , " 0xffffff" , col),
102+ Config (stringResource(id = R .string.button_border_unselected_size), " button_border_unselected_size" , " 1" ) { it.toIntOrNull() != null },
103+ Config (stringResource(id = R .string.button_border_selected_color), " button_border_selected_color" , " 0xffffff" , col),
104+ Config (stringResource(id = R .string.button_border_selected_size), " button_border_selected_size" , " 1" ) { it.toIntOrNull() != null }
105+ )
106+ val state = rememberScrollState()
107+ Column (modifier = Modifier
108+ .verticalScroll(state)
109+ .fillMaxSize()) {
110+ val saveChanges = {
96111 if (e.containsValue(false ))
97112 Toast .makeText(
98113 vm.activity!! ,
@@ -111,40 +126,71 @@ fun Themes(vm: MainActivityState) {
111126 .show()
112127 }
113128 }
114- }, enabled = ! e.containsValue(false )) {
115- Text (stringResource(R .string.save_changes))
116129 }
117- Button (onClick = {
118- vm.activity!! .startActivity(Intent (vm.activity!! , Simulator ::class .java).apply {
119- putExtra(" sdCardBlock" , vm.deviceInfo!! .bdev)
120- })
121- }) {
122- Text (text = stringResource(id = R .string.simulator))
130+ Card (modifier = Modifier
131+ .fillMaxWidth()
132+ .padding(10 .dp)) {
133+ Column (modifier = Modifier .padding(10 .dp)) {
134+ Text (stringResource(id = R .string.simulator_info))
135+ Button (onClick = {
136+ saveChanges()
137+ // sync does not work :/
138+ vm.logic!! .unmountBootset()
139+ vm.logic!! .mountBootset(vm.deviceInfo!! )
140+ vm.activity!! .startActivity(Intent (vm.activity!! , Simulator ::class .java).apply {
141+ putExtra(" sdCardBlock" , vm.deviceInfo!! .bdev)
142+ })
143+ }) {
144+ Text (text = stringResource(id = R .string.simulator))
145+ }
146+ }
147+ }
148+ Row {
149+ Button (onClick = saveChanges, enabled = ! e.containsValue(false )) {
150+ Text (stringResource(R .string.save_changes))
151+ }
152+ Button (onClick = {
153+ for (cfg in configs) {
154+ c[cfg.configKey] = cfg.default
155+ }
156+ resetCounter++
157+ saveChanges()
158+ }) {
159+ Text (stringResource(R .string.reset))
160+ }
161+ }
162+ for (cfg in configs) {
163+ ConfigTextField (c, e, resetCounter, cfg.text, cfg.configKey, cfg.default, cfg.validate)
123164 }
124165 }
125166}
126167
127168@Composable
128- private fun ConfigTextField (c : ConfigFile , e : SnapshotStateMap <Long , Boolean >, text : String , configKey : String , default : String = "", validate : (String ) -> Boolean ) {
129- val id = remember { Random ().nextLong() }
130- var value by remember { mutableStateOf(c[configKey] ? : default) }
169+ private fun ConfigTextField (c : ConfigFile , e : SnapshotStateMap <String , Boolean >, resetCounter : Int , text : String , configKey : String , default : String , validate : (String ) -> Boolean ) {
170+ var value by remember(key1 = configKey, key2 = resetCounter) {
171+ if (! c.has(configKey)) c[configKey] = default
172+ mutableStateOf(c[configKey] ? : default)
173+ }
131174 TextField (
132175 value = value,
133176 onValueChange = {
134177 value = it
135178 c[configKey] = it.trim()
136- e[id ] = validate(text )
179+ e[configKey ] = validate(it )
137180 },
138181 label = { Text (text) },
139- isError = ! (e[id ] ? : true )
182+ isError = ! (e[configKey ] ? : true )
140183 )
141- if (e[id ] == false ) {
184+ if (e[configKey ] == false ) {
142185 Text (stringResource(id = R .string.invalid_in), color = MaterialTheme .colorScheme.error)
143186 } else {
144187 Text (" " ) // Budget spacer
145188 }
146189}
147190
191+ private data class Config (val text : String , val configKey : String , val default : String ,
192+ val validate : (String ) -> Boolean )
193+
148194@Preview
149195@Composable
150196fun ThemePreview () {
0 commit comments