From 306cf24c99ec41e1cdb651ad596f980179d75c5c Mon Sep 17 00:00:00 2001 From: David Perez Date: Tue, 12 Dec 2023 08:52:51 -0600 Subject: [PATCH] Remove edit package (#372) --- .../vaultunlocked/VaultUnlockedNavigation.kt | 2 - .../feature/edit/VaultEditItemNavigation.kt | 53 ----------- .../vault/feature/edit/VaultEditItemScreen.kt | 73 --------------- .../feature/edit/VaultEditItemViewModel.kt | 93 ------------------- .../feature/edit/VaultEditItemScreenTest.kt | 66 ------------- .../edit/VaultEditItemViewModelTest.kt | 61 ------------ 6 files changed, 348 deletions(-) delete mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemNavigation.kt delete mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreen.kt delete mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModel.kt delete mode 100644 app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreenTest.kt delete mode 100644 app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModelTest.kt diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt index 2a6036fefa..8b662c7be0 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt @@ -14,7 +14,6 @@ import com.x8bit.bitwarden.ui.tools.feature.send.navigateToNewSend import com.x8bit.bitwarden.ui.tools.feature.send.newSendDestination import com.x8bit.bitwarden.ui.vault.feature.additem.navigateToVaultAddEditItem import com.x8bit.bitwarden.ui.vault.feature.additem.vaultAddEditItemDestination -import com.x8bit.bitwarden.ui.vault.feature.edit.vaultEditItemDestination import com.x8bit.bitwarden.ui.vault.feature.item.navigateToVaultItem import com.x8bit.bitwarden.ui.vault.feature.item.vaultItemDestination import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType @@ -58,7 +57,6 @@ fun NavGraphBuilder.vaultUnlockedGraph( navController.navigateToVaultAddEditItem(VaultAddEditType.EditItem(it)) }, ) - vaultEditItemDestination(onNavigateBack = { navController.popBackStack() }) newSendDestination(onNavigateBack = { navController.popBackStack() }) passwordHistoryDestination(onNavigateBack = { navController.popBackStack() }) } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemNavigation.kt deleted file mode 100644 index b06a903d01..0000000000 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemNavigation.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.x8bit.bitwarden.ui.vault.feature.edit - -import androidx.lifecycle.SavedStateHandle -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.NavType -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import com.x8bit.bitwarden.ui.platform.theme.TransitionProviders - -private const val VAULT_EDIT_ITEM_PREFIX = "vault_edit_item" -private const val VAULT_EDIT_ITEM_ID = "vault_edit_item_id" -private const val VAULT_EDIT_ROUTE = "$VAULT_EDIT_ITEM_PREFIX/{$VAULT_EDIT_ITEM_ID}" - -/** - * Class to retrieve vault item arguments from the [SavedStateHandle]. - */ -class VaultEditItemArgs(val vaultItemId: String) { - constructor(savedStateHandle: SavedStateHandle) : this( - checkNotNull(savedStateHandle[VAULT_EDIT_ITEM_ID]) as String, - ) -} - -/** - * Add the vault edit item screen to the nav graph. - */ -fun NavGraphBuilder.vaultEditItemDestination( - onNavigateBack: () -> Unit, -) { - composable( - route = VAULT_EDIT_ROUTE, - arguments = listOf( - navArgument(VAULT_EDIT_ITEM_ID) { type = NavType.StringType }, - ), - enterTransition = TransitionProviders.Enter.slideUp, - exitTransition = TransitionProviders.Exit.slideDown, - popEnterTransition = TransitionProviders.Enter.slideUp, - popExitTransition = TransitionProviders.Exit.slideDown, - ) { - VaultEditItemScreen(onNavigateBack) - } -} - -/** - * Navigate to the vault edit item screen. - */ -fun NavController.navigateToVaultEditItem( - vaultItemId: String, - navOptions: NavOptions? = null, -) { - navigate("$VAULT_EDIT_ITEM_PREFIX/$vaultItemId", navOptions) -} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreen.kt deleted file mode 100644 index f01f85129b..0000000000 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreen.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.x8bit.bitwarden.ui.vault.feature.edit - -import android.widget.Toast -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.rememberTopAppBarState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.x8bit.bitwarden.R -import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold -import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButton -import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar - -/** - * Top level composable for the vault edit item screen. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun VaultEditItemScreen( - onNavigateBack: () -> Unit, - viewModel: VaultEditItemViewModel = hiltViewModel(), -) { - val state by viewModel.stateFlow.collectAsStateWithLifecycle() - val context = LocalContext.current - val resources = context.resources - EventsEffect(viewModel = viewModel) { event -> - when (event) { - VaultEditItemEvent.NavigateBack -> onNavigateBack() - - is VaultEditItemEvent.ShowToast -> { - Toast.makeText(context, event.message(resources), Toast.LENGTH_SHORT).show() - } - } - } - - val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) - BitwardenScaffold( - modifier = Modifier - .imePadding() - .fillMaxSize() - .nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - BitwardenTopAppBar( - title = stringResource(id = R.string.edit_item), - navigationIcon = painterResource(id = R.drawable.ic_close), - navigationIconContentDescription = stringResource(id = R.string.close), - onNavigationIconClick = remember(viewModel) { - { viewModel.trySendAction(VaultEditItemAction.CloseClick) } - }, - scrollBehavior = scrollBehavior, - actions = { - BitwardenTextButton( - label = stringResource(id = R.string.save), - onClick = remember(viewModel) { - { viewModel.trySendAction(VaultEditItemAction.SaveClick) } - }, - ) - }, - ) - }, - ) { innerPadding -> } -} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModel.kt deleted file mode 100644 index 0acabe8c8e..0000000000 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModel.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.x8bit.bitwarden.ui.vault.feature.edit - -import android.os.Parcelable -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope -import com.x8bit.bitwarden.ui.platform.base.BaseViewModel -import com.x8bit.bitwarden.ui.platform.base.util.Text -import com.x8bit.bitwarden.ui.platform.base.util.asText -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.parcelize.Parcelize -import javax.inject.Inject - -private const val KEY_STATE = "state" - -/** - * ViewModel responsible for handling user interactions in the vault edit item screen - */ -@HiltViewModel -class VaultEditItemViewModel @Inject constructor( - private val savedStateHandle: SavedStateHandle, -) : BaseViewModel( - initialState = savedStateHandle[KEY_STATE] - ?: VaultEditItemState( - vaultItemId = VaultEditItemArgs(savedStateHandle).vaultItemId, - ), -) { - - init { - stateFlow - .onEach { savedStateHandle[KEY_STATE] = it } - .launchIn(viewModelScope) - } - - override fun handleAction(action: VaultEditItemAction) { - when (action) { - VaultEditItemAction.CloseClick -> handleCloseClick() - VaultEditItemAction.SaveClick -> handleSaveClick() - } - } - - private fun handleCloseClick() { - sendEvent(VaultEditItemEvent.NavigateBack) - } - - private fun handleSaveClick() { - // TODO: Persist the data to the vault (BIT-502) - sendEvent(VaultEditItemEvent.ShowToast("Not yet implemented".asText())) - } -} - -/** - * Represents the state for editing an item to the vault. - */ -@Parcelize -data class VaultEditItemState( - val vaultItemId: String, -) : Parcelable - -/** - * Represents a set of events that can be emitted during the process of editing an item in the - * vault. Each subclass of this sealed class denotes a distinct event that can occur. - */ -sealed class VaultEditItemEvent { - /** - * Shows a toast with the given [message]. - */ - data class ShowToast( - val message: Text, - ) : VaultEditItemEvent() - - /** - * Navigate back to previous screen. - */ - data object NavigateBack : VaultEditItemEvent() -} - -/** - * Represents a set of actions related to the process of editing an item in the vault. - * Each subclass of this sealed class denotes a distinct action that can be taken. - */ -sealed class VaultEditItemAction { - /** - * Represents the action when the save button is clicked. - */ - data object SaveClick : VaultEditItemAction() - - /** - * User clicked close. - */ - data object CloseClick : VaultEditItemAction() -} diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreenTest.kt deleted file mode 100644 index 70107b6e93..0000000000 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemScreenTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.x8bit.bitwarden.ui.vault.feature.edit - -import androidx.compose.ui.test.onNodeWithContentDescription -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performClick -import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import org.junit.Assert.assertTrue -import org.junit.Before -import org.junit.Test - -class VaultEditItemScreenTest : BaseComposeTest() { - - private var onNavigateBackCalled = false - - private val mutableEventFlow = MutableSharedFlow( - extraBufferCapacity = Int.MAX_VALUE, - ) - private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) - private val viewModel = mockk(relaxed = true) { - every { eventFlow } returns mutableEventFlow - every { stateFlow } returns mutableStateFlow - } - - @Before - fun setUp() { - composeTestRule.setContent { - VaultEditItemScreen( - viewModel = viewModel, - onNavigateBack = { onNavigateBackCalled = true }, - ) - } - } - - @Test - fun `NavigateBack event should invoke onNavigateBack`() { - mutableEventFlow.tryEmit(VaultEditItemEvent.NavigateBack) - assertTrue(onNavigateBackCalled) - } - - @Test - fun `on close click should send CloseClick event`() { - composeTestRule.onNodeWithContentDescription("Close").performClick() - verify(exactly = 1) { - viewModel.trySendAction(VaultEditItemAction.CloseClick) - } - } - - @Test - fun `on save click should send SaveClick event`() { - composeTestRule.onNodeWithText("Save").performClick() - verify(exactly = 1) { - viewModel.trySendAction(VaultEditItemAction.SaveClick) - } - } -} - -private const val DEFAULT_VAULT_ITEM_ID: String = "vault_item_id" - -private val DEFAULT_STATE: VaultEditItemState = VaultEditItemState( - vaultItemId = DEFAULT_VAULT_ITEM_ID, -) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModelTest.kt deleted file mode 100644 index 83e54fd87b..0000000000 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/edit/VaultEditItemViewModelTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.x8bit.bitwarden.ui.vault.feature.edit - -import androidx.lifecycle.SavedStateHandle -import app.cash.turbine.test -import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest -import com.x8bit.bitwarden.ui.platform.base.util.asText -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -class VaultEditItemViewModelTest : BaseViewModelTest() { - - @Test - fun `initial state should be correct when not set`() { - val viewModel = createViewModel(state = null) - assertEquals(DEFAULT_STATE, viewModel.stateFlow.value) - } - - @Test - fun `initial state should be correct when set`() { - val differentVaultItemId = "something_different" - val state = DEFAULT_STATE.copy(vaultItemId = differentVaultItemId) - val viewModel = createViewModel(state = state) - - assertEquals(state, viewModel.stateFlow.value) - } - - @Test - fun `on CloseClick should emit NavigateBack`() = runTest { - val viewModel = createViewModel() - viewModel.eventFlow.test { - viewModel.trySendAction(VaultEditItemAction.CloseClick) - assertEquals(VaultEditItemEvent.NavigateBack, awaitItem()) - } - } - - @Test - fun `on SaveClick should emit ShowToast`() = runTest { - val viewModel = createViewModel() - viewModel.eventFlow.test { - viewModel.trySendAction(VaultEditItemAction.SaveClick) - assertEquals(VaultEditItemEvent.ShowToast("Not yet implemented".asText()), awaitItem()) - } - } - - private fun createViewModel( - state: VaultEditItemState? = DEFAULT_STATE, - vaultItemId: String = VAULT_ITEM_ID, - ): VaultEditItemViewModel = VaultEditItemViewModel( - savedStateHandle = SavedStateHandle().apply { - set("state", state) - set("vault_edit_item_id", vaultItemId) - }, - ) -} - -private const val VAULT_ITEM_ID: String = "vault_item_id" - -private val DEFAULT_STATE: VaultEditItemState = VaultEditItemState( - vaultItemId = VAULT_ITEM_ID, -)