Compare commits

..

4 Commits

Author SHA1 Message Date
Zane Schepke ee8db0a859 fix: ui bug and graphene notification
Fixes a bug where save button was hidden on config screen

Adds a disclaimer notification for when GrapheneOS auto enabled Always-on VPN on first app tunnel start

Closes #121 #120
2024-02-20 16:17:34 -05:00
Zane Schepke c8205c4c59 fix: ui tunnel display bug
Fixes a bug where turning on auto tunneling hides the first tunnel in the app.

Closes #116
2024-02-19 08:45:52 -05:00
Zane Schepke 3247e94358 Merge pull request #105 from zaneschepke/dependabot/github_actions/actions/upload-artifact-4.3.1
build(deps): bump actions/upload-artifact from 4.3.0 to 4.3.1
2024-02-19 06:59:32 -05:00
dependabot[bot] 84b2b75271 build(deps): bump actions/upload-artifact from 4.3.0 to 4.3.1
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.0...v4.3.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-06 14:02:45 +00:00
14 changed files with 207 additions and 112 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ jobs:
echo "VERSION_CODE=$version_code" >> $GITHUB_ENV
# Save the APK after the Build job is complete to publish it as a Github release in the next job
- name: Upload APK
uses: actions/upload-artifact@v4.3.0
uses: actions/upload-artifact@v4.3.1
with:
name: wgtunnel
path: ${{ steps.apk-path.outputs.path }}
+1 -1
View File
@@ -69,7 +69,7 @@ jobs:
echo "VERSION_CODE=$version_code" >> $GITHUB_ENV
# Save the APK after the Build job is complete to publish it as a Github release in the next job
- name: Upload APK
uses: actions/upload-artifact@v4.3.0
uses: actions/upload-artifact@v4.3.1
with:
name: wgtunnel
path: ${{ steps.apk-path.outputs.path }}
@@ -18,7 +18,7 @@ object Queries {
VALUES
('false',
'false',
'[trustedSSID1,trustedSSID2]',
'sampleSSID1,sampleSSID2',
NULL,
'false',
'false',
@@ -84,6 +84,8 @@ class WireGuardTunnelService : ForegroundService() {
tunnelName = tunnel.name
vpnService.startTunnel(tunnel)
}
} else {
launchAlwaysOnDisabledNotification()
}
}
}
@@ -116,6 +118,11 @@ class WireGuardTunnelService : ForegroundService() {
}
}
private fun launchAlwaysOnDisabledNotification() {
launchVpnNotification(title = this.getString(R.string.vpn_connection_failed),
description = this.getString(R.string.always_on_disabled))
}
override fun stopService(extras: Bundle?) {
super.stopService(extras)
lifecycleScope.launch(Dispatchers.IO) {
@@ -153,24 +153,25 @@ class MainActivity : AppCompatActivity() {
{}
},
) { padding ->
Column(modifier = Modifier.padding(padding)) {
if (notificationPermissionState != null && !notificationPermissionState.status.isGranted) {
PermissionRequestFailedScreen(
onRequestAgain = {
val intentSettings =
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intentSettings.data =
Uri.fromParts(
Constants.URI_PACKAGE_SCHEME,
this@MainActivity.packageName,
null,
)
startActivity(intentSettings)
},
message = getString(R.string.notification_permission_required),
getString(R.string.open_settings),
)
return@Scaffold
Column(modifier = Modifier.padding(padding)) {
PermissionRequestFailedScreen(
onRequestAgain = {
val intentSettings =
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intentSettings.data =
Uri.fromParts(
Constants.URI_PACKAGE_SCHEME,
this@MainActivity.packageName,
null,
)
startActivity(intentSettings)
},
message = getString(R.string.notification_permission_required),
getString(R.string.open_settings),
)
return@Scaffold
}
}
NavHost(navController, startDestination = Screen.Main.route) {
composable(
@@ -186,14 +187,17 @@ class MainActivity : AppCompatActivity() {
Screen.Settings.route,
) {
SettingsScreen(
padding = padding,
showSnackbarMessage = { message -> showSnackBarMessage(message) },
focusRequester = focusRequester,
)
//
}
composable(
Screen.Support.route,
) {
SupportScreen(
padding = padding,
focusRequester = focusRequester,
showSnackbarMessage = { message -> showSnackBarMessage(message) },
)
@@ -202,6 +206,7 @@ class MainActivity : AppCompatActivity() {
val id = it.arguments?.getString("id")
if (!id.isNullOrBlank()) {
ConfigScreen(
padding = padding,
navController = navController,
id = id,
showSnackbarMessage = { message ->
@@ -212,7 +217,6 @@ class MainActivity : AppCompatActivity() {
}
}
}
}
}
}
}
@@ -7,6 +7,7 @@ import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.res.stringResource
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.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
@@ -88,6 +90,7 @@ import kotlinx.coroutines.delay
)
@Composable
fun ConfigScreen(
padding: PaddingValues,
viewModel: ConfigViewModel = hiltViewModel(),
focusRequester: FocusRequester,
navController: NavController,
@@ -125,13 +128,16 @@ fun ConfigScreen(
val fillMaxWidth = .85f
val screenPadding = 5.dp
val applicationButtonText = {
"Tunneling apps: " +
val applicationButtonText = buildAnnotatedString {
append(stringResource(id = R.string.tunneling_apps))
append(": ")
if (uiState.isAllApplicationsEnabled) {
"all"
append(stringResource(id = R.string.all))
} else {
"${uiState.checkedPackageNames.size} " +
(if (uiState.include) "included" else "excluded")
append("${uiState.checkedPackageNames.size} ")
(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),
color = MaterialTheme.colorScheme.surface,
modifier =
Modifier.fillMaxWidth()
Modifier
.fillMaxWidth()
.fillMaxHeight(if (uiState.isAllApplicationsEnabled) 1 / 5f else 4 / 5f),
) {
Column(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier
.fillMaxWidth()) {
Row(
modifier =
Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 7.dp),
Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
@@ -183,7 +193,8 @@ fun ConfigScreen(
if (!uiState.isAllApplicationsEnabled) {
Row(
modifier =
Modifier.fillMaxWidth()
Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
@@ -215,7 +226,8 @@ fun ConfigScreen(
}
Row(
modifier =
Modifier.fillMaxWidth()
Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 7.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
@@ -232,7 +244,9 @@ fun ConfigScreen(
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize().padding(5.dp),
modifier = Modifier
.fillMaxSize()
.padding(5.dp),
) {
Row(modifier = Modifier.fillMaxWidth(fillMaxWidth)) {
val drawable =
@@ -275,7 +289,9 @@ fun ConfigScreen(
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(top = 5.dp),
modifier = Modifier
.fillMaxSize()
.padding(top = 5.dp),
horizontalArrangement = Arrangement.Center,
) {
TextButton(onClick = { showApplicationsDialog = false }) {
@@ -295,7 +311,7 @@ fun ConfigScreen(
var fobColor by remember { mutableStateOf(secondaryColor) }
FloatingActionButton(
modifier =
Modifier.onFocusChanged {
Modifier.padding(bottom = 90.dp).onFocusChanged {
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
fobColor = if (it.isFocused) hoverColor else secondaryColor
}
@@ -327,7 +343,11 @@ fun ConfigScreen(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier =
Modifier.verticalScroll(rememberScrollState()).weight(1f, true).fillMaxSize(),
Modifier
.verticalScroll(rememberScrollState())
.weight(1f, true)
.fillMaxSize()
.padding(padding),
) {
Surface(
tonalElevation = 2.dp,
@@ -336,16 +356,20 @@ fun ConfigScreen(
color = MaterialTheme.colorScheme.surface,
modifier =
(if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
Modifier.fillMaxHeight(fillMaxHeight).fillMaxWidth(fillMaxWidth)
Modifier
.fillMaxHeight(fillMaxHeight)
.fillMaxWidth(fillMaxWidth)
} else {
Modifier.fillMaxWidth(fillMaxWidth)
})
.padding(top = 50.dp, bottom = 10.dp),
.padding(bottom = 10.dp),
) {
Column(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top,
modifier = Modifier.padding(15.dp).focusGroup(),
modifier = Modifier
.padding(15.dp)
.focusGroup(),
) {
SectionTitle(
stringResource(R.string.interface_),
@@ -357,10 +381,14 @@ fun ConfigScreen(
keyboardActions = keyboardActions,
label = stringResource(R.string.name),
hint = stringResource(R.string.tunnel_name).lowercase(),
modifier = Modifier.fillMaxWidth().focusRequester(focusRequester),
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester),
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth().clickable { showAuthPrompt = true },
modifier = Modifier
.fillMaxWidth()
.clickable { showAuthPrompt = true },
value = uiState.interfaceProxy.privateKey,
visualTransformation =
if ((id == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated)
@@ -388,7 +416,9 @@ fun ConfigScreen(
)
OutlinedTextField(
modifier =
Modifier.fillMaxWidth().focusRequester(FocusRequester.Default),
Modifier
.fillMaxWidth()
.focusRequester(FocusRequester.Default),
value = uiState.interfaceProxy.publicKey,
enabled = false,
onValueChange = {},
@@ -421,7 +451,9 @@ fun ConfigScreen(
keyboardActions = keyboardActions,
label = stringResource(R.string.addresses),
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(
value = uiState.interfaceProxy.listenPort,
@@ -439,7 +471,9 @@ fun ConfigScreen(
keyboardActions = keyboardActions,
label = stringResource(R.string.dns_servers),
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(
value = uiState.interfaceProxy.mtu,
@@ -452,11 +486,13 @@ fun ConfigScreen(
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(top = 5.dp),
modifier = Modifier
.fillMaxSize()
.padding(top = 5.dp),
horizontalArrangement = Arrangement.Center,
) {
TextButton(onClick = { showApplicationsDialog = true }) {
Text(applicationButtonText())
Text(applicationButtonText.text)
}
}
}
@@ -469,7 +505,9 @@ fun ConfigScreen(
color = MaterialTheme.colorScheme.surface,
modifier =
(if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
Modifier.fillMaxHeight(fillMaxHeight).fillMaxWidth(fillMaxWidth)
Modifier
.fillMaxHeight(fillMaxHeight)
.fillMaxWidth(fillMaxWidth)
} else {
Modifier.fillMaxWidth(fillMaxWidth)
})
@@ -478,12 +516,16 @@ fun ConfigScreen(
Column(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top,
modifier = Modifier.padding(horizontal = 15.dp).padding(bottom = 10.dp),
modifier = Modifier
.padding(horizontal = 15.dp)
.padding(bottom = 10.dp),
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 5.dp),
) {
SectionTitle(
stringResource(R.string.peer),
@@ -566,7 +608,9 @@ fun ConfigScreen(
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize().padding(bottom = 140.dp),
modifier = Modifier
.fillMaxSize()
.padding(bottom = 140.dp),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -13,6 +13,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
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.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@@ -287,8 +289,9 @@ fun MainScreen(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier.requiredWidth(LocalConfiguration.current.screenWidthDp.dp)
.padding(end = 5.dp),
Modifier
.requiredWidth(LocalConfiguration.current.screenWidthDp.dp)
.padding(end = 5.dp)
) {
Row {
Icon(
@@ -299,8 +302,15 @@ fun MainScreen(
if (uiState.settings.isAutoTunnelPaused) Color.Gray
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(
"Auto-tunneling: ${if (uiState.settings.isAutoTunnelPaused) "paused" else "active"}",
autoTunnelingLabel.text,
style = typography.bodyLarge,
modifier = Modifier.padding(start = 10.dp),
)
@@ -310,14 +320,14 @@ fun MainScreen(
onClick = { viewModel.resumeAutoTunneling() },
modifier = Modifier.padding(end = 10.dp),
) {
Text("Resume")
Text(stringResource(id = R.string.resume))
}
else
TextButton(
onClick = { viewModel.pauseAutoTunneling() },
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) }
FloatingActionButton(
modifier =
(if (
WireGuardAutoTunnel.isRunningOnAndroidTv() &&
uiState.tunnels.isEmpty()
)
Modifier.focusRequester(focusRequester)
else Modifier)
.onFocusChanged {
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
fobColor = if (it.isFocused) hoverColor else secondaryColor
}
},
(if (
WireGuardAutoTunnel.isRunningOnAndroidTv() &&
uiState.tunnels.isEmpty()
)
Modifier.focusRequester(focusRequester)
else Modifier)
.padding(bottom = 90.dp)
.onFocusChanged {
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
fobColor = if (it.isFocused) hoverColor else secondaryColor
}
},
onClick = { showBottomSheet = true },
containerColor = fobColor,
shape = RoundedCornerShape(16.dp),
@@ -362,7 +373,9 @@ fun MainScreen(
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize().padding(innerPadding),
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
) {
Text(text = stringResource(R.string.no_tunnels), fontStyle = FontStyle.Italic)
}
@@ -375,12 +388,13 @@ fun MainScreen(
// Sheet content
Row(
modifier =
Modifier.fillMaxWidth()
.clickable {
showBottomSheet = false
tunnelFileImportResultLauncher.launch(Constants.ALLOWED_FILE_TYPES)
}
.padding(10.dp),
Modifier
.fillMaxWidth()
.clickable {
showBottomSheet = false
tunnelFileImportResultLauncher.launch(Constants.ALLOWED_FILE_TYPES)
}
.padding(10.dp),
) {
Icon(
Icons.Filled.FileOpen,
@@ -396,23 +410,24 @@ fun MainScreen(
HorizontalDivider()
Row(
modifier =
Modifier.fillMaxWidth()
.clickable {
scope.launch {
showBottomSheet = false
val scanOptions = ScanOptions()
scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
scanOptions.setOrientationLocked(true)
scanOptions.setPrompt(
context.getString(R.string.scanning_qr)
)
scanOptions.setBeepEnabled(false)
scanOptions.captureActivity =
CaptureActivityPortrait::class.java
scanLauncher.launch(scanOptions)
}
Modifier
.fillMaxWidth()
.clickable {
scope.launch {
showBottomSheet = false
val scanOptions = ScanOptions()
scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
scanOptions.setOrientationLocked(true)
scanOptions.setPrompt(
context.getString(R.string.scanning_qr)
)
scanOptions.setBeepEnabled(false)
scanOptions.captureActivity =
CaptureActivityPortrait::class.java
scanLauncher.launch(scanOptions)
}
.padding(10.dp),
}
.padding(10.dp),
) {
Icon(
Icons.Filled.QrCode,
@@ -428,14 +443,15 @@ fun MainScreen(
HorizontalDivider()
Row(
modifier =
Modifier.fillMaxWidth()
.clickable {
showBottomSheet = false
navController.navigate(
"${Screen.Config.route}/${Constants.MANUAL_TUNNEL_CONFIG_ID}",
)
}
.padding(10.dp),
Modifier
.fillMaxWidth()
.clickable {
showBottomSheet = false
navController.navigate(
"${Screen.Config.route}/${Constants.MANUAL_TUNNEL_CONFIG_ID}",
)
}
.padding(10.dp),
) {
Icon(
Icons.Filled.Create,
@@ -454,9 +470,11 @@ fun MainScreen(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top,
modifier =
Modifier.fillMaxWidth()
.fillMaxHeight(.90f)
.overscroll(ScrollableDefaults.overscrollEffect()),
Modifier
.fillMaxWidth()
.fillMaxHeight(.90f)
.overscroll(ScrollableDefaults.overscrollEffect())
.padding(innerPadding),
state = rememberLazyListState(0, uiState.tunnels.count()),
userScrollEnabled = true,
reverseLayout = true,
@@ -496,14 +514,18 @@ fun MainScreen(
Icons.Rounded.Star,
stringResource(R.string.status),
tint = leadingIconColor,
modifier = Modifier.padding(end = 10.dp).size(20.dp),
modifier = Modifier
.padding(end = 10.dp)
.size(20.dp),
)
} else {
Icon(
Icons.Rounded.Circle,
stringResource(R.string.status),
tint = leadingIconColor,
modifier = Modifier.padding(end = 15.dp).size(15.dp),
modifier = Modifier
.padding(end = 15.dp)
.size(15.dp),
)
}
},
@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -93,6 +94,7 @@ import java.io.File
)
@Composable
fun SettingsScreen(
padding: PaddingValues,
viewModel: SettingsViewModel = hiltViewModel(),
showSnackbarMessage: (String) -> Unit,
focusRequester: FocusRequester
@@ -246,7 +248,7 @@ fun SettingsScreen(
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxSize().verticalScroll(scrollState),
modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(padding),
) {
Icon(
Icons.Rounded.LocationOff,
@@ -312,7 +314,7 @@ fun SettingsScreen(
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize().padding(padding),
) {
Text(
stringResource(R.string.one_tunnel_required),
@@ -327,7 +329,7 @@ fun SettingsScreen(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier =
Modifier.fillMaxSize().verticalScroll(scrollState).clickable(
Modifier.fillMaxSize().padding(padding).verticalScroll(scrollState).clickable(
indication = null,
interactionSource = interactionSource,
) {
@@ -8,6 +8,7 @@ import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -56,6 +57,7 @@ import com.zaneschepke.wireguardautotunnel.util.Event
@Composable
fun SupportScreen(
padding: PaddingValues,
viewModel: SupportViewModel = hiltViewModel(),
showSnackbarMessage: (String) -> Unit,
focusRequester: FocusRequester
@@ -102,7 +104,7 @@ fun SupportScreen(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier =
Modifier.fillMaxSize()
Modifier.fillMaxSize().padding(padding)
.verticalScroll(rememberScrollState())
.focusable()
) {
+11 -2
View File
@@ -73,7 +73,7 @@
<string name="last_handshake">Last handshake</string>
<string name="name">Name</string>
<string name="restart">Restart Tunnel</string>
<string name="vpn_connection_failed">VPN Connection Failed</string>
<string name="vpn_connection_failed">Connection failed</string>
<string name="failed_connection_to">Failed connection to -</string>
<string name="initial_connection_failure_message">Attempting to connect to server after 30 seconds of no response.</string>
<string name="lost_connection_failure_message">Attempting to reconnect to server after more than one minute of no response.</string>
@@ -90,7 +90,7 @@
<string name="clear_icon">Clear Icon</string>
<string name="search_icon">Search Icon</string>
<string name="attempt_connection">Attempting connection..</string>
<string name="vpn_starting">VPN Starting</string>
<string name="vpn_starting">VPN starting</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">Scanning for QR</string>
<string name="qr_result_failed">QR scan failed</string>
@@ -167,4 +167,13 @@
<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="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>
<string name="always_on_disabled">Always-on VPN attempted to start a tunnel, but this feature is disabled in settings.</string>
</resources>
+2 -2
View File
@@ -1,7 +1,7 @@
object Constants {
const val VERSION_NAME = "3.3.6"
const val VERSION_NAME = "3.3.8"
const val JVM_TARGET = "17"
const val VERSION_CODE = 33600
const val VERSION_CODE = 33800
const val TARGET_SDK = 34
const val MIN_SDK = 26
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
@@ -0,0 +1,2 @@
What's new:
- Tunnel display UI bug fix
@@ -0,0 +1,4 @@
What's new:
- Config edit UI bug fix
- Add GrapheneOS first launch AOVPN notification
- Bump versions
+2 -3
View File
@@ -14,7 +14,7 @@ google-services = "4.4.1"
hiltAndroid = "2.50"
hiltNavigationCompose = "1.1.0"
junit = "4.13.2"
kotlinx-serialization-json = "1.6.2"
kotlinx-serialization-json = "1.6.3"
lifecycle-runtime-compose = "2.7.0"
material3 = "1.2.0"
navigationCompose = "2.7.7"
@@ -97,5 +97,4 @@ zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", ve
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }