8000 BIT-678: create UI for identity by ezimet-livefront Β· Pull Request #199 Β· bitwarden/ios Β· GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

BIT-678: create UI for identity #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cfced91
BIT-678 ui for Identity view
ezimet-livefront Dec 14, 2023
c375263
added unit tests
ezimet-livefront Dec 14, 2023
4011dd6
BIT-678 BIT-349 added savings Identity
ezimet-livefront Dec 14, 2023
a549379
BIT-678 BIT-349 added unit tests for addEditItemViewTests
ezimet-livefront Dec 14, 2023
392e5d0
Merge branch 'main' of ssh://github.com/bitwarden/ios into BIT-678/cr…
ezimet-livefront Dec 14, 2023
36a635f
BIT-678 BIT-349 added mote unit tests
ezimet-livefront Dec 14, 2023
137fb1b
BIT-678 BIT-349 separated zip code and state, updated unit tests, add…
ezimet-livefront Dec 14, 2023
74d0a01
BIT-678 BIT-349 updated docs
ezimet-livefront Dec 14, 2023
46dedef
updated doc
ezimet-livefront Dec 14, 2023
4bcc789
added snapshot testing for large text
ezimet-livefront Dec 14, 2023
d7d5967
changed to rawValue for saving titleType
ezimet-livefront Dec 14, 2023
66521a4
updated snapshots
ezimet-livefront Dec 14, 2023
208dabf
BIT-678: Update snapshots
matt-livefront Dec 14, 2023
6cd3283
changed DefaultableType, added customizable title to Menuable
ezimet-livefront Dec 15, 2023
9b0101b
Merge branch 'BIT-678/create-ui-for-identity' of ssh://github.com/bit…
ezimet-livefront Dec 15, 2023
1ffdfd5
fix testing
ezimet-livefront Dec 15, 2023
6baf723
address feedback
ezimet-livefront Dec 16, 2023
5348dba
address feedback
ezimet-livefront Dec 18, 2023
e427dac
merge main & resolve merge conflict
ezimet-livefront Dec 18, 2023
dba48e4
separated identity state update action
ezimet-livefront Dec 18, 2023
f9129db
reorder action position
ezimet-livefront Dec 18, 2023
c6a6ce5
address feedback
ezimet-livefront Dec 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Foundation
enum DefaultableType<T: CaseIterable & Menuable>: CaseIterable, Menuable {
// MARK: Cases

/// placeholder default value of the type.
case `default`
case custom(T)

Expand All @@ -20,7 +21,7 @@ enum DefaultableType<T: CaseIterable & Menuable>: CaseIterable, Menuable {
var localizedName: String {
switch self {
case .default:
Localizations.default
T.defaultValueLocalizedName
case let .custom(value):
value.localizedName
}
Expand Down
63 changes: 63 additions & 0 deletions BitwardenShared/Core/Vault/Models/Enum/TitleType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/// An enum that describes how a Identity title should be matched.
///
enum TitleType: String, Codable, Equatable, Hashable, Menuable {
// swiftlint:disable identifier_name

// MARK: Cases

/// Mr title for adult men.
case mr = "Mr"

/// Mrs title for married or widowed women.
case mrs = "Mrs"

/// Ms title for women regardless of marital status.
case ms = "Ms"

/// Mx title for individuals who prefer not to specify their gender or identify as non-binary.
case mx = "Mx"

/// Dr title for individuals with a doctoral degree.
case dr = "Dr"
Comment on lines +9 to +21
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@fedemkr Could you review these values and compare them to what are we saving in the live app?
Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

For context, @fedemkr , I was wondering if this should just be a text field, as honorific abbreviations vary wildly by language.
A more complex approach would be localizing the enum.

Copy link
Member

Choose a reason for hiding this comment

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

ℹ️ I think I found an issue with this on our apps, I'll let you know as soon as I have a proper answer for this. Just in case to the user this should be presented localized but I see you have localizedName below so I guess that's already sorted out.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, I also did quick test around live Xamarin app, looks like it saves localized value directly, if user change the locale, it will show the old localized value, and when we try to edit identity, it will fail to preselect the title as new locale does not match the old one.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, exactly. We're discussing it internally on how we are going to handle that. I'll let you know as soon as I have the path forward.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

thanks, I think it would be better to merge this PR and follow up with new ticket for that.

Copy link
Member

Choose a reason for hiding this comment

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

@ezimet-livefront the value saved for the title will be the English version of it so I think those values should be correct πŸ˜„

// swiftlint:enable identifier_name

// MARK: Type Properties

/// default state title for title type
static var defaultValueLocalizedName: String {
"--\(Localizations.select)--"
}

var localizedName: String {
switch self {
case .mr: Localizations.mr
case .mrs: Localizations.mrs
case .ms: Localizations.ms
case .mx: Localizations.mx
case .dr: Localizations.dr
}
}

// MARK: Initializer

init?(rawValue: String) {
switch rawValue {
case Localizations.mr:
self = .mr
case Localizations.mrs:
self = .mrs
case Localizations.ms:
self = .ms
case Localizations.mx:
self = .mx
case Localizations.dr:
self = .dr
default:
return nil
}
}
}

extension TitleType: CaseIterable {
static var allCases: [TitleType] = [.mr, .mrs, .ms, .mx, .dr]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ import SwiftUI
/// A protocol that defines an object that can be represented and selected in
/// a `BitwardenMenuField`.
protocol Menuable: Equatable, Hashable {
/// The custom localizable title value for this default case, defaults to `Default`.
static var defaultValueLocalizedName: String { get }

/// A localized name value. This value is displayed in the Menu when the user
/// is making a selection between multiple options.
var localizedName: String { get }
}

extension Menuable {
static var defaultValueLocalizedName: String {
Localizations.default
}
}

// MARK: - BitwardenMenuField

/// A standard input field that allows the user to select between a predefined set of
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// MARK: - AddEditIdentityItemAction

import BitwardenSdk

/// Actions that can be handled by an `AddEditItemProcessor`.
enum AddEditIdentityItemAction: Equatable {
/// The title field was changed.
case titleChanged(DefaultableType<TitleType>)

/// The first name field was changed.
case firstNameChanged(String)

/// The last name field was changed.
case lastNameChanged(String)

/// The middle name field was changed.
case middleNameChanged(String)

/// The user name field was changed.
case userNameChanged(String)

/// The company field was changed.
case companyChanged(String)

/// The SSN field was changed.
case socialSecurityNumberChanged(String)

/// The passport number field was changed.
case passportNumberChanged(String)

/// The license number field was changed.
case licenseNumberChanged(String)

/// The email address field was changed.
case emailChanged(String)

/// The phone number field was changed.
case phoneNumberChanged(String)

/// The address line 1 field was changed.
case address1Changed(String)

/// The address line 2 field was changed.
case address2Changed(String)

/// The address line 3 field was changed.
case address3Changed(String)

/// The city/town field was changed.
case cityOrTownChanged(String)

/// The state field was changed.
case stateChanged(String)

/// The postal code field was changed.
case postalCodeChanged(String)

/// The country field was changed.
case countryChanged(String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import SwiftUI

// MARK: - AddEditIdentityItemView

/// A view that allows the user to add or edit Identity part of the cipherItem to a vault.
///
struct AddEditIdentityItemView: View {
// MARK: Properties

/// The `Store` for this view.
@ObservedObject var store: Store<IdentityItemState, AddEditIdentityItemAction, AddEditItemEffect>

// MARK: Views

var body: some View {
LazyVStack(alignment: .leading, spacing: 16) {
BitwardenMenuField(
title: Localizations.title,
options: DefaultableType<TitleType>.allCases,
selection: store.binding(
get: \.title,
send: AddEditIdentityItemAction.titleChanged
)
)

BitwardenTextField(
title: Localizations.firstName,
text: store.binding(
get: \.firstName,
send: AddEditIdentityItemAction.firstNameChanged
)
)

BitwardenTextField(
title: Localizations.middleName,
text: store.binding(
get: \.middleName,
send: AddEditIdentityItemAction.middleNameChanged
)
)

BitwardenTextField(
title: Localizations.lastName,
text: store.binding(
get: \.lastName,
send: AddEditIdentityItemAction.lastNameChanged
)
)

BitwardenTextField(
title: Localizations.username,
text: store.binding(
get: \.userName,
send: AddEditIdentityItemAction.userNameChanged
)
)
.textFieldConfiguration(.username)

BitwardenTextField(
title: Localizations.company,
text: store.binding(
get: \.company,
send: AddEditIdentityItemAction.companyChanged
)
)

BitwardenTextField(
title: Localizations.ssn,
text: store.binding(
get: \.socialSecurityNumber,
send: AddEditIdentityItemAction.socialSecurityNumberChanged
)
)

BitwardenTextField(
title: Localizations.passportNumber,
text: store.binding(
get: \.passportNumber,
send: AddEditIdentityItemAction.passportNumberChanged
)
)

BitwardenTextField(
title: Localizations.licenseNumber,
text: store.binding(
get: \.licenseNumber,
send: AddEditIdentityItemAction.licenseNumberChanged
)
)

BitwardenTextField(
title: Localizations.email,
text: store.binding(
get: \.email,
send: AddEditIdentityItemAction.emailChanged
)
)
.textFieldConfiguration(.email)

BitwardenTextField(
title: Localizations.phone,
text: store.binding(
get: \.phone,
send: AddEditIdentityItemAction.phoneNumberChanged
)
)

BitwardenTextField(
title: Localizations.address1,
text: store.binding(
get: \.address1,
send: AddEditIdentityItemAction.address1Changed
)
)

BitwardenTextField(
title: Localizations.address2,
text: store.binding(
get: \.address2,
send: AddEditIdentityItemAction.address2Changed
)
)

BitwardenTextField(
title: Localizations.address3,
text: store.binding(
get: \.address3,
send: AddEditIdentityItemAction.address3Changed
)
)

BitwardenTextField(
title: Localizations.cityTown,
text: store.binding(
get: \.cityOrTown,
send: AddEditIdentityItemAction.cityOrTownChanged
)
)

BitwardenTextField(
title: Localizations.stateProvince,
text: store.binding(
get: \.state,
send: AddEditIdentityItemAction.stateChanged
)
)

BitwardenTextField(
title: Localizations.zipPostalCode,
text: store.binding(
get: \.postalCode,
send: AddEditIdentityItemAction.postalCodeChanged
)
)

BitwardenTextField(
title: Localizations.country,
text: store.binding(
get: \.country,
send: AddEditIdentityItemAction.countryChanged
)
)
}
}
}

// MARK: Previews

#if DEBUG
struct AddEditIdentityItemView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ScrollView {
LazyVStack(spacing: 20) {
AddEditIdentityItemView(
store: Store(
processor: StateProcessor(
state: IdentityItemState()
)
)
)
}
.padding(16)
}
.background(Asset.Colors.backgroundSecondary.swiftUIColor)
.ignoresSafeArea()
}
.previewDisplayName("Empty Add Edit Identity State")
}
}
#endif
Loading
0