fix: ui tunnel display bug

Fixes a bug where turning on auto tunneling hides the first tunnel in the app.

Closes #116
This commit is contained in:
Zane Schepke 2024-02-19 08:45:52 -05:00
parent 3247e94358
commit c8205c4c59
9 changed files with 188 additions and 105 deletions

View File

@ -153,24 +153,25 @@ class MainActivity : AppCompatActivity() {
{} {}
}, },
) { padding -> ) { padding ->
Column(modifier = Modifier.padding(padding)) {
if (notificationPermissionState != null && !notificationPermissionState.status.isGranted) { if (notificationPermissionState != null && !notificationPermissionState.status.isGranted) {
PermissionRequestFailedScreen( Column(modifier = Modifier.padding(padding)) {
onRequestAgain = { PermissionRequestFailedScreen(
val intentSettings = onRequestAgain = {
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val intentSettings =
intentSettings.data = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
Uri.fromParts( intentSettings.data =
Constants.URI_PACKAGE_SCHEME, Uri.fromParts(
this@MainActivity.packageName, Constants.URI_PACKAGE_SCHEME,
null, this@MainActivity.packageName,
) null,
startActivity(intentSettings) )
}, startActivity(intentSettings)
message = getString(R.string.notification_permission_required), },
getString(R.string.open_settings), message = getString(R.string.notification_permission_required),
) getString(R.string.open_settings),
return@Scaffold )
return@Scaffold
}
} }
NavHost(navController, startDestination = Screen.Main.route) { NavHost(navController, startDestination = Screen.Main.route) {
composable( composable(
@ -186,14 +187,17 @@ class MainActivity : AppCompatActivity() {
Screen.Settings.route, Screen.Settings.route,
) { ) {
SettingsScreen( SettingsScreen(
padding = padding,
showSnackbarMessage = { message -> showSnackBarMessage(message) }, showSnackbarMessage = { message -> showSnackBarMessage(message) },
focusRequester = focusRequester, focusRequester = focusRequester,
) )
//
} }
composable( composable(
Screen.Support.route, Screen.Support.route,
) { ) {
SupportScreen( SupportScreen(
padding = padding,
focusRequester = focusRequester, focusRequester = focusRequester,
showSnackbarMessage = { message -> showSnackBarMessage(message) }, showSnackbarMessage = { message -> showSnackBarMessage(message) },
) )
@ -202,6 +206,7 @@ class MainActivity : AppCompatActivity() {
val id = it.arguments?.getString("id") val id = it.arguments?.getString("id")
if (!id.isNullOrBlank()) { if (!id.isNullOrBlank()) {
ConfigScreen( ConfigScreen(
padding = padding,
navController = navController, navController = navController,
id = id, id = id,
showSnackbarMessage = { message -> showSnackbarMessage = { message ->
@ -212,7 +217,6 @@ class MainActivity : AppCompatActivity() {
} }
} }
} }
}
} }
} }
} }

View File

@ -7,6 +7,7 @@ import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@ -61,6 +62,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
@ -88,6 +90,7 @@ import kotlinx.coroutines.delay
) )
@Composable @Composable
fun ConfigScreen( fun ConfigScreen(
padding: PaddingValues,
viewModel: ConfigViewModel = hiltViewModel(), viewModel: ConfigViewModel = hiltViewModel(),
focusRequester: FocusRequester, focusRequester: FocusRequester,
navController: NavController, navController: NavController,
@ -125,13 +128,16 @@ fun ConfigScreen(
val fillMaxWidth = .85f val fillMaxWidth = .85f
val screenPadding = 5.dp val screenPadding = 5.dp
val applicationButtonText = { val applicationButtonText = buildAnnotatedString {
"Tunneling apps: " + append(stringResource(id = R.string.tunneling_apps))
append(": ")
if (uiState.isAllApplicationsEnabled) { if (uiState.isAllApplicationsEnabled) {
"all" append(stringResource(id = R.string.all))
} else { } else {
"${uiState.checkedPackageNames.size} " + append("${uiState.checkedPackageNames.size} ")
(if (uiState.include) "included" else "excluded") (if (uiState.include) append(stringResource(id = R.string.included)) else append(
stringResource(id = R.string.excluded),
))
} }
} }
@ -164,13 +170,17 @@ fun ConfigScreen(
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(12.dp),
color = MaterialTheme.colorScheme.surface, color = MaterialTheme.colorScheme.surface,
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.fillMaxWidth()
.fillMaxHeight(if (uiState.isAllApplicationsEnabled) 1 / 5f else 4 / 5f), .fillMaxHeight(if (uiState.isAllApplicationsEnabled) 1 / 5f else 4 / 5f),
) { ) {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier
.fillMaxWidth()) {
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 7.dp), Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
) { ) {
@ -183,7 +193,8 @@ fun ConfigScreen(
if (!uiState.isAllApplicationsEnabled) { if (!uiState.isAllApplicationsEnabled) {
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp), .padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
@ -215,7 +226,8 @@ fun ConfigScreen(
} }
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp), .padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
@ -232,7 +244,9 @@ fun ConfigScreen(
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize().padding(5.dp), modifier = Modifier
.fillMaxSize()
.padding(5.dp),
) { ) {
Row(modifier = Modifier.fillMaxWidth(fillMaxWidth)) { Row(modifier = Modifier.fillMaxWidth(fillMaxWidth)) {
val drawable = val drawable =
@ -275,7 +289,9 @@ fun ConfigScreen(
} }
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(top = 5.dp), modifier = Modifier
.fillMaxSize()
.padding(top = 5.dp),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
) { ) {
TextButton(onClick = { showApplicationsDialog = false }) { TextButton(onClick = { showApplicationsDialog = false }) {
@ -327,7 +343,11 @@ fun ConfigScreen(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = modifier =
Modifier.verticalScroll(rememberScrollState()).weight(1f, true).fillMaxSize(), Modifier
.verticalScroll(rememberScrollState())
.weight(1f, true)
.fillMaxSize()
.padding(padding),
) { ) {
Surface( Surface(
tonalElevation = 2.dp, tonalElevation = 2.dp,
@ -336,16 +356,20 @@ fun ConfigScreen(
color = MaterialTheme.colorScheme.surface, color = MaterialTheme.colorScheme.surface,
modifier = modifier =
(if (WireGuardAutoTunnel.isRunningOnAndroidTv()) { (if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
Modifier.fillMaxHeight(fillMaxHeight).fillMaxWidth(fillMaxWidth) Modifier
.fillMaxHeight(fillMaxHeight)
.fillMaxWidth(fillMaxWidth)
} else { } else {
Modifier.fillMaxWidth(fillMaxWidth) Modifier.fillMaxWidth(fillMaxWidth)
}) })
.padding(top = 50.dp, bottom = 10.dp), .padding(bottom = 10.dp),
) { ) {
Column( Column(
horizontalAlignment = Alignment.Start, horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = Modifier.padding(15.dp).focusGroup(), modifier = Modifier
.padding(15.dp)
.focusGroup(),
) { ) {
SectionTitle( SectionTitle(
stringResource(R.string.interface_), stringResource(R.string.interface_),
@ -357,10 +381,14 @@ fun ConfigScreen(
keyboardActions = keyboardActions, keyboardActions = keyboardActions,
label = stringResource(R.string.name), label = stringResource(R.string.name),
hint = stringResource(R.string.tunnel_name).lowercase(), hint = stringResource(R.string.tunnel_name).lowercase(),
modifier = Modifier.fillMaxWidth().focusRequester(focusRequester), modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester),
) )
OutlinedTextField( OutlinedTextField(
modifier = Modifier.fillMaxWidth().clickable { showAuthPrompt = true }, modifier = Modifier
.fillMaxWidth()
.clickable { showAuthPrompt = true },
value = uiState.interfaceProxy.privateKey, value = uiState.interfaceProxy.privateKey,
visualTransformation = visualTransformation =
if ((id == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated) if ((id == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated)
@ -388,7 +416,9 @@ fun ConfigScreen(
) )
OutlinedTextField( OutlinedTextField(
modifier = modifier =
Modifier.fillMaxWidth().focusRequester(FocusRequester.Default), Modifier
.fillMaxWidth()
.focusRequester(FocusRequester.Default),
value = uiState.interfaceProxy.publicKey, value = uiState.interfaceProxy.publicKey,
enabled = false, enabled = false,
onValueChange = {}, onValueChange = {},
@ -421,7 +451,9 @@ fun ConfigScreen(
keyboardActions = keyboardActions, keyboardActions = keyboardActions,
label = stringResource(R.string.addresses), label = stringResource(R.string.addresses),
hint = stringResource(R.string.comma_separated_list), hint = stringResource(R.string.comma_separated_list),
modifier = Modifier.fillMaxWidth(3 / 5f).padding(end = 5.dp), modifier = Modifier
.fillMaxWidth(3 / 5f)
.padding(end = 5.dp),
) )
ConfigurationTextBox( ConfigurationTextBox(
value = uiState.interfaceProxy.listenPort, value = uiState.interfaceProxy.listenPort,
@ -439,7 +471,9 @@ fun ConfigScreen(
keyboardActions = keyboardActions, keyboardActions = keyboardActions,
label = stringResource(R.string.dns_servers), label = stringResource(R.string.dns_servers),
hint = stringResource(R.string.comma_separated_list), hint = stringResource(R.string.comma_separated_list),
modifier = Modifier.fillMaxWidth(3 / 5f).padding(end = 5.dp), modifier = Modifier
.fillMaxWidth(3 / 5f)
.padding(end = 5.dp),
) )
ConfigurationTextBox( ConfigurationTextBox(
value = uiState.interfaceProxy.mtu, value = uiState.interfaceProxy.mtu,
@ -452,11 +486,13 @@ fun ConfigScreen(
} }
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(top = 5.dp), modifier = Modifier
.fillMaxSize()
.padding(top = 5.dp),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
) { ) {
TextButton(onClick = { showApplicationsDialog = true }) { TextButton(onClick = { showApplicationsDialog = true }) {
Text(applicationButtonText()) Text(applicationButtonText.text)
} }
} }
} }
@ -469,7 +505,9 @@ fun ConfigScreen(
color = MaterialTheme.colorScheme.surface, color = MaterialTheme.colorScheme.surface,
modifier = modifier =
(if (WireGuardAutoTunnel.isRunningOnAndroidTv()) { (if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
Modifier.fillMaxHeight(fillMaxHeight).fillMaxWidth(fillMaxWidth) Modifier
.fillMaxHeight(fillMaxHeight)
.fillMaxWidth(fillMaxWidth)
} else { } else {
Modifier.fillMaxWidth(fillMaxWidth) Modifier.fillMaxWidth(fillMaxWidth)
}) })
@ -478,12 +516,16 @@ fun ConfigScreen(
Column( Column(
horizontalAlignment = Alignment.Start, horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = Modifier.padding(horizontal = 15.dp).padding(bottom = 10.dp), modifier = Modifier
.padding(horizontal = 15.dp)
.padding(bottom = 10.dp),
) { ) {
Row( Row(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp), modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 5.dp),
) { ) {
SectionTitle( SectionTitle(
stringResource(R.string.peer), stringResource(R.string.peer),
@ -566,7 +608,9 @@ fun ConfigScreen(
Row( Row(
horizontalArrangement = Arrangement.SpaceEvenly, horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(bottom = 140.dp), modifier = Modifier
.fillMaxSize()
.padding(bottom = 140.dp),
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,

View File

@ -13,6 +13,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable import androidx.compose.foundation.focusable
import androidx.compose.foundation.gestures.ScrollableDefaults import androidx.compose.foundation.gestures.ScrollableDefaults
@ -80,6 +81,7 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
@ -287,8 +289,9 @@ fun MainScreen(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = modifier =
Modifier.requiredWidth(LocalConfiguration.current.screenWidthDp.dp) Modifier
.padding(end = 5.dp), .requiredWidth(LocalConfiguration.current.screenWidthDp.dp)
.padding(end = 5.dp)
) { ) {
Row { Row {
Icon( Icon(
@ -299,8 +302,15 @@ fun MainScreen(
if (uiState.settings.isAutoTunnelPaused) Color.Gray if (uiState.settings.isAutoTunnelPaused) Color.Gray
else mint, else mint,
) )
val autoTunnelingLabel = buildAnnotatedString {
append(stringResource(id = R.string.auto_tunneling))
append(": ")
if(uiState.settings.isAutoTunnelPaused) append(stringResource(id = R.string.paused)) else append(
stringResource(id = R.string.active),
)
}
Text( Text(
"Auto-tunneling: ${if (uiState.settings.isAutoTunnelPaused) "paused" else "active"}", autoTunnelingLabel.text,
style = typography.bodyLarge, style = typography.bodyLarge,
modifier = Modifier.padding(start = 10.dp), modifier = Modifier.padding(start = 10.dp),
) )
@ -310,14 +320,14 @@ fun MainScreen(
onClick = { viewModel.resumeAutoTunneling() }, onClick = { viewModel.resumeAutoTunneling() },
modifier = Modifier.padding(end = 10.dp), modifier = Modifier.padding(end = 10.dp),
) { ) {
Text("Resume") Text(stringResource(id = R.string.resume))
} }
else else
TextButton( TextButton(
onClick = { viewModel.pauseAutoTunneling() }, onClick = { viewModel.pauseAutoTunneling() },
modifier = Modifier.padding(end = 10.dp), modifier = Modifier.padding(end = 10.dp),
) { ) {
Text("Pause") Text(stringResource(id = R.string.pause))
} }
} }
}, },
@ -334,17 +344,18 @@ fun MainScreen(
var fobColor by remember { mutableStateOf(secondaryColor) } var fobColor by remember { mutableStateOf(secondaryColor) }
FloatingActionButton( FloatingActionButton(
modifier = modifier =
(if ( (if (
WireGuardAutoTunnel.isRunningOnAndroidTv() && WireGuardAutoTunnel.isRunningOnAndroidTv() &&
uiState.tunnels.isEmpty() uiState.tunnels.isEmpty()
) )
Modifier.focusRequester(focusRequester) Modifier.focusRequester(focusRequester)
else Modifier) else Modifier)
.onFocusChanged { .padding(bottom = 90.dp)
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) { .onFocusChanged {
fobColor = if (it.isFocused) hoverColor else secondaryColor if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
} fobColor = if (it.isFocused) hoverColor else secondaryColor
}, }
},
onClick = { showBottomSheet = true }, onClick = { showBottomSheet = true },
containerColor = fobColor, containerColor = fobColor,
shape = RoundedCornerShape(16.dp), shape = RoundedCornerShape(16.dp),
@ -362,7 +373,9 @@ fun MainScreen(
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize().padding(innerPadding), modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
) { ) {
Text(text = stringResource(R.string.no_tunnels), fontStyle = FontStyle.Italic) Text(text = stringResource(R.string.no_tunnels), fontStyle = FontStyle.Italic)
} }
@ -375,12 +388,13 @@ fun MainScreen(
// Sheet content // Sheet content
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.clickable { .fillMaxWidth()
showBottomSheet = false .clickable {
tunnelFileImportResultLauncher.launch(Constants.ALLOWED_FILE_TYPES) showBottomSheet = false
} tunnelFileImportResultLauncher.launch(Constants.ALLOWED_FILE_TYPES)
.padding(10.dp), }
.padding(10.dp),
) { ) {
Icon( Icon(
Icons.Filled.FileOpen, Icons.Filled.FileOpen,
@ -396,23 +410,24 @@ fun MainScreen(
HorizontalDivider() HorizontalDivider()
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.clickable { .fillMaxWidth()
scope.launch { .clickable {
showBottomSheet = false scope.launch {
val scanOptions = ScanOptions() showBottomSheet = false
scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE) val scanOptions = ScanOptions()
scanOptions.setOrientationLocked(true) scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
scanOptions.setPrompt( scanOptions.setOrientationLocked(true)
context.getString(R.string.scanning_qr) scanOptions.setPrompt(
) context.getString(R.string.scanning_qr)
scanOptions.setBeepEnabled(false) )
scanOptions.captureActivity = scanOptions.setBeepEnabled(false)
CaptureActivityPortrait::class.java scanOptions.captureActivity =
scanLauncher.launch(scanOptions) CaptureActivityPortrait::class.java
} scanLauncher.launch(scanOptions)
} }
.padding(10.dp), }
.padding(10.dp),
) { ) {
Icon( Icon(
Icons.Filled.QrCode, Icons.Filled.QrCode,
@ -428,14 +443,15 @@ fun MainScreen(
HorizontalDivider() HorizontalDivider()
Row( Row(
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.clickable { .fillMaxWidth()
showBottomSheet = false .clickable {
navController.navigate( showBottomSheet = false
"${Screen.Config.route}/${Constants.MANUAL_TUNNEL_CONFIG_ID}", navController.navigate(
) "${Screen.Config.route}/${Constants.MANUAL_TUNNEL_CONFIG_ID}",
} )
.padding(10.dp), }
.padding(10.dp),
) { ) {
Icon( Icon(
Icons.Filled.Create, Icons.Filled.Create,
@ -454,9 +470,11 @@ fun MainScreen(
horizontalAlignment = Alignment.Start, horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = modifier =
Modifier.fillMaxWidth() Modifier
.fillMaxHeight(.90f) .fillMaxWidth()
.overscroll(ScrollableDefaults.overscrollEffect()), .fillMaxHeight(.90f)
.overscroll(ScrollableDefaults.overscrollEffect())
.padding(innerPadding),
state = rememberLazyListState(0, uiState.tunnels.count()), state = rememberLazyListState(0, uiState.tunnels.count()),
userScrollEnabled = true, userScrollEnabled = true,
reverseLayout = true, reverseLayout = true,
@ -496,14 +514,18 @@ fun MainScreen(
Icons.Rounded.Star, Icons.Rounded.Star,
stringResource(R.string.status), stringResource(R.string.status),
tint = leadingIconColor, tint = leadingIconColor,
modifier = Modifier.padding(end = 10.dp).size(20.dp), modifier = Modifier
.padding(end = 10.dp)
.size(20.dp),
) )
} else { } else {
Icon( Icon(
Icons.Rounded.Circle, Icons.Rounded.Circle,
stringResource(R.string.status), stringResource(R.string.status),
tint = leadingIconColor, tint = leadingIconColor,
modifier = Modifier.padding(end = 15.dp).size(15.dp), modifier = Modifier
.padding(end = 15.dp)
.size(15.dp),
) )
} }
}, },

View File

@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -93,6 +94,7 @@ import java.io.File
) )
@Composable @Composable
fun SettingsScreen( fun SettingsScreen(
padding: PaddingValues,
viewModel: SettingsViewModel = hiltViewModel(), viewModel: SettingsViewModel = hiltViewModel(),
showSnackbarMessage: (String) -> Unit, showSnackbarMessage: (String) -> Unit,
focusRequester: FocusRequester focusRequester: FocusRequester
@ -246,7 +248,7 @@ fun SettingsScreen(
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxSize().verticalScroll(scrollState), modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(padding),
) { ) {
Icon( Icon(
Icons.Rounded.LocationOff, Icons.Rounded.LocationOff,
@ -312,7 +314,7 @@ fun SettingsScreen(
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize().padding(padding),
) { ) {
Text( Text(
stringResource(R.string.one_tunnel_required), stringResource(R.string.one_tunnel_required),
@ -327,7 +329,7 @@ fun SettingsScreen(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = modifier =
Modifier.fillMaxSize().verticalScroll(scrollState).clickable( Modifier.fillMaxSize().padding(padding).verticalScroll(scrollState).clickable(
indication = null, indication = null,
interactionSource = interactionSource, interactionSource = interactionSource,
) { ) {

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -56,6 +57,7 @@ import com.zaneschepke.wireguardautotunnel.util.Event
@Composable @Composable
fun SupportScreen( fun SupportScreen(
padding: PaddingValues,
viewModel: SupportViewModel = hiltViewModel(), viewModel: SupportViewModel = hiltViewModel(),
showSnackbarMessage: (String) -> Unit, showSnackbarMessage: (String) -> Unit,
focusRequester: FocusRequester focusRequester: FocusRequester
@ -102,7 +104,7 @@ fun SupportScreen(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
modifier = modifier =
Modifier.fillMaxSize() Modifier.fillMaxSize().padding(padding)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.focusable() .focusable()
) { ) {

View File

@ -167,4 +167,12 @@
<string name="delete_tunnel">Delete tunnel</string> <string name="delete_tunnel">Delete tunnel</string>
<string name="delete_tunnel_message">Are you sure you would like to delete this tunnel?</string> <string name="delete_tunnel_message">Are you sure you would like to delete this tunnel?</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
<string name="resume">Resume</string>
<string name="pause">Pause</string>
<string name="paused">paused</string>
<string name="active">active</string>
<string name="tunneling_apps">Tunneling apps</string>
<string name="included">included</string>
<string name="excluded">excluded</string>
<string name="all">all</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
object Constants { object Constants {
const val VERSION_NAME = "3.3.6" const val VERSION_NAME = "3.3.7"
const val JVM_TARGET = "17" const val JVM_TARGET = "17"
const val VERSION_CODE = 33600 const val VERSION_CODE = 33700
const val TARGET_SDK = 34 const val TARGET_SDK = 34
const val MIN_SDK = 26 const val MIN_SDK = 26
const val APP_ID = "com.zaneschepke.wireguardautotunnel" const val APP_ID = "com.zaneschepke.wireguardautotunnel"

View File

@ -0,0 +1,2 @@
What's new:
- Tunnel display UI bug fix

View File

@ -97,5 +97,4 @@ zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", ve
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" } hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" }