fix: minor ui improvements

closes #473
This commit is contained in:
Zane Schepke 2024-12-20 02:08:05 -05:00
parent 1d2b305047
commit 7f89dcaab0
13 changed files with 103 additions and 50 deletions

View File

@ -47,8 +47,14 @@ constructor(
addAction(it) addAction(it)
} }
setContentTitle(title) setContentTitle(title)
setContentIntent(PendingIntent.getActivity(context, 0, setContentIntent(
Intent(context, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)) PendingIntent.getActivity(
context,
0,
Intent(context, MainActivity::class.java),
PendingIntent.FLAG_IMMUTABLE,
),
)
setContentText(description) setContentText(description)
setOnlyAlertOnce(onlyAlertOnce) setOnlyAlertOnce(onlyAlertOnce)
setOngoing(onGoing) setOngoing(onGoing)

View File

@ -55,7 +55,13 @@ fun ExpandingRowListItem(
modifier = Modifier.fillMaxWidth(13 / 20f), modifier = Modifier.fillMaxWidth(13 / 20f),
) { ) {
leading() leading()
Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.labelLarge) Text(
text,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onBackground,
)
} }
trailing() trailing()
} }

View File

@ -2,36 +2,22 @@ package com.zaneschepke.wireguardautotunnel.ui.common
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons
import androidx.compose.material3.MaterialTheme import androidx.compose.material.icons.outlined.CheckBox
import androidx.compose.material3.Text import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
@Composable @Composable
fun SelectedLabel() { fun SelectedLabel() {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( val icon = Icons.Outlined.CheckBox
stringResource(id = R.string.selected), Icon(icon, icon.name)
modifier =
Modifier.padding(
horizontal = 24.dp.scaledWidth(),
vertical = 16.dp.scaledHeight(),
),
color =
MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.labelSmall,
)
} }
} }

View File

@ -1,6 +1,8 @@
package com.zaneschepke.wireguardautotunnel.ui.common.button package com.zaneschepke.wireguardautotunnel.ui.common.button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale import androidx.compose.ui.draw.scale
@ -14,5 +16,13 @@ fun ScaledSwitch(checked: Boolean, onClick: (checked: Boolean) -> Unit, enabled:
{ onClick(it) }, { onClick(it) },
modifier.scale((52.dp.scaledHeight() / 52.dp)), modifier.scale((52.dp.scaledHeight() / 52.dp)),
enabled = enabled, enabled = enabled,
colors = SwitchDefaults.colors().copy(
checkedThumbColor = MaterialTheme.colorScheme.background,
checkedIconColor = MaterialTheme.colorScheme.background,
uncheckedTrackColor = MaterialTheme.colorScheme.surface,
uncheckedBorderColor = MaterialTheme.colorScheme.outline,
uncheckedThumbColor = MaterialTheme.colorScheme.outline,
uncheckedIconColor = MaterialTheme.colorScheme.outline,
),
) )
} }

View File

@ -52,6 +52,7 @@ fun SurfaceSelectionGroupButton(items: List<SelectionItem>) {
icon, icon,
icon.name, icon.name,
modifier = Modifier.size(iconSize), modifier = Modifier.size(iconSize),
tint = MaterialTheme.colorScheme.onSurface,
) )
} }
Column( Column(
@ -80,7 +81,7 @@ fun SurfaceSelectionGroupButton(items: List<SelectionItem>) {
} }
} }
} }
if (index + 1 != items.size) HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) if (index + 1 != items.size) HorizontalDivider(color = MaterialTheme.colorScheme.outline.copy(0.30f))
} }
} }
} }

View File

@ -16,6 +16,7 @@ fun GroupLabel(title: String) {
Text( Text(
title, title,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onBackground,
) )
} }
} }

View File

@ -4,12 +4,14 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
@ -57,6 +59,13 @@ fun BottomNavBar(navController: NavController, bottomNavItems: List<BottomNavIte
contentDescription = "${item.name} Icon", contentDescription = "${item.name} Icon",
) )
}, },
colors = NavigationBarItemDefaults.colors().copy(
selectedIndicatorColor = Color.Transparent,
selectedIconColor = MaterialTheme.colorScheme.primary,
selectedTextColor = MaterialTheme.colorScheme.primary,
unselectedTextColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.55f),
unselectedIconColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.55f),
),
) )
} }
} }

