diff --git a/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/MigrationTest.kt b/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/MigrationTest.kt index d218f232..2e0c1fed 100644 --- a/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/MigrationTest.kt +++ b/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/MigrationTest.kt @@ -4,10 +4,10 @@ import androidx.room.testing.MigrationTestHelper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.zaneschepke.wireguardautotunnel.data.AppDatabase +import java.io.IOException import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.io.IOException @RunWith(AndroidJUnit4::class) class MigrationTest { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelList.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelList.kt index 76b434f5..30d34f43 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelList.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelList.kt @@ -103,6 +103,7 @@ fun TunnelList( if (!tunnelState.status.isDown()) { { TunnelStatisticsRow( + tunnel, tunnelState, sharedState.isPingEnabled, sharedState.showPingStats, diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelRowItem.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelRowItem.kt deleted file mode 100644 index 77f290c5..00000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelRowItem.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.ui.screens.tunnels.components - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.* -import androidx.compose.material3.Checkbox -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.minimumInteractiveComponentSize -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.unit.dp -import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus -import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConfig -import com.zaneschepke.wireguardautotunnel.domain.state.TunnelState -import com.zaneschepke.wireguardautotunnel.ui.common.ExpandingRowListItem -import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch -import com.zaneschepke.wireguardautotunnel.util.extensions.asColor - -@Composable -fun TunnelRowItem( - state: TunnelState, - isSelected: Boolean, - tunnel: TunnelConfig, - onTvClick: () -> Unit, - onToggleSelectedTunnel: (TunnelConfig) -> Unit, - onSwitchClick: (Boolean) -> Unit, - isTv: Boolean, - isPingEnabled: Boolean, - showDetailedStats: Boolean, - modifier: Modifier = Modifier, -) { - val context = LocalContext.current - var leadingIconColor by - remember(state.status, state.logHealthState, state.pingStates, state.statistics) { - mutableStateOf(state.health().asColor()) - } - - val (leadingIcon, size, typeDescription) = - remember(tunnel) { - when { - tunnel.isPrimaryTunnel -> - Triple(Icons.Rounded.Star, 16.dp, context.getString(R.string.primary_tunnel)) - tunnel.isMobileDataTunnel -> - Triple( - Icons.Rounded.Smartphone, - 16.dp, - context.getString(R.string.mobile_tunnel), - ) - tunnel.isEthernetTunnel -> - Triple( - Icons.Rounded.SettingsEthernet, - 16.dp, - context.getString(R.string.ethernet_tunnel), - ) - else -> Triple(Icons.Rounded.Circle, 14.dp, context.getString(R.string.tunnel)) - } - } - - val statusDescription = - remember(state) { - if (state.status.isUpOrStarting()) { - context.getString(R.string.active) - } else { - context.getString(R.string.inactive) - } - } - - val combinedContentDescription = - stringResource( - R.string.tunnel_item_description, - tunnel.name, - typeDescription, - statusDescription, - ) - - ExpandingRowListItem( - modifier = modifier.semantics(mergeDescendants = true) { combinedContentDescription }, - leading = { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.Start), - ) { - if (isTv) { - Checkbox( - checked = isSelected, - onCheckedChange = { onToggleSelectedTunnel(tunnel) }, - modifier = Modifier.minimumInteractiveComponentSize().size(12.dp), - ) - } - Icon( - leadingIcon, - contentDescription = null, - tint = leadingIconColor, - modifier = Modifier.size(size), - ) - } - }, - text = tunnel.name, - expanded = { - if (state.status != TunnelStatus.Down) { - TunnelStatisticsRow(state, isPingEnabled, showDetailedStats) - } - }, - trailing = { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), - ) { - if (isTv) { - IconButton(onClick = onTvClick) { - Icon( - Icons.Rounded.Settings, - contentDescription = stringResource(R.string.settings), - ) - } - } - ScaledSwitch(checked = state.status.isUpOrStarting(), onClick = onSwitchClick) - } - }, - isSelected = isSelected, - ) -} diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelStatisticsRow.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelStatisticsRow.kt index 03f34e80..8dc3241c 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelStatisticsRow.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/tunnels/components/TunnelStatisticsRow.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.zaneschepke.wireguardautotunnel.R +import com.zaneschepke.wireguardautotunnel.domain.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.domain.state.TunnelState import com.zaneschepke.wireguardautotunnel.ui.common.label.lowercaseLabel import com.zaneschepke.wireguardautotunnel.util.NumberUtils @@ -24,6 +25,7 @@ import kotlinx.coroutines.delay @Composable fun TunnelStatisticsRow( + tunnel: TunnelConfig, tunnelState: TunnelState, pingEnabled: Boolean, showDetailedStats: Boolean, @@ -32,6 +34,16 @@ fun TunnelStatisticsRow( val textStyle = MaterialTheme.typography.bodySmall val textColor = MaterialTheme.colorScheme.outline + // needs to be set as peer stats for duplicates return as a single set of stats + val peers by remember(tunnel) { + derivedStateOf { + TunnelConfig.configFromWgQuick(tunnel.wgQuick) + .peers + .map { it.publicKey.toBase64() } + .toSet() + } + } + var currentTimeMillis by remember { mutableLongStateOf(System.currentTimeMillis()) } LaunchedEffect(Unit) { while (true) { @@ -52,7 +64,7 @@ fun TunnelStatisticsRow( verticalArrangement = Arrangement.spacedBy(10.dp), horizontalAlignment = Alignment.Start, ) { - stats.getPeers().forEach { peerBase64 -> + peers.forEach { peerBase64 -> key(peerBase64) { val peerStats = remember(stats, peerBase64) { stats.peerStats(peerBase64) } peerStats?.let { stats ->