diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt index 580c5d8..4e9df0f 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt @@ -74,7 +74,9 @@ class WireGuardAutoTunnel : Application() { tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList()) } appStateRepository.getLocale()?.let { - LocaleUtil.changeLocale(it) + withContext(mainDispatcher) { + LocaleUtil.changeLocale(it) + } } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt index d44af87..b93f813 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt @@ -222,24 +222,16 @@ class MainActivity : AppCompatActivity() { } composable { val args = it.toRoute() - ConfigScreen( - appUiState, - tunnelId = args.id, - appViewModel = viewModel, - ) + val config = appUiState.tunnels.firstOrNull { it.id == args.id } + ConfigScreen(config, viewModel) } composable { val args = it.toRoute() - OptionsScreen( - tunnelId = args.id, - appUiState = appUiState, - appViewModel = viewModel, - ) + val config = appUiState.tunnels.first { it.id == args.id } + OptionsScreen(config, viewModel) } composable { - PinLockScreen( - appViewModel = viewModel, - ) + PinLockScreen(viewModel) } composable { ScannerScreen() @@ -249,11 +241,13 @@ class MainActivity : AppCompatActivity() { } composable { val args = it.toRoute() - SplitTunnelScreen(appUiState, args.id, viewModel) + val config = appUiState.tunnels.first { it.id == args.id } + SplitTunnelScreen(config,viewModel) } composable { - val args = it.toRoute() - TunnelAutoTunnelScreen(appUiState, args.id) + val args = it.toRoute() + val config = appUiState.tunnels.first { it.id == args.id } + TunnelAutoTunnelScreen(config, appUiState.settings) } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/TunnelOptionsScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/TunnelOptionsScreen.kt index 5993bcd..8b4aafa 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/TunnelOptionsScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/TunnelOptionsScreen.kt @@ -26,7 +26,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp 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.Route 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 @Composable -fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: Int) { +fun OptionsScreen(tunnelConfig: TunnelConfig, appViewModel: AppViewModel) { val navController = LocalNavController.current - val config = appUiState.tunnels.first { it.id == tunnelId } var currentText by remember { mutableStateOf("") } - LaunchedEffect(config.tunnelNetworks) { + LaunchedEffect(tunnelConfig.tunnelNetworks) { currentText = "" } Scaffold( topBar = { - TopNavBar(config.name) + TopNavBar(tunnelConfig.name) }, ) { Column( @@ -83,11 +82,11 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: }, trailing = { ScaledSwitch( - config.isPrimaryTunnel, - onClick = { appViewModel.onTogglePrimaryTunnel(config) }, + tunnelConfig.isPrimaryTunnel, + onClick = { appViewModel.onTogglePrimaryTunnel(tunnelConfig) }, ) }, - onClick = { appViewModel.onTogglePrimaryTunnel(config) }, + onClick = { appViewModel.onTogglePrimaryTunnel(tunnelConfig) }, ), SelectionItem( Icons.Outlined.Bolt, @@ -104,10 +103,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: ) }, onClick = { - navController.navigate(Route.TunnelAutoTunnel(id = tunnelId)) + navController.navigate(Route.TunnelAutoTunnel(id = tunnelConfig.id)) }, trailing = { - ForwardButton { navController.navigate(Route.TunnelAutoTunnel(id = tunnelId)) } + ForwardButton { navController.navigate(Route.TunnelAutoTunnel(id = tunnelConfig.id)) } }, ), SelectionItem( @@ -119,10 +118,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: ) }, onClick = { - navController.navigate(Route.Config(id = tunnelId)) + navController.navigate(Route.Config(id = tunnelConfig.id)) }, trailing = { - ForwardButton { navController.navigate(Route.Config(id = tunnelId)) } + ForwardButton { navController.navigate(Route.Config(id = tunnelConfig.id)) } }, ), SelectionItem( @@ -134,10 +133,10 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: ) }, onClick = { - navController.navigate(Route.SplitTunnel(id = tunnelId)) + navController.navigate(Route.SplitTunnel(id = tunnelConfig.id)) }, trailing = { - ForwardButton { navController.navigate(Route.SplitTunnel(id = tunnelId)) } + ForwardButton { navController.navigate(Route.SplitTunnel(id = tunnelConfig.id)) } }, ), ), diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/config/ConfigScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/config/ConfigScreen.kt index e0edbe7..8448f09 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/config/ConfigScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/config/ConfigScreen.kt @@ -58,6 +58,7 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.zaneschepke.wireguardautotunnel.R +import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.AppUiState import com.zaneschepke.wireguardautotunnel.ui.AppViewModel 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 @Composable -fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: Int) { +fun ConfigScreen(tunnelConfig: TunnelConfig?, appViewModel: AppViewModel) { val context = LocalContext.current val snackbar = SnackbarController.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 tunnelConfig = appUiState.tunnels.firstOrNull { it.id == tunnelId } - val configPair = Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig()) 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( value = tunnelName, onValueChange = { tunnelName = it }, @@ -297,7 +270,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I Modifier .fillMaxWidth(), ) - val privateKeyEnabled = (tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated + val privateKeyEnabled = (tunnelConfig == null) || isAuthenticated OutlinedTextField( textStyle = MaterialTheme.typography.labelLarge, modifier = diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/splittunnel/SplitTunnelScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/splittunnel/SplitTunnelScreen.kt index cf5fc27..bbf6ba2 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/splittunnel/SplitTunnelScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/splittunnel/SplitTunnelScreen.kt @@ -48,7 +48,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.google.accompanist.drawablepainter.rememberDrawablePainter 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.common.button.SelectionItemButton import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController @@ -62,7 +62,7 @@ import java.text.Collator import java.util.Locale @Composable -fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewModel) { +fun SplitTunnelScreen(tunnelConfig: TunnelConfig, viewModel: AppViewModel) { val context = LocalContext.current val navController = LocalNavController.current @@ -76,8 +76,6 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM if (popBackStack) navController.popBackStack() } - val config = appUiState.tunnels.first { it.id == tunnelId } - val splitTunnelApps by viewModel.splitTunnelApps.collectAsStateWithLifecycle() var proxyInterface by remember { mutableStateOf(InterfaceProxy()) } @@ -87,7 +85,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM val selectedPackages = remember { mutableStateListOf() } LaunchedEffect(Unit) { - proxyInterface = InterfaceProxy.from(config.toAmConfig().`interface`) + proxyInterface = InterfaceProxy.from(tunnelConfig.toAmConfig().`interface`) val pair = when { proxyInterface.excludedApplications.isNotEmpty() -> Pair(SplitOptions.EXCLUDE, proxyInterface.excludedApplications) proxyInterface.includedApplications.isNotEmpty() -> Pair(SplitOptions.INCLUDE, proxyInterface.includedApplications) @@ -107,7 +105,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM LaunchedEffect(Unit) { // 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( @@ -127,7 +125,7 @@ fun SplitTunnelScreen(appUiState: AppUiState, tunnelId: Int, viewModel: AppViewM } SplitOptions.ALL -> Unit } - viewModel.updateExistingTunnelConfig(config, `interface` = proxyInterface) + viewModel.updateExistingTunnelConfig(tunnelConfig, `interface` = proxyInterface) }) { val icon = Icons.Outlined.Save Icon( diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/tunnelautotunnel/TunnelAutoTunnelScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/tunnelautotunnel/TunnelAutoTunnelScreen.kt index f23c27a..7464304 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/tunnelautotunnel/TunnelAutoTunnelScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunneloptions/tunnelautotunnel/TunnelAutoTunnelScreen.kt @@ -33,7 +33,8 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel 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.surface.SelectionItem 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 @Composable -fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunnelViewModel: TunnelAutoTunnelViewModel = hiltViewModel()) { - val config = appUiState.tunnels.first { it.id == tunnelId } +fun TunnelAutoTunnelScreen(tunnelConfig: TunnelConfig, settings: Settings, tunnelAutoTunnelViewModel: TunnelAutoTunnelViewModel = hiltViewModel()) { var currentText by remember { mutableStateOf("") } - LaunchedEffect(config.tunnelNetworks) { + LaunchedEffect(tunnelConfig.tunnelNetworks) { currentText = "" } Scaffold( topBar = { - TopNavBar(config.name) + TopNavBar(tunnelConfig.name) }, ) { padding -> Column( @@ -92,11 +92,11 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn }, trailing = { ScaledSwitch( - config.isMobileDataTunnel, - onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(config) }, + tunnelConfig.isMobileDataTunnel, + onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(tunnelConfig) }, ) }, - onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(config) }, + onClick = { tunnelAutoTunnelViewModel.onToggleIsMobileDataTunnel(tunnelConfig) }, ), SelectionItem( Icons.Outlined.SettingsEthernet, @@ -114,11 +114,11 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn }, trailing = { ScaledSwitch( - config.isEthernetTunnel, - onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(config) }, + tunnelConfig.isEthernetTunnel, + onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(tunnelConfig) }, ) }, - onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(config) }, + onClick = { tunnelAutoTunnelViewModel.onToggleIsEthernetTunnel(tunnelConfig) }, ), SelectionItem( Icons.Outlined.NetworkPing, @@ -130,27 +130,27 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn }, trailing = { ScaledSwitch( - checked = config.isPingEnabled, - onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(config) }, + checked = tunnelConfig.isPingEnabled, + onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(tunnelConfig) }, ) }, - onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(config) }, + onClick = { tunnelAutoTunnelViewModel.onToggleRestartOnPing(tunnelConfig) }, ), ), ) - if (config.isPingEnabled || appUiState.settings.isPingEnabled) { + if (tunnelConfig.isPingEnabled || settings.isPingEnabled) { add( SelectionItem( title = {}, description = { SubmitConfigurationTextBox( - config.pingIp, + tunnelConfig.pingIp, stringResource(R.string.set_custom_ping_ip), stringResource(R.string.default_ping_ip), isErrorValue = { !it.isNullOrBlank() && !it.isValidIpv4orIpv6Address() }, onSubmit = { 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 } SubmitConfigurationTextBox( - config.pingInterval?.let { (it / 1000).toString() }, + tunnelConfig.pingInterval?.let { (it / 1000).toString() }, stringResource(R.string.set_custom_ping_internal), "(${stringResource(R.string.optional_default)} ${Constants.PING_INTERVAL / 1000})", keyboardOptions = KeyboardOptions( @@ -168,12 +168,12 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn isErrorValue = ::isSecondsError, onSubmit = { 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( - config.pingCooldown?.let { (it / 1000).toString() }, + tunnelConfig.pingCooldown?.let { (it / 1000).toString() }, stringResource(R.string.set_custom_ping_cooldown), "(${stringResource(R.string.optional_default)} ${Constants.PING_COOLDOWN / 1000})", keyboardOptions = KeyboardOptions( @@ -182,7 +182,7 @@ fun TunnelAutoTunnelScreen(appUiState: AppUiState, tunnelId: Int, tunnelAutoTunn isErrorValue = ::isSecondsError, onSubmit = { 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 = { TrustedNetworkTextBox( - config.tunnelNetworks, - onDelete = { tunnelAutoTunnelViewModel.onDeleteRunSSID(it, config) }, + tunnelConfig.tunnelNetworks, + onDelete = { tunnelAutoTunnelViewModel.onDeleteRunSSID(it, tunnelConfig) }, currentText = currentText, - onSave = { tunnelAutoTunnelViewModel.onSaveRunSSID(it, config) }, + onSave = { tunnelAutoTunnelViewModel.onSaveRunSSID(it, tunnelConfig) }, onValueChange = { currentText = it }, supporting = { - if (appUiState.settings.isWildcardsEnabled) { + if (settings.isWildcardsEnabled) { WildcardsLabel() } }, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 718bc64..355e1d6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ coreKtx = "1.15.0" datastorePreferences = "1.1.1" desugar_jdk_libs = "2.1.4" espressoCore = "3.6.1" -hiltAndroid = "2.53" +hiltAndroid = "2.54" hiltNavigationCompose = "1.2.0" junit = "4.13.2" kotlinx-serialization-json = "1.7.3"