Skip to content

Commit

Permalink
Use NavArgs & SavedStateHandle
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawa committed Jul 3, 2024
1 parent c6771e8 commit 36632d4
Show file tree
Hide file tree
Showing 42 changed files with 337 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ class DeleteCustomListConfirmationDialogTest {
val name = CustomListName.fromString("List should be deleted")
setContentWithTheme {
DeleteCustomListConfirmationDialog(
name = name,
state = DeleteCustomListUiState(null)
state = DeleteCustomListUiState(name = name, deleteError = null),
)
}

Expand All @@ -49,8 +48,7 @@ class DeleteCustomListConfirmationDialogTest {
val mockedOnDelete: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
DeleteCustomListConfirmationDialog(
name = name,
state = DeleteCustomListUiState(null),
state = DeleteCustomListUiState(name = name, deleteError = null),
onDelete = mockedOnDelete
)
}
Expand All @@ -70,8 +68,7 @@ class DeleteCustomListConfirmationDialogTest {
val mockedOnBack: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
DeleteCustomListConfirmationDialog(
name = name,
state = DeleteCustomListUiState(null),
state = DeleteCustomListUiState(name = name, deleteError = null),
onBack = mockedOnBack
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class EditCustomListNameDialogTest {
fun whenInputIsChangedShouldCallOnInputChanged() =
composeExtension.use {
// Arrange
val mockedOnInputChanged: () -> Unit = mockk(relaxed = true)
val mockedOnInputChanged: (String) -> Unit = mockk(relaxed = true)
val inputText = "NEW NAME"
val state = EditCustomListNameUiState()
setContentWithTheme {
Expand All @@ -137,7 +137,7 @@ class EditCustomListNameDialogTest {
onNodeWithTag(EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG).performTextInput(inputText)

// Assert
verify { mockedOnInputChanged.invoke() }
verify { mockedOnInputChanged.invoke(inputText) }
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class EditCustomListScreenTest {
fun whenClickingOnDeleteDropdownShouldCallOnDeleteList() =
composeExtension.use {
// Arrange
val mockedOnDelete: (CustomListName) -> Unit = mockk(relaxed = true)
val mockedOnDelete: (CustomListId, CustomListName) -> Unit = mockk(relaxed = true)
val customList = DUMMY_CUSTOM_LISTS[0]
setContentWithTheme {
EditCustomListScreen(
Expand All @@ -112,7 +112,7 @@ class EditCustomListScreenTest {
onNodeWithTag(DELETE_DROPDOWN_MENU_ITEM_TEST_TAG).performClick()

// Assert
verify { mockedOnDelete(customList.name) }
verify { mockedOnDelete(customList.id, customList.name) }
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import net.mullvad.mullvadvpn.usecase.customlists.CreateWithLocationsError
import net.mullvad.mullvadvpn.viewmodel.CreateCustomListDialogSideEffect
import net.mullvad.mullvadvpn.viewmodel.CreateCustomListDialogViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
Expand All @@ -55,15 +54,18 @@ private fun PreviewCreateCustomListDialogError() {
}
}

data class CreateCustomListNavArgs(val locationCode: GeoLocationId?)

@Composable
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
@Destination<RootGraph>(
style = DestinationStyle.Dialog::class,
navArgs = CreateCustomListNavArgs::class
)
fun CreateCustomList(
navigator: DestinationsNavigator,
backNavigator: ResultBackNavigator<Created>,
locationCode: GeoLocationId? = null
) {
val vm: CreateCustomListDialogViewModel =
koinViewModel(parameters = { parametersOf(locationCode) })
val vm: CreateCustomListDialogViewModel = koinViewModel()
LaunchedEffect(key1 = Unit) {
vm.uiSideEffect.collect { sideEffect ->
when (sideEffect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.viewmodel.DeleteApiAccessMethodConfirmationSideEffect
import net.mullvad.mullvadvpn.viewmodel.DeleteApiAccessMethodConfirmationViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
private fun PreviewDeleteApiAccessMethodConfirmationDialog() {
AppTheme { DeleteApiAccessMethodConfirmationDialog(state = DeleteApiAccessMethodUiState(null)) }
}

data class DeleteApiAccessMethodNavArgs(val apiAccessMethodId: ApiAccessMethodId)

@Composable
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
@Destination<RootGraph>(
style = DestinationStyle.Dialog::class,
navArgs = DeleteApiAccessMethodNavArgs::class
)
fun DeleteApiAccessMethodConfirmation(
navigator: ResultBackNavigator<Boolean>,
apiAccessMethodId: ApiAccessMethodId
) {
val viewModel =
koinViewModel<DeleteApiAccessMethodConfirmationViewModel>(
parameters = { parametersOf(apiAccessMethodId) }
)
val viewModel = koinViewModel<DeleteApiAccessMethodConfirmationViewModel>()
val state = viewModel.uiState.collectAsStateWithLifecycle()

LaunchedEffectCollect(viewModel.uiSideEffect) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn.compose.dialog

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle
Expand All @@ -19,29 +20,29 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.viewmodel.DeleteCustomListConfirmationSideEffect
import net.mullvad.mullvadvpn.viewmodel.DeleteCustomListConfirmationViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
private fun PreviewRemoveDeviceConfirmationDialog() {
AppTheme {
DeleteCustomListConfirmationDialog(
state = DeleteCustomListUiState(null),
name = CustomListName.fromString("My Custom List")
state = DeleteCustomListUiState(CustomListName.fromString("My Custom List"), null)
)
}
}

data class DeleteCustomListNavArgs(val customListId: CustomListId, val name: CustomListName)

@Composable
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
@Destination<RootGraph>(
style = DestinationStyle.Dialog::class,
navArgs = DeleteCustomListNavArgs::class
)
fun DeleteCustomList(
navigator: ResultBackNavigator<Deleted>,
customListId: CustomListId,
name: CustomListName
) {
val viewModel: DeleteCustomListConfirmationViewModel =
koinViewModel(parameters = { parametersOf(customListId) })
val state = viewModel.uiState.collectAsStateWithLifecycle()
val viewModel: DeleteCustomListConfirmationViewModel = koinViewModel()
val state by viewModel.uiState.collectAsStateWithLifecycle()

LaunchedEffectCollect(viewModel.uiSideEffect) {
when (it) {
Expand All @@ -51,8 +52,7 @@ fun DeleteCustomList(
}

DeleteCustomListConfirmationDialog(
state = state.value,
name = name,
state = state,
onDelete = viewModel::deleteCustomList,
onBack = dropUnlessResumed { navigator.navigateBack() }
)
Expand All @@ -61,15 +61,17 @@ fun DeleteCustomList(
@Composable
fun DeleteCustomListConfirmationDialog(
state: DeleteCustomListUiState,
name: CustomListName,
onDelete: () -> Unit = {},
onBack: () -> Unit = {}
) {
DeleteConfirmationDialog(
onDelete = onDelete,
onBack = onBack,
message =
stringResource(id = R.string.delete_custom_list_confirmation_description, name.value),
stringResource(
id = R.string.delete_custom_list_confirmation_description,
state.name.value
),
errorMessage =
if (state.deleteError != null) {
stringResource(id = R.string.error_occurred)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import net.mullvad.mullvadvpn.viewmodel.DnsDialogViewModel
import net.mullvad.mullvadvpn.viewmodel.DnsDialogViewState
import net.mullvad.mullvadvpn.viewmodel.ValidationError
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
Expand All @@ -52,15 +51,17 @@ private fun PreviewDnsDialogEditAllowLanDisabled() {
AppTheme { DnsDialog(DnsDialogViewState("192.168.1.1", null, true, false, 0), {}, {}, {}, {}) }
}

@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
data class DnsDialogNavArgs(
val index: Int? = null,
val initialValue: String? = null,
)

@Destination<RootGraph>(style = DestinationStyle.Dialog::class, navArgs = DnsDialogNavArgs::class)
@Composable
fun DnsDialog(
resultNavigator: ResultBackNavigator<DnsDialogResult>,
index: Int?,
initialValue: String?,
) {
val viewModel =
koinViewModel<DnsDialogViewModel>(parameters = { parametersOf(initialValue, index) })
val viewModel = koinViewModel<DnsDialogViewModel>()

LaunchedEffectCollect(viewModel.uiSideEffect) {
when (it) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -35,23 +32,27 @@ import net.mullvad.mullvadvpn.usecase.customlists.RenameError
import net.mullvad.mullvadvpn.viewmodel.EditCustomListNameDialogSideEffect
import net.mullvad.mullvadvpn.viewmodel.EditCustomListNameDialogViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
private fun PreviewEditCustomListNameDialog() {
AppTheme { EditCustomListNameDialog(EditCustomListNameUiState()) }
}

data class EditCustomListNameNavArgs(
val customListId: CustomListId,
val initialName: CustomListName
)

@Composable
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
@Destination<RootGraph>(
style = DestinationStyle.Dialog::class,
navArgs = EditCustomListNameNavArgs::class
)
fun EditCustomListName(
backNavigator: ResultBackNavigator<Renamed>,
customListId: CustomListId,
initialName: CustomListName
) {
val vm: EditCustomListNameDialogViewModel =
koinViewModel(parameters = { parametersOf(customListId, initialName) })
val vm: EditCustomListNameDialogViewModel = koinViewModel()
LaunchedEffectCollect(vm.uiSideEffect) { sideEffect ->
when (sideEffect) {
is EditCustomListNameDialogSideEffect.ReturnWithResult -> {
Expand All @@ -64,7 +65,7 @@ fun EditCustomListName(
EditCustomListNameDialog(
state = state,
updateName = vm::updateCustomListName,
onInputChanged = vm::clearError,
onInputChanged = vm::onNameChanged,
onDismiss = dropUnlessResumed { backNavigator.navigateBack() }
)
}
Expand All @@ -73,12 +74,9 @@ fun EditCustomListName(
fun EditCustomListNameDialog(
state: EditCustomListNameUiState,
updateName: (String) -> Unit = {},
onInputChanged: () -> Unit = {},
onInputChanged: (String) -> Unit = {},
onDismiss: () -> Unit = {}
) {
val name = remember { mutableStateOf(state.name) }
val isValidName by remember { derivedStateOf { name.value.isNotBlank() } }

AlertDialog(
title = {
Text(
Expand All @@ -87,14 +85,11 @@ fun EditCustomListNameDialog(
},
text = {
CustomListNameTextField(
name = name.value,
isValidName = isValidName,
name = state.name,
isValidName = state.isValidName,
error = state.error?.errorString(),
onSubmit = updateName,
onValueChanged = {
name.value = it
onInputChanged()
},
onValueChanged = onInputChanged,
modifier = Modifier.testTag(EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG)
)
},
Expand All @@ -104,8 +99,8 @@ fun EditCustomListNameDialog(
confirmButton = {
PrimaryButton(
text = stringResource(id = R.string.save),
onClick = { updateName(name.value) },
isEnabled = isValidName
onClick = { updateName(state.name) },
isEnabled = state.isValidName
)
},
dismissButton = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ import net.mullvad.mullvadvpn.viewmodel.MtuDialogSideEffect
import net.mullvad.mullvadvpn.viewmodel.MtuDialogUiState
import net.mullvad.mullvadvpn.viewmodel.MtuDialogViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
private fun PreviewMtuDialog() {
AppTheme { MtuDialog(mtuInitial = Mtu(1234), EmptyResultBackNavigator()) }
AppTheme { MtuDialog(EmptyResultBackNavigator()) }
}

@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
data class MtuNavArgs(val initialMtu: Mtu? = null)

@Destination<RootGraph>(style = DestinationStyle.Dialog::class, navArgs = MtuNavArgs::class)
@Composable
fun MtuDialog(mtuInitial: Mtu?, navigator: ResultBackNavigator<Boolean>) {
val viewModel = koinViewModel<MtuDialogViewModel>(parameters = { parametersOf(mtuInitial) })
fun MtuDialog(navigator: ResultBackNavigator<Boolean>) {
val viewModel = koinViewModel<MtuDialogViewModel>()

val uiState by viewModel.uiState.collectAsStateWithLifecycle()
LaunchedEffectCollect(viewModel.uiSideEffect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.viewmodel.SaveApiAccessMethodSideEffect
import net.mullvad.mullvadvpn.viewmodel.SaveApiAccessMethodViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

@Preview
@Composable
Expand All @@ -46,18 +45,21 @@ private fun PreviewSaveApiAccessMethodDialog(
AppTheme { SaveApiAccessMethodDialog(state = state) }
}

@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
data class SaveApiAccessMethodNavArgs(
val id: ApiAccessMethodId?,
val name: ApiAccessMethodName,
val customProxy: ApiAccessMethod.CustomProxy
)

@Destination<RootGraph>(
style = DestinationStyle.Dialog::class,
navArgs = SaveApiAccessMethodNavArgs::class
)
@Composable
fun SaveApiAccessMethod(
backNavigator: ResultBackNavigator<Boolean>,
id: ApiAccessMethodId?,
name: ApiAccessMethodName,
customProxy: ApiAccessMethod.CustomProxy
) {
val viewModel =
koinViewModel<SaveApiAccessMethodViewModel>(
parameters = { parametersOf(id, name, customProxy) }
)
val viewModel = koinViewModel<SaveApiAccessMethodViewModel>()

LaunchedEffectCollect(sideEffect = viewModel.uiSideEffect) {
when (it) {
Expand Down
Loading

0 comments on commit 36632d4

Please sign in to comment.