View File

@ -21,22 +21,21 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.toThreeDecimalPlaceSt
@Composable @Composable
fun TunnelStatisticsRow(statistics: TunnelStatistics?, tunnelConfig: TunnelConfig) { fun TunnelStatisticsRow(statistics: TunnelStatistics?, tunnelConfig: TunnelConfig) {
val config = TunnelConfig.configFromAmQuick(tunnelConfig.wgQuick) val config = TunnelConfig.configFromAmQuick(tunnelConfig.wgQuick)
config.peers.forEach { peer ->
Row( Row(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(end = 10.dp, bottom = 10.dp, start = 45.dp), .padding(end = 10.dp, bottom = 10.dp, start = 45.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(30.dp, Alignment.Start), horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.Start),
) { ) {
config.peers.forEach { val peerId = peer.publicKey.toBase64().subSequence(0, 3).toString() + "***"
val peerId = it.publicKey.toBase64().subSequence(0, 3).toString() + "***" val peerRx = statistics?.peerStats(peer.publicKey)?.rxBytes ?: 0
val peerRx = statistics?.peerStats(it.publicKey)?.rxBytes ?: 0 val peerTx = statistics?.peerStats(peer.publicKey)?.txBytes ?: 0
val peerTx = statistics?.peerStats(it.publicKey)?.txBytes ?: 0
val peerTxMB = NumberUtils.bytesToMB(peerTx).toThreeDecimalPlaceString() val peerTxMB = NumberUtils.bytesToMB(peerTx).toThreeDecimalPlaceString()
val peerRxMB = NumberUtils.bytesToMB(peerRx).toThreeDecimalPlaceString() val peerRxMB = NumberUtils.bytesToMB(peerRx).toThreeDecimalPlaceString()
val handshake = statistics?.peerStats(it.publicKey)?.latestHandshakeEpochMillis?.let { val handshake = statistics?.peerStats(peer.publicKey)?.latestHandshakeEpochMillis?.let {
if (it == 0L) { if (it == 0L) {
stringResource(R.string.never) stringResource(R.string.never)
} else { } else {
@ -56,7 +55,11 @@ fun TunnelStatisticsRow(statistics: TunnelStatistics?, tunnelConfig: TunnelConfi
Column( Column(
verticalArrangement = Arrangement.spacedBy(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp),
) { ) {
Text(stringResource(R.string.handshake) + ": $handshake", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline) Text(
stringResource(R.string.handshake) + ": $handshake",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.outline,
)
Text("rx: $peerRxMB MB", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline) Text("rx: $peerRxMB MB", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline)
} }
} }

View File

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Contrast import androidx.compose.material.icons.outlined.Contrast
import androidx.compose.material.icons.outlined.Notifications
import androidx.compose.material.icons.outlined.Translate import androidx.compose.material.icons.outlined.Translate
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -13,6 +14,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.R
@ -22,12 +24,14 @@ import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SurfaceSelec
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.components.ForwardButton import com.zaneschepke.wireguardautotunnel.ui.screens.settings.components.ForwardButton
import com.zaneschepke.wireguardautotunnel.util.extensions.launchNotificationSettings
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
@Composable @Composable
fun AppearanceScreen() { fun AppearanceScreen() {
val navController = LocalNavController.current val navController = LocalNavController.current
val context = LocalContext.current
Scaffold( Scaffold(
topBar = { topBar = {
@ -55,6 +59,20 @@ fun AppearanceScreen() {
), ),
), ),
) )
SurfaceSelectionGroupButton(
listOf(
SelectionItem(
Icons.Outlined.Notifications,
title = { Text(stringResource(R.string.notifications), style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface)) },
onClick = {
context.launchNotificationSettings()
},
trailing = {
ForwardButton { context.launchNotificationSettings() }
},
),
),
)
SurfaceSelectionGroupButton( SurfaceSelectionGroupButton(
listOf( listOf(
SelectionItem( SelectionItem(

View File

@ -60,8 +60,10 @@ fun LanguageScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
appViewModel.onLocaleChange(LocaleUtil.OPTION_PHONE_LANGUAGE) appViewModel.onLocaleChange(LocaleUtil.OPTION_PHONE_LANGUAGE)
}, },
trailing = { trailing = {
if (appUiState.generalState.locale == LocaleUtil.OPTION_PHONE_LANGUAGE) { with(appUiState.generalState.locale) {
SelectedLabel() if (this == LocaleUtil.OPTION_PHONE_LANGUAGE || this == null) {
SelectedLabel()
}
} }
}, },
ripple = false, ripple = false,

View File

@ -174,7 +174,7 @@ fun SupportScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
title = { title = {
Text( Text(
stringResource(R.string.chat_description), stringResource(R.string.chat_description),
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface), style = MaterialTheme.typography.bodySmall.copy(MaterialTheme.colorScheme.onSurface),
) )
}, },
trailing = { trailing = {

View File

@ -2,8 +2,9 @@ package com.zaneschepke.wireguardautotunnel.ui.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
val OffWhite = Color(0xFFE5E1E5) val OffWhite = Color(0xFFF2F2F4)
val LightGrey = Color(0xFFCAC4D0) val CoolGray = Color(0xFF8D9D9F)
val LightGrey = Color(0xFFECEDEF)
val Aqua = Color(0xFF76BEBD) val Aqua = Color(0xFF76BEBD)
val SilverTree = Color(0xFF6DB58B) val SilverTree = Color(0xFF6DB58B)
val Plantation = Color(0xFF264A49) val Plantation = Color(0xFF264A49)
@ -18,14 +19,18 @@ sealed class ThemeColors(
val primary: Color, val primary: Color,
val secondary: Color, val secondary: Color,
val onSurface: Color, val onSurface: Color,
val onBackground: Color,
val outline: Color,
) { ) {
data object Light : ThemeColors( data object Light : ThemeColors(
background = LightGrey, background = LightGrey.copy(alpha = 0.95f),
surface = OffWhite, surface = OffWhite,
primary = Plantation, primary = Aqua,
secondary = OffWhite, secondary = LightGrey,
onSurface = BalticSea, onSurface = BalticSea,
outline = Plantation.copy(alpha = .75f),
onBackground = BalticSea,
) )
data object Dark : ThemeColors( data object Dark : ThemeColors(
@ -34,5 +39,7 @@ sealed class ThemeColors(
primary = Aqua, primary = Aqua,
secondary = Plantation, secondary = Plantation,
onSurface = OffWhite, onSurface = OffWhite,
outline = CoolGray,
onBackground = OffWhite,
) )
} }

View File

@ -21,9 +21,11 @@ private val DarkColorScheme =
primary = ThemeColors.Dark.primary, primary = ThemeColors.Dark.primary,
surface = ThemeColors.Dark.surface, surface = ThemeColors.Dark.surface,
background = ThemeColors.Dark.background, background = ThemeColors.Dark.background,
secondaryContainer = ThemeColors.Dark.secondary, secondary = ThemeColors.Dark.secondary,
onSurface = ThemeColors.Dark.onSurface, onSurface = ThemeColors.Dark.onSurface,
onSecondaryContainer = ThemeColors.Dark.primary, onSecondaryContainer = ThemeColors.Dark.primary,
outline = ThemeColors.Dark.outline,
onBackground = ThemeColors.Dark.onBackground,
) )
private val LightColorScheme = private val LightColorScheme =
@ -31,9 +33,11 @@ private val LightColorScheme =
primary = ThemeColors.Light.primary, primary = ThemeColors.Light.primary,
surface = ThemeColors.Light.surface, surface = ThemeColors.Light.surface,
background = ThemeColors.Light.background, background = ThemeColors.Light.background,
secondaryContainer = ThemeColors.Light.secondary, secondary = ThemeColors.Light.secondary,
onSurface = ThemeColors.Light.onSurface, onSurface = ThemeColors.Light.onSurface,
onSecondaryContainer = ThemeColors.Light.primary, onSecondaryContainer = ThemeColors.Light.primary,
outline = ThemeColors.Light.outline,
onBackground = ThemeColors.Light.onBackground,
) )
enum class Theme { enum class Theme {