refactor: navigation

This commit is contained in:
Zane Schepke 2025-01-01 00:08:33 -05:00
parent ab858ab59e
commit 85319ba874
7 changed files with 60 additions and 94 deletions

View File

@ -74,7 +74,9 @@ class WireGuardAutoTunnel : Application() {
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList()) tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
} }
appStateRepository.getLocale()?.let { appStateRepository.getLocale()?.let {
LocaleUtil.changeLocale(it) withContext(mainDispatcher) {
LocaleUtil.changeLocale(it)
}
} }
} }
} }

View File

@ -222,24 +222,16 @@ class MainActivity : AppCompatActivity() {
} }
composable<Route.Config> { composable<Route.Config> {
val args = it.toRoute<Route.Config>() val args = it.toRoute<Route.Config>()
ConfigScreen( val config = appUiState.tunnels.firstOrNull { it.id == args.id }
appUiState, ConfigScreen(config, viewModel)
tunnelId = args.id,
appViewModel = viewModel,
)
} }
composable<Route.TunnelOptions> { composable<Route.TunnelOptions> {
val args = it.toRoute<Route.TunnelOptions>() val args = it.toRoute<Route.TunnelOptions>()
OptionsScreen( val config = appUiState.tunnels.first { it.id == args.id }
tunnelId = args.id, OptionsScreen(config, viewModel)
appUiState = appUiState,
appViewModel = viewModel,
)
} }
composable<Route.Lock> { composable<Route.Lock> {
PinLockScreen( PinLockScreen(viewModel)
appViewModel = viewModel,
)
} }
composable<Route.Scanner> { composable<Route.Scanner> {
ScannerScreen() ScannerScreen()
@ -249,11 +241,13 @@ class MainActivity : AppCompatActivity() {
} }
composable<Route.SplitTunnel> { composable<Route.SplitTunnel> {
val args = it.toRoute<Route.SplitTunnel>() val args = it.toRoute<Route.SplitTunnel>()
SplitTunnelScreen(appUiState, args.id, viewModel) val config = appUiState.tunnels.first { it.id == args.id }
SplitTunnelScreen(config,viewModel)
} }
composable<Route.TunnelAutoTunnel> { composable<Route.TunnelAutoTunnel> {
val args = it.toRoute<Route.SplitTunnel>() val args = it.toRoute<Route.TunnelOptions>()
TunnelAutoTunnelScreen(appUiState, args.id) val config = appUiState.tunnels.first { it.id == args.id }
TunnelAutoTunnelScreen(config, appUiState.settings)
} }
} }
} }

View File

@ -26,7 +26,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.ui.AppUiState import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
import com.zaneschepke.wireguardautotunnel.ui.Route import com.zaneschepke.wireguardautotunnel.ui.Route
import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch
@ -39,18 +39,17 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
@Composable @Composable
fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: Int) { fun OptionsScreen(tunnelConfig: TunnelConfig, appViewModel: AppViewModel) {
val navController = LocalNavController.current val navController = LocalNavController.current
val config = appUiState.tunnels.first { it.id == tunnelId }
var currentText by remember { mutableStateOf("") } var currentText by remember { mutableStateOf("") }
LaunchedEffect(config.tunnelNetworks) { LaunchedEffect(tunnelConfig.tunnelNetworks) {
currentText = "" currentText = ""
} }
Scaffold( Scaffold(
topBar = { topBar = {
TopNavBar(config.name) TopNavBar(tunnelConfig.name)
}, },
) { ) {
Column( Column(
@ -83,11 +82,11 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
}, },
trailing = { trailing = {
ScaledSwitch( ScaledSwitch(
config.isPrimaryTunnel, tunnelConfig.isPrimaryTunnel,
onClick = { appViewModel.onTogglePrimaryTunnel(config) }, onClick = { appViewModel.onTogglePrimaryTunnel(tunnelConfig) },
) )
}, },
onClick = { appViewModel.onTogglePrimaryTunnel(config) }, onClick = { appViewModel.onTogglePrimaryTunnel(tunnelConfig) },
), ),
SelectionItem( SelectionItem(
Icons.Outlined.Bolt, Icons.Outlined.Bolt,
@ -104,10 +103,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
) )
}, },
onClick = { onClick = {
navController.navigate(Route.TunnelAutoTunnel(id = tunnelId)) navController.navigate(Route.TunnelAutoTunnel(id = tunnelConfig.id))
}, },
trailing = { trailing = {
ForwardButton { navController.navigate(Route.TunnelAutoTunnel(id = tunnelId)) } ForwardButton { navController.navigate(Route.TunnelAutoTunnel(id = tunnelConfig.id)) }
}, },
), ),
SelectionItem( SelectionItem(
@ -119,10 +118,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
) )
}, },
onClick = { onClick = {
navController.navigate(Route.Config(id = tunnelId)) navController.navigate(Route.Config(id = tunnelConfig.id))
}, },
trailing = { trailing = {
ForwardButton { navController.navigate(Route.Config(id = tunnelId)) } ForwardButton { navController.navigate(Route.Config(id = tunnelConfig.id)) }
}, },
), ),
SelectionItem( SelectionItem(
@ -134,10 +133,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
) )
}, },
onClick = { onClick = {
navController.navigate(Route.SplitTunnel(id = tunnelId)) navController.navigate(Route.SplitTunnel(id = tunnelConfig.id))
}, },
trailing = { trailing = {
ForwardButton { navController.navigate(Route.SplitTunnel(id = tunnelId)) } ForwardButton { navController.navigate(Route.SplitTunnel(id = tunnelConfig.id)) }
}, },
), ),
), ),

