parent
4196a543b2
commit
ab858ab59e
|
@ -115,7 +115,9 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel:
|
|||
val onAutoTunnelClick = {
|
||||
if (!uiState.generalState.isLocationDisclosureShown) {
|
||||
navController.navigate(Route.LocationDisclosure)
|
||||
} else navController.navigate(Route.AutoTunnel)
|
||||
} else {
|
||||
navController.navigate(Route.AutoTunnel)
|
||||
}
|
||||
}
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
|
@ -21,7 +22,6 @@ import androidx.compose.material.icons.outlined.Security
|
|||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.SettingsEthernet
|
||||
import androidx.compose.material.icons.outlined.SignalCellular4Bar
|
||||
import androidx.compose.material.icons.outlined.VpnKeyOff
|
||||
import androidx.compose.material.icons.outlined.Wifi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -135,6 +135,7 @@ fun AutoTunnelScreen(uiState: AppUiState, viewModel: AutoTunnelViewModel = hiltV
|
|||
.fillMaxSize()
|
||||
.padding(padding)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.imePadding()
|
||||
.padding(top = 24.dp.scaledHeight())
|
||||
.padding(horizontal = 24.dp.scaledWidth()),
|
||||
) {
|
||||
|
@ -376,7 +377,7 @@ fun AutoTunnelScreen(uiState: AppUiState, viewModel: AutoTunnelViewModel = hiltV
|
|||
ForwardButton { navController.navigate(Route.AutoTunnelAdvanced) }
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
|
|||
|
||||
@Composable
|
||||
fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
|
||||
|
||||
var isDropDownExpanded by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
@ -47,9 +46,9 @@ fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
|
|||
var selected by remember { mutableIntStateOf(appUiState.settings.debounceDelaySeconds) }
|
||||
|
||||
LaunchedEffect(selected) {
|
||||
if(selected == appUiState.settings.debounceDelaySeconds) return@LaunchedEffect
|
||||
if (selected == appUiState.settings.debounceDelaySeconds) return@LaunchedEffect
|
||||
appViewModel.saveSettings(appUiState.settings.copy(debounceDelaySeconds = selected))
|
||||
if(appUiState.settings.isAutoTunnelEnabled) {
|
||||
if (appUiState.settings.isAutoTunnelEnabled) {
|
||||
appViewModel.bounceAutoTunnel()
|
||||
}
|
||||
}
|
||||
|
@ -86,32 +85,36 @@ fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
|
|||
trailing = {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally),
|
||||
verticalAlignment = Alignment.CenterVertically) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(text = selected.toString(), style = MaterialTheme.typography.bodyMedium)
|
||||
val icon = Icons.Default.ArrowDropDown
|
||||
Icon(icon, icon.name)
|
||||
}
|
||||
DropdownMenu(
|
||||
modifier = Modifier.height(140.dp.scaledHeight()),
|
||||
modifier = Modifier.height(250.dp.scaledHeight()),
|
||||
scrollState = rememberScrollState(),
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
expanded = isDropDownExpanded,
|
||||
onDismissRequest = {
|
||||
isDropDownExpanded = false
|
||||
}) {
|
||||
},
|
||||
) {
|
||||
(0..10).forEachIndexed { index, num ->
|
||||
DropdownMenuItem(text = {
|
||||
Text(text = num.toString())
|
||||
},
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = num.toString())
|
||||
},
|
||||
onClick = {
|
||||
isDropDownExpanded = false
|
||||
selected = num
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced
|
||||
|
||||
enum class InterfaceActions {
|
||||
TOGGLE_AMNEZIA_VALUES,
|
||||
SET_AMNEZIA_COMPATIBILITY,
|
||||
TOGGLE_SHOW_SCRIPTS,
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced
|
||||
|
||||
enum class PeerActions {
|
||||
EXCLUDE_LAN,
|
||||
}
|
|
@ -3,12 +3,12 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.CallSplit
|
||||
import androidx.compose.material.icons.outlined.Adjust
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material.icons.outlined.Edit
|
||||
import androidx.compose.material.icons.outlined.Star
|
||||
|
@ -32,28 +32,17 @@ import com.zaneschepke.wireguardautotunnel.ui.Route
|
|||
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
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.label.GroupLabel
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.components.ForwardButton
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.isWgCompatibilityMode
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.resetAmneziaProperties
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.toAmneziaCompatibilityConfig
|
||||
|
||||
@Composable
|
||||
fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: Int) {
|
||||
val navController = LocalNavController.current
|
||||
val config = appUiState.tunnels.first { it.id == tunnelId }
|
||||
|
||||
// TODO optimize
|
||||
|
||||
val amConfig = config.toAmConfig()
|
||||
|
||||
val isAmneziaCompatibilityEnabled = amConfig.`interface`.isWgCompatibilityMode()
|
||||
|
||||
var currentText by remember { mutableStateOf("") }
|
||||
|
||||
LaunchedEffect(config.tunnelNetworks) {
|
||||
|
@ -71,6 +60,7 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
|
|||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
.imePadding()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 24.dp.scaledHeight())
|
||||
.padding(horizontal = 24.dp.scaledWidth()),
|
||||
|
@ -152,38 +142,6 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
|
|||
),
|
||||
),
|
||||
)
|
||||
val amneziaClick = {
|
||||
val proxy = InterfaceProxy.from(amConfig.`interface`)
|
||||
val `interface` = if (!isAmneziaCompatibilityEnabled) proxy.toAmneziaCompatibilityConfig() else proxy.resetAmneziaProperties()
|
||||
appViewModel.updateExistingTunnelConfig(config, `interface` = `interface`)
|
||||
}
|
||||
GroupLabel(stringResource(R.string.quick_actions))
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
SelectionItem(
|
||||
Icons.Outlined.Adjust,
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.enable_amnezia),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
description = {
|
||||
Text(
|
||||
stringResource(R.string.wg_compat_mode),
|
||||
style = MaterialTheme.typography.bodySmall.copy(MaterialTheme.colorScheme.outline),
|
||||
)
|
||||
},
|
||||
trailing = {
|
||||
ScaledSwitch(
|
||||
isAmneziaCompatibilityEnabled,
|
||||
onClick = { amneziaClick() },
|
||||
)
|
||||
},
|
||||
onClick = { amneziaClick() },
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusGroup
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
@ -8,7 +9,9 @@ import androidx.compose.foundation.layout.IntrinsicSize
|
|||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
@ -19,7 +22,10 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.outlined.Save
|
||||
import androidx.compose.material.icons.rounded.ContentCopy
|
||||
import androidx.compose.material.icons.rounded.Delete
|
||||
import androidx.compose.material.icons.rounded.MoreVert
|
||||
import androidx.compose.material.icons.rounded.Refresh
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -30,15 +36,14 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.platform.ClipboardManager
|
||||
|
@ -56,18 +61,19 @@ import com.zaneschepke.wireguardautotunnel.R
|
|||
import com.zaneschepke.wireguardautotunnel.ui.AppUiState
|
||||
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationTextBox
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationToggle
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.label.GroupLabel
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.prompt.AuthorizationPrompt
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced.InterfaceActions
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced.PeerActions
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.PeerProxy
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.iconSize
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
|
||||
import kotlinx.coroutines.launch
|
||||
import org.amnezia.awg.crypto.KeyPair
|
||||
|
||||
@Composable
|
||||
|
@ -77,21 +83,16 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
val clipboardManager: ClipboardManager = LocalClipboardManager.current
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
val navController = LocalNavController.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var isInterfaceDropDownExpanded by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
val popBackStack by appViewModel.popBackStack.collectAsStateWithLifecycle(false)
|
||||
|
||||
val tunnelConfig by remember {
|
||||
derivedStateOf {
|
||||
appUiState.tunnels.firstOrNull { it.id == tunnelId }
|
||||
}
|
||||
}
|
||||
val tunnelConfig = appUiState.tunnels.firstOrNull { it.id == tunnelId }
|
||||
|
||||
val configPair by remember {
|
||||
derivedStateOf {
|
||||
Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig())
|
||||
}
|
||||
}
|
||||
val configPair = Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig())
|
||||
|
||||
var tunnelName by remember {
|
||||
mutableStateOf(configPair.first)
|
||||
|
@ -173,6 +174,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(padding)
|
||||
.imePadding()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 24.dp.scaledHeight())
|
||||
.padding(horizontal = 24.dp.scaledWidth()),
|
||||
|
@ -188,35 +190,103 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
.padding(16.dp.scaledWidth())
|
||||
.focusGroup(),
|
||||
) {
|
||||
GroupLabel(
|
||||
stringResource(R.string.interface_),
|
||||
)
|
||||
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
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier =
|
||||
Modifier.fillMaxWidth(),
|
||||
) {
|
||||
GroupLabel(
|
||||
stringResource(R.string.interface_),
|
||||
)
|
||||
Column {
|
||||
IconButton(
|
||||
modifier = Modifier.size(iconSize),
|
||||
onClick = {
|
||||
isInterfaceDropDownExpanded = true
|
||||
},
|
||||
) {
|
||||
val icon = Icons.Rounded.MoreVert
|
||||
Icon(icon, icon.name)
|
||||
}
|
||||
},
|
||||
)
|
||||
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
|
||||
}
|
||||
DropdownMenu(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
expanded = isInterfaceDropDownExpanded,
|
||||
modifier = Modifier.shadow(12.dp).background(MaterialTheme.colorScheme.surface),
|
||||
onDismissRequest = {
|
||||
isInterfaceDropDownExpanded = false
|
||||
},
|
||||
) {
|
||||
val isAmneziaCompatibilitySet = interfaceState.isAmneziaCompatibilityModeSet()
|
||||
InterfaceActions.entries.forEach { action ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = when (action) {
|
||||
InterfaceActions.TOGGLE_SHOW_SCRIPTS -> if (showScripts) {
|
||||
stringResource(R.string.hide_scripts)
|
||||
} else {
|
||||
stringResource(R.string.show_scripts)
|
||||
}
|
||||
InterfaceActions.TOGGLE_AMNEZIA_VALUES -> if (showAmneziaValues) {
|
||||
stringResource(R.string.hide_amnezia_properties)
|
||||
} else {
|
||||
stringResource(R.string.show_amnezia_properties)
|
||||
}
|
||||
|
||||
InterfaceActions.SET_AMNEZIA_COMPATIBILITY -> if (isAmneziaCompatibilitySet) {
|
||||
stringResource(R.string.remove_amnezia_compatibility)
|
||||
} else {
|
||||
stringResource(R.string.enable_amnezia_compatibility)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
isInterfaceDropDownExpanded = false
|
||||
when (action) {
|
||||
InterfaceActions.TOGGLE_AMNEZIA_VALUES -> showAmneziaValues = !showAmneziaValues
|
||||
InterfaceActions.TOGGLE_SHOW_SCRIPTS -> showScripts = !showScripts
|
||||
InterfaceActions.SET_AMNEZIA_COMPATIBILITY -> if (isAmneziaCompatibilitySet) {
|
||||
showAmneziaValues = false
|
||||
interfaceState = interfaceState.resetAmneziaProperties()
|
||||
} else {
|
||||
showAmneziaValues = true
|
||||
interfaceState = interfaceState.toAmneziaCompatibilityConfig()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
// 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 },
|
||||
|
@ -246,7 +316,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
trailingIcon = {
|
||||
IconButton(
|
||||
enabled = privateKeyEnabled,
|
||||
modifier = Modifier.focusRequester(FocusRequester.Default),
|
||||
modifier = Modifier.focusRequester(FocusRequester.Default).size(iconSize),
|
||||
onClick = {
|
||||
val keypair = KeyPair()
|
||||
interfaceState = interfaceState.copy(
|
||||
|
@ -287,7 +357,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
},
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
modifier = Modifier.focusRequester(FocusRequester.Default),
|
||||
modifier = Modifier.focusRequester(FocusRequester.Default).size(iconSize),
|
||||
onClick = {
|
||||
clipboardManager.setText(
|
||||
AnnotatedString(interfaceState.publicKey),
|
||||
|
@ -540,13 +610,17 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
}
|
||||
}
|
||||
peersState.forEachIndexed { index, peer ->
|
||||
var isPeerDropDownExpanded by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val isLanExcluded = peer.isLanExcluded()
|
||||
Surface(
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.Top),
|
||||
modifier = Modifier
|
||||
.padding(16.dp.scaledWidth())
|
||||
.focusGroup(),
|
||||
|
@ -560,11 +634,65 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
|
|||
GroupLabel(
|
||||
stringResource(R.string.peer),
|
||||
)
|
||||
IconButton(onClick = {
|
||||
peersState.removeAt(index)
|
||||
}) {
|
||||
val icon = Icons.Rounded.Delete
|
||||
Icon(icon, icon.name)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
IconButton(
|
||||
modifier = Modifier.size(iconSize),
|
||||
onClick = {
|
||||
// TODO make a dialog to confirm this
|
||||
peersState.removeAt(index)
|
||||
},
|
||||
) {
|
||||
val icon = Icons.Rounded.Delete
|
||||
Icon(icon, icon.name)
|
||||
}
|
||||
Column {
|
||||
IconButton(
|
||||
modifier = Modifier.size(iconSize),
|
||||
onClick = {
|
||||
isPeerDropDownExpanded = true
|
||||
},
|
||||
) {
|
||||
val icon = Icons.Rounded.MoreVert
|
||||
Icon(icon, icon.name)
|
||||
}
|
||||
DropdownMenu(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
expanded = isPeerDropDownExpanded,
|
||||
modifier = Modifier.shadow(12.dp).background(MaterialTheme.colorScheme.surface),
|
||||
onDismissRequest = {
|
||||
isPeerDropDownExpanded = false
|
||||
},
|
||||
) {
|
||||
PeerActions.entries.forEach { action ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = when (action) {
|
||||
PeerActions.EXCLUDE_LAN -> if (isLanExcluded) {
|
||||
stringResource(R.string.include_lan)
|
||||
} else {
|
||||
stringResource(R.string.exclude_lan)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
isPeerDropDownExpanded = false
|
||||
when (action) {
|
||||
PeerActions.EXCLUDE_LAN -> if (isLanExcluded) {
|
||||
peersState[index] = peer.includeLan()
|
||||
} else {
|
||||
peersState[index] = peer.excludeLan()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.mode
|
|||
import com.wireguard.config.Interface
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.joinAndTrim
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.toTrimmedList
|
||||
import kotlin.ranges.contains
|
||||
|
||||
data class InterfaceProxy(
|
||||
val privateKey: String = "",
|
||||
|
@ -44,6 +45,46 @@ data class InterfaceProxy(
|
|||
}.build()
|
||||
}
|
||||
|
||||
fun toAmneziaCompatibilityConfig(): InterfaceProxy {
|
||||
return copy(
|
||||
junkPacketCount = "4",
|
||||
junkPacketMinSize = "40",
|
||||
junkPacketMaxSize = "70",
|
||||
initPacketJunkSize = "0",
|
||||
responsePacketJunkSize = "0",
|
||||
initPacketMagicHeader = "1",
|
||||
responsePacketMagicHeader = "2",
|
||||
underloadPacketMagicHeader = "3",
|
||||
transportPacketMagicHeader = "4",
|
||||
)
|
||||
}
|
||||
|
||||
fun resetAmneziaProperties(): InterfaceProxy {
|
||||
return copy(
|
||||
junkPacketCount = "",
|
||||
junkPacketMinSize = "",
|
||||
junkPacketMaxSize = "",
|
||||
initPacketJunkSize = "",
|
||||
responsePacketJunkSize = "",
|
||||
initPacketMagicHeader = "",
|
||||
responsePacketMagicHeader = "",
|
||||
underloadPacketMagicHeader = "",
|
||||
transportPacketMagicHeader = "",
|
||||
)
|
||||
}
|
||||
|
||||
fun isAmneziaCompatibilityModeSet(): Boolean {
|
||||
return junkPacketCount.toIntOrNull() in 3..<5 &&
|
||||
junkPacketMinSize.toIntOrNull() == 40 &&
|
||||
junkPacketMaxSize.toIntOrNull() == 70 &&
|
||||
with(initPacketJunkSize.toIntOrNull()) { this == 0 || this == null } &&
|
||||
with(responsePacketJunkSize.toIntOrNull()) { this == 0 || this == null } &&
|
||||
initPacketMagicHeader.toLongOrNull() == 1L &&
|
||||
responsePacketMagicHeader.toLongOrNull() == 2L &&
|
||||
underloadPacketMagicHeader.toLongOrNull() == 3L &&
|
||||
transportPacketMagicHeader.toLongOrNull() == 4L
|
||||
}
|
||||
|
||||
fun toAmInterface(): org.amnezia.awg.config.Interface {
|
||||
return org.amnezia.awg.config.Interface.Builder().apply {
|
||||
parseAddresses(addresses)
|
||||
|
|
|
@ -8,7 +8,7 @@ data class PeerProxy(
|
|||
val preSharedKey: String = "",
|
||||
val persistentKeepalive: String = "",
|
||||
val endpoint: String = "",
|
||||
val allowedIps: String = IPV4_WILDCARD.joinAndTrim(),
|
||||
val allowedIps: String = ALL_IPS.joinAndTrim(),
|
||||
) {
|
||||
fun toWgPeer(): Peer {
|
||||
return Peer.Builder().apply {
|
||||
|
@ -29,6 +29,22 @@ data class PeerProxy(
|
|||
}.build()
|
||||
}
|
||||
|
||||
fun isLanExcluded(): Boolean {
|
||||
return this.allowedIps.contains(IPV4_PUBLIC_NETWORKS.joinAndTrim())
|
||||
}
|
||||
|
||||
fun includeLan(): PeerProxy {
|
||||
return this.copy(
|
||||
allowedIps = ALL_IPS.joinAndTrim(),
|
||||
)
|
||||
}
|
||||
|
||||
fun excludeLan(): PeerProxy {
|
||||
return this.copy(
|
||||
allowedIps = IPV4_PUBLIC_NETWORKS.joinAndTrim(),
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun from(peer: Peer): PeerProxy {
|
||||
return PeerProxy(
|
||||
|
@ -113,6 +129,6 @@ data class PeerProxy(
|
|||
"200.0.0.0/5",
|
||||
"208.0.0.0/4",
|
||||
)
|
||||
val IPV4_WILDCARD = setOf("0.0.0.0/0")
|
||||
val ALL_IPS = setOf("0.0.0.0/0", "::/0")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,14 @@ import com.wireguard.config.Peer
|
|||
import com.zaneschepke.wireguardautotunnel.service.tunnel.BackendState
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.statistics.TunnelStatistics
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.SilverTree
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.Straw
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
|
||||
import org.amnezia.awg.backend.Backend
|
||||
import org.amnezia.awg.config.Config
|
||||
import org.amnezia.awg.config.Interface
|
||||
import timber.log.Timber
|
||||
import java.net.InetAddress
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
fun TunnelStatistics.mapPeerStats(): Map<org.amnezia.awg.crypto.Key, TunnelStatistics.PeerStats?> {
|
||||
return this.getPeers().associateWith { key -> (this.peerStats(key)) }
|
||||
|
@ -98,45 +95,3 @@ fun Backend.BackendState.asBackendState(): BackendState {
|
|||
fun BackendState.asAmBackendState(): Backend.BackendState {
|
||||
return Backend.BackendState.valueOf(this.name)
|
||||
}
|
||||
|
||||
fun Interface.isWgCompatibilityMode(): Boolean {
|
||||
return (
|
||||
junkPacketCount.getOrNull() in 3..<5 &&
|
||||
junkPacketMinSize.getOrNull() == 40 &&
|
||||
junkPacketMaxSize.getOrNull() == 70 &&
|
||||
with(initPacketJunkSize.getOrNull()) { this == 0 || this == null } &&
|
||||
with(responsePacketJunkSize.getOrNull()) { this == 0 || this == null } &&
|
||||
initPacketMagicHeader.getOrNull() == 1L &&
|
||||
responsePacketMagicHeader.getOrNull() == 2L &&
|
||||
underloadPacketMagicHeader.getOrNull() == 3L &&
|
||||
transportPacketMagicHeader.getOrNull() == 4L
|
||||
)
|
||||
}
|
||||
|
||||
fun InterfaceProxy.toAmneziaCompatibilityConfig(): InterfaceProxy {
|
||||
return copy(
|
||||
junkPacketCount = "4",
|
||||
junkPacketMinSize = "40",
|
||||
junkPacketMaxSize = "70",
|
||||
initPacketJunkSize = "0",
|
||||
responsePacketJunkSize = "0",
|
||||
initPacketMagicHeader = "1",
|
||||
responsePacketMagicHeader = "2",
|
||||
underloadPacketMagicHeader = "3",
|
||||
transportPacketMagicHeader = "4",
|
||||
)
|
||||
}
|
||||
|
||||
fun InterfaceProxy.resetAmneziaProperties(): InterfaceProxy {
|
||||
return copy(
|
||||
junkPacketCount = "",
|
||||
junkPacketMinSize = "",
|
||||
junkPacketMaxSize = "",
|
||||
initPacketJunkSize = "",
|
||||
responsePacketJunkSize = "",
|
||||
initPacketMagicHeader = "",
|
||||
responsePacketMagicHeader = "",
|
||||
underloadPacketMagicHeader = "",
|
||||
transportPacketMagicHeader = "",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -196,4 +196,10 @@
|
|||
<string name="quick_actions">Quick actions</string>
|
||||
<string name="advanced_settings">Advanced settings</string>
|
||||
<string name="debounce_delay">Debounce delay</string>
|
||||
<string name="hide_amnezia_properties">Hide Amnezia properties</string>
|
||||
<string name="hide_scripts">Hide scripts</string>
|
||||
<string name="enable_amnezia_compatibility">Enable Amnezia compatibility</string>
|
||||
<string name="remove_amnezia_compatibility">Remove Amnezia compatibility</string>
|
||||
<string name="exclude_lan">Exclude LAN</string>
|
||||
<string name="include_lan">Include LAN</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue