Skip to content

PM-25654: feat: Preview attachment#6675

Open
david-livefront wants to merge 3 commits intomainfrom
PM-25654-preview-attachment
Open

PM-25654: feat: Preview attachment#6675
david-livefront wants to merge 3 commits intomainfrom
PM-25654-preview-attachment

Conversation

@david-livefront
Copy link
Collaborator

@david-livefront david-livefront commented Mar 16, 2026

🎟️ Tracking

PM-25654
Community Forum

📔 Objective

This PR adds the Preview Attachment functionality to the VaultItemScreen.

Viewing image attachments is a hassle since you have to download, save, and open them in another app.
This adds a built-in preview for images, Ideally, we’d have a full file manager that supports all types, but since images are the ones most often needing quick viewing, I think this is okay for now.

The implementation:

  • Downloads the file temporarily.
  • Loads and displays the image with zoom and pan support.
  • Automatically deletes the file once it has been loaded.

📸 Screenshots

Screen_recording_20260316_093623.mp4

@david-livefront david-livefront requested a review from a team as a code owner March 16, 2026 14:37
@david-livefront david-livefront added the ai-review Request a Claude code review label Mar 16, 2026
@github-actions github-actions bot added app:password-manager Bitwarden Password Manager app context app:authenticator Bitwarden Authenticator app context t:feature Change Type - Feature Development labels Mar 16, 2026
@claude
Copy link
Contributor

claude bot commented Mar 16, 2026

Claude finished @david-livefront's task in 3m 37s —— View job


Overall Assessment: APPROVE

This PR adds an image attachment preview feature, allowing users to tap vault item attachments to preview supported image formats (PNG, JPG, JPEG, GIF, WEBP, BMP) in a dedicated screen with pinch-to-zoom and pan gestures. Non-previewable file types display an informative error with a download option. The implementation introduces a new PreviewAttachmentViewModel, PreviewAttachmentScreen, and reusable ImagePreviewContent composable with bitmap downsampling. Navigation is wired through all vault item content types (login, card, identity, secure note, SSH key) and the BitwardenBasicDialog gains a customizable confirm button label.

Code Review Details

No new findings. Previous review findings have been addressed by the developer. The one unresolved inline thread from SaintPatrck regarding adding errorMessage to DownloadAttachmentResult.Failure for Cookie Redirect Exception handling is already being tracked.

@codecov
Copy link

codecov bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 82.49400% with 73 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.73%. Comparing base (6d04c04) to head (a44ba4f).

Files with missing lines Patch % Lines
.../attachments/preview/PreviewAttachmentViewModel.kt 91.76% 15 Missing and 5 partials ⚠️
...ure/attachments/preview/PreviewAttachmentScreen.kt 76.54% 15 Missing and 4 partials ⚠️
...attachments/preview/PreviewAttachmentNavigation.kt 21.73% 18 Missing ⚠️
...warden/ui/vault/feature/item/VaultItemViewModel.kt 35.71% 8 Missing and 1 partial ⚠️
...i/vault/feature/item/VaultItemAttachmentContent.kt 88.88% 5 Missing ⚠️
...arden/ui/vault/feature/item/VaultItemNavigation.kt 0.00% 1 Missing ⚠️
...ature/item/handlers/VaultCommonItemTypeHandlers.kt 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6675      +/-   ##
==========================================
- Coverage   85.80%   85.73%   -0.07%     
==========================================
  Files         807      810       +3     
  Lines       57331    57738     +407     
  Branches     8362     8417      +55     
==========================================
+ Hits        49193    49502     +309     
- Misses       5220     5307      +87     
- Partials     2918     2929      +11     
Flag Coverage Δ
app-data 17.55% <0.00%> (-0.12%) ⬇️
app-ui-auth-tools 20.66% <0.00%> (-0.14%) ⬇️
app-ui-platform 14.96% <0.24%> (-0.10%) ⬇️
app-ui-vault 26.21% <82.25%> (+0.37%) ⬆️
authenticator 6.57% <0.00%> (-0.03%) ⬇️
lib-core-network-bridge 4.26% <0.00%> (-0.03%) ⬇️
lib-data-ui 0.95% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 16, 2026

