diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendContent.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendContent.kt index 9a53502e3f4..08ca25e489a 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendContent.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendContent.kt @@ -108,10 +108,13 @@ fun SendContent( .standardHorizontalMargin(), ) } + + item { + Spacer(modifier = Modifier.height(height = 16.dp)) + } } item { - Spacer(modifier = Modifier.height(16.dp)) BitwardenListHeaderText( label = stringResource(id = BitwardenString.all_sends), supportingLabel = state.sendItems.size.toString(), @@ -129,6 +132,7 @@ fun SendContent( label = it.name, supportingLabel = it.deletionDate, trailingLabelIcons = it.iconList, + isDisabled = it.isDisabled, showMoreOptions = !policyDisablesSend, onClick = { sendHandlers.onSendClick(it) }, onViewClick = { sendHandlers.onViewSendClick(it) }, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendListItem.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendListItem.kt index e381437da00..f2ea19010d2 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendListItem.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendListItem.kt @@ -26,8 +26,9 @@ import kotlinx.collections.immutable.toPersistentList * A Composable function that displays a row send item. * * @param label The primary text label to display for the item. - * @param supportingLabel An secondary text label to display beneath the label. + * @param supportingLabel A secondary text label to display beneath the label. * @param startIcon The [Painter] object used to draw the icon at the start of the item. + * @param isDisabled Whether the item is disabled or not. * @param showMoreOptions Whether to show the button for the overflow options. * @param onClick The lambda to be invoked when the item is clicked. * @param onViewClick The lambda to be invoked when the view option is clicked from the menu. @@ -47,6 +48,7 @@ fun SendListItem( label: String, supportingLabel: String, startIcon: IconData, + isDisabled: Boolean, trailingLabelIcons: ImmutableList, showMoreOptions: Boolean, onClick: () -> Unit, @@ -86,7 +88,8 @@ fun SendListItem( SelectionItemData( text = stringResource(id = BitwardenString.edit), onClick = onEditClick, - ), + ) + .takeUnless { isDisabled }, onRemovePasswordClick?.let { SelectionItemData( text = stringResource(id = BitwardenString.remove_password), @@ -130,6 +133,7 @@ private fun SendListItem_preview() { supportingLabel = "Jan 3, 2024, 10:35 AM", startIcon = IconData.Local(BitwardenDrawable.ic_file_text), trailingLabelIcons = persistentListOf(), + isDisabled = false, showMoreOptions = true, onClick = {}, onCopyClick = {}, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendViewModel.kt index 10f37c8e4d3..a8c24139841 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendViewModel.kt @@ -66,7 +66,8 @@ class SendViewModel @Inject constructor( ) : BaseViewModel( // We load the state from the savedStateHandle for testing purposes. initialState = savedStateHandle[KEY_STATE] - ?: policyManager.getEffectiveSendPolicy().let { effectiveSendPolicy -> + ?: run { + val effectiveSendPolicy = policyManager.getEffectiveSendPolicy() SendState( viewState = SendState.ViewState.Loading, dialogState = null, @@ -565,7 +566,7 @@ data class SendState( override val shouldDisplayFab: Boolean get() = true /** - * Represents the an individual send item to be displayed. + * Represents an individual send item to be displayed. */ @Parcelize data class SendItem( @@ -576,6 +577,7 @@ data class SendState( val iconList: ImmutableList, val shareUrl: String, val hasPassword: Boolean, + val isDisabled: Boolean, ) : Parcelable { /** * Indicates the type of send this, a text or file. diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensions.kt index 6389d9b3973..a5f1ecc6b2b 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensions.kt @@ -46,6 +46,7 @@ private fun List.toSendContent( iconList = sendView.toLabelIcons(), shareUrl = sendView.toSendUrl(baseWebSendUrl), hasPassword = sendView.hasPassword, + isDisabled = sendView.disabled, ) }, ) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensions.kt index 28145da7868..be4210ec1d5 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensions.kt @@ -47,7 +47,8 @@ fun SendView.toOverflowActions( sendUrl = toSendUrl(baseWebSendUrl = baseWebSendUrl), ), ListingItemOverflowAction.SendAction.ViewClick(sendId = sendId, sendType = type), - ListingItemOverflowAction.SendAction.EditClick(sendId = sendId, sendType = type), + ListingItemOverflowAction.SendAction.EditClick(sendId = sendId, sendType = type) + .takeUnless { this.disabled }, ListingItemOverflowAction.SendAction.RemovePasswordClick(sendId = sendId).takeIf { hasPassword }, diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt index 0031de8c982..8d5a551780c 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt @@ -621,6 +621,40 @@ class SendScreenTest : BitwardenComposeTest() { composeTestRule.assertNoDialogExists() } + @Test + fun `on send item overflow dialog edit should not be displayed when the send is disabled`() { + mutableStateFlow.update { + it.copy( + viewState = SendState.ViewState.Content( + textTypeCount = 0, + fileTypeCount = 1, + sendItems = listOf( + DEFAULT_SEND_ITEM.copy(isDisabled = true), + DEFAULT_SEND_ITEM.copy(id = "mockId-2", name = "mockName-2"), + ), + ), + ) + } + composeTestRule.assertNoDialogExists() + + // We scroll to the last item but click the first one to avoid clicking the FAB by mistake + composeTestRule + .onNodeWithText("mockName-2") + .performScrollTo() + .assertIsDisplayed() + + composeTestRule + .onNodeWithText("mockName-1") + .onChildren() + .filterToOne(hasContentDescription("More options")) + .assertIsDisplayed() + .performClick() + + composeTestRule + .onNodeWithText("Edit") + .assertDoesNotExist() + } + @Test fun `on send item overflow dialog copy click should send CopyClick`() { mutableStateFlow.update { @@ -1144,6 +1178,7 @@ private val DEFAULT_SEND_ITEM: SendState.ViewState.Content.SendItem = iconList = persistentListOf(), shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1", hasPassword = true, + isDisabled = false, ) private val DEFAULT_CONTENT_VIEW_STATE: SendState.ViewState.Content = SendState.ViewState.Content( @@ -1159,6 +1194,7 @@ private val DEFAULT_CONTENT_VIEW_STATE: SendState.ViewState.Content = SendState. iconList = persistentListOf(), shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1", hasPassword = true, + isDisabled = false, ), ), ) diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensionsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensionsTest.kt index 394ea375094..468a429939d 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensionsTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendDataExtensionsTest.kt @@ -54,8 +54,8 @@ class SendDataExtensionsTest { @Test fun `toViewState should return Content when SendData is not empty`() { - val textSendView = createMockSendView(number = 2, type = SendType.TEXT) - val fileSendView = createMockSendView(number = 1, type = SendType.FILE) + val textSendView = createMockSendView(number = 2, type = SendType.TEXT, disabled = true) + val fileSendView = createMockSendView(number = 1, type = SendType.FILE, disabled = false) val list = listOf( fileSendView, textSendView, @@ -83,6 +83,7 @@ class SendDataExtensionsTest { iconList = DEFAULT_SEND_STATUS_ICONS, shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1", hasPassword = true, + isDisabled = false, ), SendState.ViewState.Content.SendItem( id = "mockId-2", @@ -92,6 +93,7 @@ class SendDataExtensionsTest { iconList = DEFAULT_SEND_STATUS_ICONS, shareUrl = "www.test.com/#/send/mockAccessId-2/mockKey-2", hasPassword = true, + isDisabled = true, ), ), ), diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensionsTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensionsTest.kt index 3f21f38b6a1..b54b9fa6911 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensionsTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/util/SendViewExtensionsTest.kt @@ -101,6 +101,26 @@ class SendViewExtensionsTest { ) } + @Suppress("MaxLineLength") + @Test + fun `toOverflowActions should return overflow options without Edit when the send is disabled`() { + val baseWebSendUrl = "www.test.com" + val sendView = createMockSendView( + number = 1, + // Make sure the send is disabled to remove the edit action + disabled = true, + ) + + val result = sendView.toOverflowActions(baseWebSendUrl = baseWebSendUrl) + + assertEquals( + ALL_SEND_OVERFLOW_OPTIONS.filter { + it !is ListingItemOverflowAction.SendAction.EditClick + }, + result, + ) + } + @Test fun `toOverflowActions should return no overflow options when the id is null`() { val baseWebSendUrl = "www.test.com"