mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
refactor: ui screen content spacing
This commit is contained in:
@@ -254,7 +254,10 @@ class MainActivity : AppCompatActivity() {
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.padding(padding)
|
||||
.padding(
|
||||
top = padding.calculateTopPadding().plus(8.dp),
|
||||
bottom = padding.calculateBottomPadding(),
|
||||
)
|
||||
.consumeWindowInsets(padding)
|
||||
.imePadding()
|
||||
) {
|
||||
|
||||
+6
-8
@@ -4,13 +4,11 @@ import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -22,29 +20,28 @@ fun ExpandingRowListItem(
|
||||
text: String,
|
||||
trailing: @Composable () -> Unit,
|
||||
isSelected: Boolean,
|
||||
expanded: (@Composable () -> Unit),
|
||||
expanded: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
modifier
|
||||
.animateContentSize()
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(
|
||||
if (isSelected) MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
|
||||
else Color.Transparent
|
||||
)
|
||||
) {
|
||||
Column {
|
||||
Column(Modifier.padding(horizontal = 16.dp)) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp).height(48.dp),
|
||||
modifier = Modifier.fillMaxWidth().height(54.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier.fillMaxWidth(13 / 20f),
|
||||
modifier = Modifier.weight(1f),
|
||||
) {
|
||||
leading()
|
||||
Text(
|
||||
@@ -53,6 +50,7 @@ fun ExpandingRowListItem(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
trailing()
|
||||
|
||||
+1
-3
@@ -36,9 +36,7 @@ fun SelectionItemButton(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = { onClick() },
|
||||
)
|
||||
.height(IntrinsicSize.Min)
|
||||
.padding(horizontal = 12.dp)
|
||||
.padding(end = 12.dp),
|
||||
.height(IntrinsicSize.Min),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.Transparent),
|
||||
) {
|
||||
Row(
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ fun SurfaceSelectionGroupButton(items: List<SelectionItem>, modifier: Modifier =
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(0.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
items.forEach { item ->
|
||||
@@ -52,7 +52,7 @@ fun SurfaceSelectionGroupButton(items: List<SelectionItem>, modifier: Modifier =
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
||||
@@ -18,7 +18,7 @@ fun GroupLabel(title: String, modifier: Modifier = Modifier) {
|
||||
) {
|
||||
Text(
|
||||
title,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
|
||||
+5
-1
@@ -2,11 +2,13 @@ package com.zaneschepke.wireguardautotunnel.ui.navigation.components
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.zaneschepke.wireguardautotunnel.ui.state.NavbarState
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.LockedDownBannerHeight
|
||||
|
||||
@@ -17,7 +19,9 @@ fun DynamicTopAppBar(navBarState: NavbarState, modifier: Modifier = Modifier) {
|
||||
modifier = modifier.padding(top = LockedDownBannerHeight),
|
||||
colors = TopAppBarDefaults.topAppBarColors().copy(Color.Transparent),
|
||||
navigationIcon = { navBarState.topLeading?.invoke() },
|
||||
title = { navBarState.topTitle?.invoke() },
|
||||
title = {
|
||||
navBarState.topTitle?.let { Text(it, maxLines = 1, overflow = TextOverflow.Ellipsis) }
|
||||
},
|
||||
actions = { navBarState.topTrailing?.invoke() },
|
||||
)
|
||||
}
|
||||
|
||||
+27
-30
@@ -6,11 +6,10 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.rounded.Sort
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
@@ -31,6 +30,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
val sharedState by sharedViewModel.container.stateFlow.collectAsStateWithLifecycle()
|
||||
val backStackEntry by currentBackStackEntryAsState()
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
val context = LocalContext.current
|
||||
val route =
|
||||
remember(backStackEntry) {
|
||||
backStackEntry?.destination?.route?.let {
|
||||
@@ -97,7 +97,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.advanced_settings)) },
|
||||
topTitle = context.getString(R.string.advanced_settings),
|
||||
)
|
||||
Route.Appearance ->
|
||||
NavbarState(
|
||||
@@ -107,7 +107,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.appearance)) },
|
||||
topTitle = context.getString(R.string.appearance),
|
||||
)
|
||||
Route.AutoTunnel ->
|
||||
NavbarState(
|
||||
@@ -115,7 +115,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
topTitle =
|
||||
if (!sharedState.isLocationDisclosureShown) null
|
||||
else {
|
||||
{ Text(stringResource(R.string.auto_tunnel)) }
|
||||
context.getString(R.string.auto_tunnel)
|
||||
},
|
||||
)
|
||||
Route.Display ->
|
||||
@@ -126,7 +126,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.display_theme)) },
|
||||
topTitle = context.getString(R.string.display_theme),
|
||||
)
|
||||
Route.Dns ->
|
||||
NavbarState(
|
||||
@@ -136,7 +136,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.dns_settings)) },
|
||||
topTitle = context.getString(R.string.dns_settings),
|
||||
)
|
||||
Route.Language ->
|
||||
NavbarState(
|
||||
@@ -146,7 +146,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.language)) },
|
||||
topTitle = context.getString(R.string.language),
|
||||
)
|
||||
Route.License ->
|
||||
NavbarState(
|
||||
@@ -156,7 +156,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.licenses)) },
|
||||
topTitle = context.getString(R.string.licenses),
|
||||
)
|
||||
Route.LocationDisclosure -> NavbarState(showBottomItems = true)
|
||||
Route.Lock -> NavbarState(showBottomItems = false)
|
||||
@@ -164,7 +164,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
NavbarState(
|
||||
showBottomItems = false,
|
||||
removeBottom = true,
|
||||
topTitle = { Text(stringResource(R.string.logs)) },
|
||||
topTitle = context.getString(R.string.logs),
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Menu, R.string.quick_actions) {
|
||||
sharedViewModel.postSideEffect(LocalSideEffect.Sheet.LoggerActions)
|
||||
@@ -179,7 +179,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.proxy_settings)) },
|
||||
topTitle = context.getString(R.string.proxy_settings),
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Save, R.string.save) {
|
||||
keyboardController?.hide()
|
||||
@@ -190,7 +190,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
Route.Settings ->
|
||||
NavbarState(
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.settings)) },
|
||||
topTitle = context.getString(R.string.settings),
|
||||
topTrailing = {
|
||||
ActionIconButton(
|
||||
Icons.Rounded.SettingsBackupRestore,
|
||||
@@ -208,7 +208,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.sort)) },
|
||||
topTitle = context.getString(R.string.sort),
|
||||
topTrailing = {
|
||||
Row {
|
||||
ActionIconButton(Icons.Rounded.SortByAlpha, R.string.sort) {
|
||||
@@ -229,10 +229,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = {
|
||||
val title = tunnel?.tunName ?: stringResource(R.string.new_tunnel)
|
||||
Text(title)
|
||||
},
|
||||
topTitle = tunnel?.tunName ?: context.getString(R.string.new_tunnel),
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Save, R.string.save) {
|
||||
keyboardController?.hide()
|
||||
@@ -249,7 +246,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(tunnel?.tunName ?: "") },
|
||||
topTitle = tunnel?.tunName ?: "",
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Save, R.string.save) {
|
||||
sharedViewModel.postSideEffect(LocalSideEffect.SaveChanges)
|
||||
@@ -265,7 +262,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.splt_tunneling)) },
|
||||
topTitle = context.getString(R.string.splt_tunneling),
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Save, R.string.save) {
|
||||
sharedViewModel.postSideEffect(LocalSideEffect.SaveChanges)
|
||||
@@ -282,7 +279,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(stringResource(R.string.configuration)) },
|
||||
topTitle = context.getString(R.string.configuration),
|
||||
topTrailing = {
|
||||
ActionIconButton(Icons.Rounded.Save, R.string.save) {
|
||||
keyboardController?.hide()
|
||||
@@ -293,7 +290,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
Route.Support ->
|
||||
NavbarState(
|
||||
topTitle = { Text(stringResource(R.string.support)) },
|
||||
topTitle = context.getString(R.string.support),
|
||||
showBottomItems = true,
|
||||
)
|
||||
Route.SystemFeatures ->
|
||||
@@ -303,7 +300,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.android_integrations)) },
|
||||
topTitle = context.getString(R.string.android_integrations),
|
||||
showBottomItems = true,
|
||||
)
|
||||
is Route.TunnelAutoTunnel -> {
|
||||
@@ -315,7 +312,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(tunnel?.tunName ?: "") },
|
||||
topTitle = tunnel?.tunName ?: "",
|
||||
)
|
||||
}
|
||||
Route.TunnelMonitoring ->
|
||||
@@ -325,7 +322,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.tunnel_monitoring)) },
|
||||
topTitle = context.getString(R.string.tunnel_monitoring),
|
||||
showBottomItems = true,
|
||||
)
|
||||
is Route.TunnelOptions -> {
|
||||
@@ -337,7 +334,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
},
|
||||
showBottomItems = true,
|
||||
topTitle = { Text(tunnel?.tunName ?: "") },
|
||||
topTitle = tunnel?.tunName ?: "",
|
||||
topTrailing = {
|
||||
Row {
|
||||
ActionIconButton(Icons.Rounded.QrCode2, R.string.show_qr) {
|
||||
@@ -352,7 +349,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
}
|
||||
Route.Tunnels -> {
|
||||
NavbarState(
|
||||
topTitle = { Text(stringResource(R.string.tunnels)) },
|
||||
topTitle = context.getString(R.string.tunnels),
|
||||
topTrailing = {
|
||||
when (selectedCount) {
|
||||
0 -> DefaultTunnelsActions(navController, sharedViewModel)
|
||||
@@ -404,7 +401,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.wifi_detection_method)) },
|
||||
topTitle = context.getString(R.string.wifi_detection_method),
|
||||
showBottomItems = true,
|
||||
)
|
||||
Route.Donate -> {
|
||||
@@ -414,7 +411,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.donate_title)) },
|
||||
topTitle = context.getString(R.string.donate_title),
|
||||
showBottomItems = true,
|
||||
)
|
||||
}
|
||||
@@ -425,7 +422,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.addresses)) },
|
||||
topTitle = context.getString(R.string.addresses),
|
||||
showBottomItems = true,
|
||||
)
|
||||
}
|
||||
@@ -436,7 +433,7 @@ fun NavHostController.currentBackStackEntryAsNavbarState(
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topTitle = { Text(stringResource(R.string.tunnel_global_overrides)) },
|
||||
topTitle = context.getString(R.string.tunnel_global_overrides),
|
||||
showBottomItems = true,
|
||||
)
|
||||
}
|
||||
|
||||
+1
-4
@@ -96,10 +96,7 @@ fun AutoTunnelScreen(viewModel: AutoTunnelViewModel = hiltViewModel()) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
WarningBanner(
|
||||
stringResource(R.string.location_services_not_detected),
|
||||
|
||||
+1
-4
@@ -29,10 +29,7 @@ fun AutoTunnelAdvancedScreen(viewModel: AutoTunnelViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
LabelledDropdown(
|
||||
title = {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ fun WifiDetectionMethodScreen(viewModel: AutoTunnelViewModel) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(top = 24.dp).padding(horizontal = 24.dp),
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp),
|
||||
) {
|
||||
enumValues<WifiDetectionMethod>().forEach {
|
||||
val title = it.asTitleString(context)
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ fun LocationDisclosureScreen(viewModel: AutoTunnelViewModel) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(18.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(top = 18.dp).padding(horizontal = 24.dp),
|
||||
modifier = Modifier.fillMaxSize().padding(top = 18.dp).padding(horizontal = 16.dp),
|
||||
) {
|
||||
LocationDisclosureHeader()
|
||||
SurfaceSelectionGroupButton(
|
||||
|
||||
+2
-2
@@ -83,7 +83,6 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel()) {
|
||||
modifier =
|
||||
Modifier.verticalScroll(rememberScrollState())
|
||||
.fillMaxSize()
|
||||
.padding(vertical = 24.dp)
|
||||
.then(
|
||||
if (!isTv) {
|
||||
Modifier.clickable(
|
||||
@@ -94,7 +93,8 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel()) {
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
),
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(appModeItem(settingsState.settings.appMode) { showAppModeSheet = true })
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ fun AppearanceScreen() {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(vertical = 24.dp).padding(horizontal = 12.dp),
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(items = listOf(LanguageItem(navController)))
|
||||
SectionDivider()
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@ fun DisplayScreen() {
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(top = 24.dp).padding(horizontal = 24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp),
|
||||
) {
|
||||
enumValues<Theme>().forEach {
|
||||
val title =
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ fun LanguageScreen() {
|
||||
state = lazyListState,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Top,
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
item {
|
||||
IconSurfaceButton(
|
||||
|
||||
+1
-4
@@ -36,10 +36,7 @@ fun DnsSettingsScreen(viewModel: SettingsViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
LabelledDropdown(
|
||||
title = {
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ fun TunnelGlobalsScreen(globalTunnelId: Int) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.verticalScroll(rememberScrollState()).fillMaxSize().padding(vertical = 24.dp),
|
||||
Modifier.verticalScroll(rememberScrollState()).fillMaxSize().padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
|
||||
+2
-7
@@ -2,7 +2,6 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.settings.logs
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -12,7 +11,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
@@ -84,10 +82,7 @@ fun LogsScreen(viewModel: LoggerViewModel = hiltViewModel()) {
|
||||
}
|
||||
|
||||
if (loggerState.messages.isEmpty()) {
|
||||
return Box(
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 24.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
return Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Text(
|
||||
text = stringResource(R.string.nothing_here_yet),
|
||||
fontStyle = FontStyle.Italic,
|
||||
@@ -100,6 +95,6 @@ fun LogsScreen(viewModel: LoggerViewModel = hiltViewModel()) {
|
||||
LogList(
|
||||
logs = loggerState.messages,
|
||||
lazyColumnListState = lazyColumnListState,
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 24.dp),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
package com.zaneschepke.wireguardautotunnel.ui.screens.settings.logs.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
@@ -20,7 +21,7 @@ fun LogList(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Top),
|
||||
state = lazyColumnListState,
|
||||
modifier = modifier,
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
) {
|
||||
itemsIndexed(items = logs, key = { index, _ -> index }, contentType = { _, _ -> null }) {
|
||||
_,
|
||||
|
||||
+1
-4
@@ -35,10 +35,7 @@ fun TunnelMonitoringScreen(viewModel: SettingsViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ fun ProxySettingsScreen(viewModel: ProxySettingsViewModel = hiltViewModel()) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.Top),
|
||||
modifier = Modifier.fillMaxSize().padding(top = 24.dp).padding(horizontal = 12.dp),
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
|
||||
+1
-4
@@ -31,10 +31,7 @@ fun SystemFeaturesScreen(viewModel: SettingsViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(buildList { if (!isTv) add(nativeKillSwitchItem()) })
|
||||
SectionDivider()
|
||||
|
||||
+3
-7
@@ -126,16 +126,12 @@ fun SupportScreen(viewModel: SupportViewModel) {
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
) {
|
||||
GroupLabel(
|
||||
stringResource(R.string.thank_you),
|
||||
modifier = Modifier.padding(horizontal = 12.dp).padding(bottom = 12.dp),
|
||||
)
|
||||
GroupLabel(stringResource(R.string.thank_you), modifier = Modifier.padding(bottom = 12.dp))
|
||||
UpdateSection { viewModel.checkForUpdate() }
|
||||
SectionDivider()
|
||||
DonateSection { navController.navigate(Route.Donate) }
|
||||
|
||||
+1
-4
@@ -25,10 +25,7 @@ fun DonateScreen(navController: NavController) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
DonationHeroSection()
|
||||
SectionDivider()
|
||||
|
||||
+3
-10
@@ -3,11 +3,8 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.support.donate.components
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -20,13 +17,9 @@ import com.zaneschepke.wireguardautotunnel.R
|
||||
|
||||
@Composable
|
||||
fun DonationHeroSection() {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
|
||||
) {
|
||||
Surface(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
|
||||
+1
-4
@@ -20,10 +20,7 @@ fun AddressesScreen() {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
val clipboard = rememberClipboardHelper()
|
||||
SurfaceSelectionGroupButton(
|
||||
|
||||
+23
-22
@@ -19,31 +19,32 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.openWebUrl
|
||||
fun LicenseList(licenses: List<LicenseFileEntry>) {
|
||||
val context = LocalContext.current
|
||||
|
||||
LazyColumn(modifier = Modifier.fillMaxSize().padding(24.dp)) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(licenses) { entry ->
|
||||
Column(modifier = Modifier.padding(bottom = 12.dp)) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = "${entry.artifactId} (${entry.version})",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = "${entry.artifactId} (${entry.version})",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
|
||||
entry.spdxLicenses.forEach { license ->
|
||||
Text(
|
||||
text = license.name,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
entry.spdxLicenses.forEach { license ->
|
||||
Text(
|
||||
text = license.name,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
entry.scm?.url?.let { scmUrl ->
|
||||
LinkIconButton(modifier = Modifier.size(20.dp).focusable()) {
|
||||
context.openWebUrl(scmUrl)
|
||||
}
|
||||
}
|
||||
entry.scm?.url?.let { scmUrl ->
|
||||
LinkIconButton(modifier = Modifier.size(20.dp).focusable()) {
|
||||
context.openWebUrl(scmUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -3,7 +3,6 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunnels
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -12,7 +11,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.journeyapps.barcodescanner.ScanContract
|
||||
import com.journeyapps.barcodescanner.ScanOptions
|
||||
@@ -144,7 +142,7 @@ fun TunnelsScreen(viewModel: TunnelsViewModel) {
|
||||
TunnelList(
|
||||
tunnelsState,
|
||||
sharedState,
|
||||
modifier = Modifier.fillMaxSize().padding(vertical = 24.dp).padding(horizontal = 12.dp),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
sharedViewModel,
|
||||
navController,
|
||||
)
|
||||
|
||||
+1
-4
@@ -33,10 +33,7 @@ fun TunnelAutoTunnelScreen(tunnelId: Int, viewModel: TunnelsViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
items =
|
||||
|
||||
+2
-5
@@ -4,7 +4,6 @@ import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.gestures.ScrollableDefaults
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
@@ -16,7 +15,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.zaneschepke.wireguardautotunnel.domain.state.TunnelState
|
||||
import com.zaneschepke.wireguardautotunnel.ui.LocalIsAndroidTV
|
||||
@@ -42,7 +40,6 @@ fun TunnelList(
|
||||
|
||||
LazyColumn(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
|
||||
modifier =
|
||||
modifier
|
||||
.pointerInput(Unit) {
|
||||
@@ -84,7 +81,7 @@ fun TunnelList(
|
||||
isPingEnabled = tunnelsState.isPingEnabled,
|
||||
showDetailedStats = tunnelsState.showPingStats,
|
||||
modifier =
|
||||
if (!isTv)
|
||||
(if (!isTv)
|
||||
Modifier.combinedClickable(
|
||||
onClick = {
|
||||
if (sharedState.selectedTunnels.isNotEmpty()) {
|
||||
@@ -98,7 +95,7 @@ fun TunnelList(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null,
|
||||
)
|
||||
else Modifier,
|
||||
else Modifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -59,10 +59,7 @@ fun ConfigScreen(tunnelId: Int? = null) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 12.dp, bottom = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
InterfaceSection(
|
||||
isGlobalConfig,
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ fun InterfaceSection(
|
||||
Surface(shape = RoundedCornerShape(12.dp), color = MaterialTheme.colorScheme.surface) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp).focusGroup(),
|
||||
modifier = Modifier.focusGroup(),
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ fun PeersSection(
|
||||
Surface(shape = RoundedCornerShape(12.dp), color = MaterialTheme.colorScheme.surface) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp).focusGroup(),
|
||||
modifier = Modifier.focusGroup(),
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
||||
+1
-2
@@ -88,8 +88,7 @@ fun SortScreen(viewModel: TunnelsViewModel) {
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.pointerInput(Unit) { if (tunnelsState.tunnels.isEmpty()) return@pointerInput }
|
||||
.overscroll(rememberOverscrollEffect())
|
||||
.padding(horizontal = 16.dp, vertical = 24.dp),
|
||||
.overscroll(rememberOverscrollEffect()),
|
||||
state = lazyListState,
|
||||
userScrollEnabled = true,
|
||||
reverseLayout = false,
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ fun AppListSection(
|
||||
label = {},
|
||||
leading = { Icon(Icons.Outlined.Search, stringResource(R.string.search)) },
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
modifier = Modifier.fillMaxWidth().height(inputHeight).padding(horizontal = 24.dp),
|
||||
modifier = Modifier.fillMaxWidth().height(inputHeight),
|
||||
singleLine = true,
|
||||
keyboardOptions =
|
||||
KeyboardOptions(
|
||||
|
||||
-2
@@ -3,7 +3,6 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunnels.splittunnel.compo
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -27,7 +26,6 @@ fun SplitOptionSelector(selectedOption: SplitOption, onOptionChange: (SplitOptio
|
||||
modifier =
|
||||
Modifier.background(color = MaterialTheme.colorScheme.surface)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 24.dp)
|
||||
.height(inputHeight)
|
||||
) {
|
||||
SplitOption.entries.forEachIndexed { index, entry ->
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ fun SplitTunnelContent(
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 24.dp),
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
) {
|
||||
SplitOptionSelector(
|
||||
selectedOption = splitConfig.first,
|
||||
|
||||
+1
-4
@@ -54,10 +54,7 @@ fun TunnelOptionsScreen(tunnelId: Int, viewModel: TunnelsViewModel) {
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top),
|
||||
modifier =
|
||||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 24.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 16.dp),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
items =
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.zaneschepke.wireguardautotunnel.ui.state
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
data class NavbarState(
|
||||
val topTitle: (@Composable () -> Unit)? = null,
|
||||
val topTitle: String? = null,
|
||||
val topTrailing: (@Composable () -> Unit)? = null,
|
||||
val topLeading: (@Composable () -> Unit)? = null,
|
||||
val showBottomItems: Boolean = false,
|
||||
|
||||
@@ -99,7 +99,6 @@
|
||||
<string name="telegram_url" translatable="false">https://t.me/wgtunnel</string>
|
||||
<string name="unsure_how">nasıl devam edeceğinizden emin değilseniz</string>
|
||||
<string name="see_the">Bakınız</string>
|
||||
<string name="getting_started_url" translatable="false">https://zaneschepke.com/wgtunnel-docs/getting-started.html</string>
|
||||
<string name="getting_started_guide">başlangıç kılavuzu</string>
|
||||
<string name="restart_at_boot">Başlangıçta yeniden başlat</string>
|
||||
<string name="vpn_denied_dialog_title">İzin Reddedildi</string>
|
||||
|
||||
Reference in New Issue
Block a user