Logo
Checkmarx One – Scan Summary & Details9c17c508-d0d5-455b-a366-a42b0464f0a3


New Issues (1) Checkmarx found the following issues in this Pull Request
# Severity Issue Source File / Package Checkmarx Insight
1 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt: 147
detailsThe application uses the hard-coded password "cipherId1234" for authentication purposes, either using it to verify users' identities, or to access...
Attack Vector

@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from 72b29ac to b4b87af Compare March 16, 2026 14:46
@claude
Copy link
Contributor

claude bot commented Mar 16, 2026

test read access

@claude
Copy link
Contributor

claude bot commented Mar 16, 2026

Overall Assessment: REQUEST CHANGES

Reviewed the new Preview Attachment feature across 21 changed files (1965 additions, 51 deletions). The architecture follows established Bitwarden patterns well (BaseViewModel UDF, navigation, screen/VM separation). Two issues need to be addressed before merge.

Code Review Details
  • CRITICAL: Bitmap render error shows "Delete" to the user instead of a meaningful error message

    • PreviewAttachmentViewModel.kt:329-336handleBitmapRenderError() uses BitwardenString.delete (which resolves to the string "Delete") as the error message when an image fails to render. This PR added the string resource bitwarden_could_not_decrypt_this_file_so_the_preview_cannot_be_displayed in strings.xml:1231 specifically for this use case, but it is never referenced in any Kotlin code. The fix is to replace BitwardenString.delete.asText() with BitwardenString.bitwarden_could_not_decrypt_this_file_so_the_preview_cannot_be_displayed.asText() in handleBitmapRenderError(), and update the corresponding assertion in PreviewAttachmentViewModelTest.kt at line 1529.
  • ⚠️ IMPORTANT: .first() can suspend indefinitely if cipher data is never non-null, leaving the user with a stuck loading dialog

    • PreviewAttachmentViewModel.kt:310-321 — In handleDownloadClick(), the expression .mapNotNull { it.data }.first() will never complete if the vault item state flow only emits states with null data (e.g., persistent DataState.Error(data = null)). The user sees a loading dialog with no way to dismiss it. The existing VaultItemViewModel.handleAttachmentDownloadClick avoids this pattern by using requireNotNull(content.common.currentCipher) from already-loaded state rather than creating a new flow subscription. Consider adding a timeout via withTimeoutOrNull or restructuring to use already-available cipher data.

@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from b4b87af to ac3822c Compare March 16, 2026 17:36
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from ac3822c to 215e226 Compare March 16, 2026 17:54
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from 215e226 to 063ee14 Compare March 16, 2026 18:05
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from 063ee14 to 81bd3e2 Compare March 16, 2026 18:35
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from 81bd3e2 to 0bb64ac Compare March 16, 2026 21:09
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch 2 times, most recently from f57df9a to bcdecbd Compare March 17, 2026 16:32
@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch 3 times, most recently from 01cef34 to 7ad52ee Compare March 17, 2026 21:27
* The attachment file has been received saving.
*/
data class DownloadAttachmentReceive(
val result: DownloadAttachmentResult,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we go ahead and add errorMessage to DownloadAttachmentResult.Failure to handle the potential Cookie Redirect Exception?

@SaintPatrck SaintPatrck added hold do not merge yet labels Mar 18, 2026
@SaintPatrck
Copy link
Contributor

Requesting hold until after next RC cut.

@david-livefront david-livefront force-pushed the PM-25654-preview-attachment branch from 7ad52ee to a44ba4f Compare March 18, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review app:authenticator Bitwarden Authenticator app context app:password-manager Bitwarden Password Manager app context community-pr hold do not merge yet t:feature Change Type - Feature Development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants