Skip to content

[PM-38150] feat: Add Driver's License view screen#2758

Open
SaintPatrck wants to merge 1 commit into
mainfrom
vault/pm-38150-ios-license-view
Open

[PM-38150] feat: Add Driver's License view screen#2758
SaintPatrck wants to merge 1 commit into
mainfrom
vault/pm-38150-ios-license-view

Conversation

@SaintPatrck

@SaintPatrck SaintPatrck commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

🎟️ Tracking

📔 Objective

Adds the read-only detail view for Driver's License items. Renders the License details section: first/middle/last name (with copy), license number (masked with a reveal toggle + copy), date of birth / issue date / expiration date (formatted long dates), issuing country / state / authority, and license class. Empty fields are hidden. Wires the view into the per-type dispatch in ViewItemDetailsView.

📸 Screenshots

Figma Actual

@SaintPatrck SaintPatrck added the ai-review Request a Claude code review label Jun 5, 2026
@github-actions github-actions Bot added app:password-manager Bitwarden Password Manager app context t:feature labels Jun 5, 2026
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the read-only Driver's License view screen wired into ViewItemDetailsView. The change introduces ViewDriversLicenseItemView, which mirrors the established ViewCardItemView pattern: section-level visibility via isLicenseDetailsSectionEmpty, per-field empty hiding, PasswordText masking with PasswordVisibilityButton for the license number, and per-field copy buttons routed through new CopyableField cases. ViewItemProcessor.handleDriversLicenseAction guards on both loading state and cipher type, logging through errorReporter consistent with the card path. Unit, ViewInspector, and (disabled) snapshot tests cover toggle dispatch, copy dispatch for each field, the empty-state branch, the loading-state guard, and the wrong-cipher-type guard.

Code Review Details

No findings.

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.03352% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.85%. Comparing base (89c925a) to head (1b02754).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
...tem/ViewDriversLicenseItemView+SnapshotTests.swift 0.00% 43 Missing ⚠️
...Vault/VaultItem/ViewItem/ViewItemDetailsView.swift 0.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2758      +/-   ##
==========================================
- Coverage   87.85%   87.85%   -0.01%     
==========================================
  Files        1712     1715       +3     
  Lines      166702   167058     +356     
==========================================
+ Hits       146463   146769     +306     
- Misses      20239    20289      +50     

☔ View full report in Codecov by Harness.
📢 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.

Base automatically changed from vault/pm-38149-ios-license-add-edit to main June 5, 2026 15:23
Adds the read-only detail view for driver's license items, rendering the license details section: first/middle/last name, license number, dates, issuing country/state/authority, and license class. The license number is masked with a reveal toggle; the name and license-number fields support copy. Wires the view into the per-type dispatch in ViewItemDetailsView.
@SaintPatrck SaintPatrck force-pushed the vault/pm-38150-ios-license-view branch from f0b24fd to 1b02754 Compare June 5, 2026 16:31
@SaintPatrck SaintPatrck marked this pull request as ready for review June 9, 2026 13:42
@SaintPatrck SaintPatrck requested review from a team and matt-livefront as code owners June 9, 2026 13:42
@ObservedObject var store: Store<DriversLicenseItemState, ViewItemAction, Void>

var body: some View {
if !store.state.isLicenseDetailsSectionEmpty {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

♻️ Not to change int his PR, but @KatherineInCode @matt-livefront do you remember why we took this approach of checking if the specific cipher type details are empty inside the cipher type item view instead of doing it in ViewItemDetailsView wrapping each specific cipher type item view with the empty check?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't really mind it here, creating the view is cheap and it keeps the empty check encapsulated within this view. If you move the check into the parent view, that view would need to reach into the child state to do the empty check.


// MARK: Private Views

@ViewBuilder private var firstNameItem: some View {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

⛏️ Add docs as well as the other view builder properties.

Comment on lines +99 to +104
PasswordVisibilityButton(
accessibilityIdentifier: "ShowDriversLicenseNumberButton",
isPasswordVisible: isVisible,
) {
store.send(.driversLicenseItemAction(.toggleLicenseNumberVisibilityChanged(!isVisible)))
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤔 I know we're doing this on this way on Card, but I feel Identity/Login handles this better by not having to pass isVisible value here. I mean IMO the view should only send the processor .toggleLicenseNumberVisibilityChanged without parameters and then the processor check the current state and invert the visibility of the field.
I feel like doing it this way removes some logic from the View and it goes to the processor where it should live.
@bitwarden/team-ios @matt-livefront what do you think? Also I think we should have a tech-debt to update the Card approach as well.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

From a unidirectional data flow perspective, it would be better to not have the view do the toggling and dictate the new value to the processor. We're not very consistent on this though, and SwiftUI sometimes fights us. If you use a binding, the binding sends the new value as part of the action, which ends up being easier to use than to ignore it. I like updating this and the card cases though, it would end up being simpler than manually toggling it.

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:password-manager Bitwarden Password Manager app context t:feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants