Skip to content

Commit 75cdc74

Browse files
committed
Simplify code using LaunchCollectEffect
1 parent e6211a5 commit 75cdc74

15 files changed

+106
-145
lines changed

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import androidx.compose.material3.AlertDialog
88
import androidx.compose.material3.MaterialTheme
99
import androidx.compose.material3.Text
1010
import androidx.compose.runtime.Composable
11-
import androidx.compose.runtime.LaunchedEffect
1211
import androidx.compose.runtime.collectAsState
1312
import androidx.compose.runtime.getValue
1413
import androidx.compose.ui.Modifier
@@ -22,6 +21,7 @@ import net.mullvad.mullvadvpn.R
2221
import net.mullvad.mullvadvpn.compose.button.NegativeButton
2322
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
2423
import net.mullvad.mullvadvpn.compose.textfield.DnsTextField
24+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
2525
import net.mullvad.mullvadvpn.lib.theme.AppTheme
2626
import net.mullvad.mullvadvpn.lib.theme.Dimens
2727
import net.mullvad.mullvadvpn.viewmodel.DnsDialogSideEffect
@@ -100,11 +100,9 @@ fun DnsDialog(
100100
val viewModel =
101101
koinViewModel<DnsDialogViewModel>(parameters = { parametersOf(initialValue, index) })
102102

103-
LaunchedEffect(Unit) {
104-
viewModel.uiSideEffect.collect {
105-
when (it) {
106-
DnsDialogSideEffect.Complete -> resultNavigator.navigateBack(result = true)
107-
}
103+
LaunchedEffectCollect(viewModel.uiSideEffect) {
104+
when (it) {
105+
DnsDialogSideEffect.Complete -> resultNavigator.navigateBack(result = true)
108106
}
109107
}
110108
val state by viewModel.uiState.collectAsState(null)

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import androidx.compose.material3.AlertDialog
88
import androidx.compose.material3.MaterialTheme
99
import androidx.compose.material3.Text
1010
import androidx.compose.runtime.Composable
11-
import androidx.compose.runtime.LaunchedEffect
1211
import androidx.compose.runtime.mutableStateOf
1312
import androidx.compose.runtime.remember
1413
import androidx.compose.ui.Modifier
@@ -21,6 +20,7 @@ import com.ramcosta.composedestinations.spec.DestinationStyle
2120
import net.mullvad.mullvadvpn.R
2221
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
2322
import net.mullvad.mullvadvpn.compose.textfield.MtuTextField
23+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
2424
import net.mullvad.mullvadvpn.constant.MTU_MAX_VALUE
2525
import net.mullvad.mullvadvpn.constant.MTU_MIN_VALUE
2626
import net.mullvad.mullvadvpn.lib.theme.AppTheme
@@ -42,11 +42,9 @@ private fun PreviewMtuDialog() {
4242
fun MtuDialog(mtuInitial: Int?, navigator: DestinationsNavigator) {
4343
val viewModel = koinViewModel<MtuDialogViewModel>()
4444

45-
LaunchedEffect(Unit) {
46-
viewModel.uiSideEffect.collect {
47-
when (it) {
48-
MtuDialogSideEffect.Complete -> navigator.navigateUp()
49-
}
45+
LaunchedEffectCollect(viewModel.uiSideEffect) {
46+
when (it) {
47+
MtuDialogSideEffect.Complete -> navigator.navigateUp()
5048
}
5149
}
5250
MtuDialog(

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/payment/PaymentDialog.kt

+5-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.ramcosta.composedestinations.spec.DestinationStyle
2020
import net.mullvad.mullvadvpn.R
2121
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
2222
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorMedium
23+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
2324
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
2425
import net.mullvad.mullvadvpn.lib.theme.AppTheme
2526
import net.mullvad.mullvadvpn.lib.theme.color.AlphaDescription
@@ -125,12 +126,10 @@ fun Payment(productId: ProductId, resultBackNavigator: ResultBackNavigator<Boole
125126
val vm = koinViewModel<PaymentViewModel>()
126127
val uiState = vm.uiState.collectAsState().value
127128

128-
LaunchedEffect(Unit) {
129-
vm.uiSideEffect.collect {
130-
when (it) {
131-
is PaymentUiSideEffect.PaymentCancelled ->
132-
resultBackNavigator.navigateBack(result = false)
133-
}
129+
LaunchedEffectCollect(vm.uiSideEffect) {
130+
when (it) {
131+
is PaymentUiSideEffect.PaymentCancelled ->
132+
resultBackNavigator.navigateBack(result = false)
134133
}
135134
}
136135

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt

+13-15
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import androidx.compose.material3.MaterialTheme
1616
import androidx.compose.material3.SnackbarHostState
1717
import androidx.compose.material3.Text
1818
import androidx.compose.runtime.Composable
19-
import androidx.compose.runtime.LaunchedEffect
2019
import androidx.compose.runtime.collectAsState
2120
import androidx.compose.runtime.getValue
2221
import androidx.compose.runtime.remember
@@ -55,6 +54,7 @@ import net.mullvad.mullvadvpn.compose.destinations.RedeemVoucherDestination
5554
import net.mullvad.mullvadvpn.compose.destinations.VerificationPendingDialogDestination
5655
import net.mullvad.mullvadvpn.compose.state.PaymentState
5756
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromBottomTransition
57+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
5858
import net.mullvad.mullvadvpn.compose.util.SecureScreenWhileInView
5959
import net.mullvad.mullvadvpn.lib.common.util.openAccountPageInBrowser
6060
import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct
@@ -171,22 +171,20 @@ fun AccountScreen(
171171
val clipboardManager = LocalClipboardManager.current
172172
val snackbarHostState = remember { SnackbarHostState() }
173173
val copyTextString = stringResource(id = R.string.copied_mullvad_account_number)
174-
LaunchedEffect(Unit) {
175-
uiSideEffect.collect { uiSideEffect ->
176-
when (uiSideEffect) {
177-
AccountViewModel.UiSideEffect.NavigateToLogin -> navigateToLogin()
178-
is AccountViewModel.UiSideEffect.OpenAccountManagementPageInBrowser ->
179-
context.openAccountPageInBrowser(uiSideEffect.token)
180-
is AccountViewModel.UiSideEffect.CopyAccountNumber ->
181-
launch {
182-
clipboardManager.setText(AnnotatedString(uiSideEffect.accountNumber))
174+
LaunchedEffectCollect(uiSideEffect) { sideEffect ->
175+
when (sideEffect) {
176+
AccountViewModel.UiSideEffect.NavigateToLogin -> navigateToLogin()
177+
is AccountViewModel.UiSideEffect.OpenAccountManagementPageInBrowser ->
178+
context.openAccountPageInBrowser(sideEffect.token)
179+
is AccountViewModel.UiSideEffect.CopyAccountNumber ->
180+
launch {
181+
clipboardManager.setText(AnnotatedString(sideEffect.accountNumber))
183182

184-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
185-
snackbarHostState.currentSnackbarData?.dismiss()
186-
snackbarHostState.showSnackbar(message = copyTextString)
187-
}
183+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
184+
snackbarHostState.currentSnackbarData?.dismiss()
185+
snackbarHostState.showSnackbar(message = copyTextString)
188186
}
189-
}
187+
}
190188
}
191189
}
192190

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt

-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ import net.mullvad.mullvadvpn.model.LatLong
8484
import net.mullvad.mullvadvpn.model.Latitude
8585
import net.mullvad.mullvadvpn.model.Longitude
8686
import net.mullvad.mullvadvpn.model.TunnelState
87-
import net.mullvad.mullvadvpn.util.CollectSideEffectWithLifecycle
8887
import net.mullvad.mullvadvpn.util.appendHideNavOnPlayBuild
8988
import net.mullvad.mullvadvpn.viewmodel.ConnectViewModel
9089
import org.koin.androidx.compose.koinViewModel

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt

+7-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.size
99
import androidx.compose.material3.MaterialTheme
1010
import androidx.compose.material3.Text
1111
import androidx.compose.runtime.Composable
12-
import androidx.compose.runtime.LaunchedEffect
1312
import androidx.compose.runtime.collectAsState
1413
import androidx.compose.runtime.getValue
1514
import androidx.compose.ui.Modifier
@@ -32,6 +31,7 @@ import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar
3231
import net.mullvad.mullvadvpn.compose.destinations.LoginDestination
3332
import net.mullvad.mullvadvpn.compose.destinations.SettingsDestination
3433
import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
34+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
3535
import net.mullvad.mullvadvpn.lib.theme.AppTheme
3636
import net.mullvad.mullvadvpn.lib.theme.Dimens
3737
import net.mullvad.mullvadvpn.viewmodel.DeviceRevokedSideEffect
@@ -51,16 +51,13 @@ fun DeviceRevoked(navigator: DestinationsNavigator) {
5151

5252
val state by viewModel.uiState.collectAsState()
5353

54-
LaunchedEffect(Unit) {
55-
viewModel.uiSideEffect.collect { sideEffect ->
56-
when (sideEffect) {
57-
DeviceRevokedSideEffect.NavigateToLogin -> {
58-
navigator.navigate(LoginDestination()) {
59-
launchSingleTop = true
60-
popUpTo(NavGraphs.root) { inclusive = true }
61-
}
54+
LaunchedEffectCollect(viewModel.uiSideEffect) { sideEffect ->
55+
when (sideEffect) {
56+
DeviceRevokedSideEffect.NavigateToLogin ->
57+
navigator.navigate(LoginDestination()) {
58+
launchSingleTop = true
59+
popUpTo(NavGraphs.root) { inclusive = true }
6260
}
63-
}
6461
}
6562
}
6663

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import androidx.compose.material3.MaterialTheme
1717
import androidx.compose.material3.Scaffold
1818
import androidx.compose.material3.Text
1919
import androidx.compose.runtime.Composable
20-
import androidx.compose.runtime.LaunchedEffect
2120
import androidx.compose.runtime.collectAsState
2221
import androidx.compose.runtime.getValue
2322
import androidx.compose.runtime.mutableStateOf
@@ -39,6 +38,7 @@ import net.mullvad.mullvadvpn.compose.cell.ExpandableComposeCell
3938
import net.mullvad.mullvadvpn.compose.cell.SelectableCell
4039
import net.mullvad.mullvadvpn.compose.state.RelayFilterState
4140
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition
41+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
4242
import net.mullvad.mullvadvpn.lib.theme.AppTheme
4343
import net.mullvad.mullvadvpn.lib.theme.Dimens
4444
import net.mullvad.mullvadvpn.model.Ownership
@@ -72,11 +72,9 @@ fun FilterScreen(navigator: DestinationsNavigator) {
7272
val viewModel = koinViewModel<FilterViewModel>()
7373
val uiState by viewModel.uiState.collectAsState()
7474

75-
LaunchedEffect(Unit) {
76-
viewModel.uiSideEffect.collect {
77-
when (it) {
78-
FilterScreenSideEffect.CloseScreen -> navigator.navigateUp()
79-
}
75+
LaunchedEffectCollect(viewModel.uiSideEffect) {
76+
when (it) {
77+
FilterScreenSideEffect.CloseScreen -> navigator.navigateUp()
8078
}
8179
}
8280
FilterScreen(

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import net.mullvad.mullvadvpn.compose.util.accountTokenVisualTransformation
7979
import net.mullvad.mullvadvpn.lib.theme.AppTheme
8080
import net.mullvad.mullvadvpn.lib.theme.Dimens
8181
import net.mullvad.mullvadvpn.lib.theme.color.AlphaTopBar
82-
import net.mullvad.mullvadvpn.util.CollectSideEffectWithLifecycle
8382
import net.mullvad.mullvadvpn.viewmodel.LoginUiSideEffect
8483
import net.mullvad.mullvadvpn.viewmodel.LoginViewModel
8584
import org.koin.androidx.compose.koinViewModel

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt

+12-18
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package net.mullvad.mullvadvpn.compose.screen
33
import androidx.compose.foundation.layout.fillMaxSize
44
import androidx.compose.runtime.Composable
55
import androidx.compose.runtime.DisposableEffect
6-
import androidx.compose.runtime.LaunchedEffect
76
import androidx.compose.ui.ExperimentalComposeUiApi
87
import androidx.compose.ui.Modifier
98
import androidx.compose.ui.semantics.semantics
@@ -14,14 +13,14 @@ import com.ramcosta.composedestinations.navigation.navigate
1413
import com.ramcosta.composedestinations.navigation.popBackStack
1514
import com.ramcosta.composedestinations.rememberNavHostEngine
1615
import com.ramcosta.composedestinations.utils.destination
17-
import kotlinx.coroutines.flow.collect
1816
import kotlinx.coroutines.flow.first
1917
import kotlinx.coroutines.flow.map
2018
import net.mullvad.mullvadvpn.compose.NavGraphs
2119
import net.mullvad.mullvadvpn.compose.destinations.ChangelogDestination
2220
import net.mullvad.mullvadvpn.compose.destinations.ConnectDestination
2321
import net.mullvad.mullvadvpn.compose.destinations.NoDaemonScreenDestination
2422
import net.mullvad.mullvadvpn.compose.destinations.OutOfTimeDestination
23+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
2524
import net.mullvad.mullvadvpn.viewmodel.ChangelogViewModel
2625
import net.mullvad.mullvadvpn.viewmodel.DaemonScreenEvent
2726
import net.mullvad.mullvadvpn.viewmodel.NoDaemonViewModel
@@ -50,28 +49,23 @@ fun MullvadApp() {
5049
)
5150

5251
// Globally handle daemon dropped connection with NoDaemonScreen
53-
LaunchedEffect(Unit) {
54-
serviceVm.uiSideEffect.collect {
55-
when (it) {
56-
DaemonScreenEvent.Show ->
57-
navController.navigate(NoDaemonScreenDestination) { launchSingleTop = true }
58-
DaemonScreenEvent.Remove ->
59-
navController.popBackStack(NoDaemonScreenDestination, true)
60-
}
52+
LaunchedEffectCollect(serviceVm.uiSideEffect) {
53+
when (it) {
54+
DaemonScreenEvent.Show ->
55+
navController.navigate(NoDaemonScreenDestination) { launchSingleTop = true }
56+
DaemonScreenEvent.Remove -> navController.popBackStack(NoDaemonScreenDestination, true)
6157
}
6258
}
6359

6460
// Globally show the changelog
6561
val changeLogsViewModel = koinViewModel<ChangelogViewModel>()
66-
LaunchedEffect(Unit) {
67-
changeLogsViewModel.uiSideEffect.collect {
62+
LaunchedEffectCollect(changeLogsViewModel.uiSideEffect) {
6863

69-
// Wait until we are in an acceptable destination
70-
navController.currentBackStackEntryFlow
71-
.map { it.destination() }
72-
.first { it in changeLogDestinations }
64+
// Wait until we are in an acceptable destination
65+
navController.currentBackStackEntryFlow
66+
.map { it.destination() }
67+
.first { it in changeLogDestinations }
7368

74-
navController.navigate(ChangelogDestination(it).route)
75-
}
69+
navController.navigate(ChangelogDestination(it).route)
7670
}
7771
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt

+9-12
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import androidx.compose.foundation.verticalScroll
1313
import androidx.compose.material3.MaterialTheme
1414
import androidx.compose.material3.Text
1515
import androidx.compose.runtime.Composable
16-
import androidx.compose.runtime.LaunchedEffect
1716
import androidx.compose.runtime.collectAsState
1817
import androidx.compose.ui.Alignment
1918
import androidx.compose.ui.Modifier
@@ -45,6 +44,7 @@ import net.mullvad.mullvadvpn.compose.extensions.createOpenAccountPageHook
4544
import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
4645
import net.mullvad.mullvadvpn.compose.test.OUT_OF_TIME_SCREEN_TITLE_TEST_TAG
4746
import net.mullvad.mullvadvpn.compose.transitions.HomeTransition
47+
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
4848
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
4949
import net.mullvad.mullvadvpn.lib.theme.AppTheme
5050
import net.mullvad.mullvadvpn.lib.theme.Dimens
@@ -134,18 +134,15 @@ fun OutOfTime(
134134
}
135135

136136
val openAccountPage = LocalUriHandler.current.createOpenAccountPageHook()
137-
LaunchedEffect(Unit) {
138-
vm.uiSideEffect.collect { uiSideEffect ->
139-
when (uiSideEffect) {
140-
is OutOfTimeViewModel.UiSideEffect.OpenAccountView ->
141-
openAccountPage(uiSideEffect.token)
142-
OutOfTimeViewModel.UiSideEffect.OpenConnectScreen -> {
143-
navigator.navigate(ConnectDestination) {
144-
launchSingleTop = true
145-
popUpTo(NavGraphs.root) { inclusive = true }
146-
}
137+
LaunchedEffectCollect(vm.uiSideEffect) { uiSideEffect ->
138+
when (uiSideEffect) {
139+
is OutOfTimeViewModel.UiSideEffect.OpenAccountView ->
140+
openAccountPage(uiSideEffect.token)
141+
OutOfTimeViewModel.UiSideEffect.OpenConnectScreen ->
142+
navigator.navigate(ConnectDestination) {
143+
launchSingleTop = true
144+
popUpTo(NavGraphs.root) { inclusive = true }
147145
}
148-
}
149146
}
150147
}
151148

0 commit comments

Comments
 (0)