View File

@ -58,6 +58,7 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
import com.zaneschepke.wireguardautotunnel.ui.AppUiState import com.zaneschepke.wireguardautotunnel.ui.AppUiState
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationTextBox import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationTextBox
@ -77,7 +78,7 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
import org.amnezia.awg.crypto.KeyPair import org.amnezia.awg.crypto.KeyPair
@Composable @Composable
fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: Int) { fun ConfigScreen(tunnelConfig: TunnelConfig?, appViewModel: AppViewModel) {
val context = LocalContext.current val context = LocalContext.current
val snackbar = SnackbarController.current val snackbar = SnackbarController.current
val clipboardManager: ClipboardManager = LocalClipboardManager.current val clipboardManager: ClipboardManager = LocalClipboardManager.current
@ -90,8 +91,6 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
val popBackStack by appViewModel.popBackStack.collectAsStateWithLifecycle(false) val popBackStack by appViewModel.popBackStack.collectAsStateWithLifecycle(false)
val tunnelConfig = appUiState.tunnels.firstOrNull { it.id == tunnelId }
val configPair = Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig()) val configPair = Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig())
var tunnelName by remember { var tunnelName by remember {
@ -261,32 +260,6 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
} }
} }
} }
// ConfigurationToggle(
// stringResource(id = R.string.show_amnezia_properties),
// checked = showAmneziaValues,
// onCheckChanged = {
// if (appUiState.settings.isKernelEnabled) {
// snackbar.showMessage(context.getString(R.string.amnezia_kernel_message))
// } else {
// showAmneziaValues = it
// }
// },
// )
// ConfigurationToggle(
// stringResource(id = R.string.show_scripts),
// checked = showScripts,
// onCheckChanged = { checked ->
// if (appUiState.settings.isKernelEnabled) {
// showScripts = checked
// } else {
// scope.launch {
// appViewModel.requestRoot().onSuccess {
// showScripts = checked
// }
// }
// }
// },
// )
ConfigurationTextBox( ConfigurationTextBox(
value = tunnelName, value = tunnelName,
onValueChange = { tunnelName = it }, onValueChange = { tunnelName = it },
@ -297,7 +270,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
Modifier Modifier
.fillMaxWidth(), .fillMaxWidth(),
) )
val privateKeyEnabled = (tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated val privateKeyEnabled = (tunnelConfig == null) || isAuthenticated
OutlinedTextField( OutlinedTextField(
textStyle = MaterialTheme.typography.labelLarge, textStyle = MaterialTheme.typography.labelLarge,
modifier = modifier =

View File

@ -48,7 +48,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.ui.AppUiState import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
import com.zaneschepke.wireguardautotunnel.ui.common.button.SelectionItemButton import com.zaneschepke.wireguardautotunnel.ui.common.button.SelectionItemButton
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
@ -62,7 +62,7 @@ import java.text.Collator
import java.util.Locale import java.util.Locale
@Composable @Composable
fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewModel) { fun SplitTunnelScreen(tunnelConfig: TunnelConfig, viewModel: AppViewModel) {
val context = LocalContext.current val context = LocalContext.current
val navController = LocalNavController.current val navController = LocalNavController.current
@ -76,8 +76,6 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM
if (popBackStack) navController.popBackStack() if (popBackStack) navController.popBackStack()
} }
val config = appUiState.tunnels.first { it.id == tunnelId }
val splitTunnelApps by viewModel.splitTunnelApps.collectAsStateWithLifecycle() val splitTunnelApps by viewModel.splitTunnelApps.collectAsStateWithLifecycle()
var proxyInterface by remember { mutableStateOf(InterfaceProxy()) } var proxyInterface by remember { mutableStateOf(InterfaceProxy()) }
@ -87,7 +85,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM
val selectedPackages = remember { mutableStateListOf<String>() } val selectedPackages = remember { mutableStateListOf<String>() }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
proxyInterface = InterfaceProxy.from(config.toAmConfig().`interface`) proxyInterface = InterfaceProxy.from(tunnelConfig.toAmConfig().`interface`)
val pair = when { val pair = when {
proxyInterface.excludedApplications.isNotEmpty() -> Pair(SplitOptions.EXCLUDE, proxyInterface.excludedApplications) proxyInterface.excludedApplications.isNotEmpty() -> Pair(SplitOptions.EXCLUDE, proxyInterface.excludedApplications)
proxyInterface.includedApplications.isNotEmpty() -> Pair(SplitOptions.INCLUDE, proxyInterface.includedApplications) proxyInterface.includedApplications.isNotEmpty() -> Pair(SplitOptions.INCLUDE, proxyInterface.includedApplications)
@ -107,7 +105,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
// clean up any split tunnel packages for apps that were uninstalled // clean up any split tunnel packages for apps that were uninstalled
viewModel.cleanUpUninstalledApps(config, splitTunnelApps.map { it.`package` }) viewModel.cleanUpUninstalledApps(tunnelConfig, splitTunnelApps.map { it.`package` })
} }
Scaffold( Scaffold(
@ -127,7 +125,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM
} }
SplitOptions.ALL -> Unit SplitOptions.ALL -> Unit
} }
viewModel.updateExistingTunnelConfig(config, `interface` = proxyInterface) viewModel.updateExistingTunnelConfig(tunnelConfig, `interface` = proxyInterface)
}) { }) {
val icon = Icons.Outlined.Save val icon = Icons.Outlined.Save
Icon( Icon(

View File

@ -33,7 +33,8 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.ui.AppUiState import com.zaneschepke.wireguardautotunnel.data.domain.Settings
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch
import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SelectionItem import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SelectionItem
import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SurfaceSelectionGroupButton import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SurfaceSelectionGroupButton
@ -48,17 +49,16 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
@Composable @Composable
fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunnelViewModel: TunnelAutoTunnelViewModel = hiltViewModel()) { fun TunnelAutoTunnelScreen(tunnelConfig: TunnelConfig, settings: Settings, tunnelAutoTunnelViewModel: TunnelAutoTunnelViewModel = hiltViewModel()) {
val config = appUiState.tunnels.first { it.id == tunnelId }
var currentText by remember { mutableStateOf("") } var currentText by remember { mutableStateOf("") }
LaunchedEffect(config.tunnelNetworks) { LaunchedEffect(tunnelConfig.tunnelNetworks) {
currentText = "" currentText = ""
} }
Scaffold( Scaffold(
topBar = { topBar = {
TopNavBar(config.name) TopNavBar(tunnelConfig.name)
}, },
) { padding -> ) { padding ->
Column( Column(
@ -92,11 +92,11 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
}, },
trailing = { trailing = {
ScaledSwitch( ScaledSwitch(
config.isMobileDataTunnel, tunnelConfig.isMobileDataTunnel,
onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(tunnelConfig) },
) )
}, },
onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(tunnelConfig) },
), ),
SelectionItem( SelectionItem(
Icons.Outlined.SettingsEthernet, Icons.Outlined.SettingsEthernet,
@ -114,11 +114,11 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
}, },
trailing = { trailing = {
ScaledSwitch( ScaledSwitch(
config.isEthernetTunnel, tunnelConfig.isEthernetTunnel,
onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(tunnelConfig) },
) )
}, },
onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(tunnelConfig) },
), ),
SelectionItem( SelectionItem(
Icons.Outlined.NetworkPing, Icons.Outlined.NetworkPing,
@ -130,27 +130,27 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
}, },
trailing = { trailing = {
ScaledSwitch( ScaledSwitch(
checked = config.isPingEnabled, checked = tunnelConfig.isPingEnabled,
onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(tunnelConfig) },
) )
}, },
onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(config) }, onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(tunnelConfig) },
), ),
), ),
) )
if (config.isPingEnabled || appUiState.settings.isPingEnabled) { if (tunnelConfig.isPingEnabled || settings.isPingEnabled) {
add( add(
SelectionItem( SelectionItem(
title = {}, title = {},
description = { description = {
SubmitConfigurationTextBox( SubmitConfigurationTextBox(
config.pingIp, tunnelConfig.pingIp,
stringResource(R.string.set_custom_ping_ip), stringResource(R.string.set_custom_ping_ip),
stringResource(R.string.default_ping_ip), stringResource(R.string.default_ping_ip),
isErrorValue = { !it.isNullOrBlank() && !it.isValidIpv4orIpv6Address() }, isErrorValue = { !it.isNullOrBlank() && !it.isValidIpv4orIpv6Address() },
onSubmit = { onSubmit = {
tunnelAutoTunnelViewModel.saveTunnelChanges( tunnelAutoTunnelViewModel.saveTunnelChanges(
config.copy(pingIp = it.ifBlank { null }), tunnelConfig.copy(pingIp = it.ifBlank { null }),
) )
}, },
) )
@ -158,7 +158,7 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
return seconds?.let { value -> if (value.isBlank()) false else value.toLong() >= Long.MAX_VALUE / 1000 } ?: false return seconds?.let { value -> if (value.isBlank()) false else value.toLong() >= Long.MAX_VALUE / 1000 } ?: false
} }
SubmitConfigurationTextBox( SubmitConfigurationTextBox(
config.pingInterval?.let { (it / 1000).toString() }, tunnelConfig.pingInterval?.let { (it / 1000).toString() },
stringResource(R.string.set_custom_ping_internal), stringResource(R.string.set_custom_ping_internal),
"(${stringResource(R.string.optional_default)} ${Constants.PING_INTERVAL / 1000})", "(${stringResource(R.string.optional_default)} ${Constants.PING_INTERVAL / 1000})",
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
@ -168,12 +168,12 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
isErrorValue = ::isSecondsError, isErrorValue = ::isSecondsError,
onSubmit = { onSubmit = {
tunnelAutoTunnelViewModel.saveTunnelChanges( tunnelAutoTunnelViewModel.saveTunnelChanges(
config.copy(pingInterval = if (it.isBlank()) null else it.toLong() * 1000), tunnelConfig.copy(pingInterval = if (it.isBlank()) null else it.toLong() * 1000),
) )
}, },
) )
SubmitConfigurationTextBox( SubmitConfigurationTextBox(
config.pingCooldown?.let { (it / 1000).toString() }, tunnelConfig.pingCooldown?.let { (it / 1000).toString() },
stringResource(R.string.set_custom_ping_cooldown), stringResource(R.string.set_custom_ping_cooldown),
"(${stringResource(R.string.optional_default)} ${Constants.PING_COOLDOWN / 1000})", "(${stringResource(R.string.optional_default)} ${Constants.PING_COOLDOWN / 1000})",
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
@ -182,7 +182,7 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
isErrorValue = ::isSecondsError, isErrorValue = ::isSecondsError,
onSubmit = { onSubmit = {
tunnelAutoTunnelViewModel.saveTunnelChanges( tunnelAutoTunnelViewModel.saveTunnelChanges(
config.copy(pingCooldown = if (it.isBlank()) null else it.toLong() * 1000), tunnelConfig.copy(pingCooldown = if (it.isBlank()) null else it.toLong() * 1000),
) )
}, },
) )
@ -229,13 +229,13 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn
}, },
description = { description = {
TrustedNetworkTextBox( TrustedNetworkTextBox(
config.tunnelNetworks, tunnelConfig.tunnelNetworks,
onDelete = { tunnelAutoTunnelViewModel.onDeleteRunSSID(it, config) }, onDelete = { tunnelAutoTunnelViewModel.onDeleteRunSSID(it, tunnelConfig) },
currentText = currentText, currentText = currentText,
onSave = { tunnelAutoTunnelViewModel.onSaveRunSSID(it, config) }, onSave = { tunnelAutoTunnelViewModel.onSaveRunSSID(it, tunnelConfig) },
onValueChange = { currentText = it }, onValueChange = { currentText = it },
supporting = { supporting = {
if (appUiState.settings.isWildcardsEnabled) { if (settings.isWildcardsEnabled) {
WildcardsLabel() WildcardsLabel()
} }
}, },

View File

@ -9,7 +9,7 @@ coreKtx = "1.15.0"
datastorePreferences = "1.1.1" datastorePreferences = "1.1.1"
desugar_jdk_libs = "2.1.4" desugar_jdk_libs = "2.1.4"
espressoCore = "3.6.1" espressoCore = "3.6.1"
hiltAndroid = "2.53" hiltAndroid = "2.54"
hiltNavigationCompose = "1.2.0" hiltNavigationCompose = "1.2.0"
junit = "4.13.2" junit = "4.13.2"
kotlinx-serialization-json = "1.7.3" kotlinx-serialization-json = "1.7.3"