Skip to content

Commit

Permalink
Add support for more detailed location changed messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Pururun committed Jul 31, 2024
1 parent 6aa0f47 commit ea0280d
Show file tree
Hide file tree
Showing 16 changed files with 303 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package net.mullvad.mullvadvpn.compose.communication

import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import net.mullvad.mullvadvpn.lib.model.CustomListName

sealed interface CustomListActionResultData : Parcelable {

sealed interface Success : CustomListActionResultData, Parcelable {
val undo: CustomListAction

@Parcelize
data class CreatedWithLocations(
val customListName: CustomListName,
val locationNames: List<String>,
override val undo: CustomListAction
) : Success

@Parcelize
data class Deleted(
val customListName: CustomListName,
override val undo: CustomListAction.Create
) : Success

@Parcelize
data class Renamed(
val newName: CustomListName,
override val undo: CustomListAction.Rename
) : Success

@Parcelize
data class LocationAdded(
val customListName: CustomListName,
val locationName: String,
override val undo: CustomListAction
) : Success

@Parcelize
data class LocationRemoved(
val customListName: CustomListName,
val locationName: String,
override val undo: CustomListAction
) : Success

@Parcelize
data class LocationChanged(
val customListName: CustomListName,
override val undo: CustomListAction
) : Success
}

@Parcelize data object GenericError : CustomListActionResultData
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package net.mullvad.mullvadvpn.compose.communication

import android.os.Parcelable
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.CustomListName
import net.mullvad.mullvadvpn.lib.model.GeoLocationId

sealed interface CustomListSuccess : Parcelable {
val undo: CustomListAction
Expand Down Expand Up @@ -31,6 +33,14 @@ data class Renamed(override val undo: CustomListAction.Rename) : CustomListSucce

@Parcelize
data class LocationsChanged(
val id: CustomListId,
val name: CustomListName,
val locations: List<GeoLocationId>,
val oldLocations: List<GeoLocationId>,
) : CustomListSuccess {
override val undo: CustomListAction.UpdateLocations
) : CustomListSuccess
get() = CustomListAction.UpdateLocations(id, oldLocations)

@IgnoredOnParcel val addedLocations = locations - oldLocations
@IgnoredOnParcel val removedLocations = oldLocations - locations
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
import net.mullvad.mullvadvpn.compose.communication.Created
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.component.CustomListNameTextField
import net.mullvad.mullvadvpn.compose.state.CreateCustomListUiState
import net.mullvad.mullvadvpn.compose.test.CREATE_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG
Expand Down Expand Up @@ -63,7 +63,7 @@ data class CreateCustomListNavArgs(val locationCode: GeoLocationId?)
)
fun CreateCustomList(
navigator: DestinationsNavigator,
backNavigator: ResultBackNavigator<Created>,
backNavigator: ResultBackNavigator<CustomListActionResultData.Success.CreatedWithLocations>,
) {
val vm: CreateCustomListDialogViewModel = koinViewModel()
LaunchedEffect(key1 = Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.communication.Deleted
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.state.DeleteCustomListUiState
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
import net.mullvad.mullvadvpn.lib.model.CustomListId
Expand Down Expand Up @@ -39,7 +39,7 @@ data class DeleteCustomListNavArgs(val customListId: CustomListId, val name: Cus
navArgs = DeleteCustomListNavArgs::class
)
fun DeleteCustomList(
navigator: ResultBackNavigator<Deleted>,
navigator: ResultBackNavigator<CustomListActionResultData.Success.Deleted>,
) {
val viewModel: DeleteCustomListConfirmationViewModel = koinViewModel()
val state by viewModel.uiState.collectAsStateWithLifecycle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
import net.mullvad.mullvadvpn.compose.communication.Renamed
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.component.CustomListNameTextField
import net.mullvad.mullvadvpn.compose.state.EditCustomListNameUiState
import net.mullvad.mullvadvpn.compose.test.EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG
Expand Down Expand Up @@ -50,7 +50,7 @@ data class EditCustomListNameNavArgs(
navArgs = EditCustomListNameNavArgs::class
)
fun EditCustomListName(
backNavigator: ResultBackNavigator<Renamed>,
backNavigator: ResultBackNavigator<CustomListActionResultData.Success.Renamed>,
) {
val vm: EditCustomListNameDialogViewModel = koinViewModel()
LaunchedEffectCollect(vm.uiSideEffect) { sideEffect ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.mullvad.mullvadvpn.compose.screen

import android.content.Context
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -13,16 +12,12 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -35,10 +30,9 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.NavResult
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.cell.CheckableRelayLocationCell
import net.mullvad.mullvadvpn.compose.communication.LocationsChanged
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.component.LocationsEmptyText
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton
Expand All @@ -52,7 +46,6 @@ import net.mullvad.mullvadvpn.compose.test.SAVE_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.compose.textfield.SearchTextField
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.theme.Dimens
Expand All @@ -79,7 +72,7 @@ data class CustomListLocationsNavArgs(
)
fun CustomListLocations(
navigator: DestinationsNavigator,
backNavigator: ResultBackNavigator<LocationsChanged>,
backNavigator: ResultBackNavigator<CustomListActionResultData>,
discardChangesResultRecipient: ResultRecipient<DiscardChangesDestination, Boolean>,
) {
val customListsViewModel = koinViewModel<CustomListLocationsViewModel>()
Expand All @@ -95,27 +88,16 @@ fun CustomListLocations(
}
}

val snackbarHostState = remember { SnackbarHostState() }
val context: Context = LocalContext.current
LaunchedEffectCollect(customListsViewModel.uiSideEffect) { sideEffect ->
when (sideEffect) {
is CustomListLocationsSideEffect.ReturnWithResult ->
is CustomListLocationsSideEffect.ReturnWithResultData ->
backNavigator.navigateBack(result = sideEffect.result)
CustomListLocationsSideEffect.CloseScreen -> backNavigator.navigateBack()
CustomListLocationsSideEffect.Error ->
launch {
snackbarHostState.showSnackbarImmediately(
message = context.getString(R.string.error_occurred),
duration = SnackbarDuration.Short
)
}
}
}

val state by customListsViewModel.uiState.collectAsStateWithLifecycle()
CustomListLocationsScreen(
state = state,
snackbarHostState = snackbarHostState,
onSearchTermInput = customListsViewModel::onSearchTermInput,
onSaveClick = customListsViewModel::save,
onRelaySelectionClick = customListsViewModel::onRelaySelectionClick,
Expand All @@ -134,15 +116,13 @@ fun CustomListLocations(
@Composable
fun CustomListLocationsScreen(
state: CustomListLocationsUiState,
snackbarHostState: SnackbarHostState = SnackbarHostState(),
onSearchTermInput: (String) -> Unit = {},
onSaveClick: () -> Unit = {},
onRelaySelectionClick: (RelayItem.Location, selected: Boolean) -> Unit = { _, _ -> },
onExpand: (RelayItem.Location, selected: Boolean) -> Unit = { _, _ -> },
onBackClick: () -> Unit = {}
) {
ScaffoldWithSmallTopBar(
snackbarHostState = snackbarHostState,
appBarTitle =
stringResource(
if (state.newList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.cell.NavigationComposeCell
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.communication.Deleted
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton
Expand Down Expand Up @@ -63,7 +64,8 @@ private fun PreviewCustomListsScreen() {
@Destination<RootGraph>(style = SlideInFromRightTransition::class)
fun CustomLists(
navigator: DestinationsNavigator,
editCustomListResultRecipient: ResultRecipient<EditCustomListDestination, Deleted>
editCustomListResultRecipient:
ResultRecipient<EditCustomListDestination, CustomListActionResultData.Success.Deleted>
) {
val viewModel = koinViewModel<CustomListsViewModel>()
val state by viewModel.uiState.collectAsStateWithLifecycle()
Expand All @@ -82,7 +84,7 @@ fun CustomLists(
message =
context.getString(
R.string.delete_custom_list_message,
result.value.name
result.value.customListName
),
actionLabel = context.getString(R.string.undo),
duration = SnackbarDuration.Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.cell.TwoRowCell
import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData
import net.mullvad.mullvadvpn.compose.communication.Deleted
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton
Expand Down Expand Up @@ -83,8 +84,9 @@ data class EditCustomListNavArgs(val customListId: CustomListId)
)
fun EditCustomList(
navigator: DestinationsNavigator,
backNavigator: ResultBackNavigator<Deleted>,
confirmDeleteListResultRecipient: ResultRecipient<DeleteCustomListDestination, Deleted>
backNavigator: ResultBackNavigator<CustomListActionResultData.Success.Deleted>,
confirmDeleteListResultRecipient:
ResultRecipient<DeleteCustomListDestination, CustomListActionResultData.Success.Deleted>
) {
val viewModel = koinViewModel<EditCustomListViewModel>()

Expand Down
Loading

0 comments on commit ea0280d

Please sign in to comment.