diff --git a/AuthenticatorShared/UI/Platform/Application/Views/AccessoryButton.swift b/AuthenticatorShared/UI/Platform/Application/Views/AccessoryButton.swift deleted file mode 100644 index b2227ebb5..000000000 --- a/AuthenticatorShared/UI/Platform/Application/Views/AccessoryButton.swift +++ /dev/null @@ -1,87 +0,0 @@ -import BitwardenKit -import BitwardenResources -import SwiftUI - -/// A view that displays a button for use as an accessory to a field. -/// -struct AccessoryButton: View { - // MARK: Types - - /// A type that wraps a synchrounous or asynchrounous block that is executed by this button. - /// - enum Action { - /// An action run synchrounously. - case sync(() -> Void) - - /// An action run asynchrounously. - case async(() async -> Void) - } - - // MARK: Properties - - /// The accessibility label of the button. - var accessibilityLabel: String - - /// The action to perform when the user interacts with this button. - var action: Action - - /// The image to display in the button. - var asset: SharedImageAsset - - var body: some View { - switch action { - case let .async(action): - AsyncButton(action: action) { - asset.swiftUIImage - .resizable() - .frame(width: 14, height: 14) - } - .buttonStyle(.accessory) - .accessibilityLabel(Text(accessibilityLabel)) - case let .sync(action): - Button(action: action) { - asset.swiftUIImage - .resizable() - .frame(width: 14, height: 14) - } - .buttonStyle(.accessory) - .accessibilityLabel(Text(accessibilityLabel)) - } - } - - // MARK: Initialization - - /// Initializes a `AccessoryButton` which styles a button for display as an accessory to a - /// field. - /// - /// - Parameters: - /// - asset: The image to display in the button. - /// - accessibilityLabel: The accessibility label of the button. - /// - action: The action to perform when the user triggers the button. - /// - init(asset: SharedImageAsset, accessibilityLabel: String, action: @escaping () -> Void) { - self.accessibilityLabel = accessibilityLabel - self.action = .sync(action) - self.asset = asset - } - - /// Initializes a `AccessoryButton` which styles a button for display as an accessory to a - /// field. - /// - /// - Parameters: - /// - asset: The image to display in the button. - /// - accessibilityLabel: The accessibility label of the button. - /// - action: The action to perform when the user triggers the button. - /// - init(asset: SharedImageAsset, accessibilityLabel: String, action: @escaping () async -> Void) { - self.accessibilityLabel = accessibilityLabel - self.action = .async(action) - self.asset = asset - } -} - -// MARK: Previews - -#Preview { - AccessoryButton(asset: SharedAsset.Icons.copy16, accessibilityLabel: Localizations.copy) {} -} diff --git a/AuthenticatorShared/UI/Platform/Application/Views/BitwardenField.swift b/AuthenticatorShared/UI/Platform/Application/Views/BitwardenField.swift deleted file mode 100644 index c10c415cb..000000000 --- a/AuthenticatorShared/UI/Platform/Application/Views/BitwardenField.swift +++ /dev/null @@ -1,126 +0,0 @@ -import SwiftUI - -// MARK: - BitwardenField - -/// A standardized view used to wrap some content into a row of a list. This is commonly used in -/// forms. -struct BitwardenField: View where Content: View, AccessoryContent: View { - /// The (optional) title of the field. - var title: String? - - /// The (optional) accessibility identifier to apply to the title of the field (if it exists) - var titleAccessibilityIdentifier: String? - - /// The (optional) footer to display underneath the field. - var footer: String? - - /// The (optional) accessibility identifier to apply to the fooder of the field (if it exists) - var footerAccessibilityIdentifier: String? - - /// The vertical padding to apply around `content`. Defaults to `8`. - var verticalPadding: CGFloat - - /// The content that should be displayed in the field. - var content: Content - - /// Any accessory content that should be displayed on the trailing edge of the field. This - /// content automatically has the `AccessoryButtonStyle` applied to it. - var accessoryContent: AccessoryContent? - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - if let title { - Text(title) - .styleGuide(.subheadline, weight: .semibold) - .foregroundColor(Asset.Colors.textSecondary.swiftUIColor) - .accessibilityIdentifier(titleAccessibilityIdentifier ?? title) - } - - HStack(spacing: 8) { - content - .frame(maxWidth: .infinity, minHeight: 28, alignment: .leading) - .padding(.horizontal, 16) - .padding(.vertical, verticalPadding) - .background(Asset.Colors.backgroundPrimary.swiftUIColor) - .clipShape(RoundedRectangle(cornerRadius: 10)) - - if let accessoryContent { - accessoryContent - .buttonStyle(.accessory) - } - } - - if let footer { - Text(footer) - .styleGuide(.footnote) - .foregroundColor(Asset.Colors.textSecondary.swiftUIColor) - .accessibilityIdentifier(footerAccessibilityIdentifier ?? footer) - } - } - } - - // MARK: Initialization - - /// Creates a new `BitwardenField`. - /// - /// - Parameters: - /// - title: The (optional) title of the field. - /// - titleAccessibilityIdentifier: The (optional) accessibility identifier to apply - /// to the title of the field (if it exists) - /// - footer: The (optional) footer to display underneath the field. - /// - footerAccessibilityIdentifier: The (optional) accessibility identifier to apply - /// to the fooder of the field (if it exists) - /// - verticalPadding: The vertical padding to apply around `content`. Defaults to `8`. - /// - content: The content that should be displayed in the field. - /// - accessoryContent: Any accessory content that should be displayed on the trailing edge of - /// the field. This content automatically has the `AccessoryButtonStyle` applied to it. - /// - init( - title: String? = nil, - titleAccessibilityIdentifier: String? = nil, - footer: String? = nil, - footerAccessibilityIdentifier: String? = nil, - verticalPadding: CGFloat = 8, - @ViewBuilder content: () -> Content, - @ViewBuilder accessoryContent: () -> AccessoryContent, - ) { - self.title = title - self.titleAccessibilityIdentifier = titleAccessibilityIdentifier - self.footer = footer - self.footerAccessibilityIdentifier = footerAccessibilityIdentifier - self.verticalPadding = verticalPadding - self.content = content() - self.accessoryContent = accessoryContent() - } -} - -extension BitwardenField where AccessoryContent == EmptyView { - /// Creates a new `BitwardenField` without accessory content. - /// - /// - Parameters: - /// - title: The (optional) title of the field. - /// - titleAccessibilityIdentifier: The (optional) accessibility identifier to apply - /// to the title of the field (if it exists) - /// - footer: The (optional) footer to display underneath the field. - /// - footerAccessibilityIdentifier: The (optional) accessibility identifier to apply - /// to the fooder of the field (if it exists) - /// - verticalPadding: The vertical padding to apply around `content`. Defaults to `8`. - /// - content: The content that should be displayed in the field. - /// - init( - title: String? = nil, - titleAccessibilityIdentifier: String? = nil, - footer: String? = nil, - footerAccessibilityIdentifier: String? = nil, - verticalPadding: CGFloat = 8, - @ViewBuilder content: () -> Content, - ) { - self.title = title - self.titleAccessibilityIdentifier = titleAccessibilityIdentifier - self.footer = footer - self.footerAccessibilityIdentifier = footerAccessibilityIdentifier - self.verticalPadding = verticalPadding - self.content = content() - accessoryContent = nil - } -} diff --git a/AuthenticatorShared/UI/Platform/Application/Views/BitwardenTextValueField.swift b/AuthenticatorShared/UI/Platform/Application/Views/BitwardenTextValueField.swift index d14de6015..02cad8d12 100644 --- a/AuthenticatorShared/UI/Platform/Application/Views/BitwardenTextValueField.swift +++ b/AuthenticatorShared/UI/Platform/Application/Views/BitwardenTextValueField.swift @@ -1,3 +1,4 @@ +import BitwardenKit import SwiftUI /// A standardized view used to display some text into a row of a list. This is commonly used in diff --git a/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuField.swift b/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuField.swift deleted file mode 100644 index fd391d2b4..000000000 --- a/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuField.swift +++ /dev/null @@ -1,134 +0,0 @@ -import BitwardenKit -import SwiftUI - -// MARK: - SettingsMenuField - -/// A standard input field that allows the user to select between a predefined set of -/// options. -/// -struct SettingsMenuField: View where T: Menuable { - // MARK: Properties - - /// The accessibility ID for the menu field. - let accessibilityIdentifier: String? - - /// Whether the menu field should have a bottom divider. - let hasDivider: Bool - - /// The selection chosen from the menu. - @Binding var selection: T - - /// The accessibility ID for the picker selection. - let selectionAccessibilityID: String? - - /// The options displayed in the menu. - let options: [T] - - /// The title of the menu field. - let title: String - - // MARK: View - - var body: some View { - VStack(spacing: 0) { - Menu { - Picker(selection: $selection) { - ForEach(options, id: \.hashValue) { option in - Text(option.localizedName).tag(option) - } - } label: { - Text("") - } - } label: { - HStack { - Text(title) - .multilineTextAlignment(.leading) - .foregroundColor(Asset.Colors.textPrimary.swiftUIColor) - .padding(.vertical, 19) - .fixedSize(horizontal: false, vertical: true) - - Spacer() - - Text(selection.localizedName) - .accessibilityIdentifier(selectionAccessibilityID ?? "") - .multilineTextAlignment(.trailing) - .foregroundColor(Asset.Colors.textSecondary.swiftUIColor) - .accessibilityIdentifier(selectionAccessibilityID ?? "") - } - } - .styleGuide(.body) - .accessibilityIdentifier(accessibilityIdentifier ?? "") - .id(title) - .padding(.horizontal, 16) - - if hasDivider { - Divider() - .padding(.leading, 16) - } - } - .background(Asset.Colors.backgroundPrimary.swiftUIColor) - } - - /// Initializes a new `SettingsMenuField`. - /// - /// - Parameters: - /// - title: The title of the menu field. - /// - options: The options that the user can choose between. - /// - hasDivider: Whether the menu field should have a bottom divider. - /// - accessibilityIdentifier: The accessibility ID for the menu field. - /// - selectionAccessibilityID: The accessibility ID for the picker selection. - /// - selection: A `Binding` for the currently selected option. - /// - init( - title: String, - options: [T], - hasDivider: Bool = true, - accessibilityIdentifier: String? = nil, - selectionAccessibilityID: String? = nil, - selection: Binding, - ) { - self.accessibilityIdentifier = accessibilityIdentifier - self.hasDivider = hasDivider - self.options = options - _selection = selection - self.selectionAccessibilityID = selectionAccessibilityID - self.title = title - } -} - -// MARK: Previews - -#if DEBUG -private enum MenuPreviewOptions: CaseIterable, Menuable { - case bear, bird, dog - - var localizedName: String { - switch self { - case .bear: "🧸" - case .bird: "🪿" - case .dog: "🐕" - } - } -} - -#Preview { - Group { - VStack(spacing: 0) { - SettingsMenuField( - title: "Bear", - options: MenuPreviewOptions.allCases, - selection: .constant(.bear), - ) - - SettingsMenuField( - title: "Dog", - options: MenuPreviewOptions.allCases, - hasDivider: false, - selection: .constant(.dog), - ) - } - .padding(8) - } - .background(Color(.systemGroupedBackground)) -} -#endif diff --git a/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift b/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift deleted file mode 100644 index 0d328a9ee..000000000 --- a/AuthenticatorShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift +++ /dev/null @@ -1,61 +0,0 @@ -import BitwardenKit -import SwiftUI -import ViewInspector -import XCTest - -@testable import AuthenticatorShared - -class SettingsMenuFieldTests: BitwardenTestCase { - // MARK: Types - - enum TestValue: String, CaseIterable, Menuable { - case value1 - case value2 - - var localizedName: String { - rawValue - } - } - - // MARK: Properties - - var selection: TestValue! - var subject: SettingsMenuField! - - // MARK: Setup & Teardown - - override func setUp() { - super.setUp() - selection = .value1 - let binding = Binding { - self.selection! - } set: { newValue in - self.selection = newValue - } - subject = SettingsMenuField( - title: "Title", - options: TestValue.allCases, - selection: binding, - ) - } - - override func tearDown() { - super.tearDown() - selection = nil - subject = nil - } - - // MARK: Tests - - func test_newSelection() throws { - let picker = try subject.inspect().find(ViewType.Picker.self) - try picker.select(value: TestValue.value2) - XCTAssertEqual(selection, .value2) - - let menu = try subject.inspect().find(ViewType.Menu.self) - let title = try menu.labelView().find(ViewType.Text.self).string() - let pickerValue = try menu.find(ViewType.HStack.self).find(text: "value2").string() - XCTAssertEqual(title, "Title") - XCTAssertEqual(pickerValue, "value2") - } -} diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView.swift index 44fb18a27..eb494a930 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView.swift @@ -1,3 +1,4 @@ +import BitwardenKit import BitwardenResources import SwiftUI @@ -14,13 +15,11 @@ struct SelectLanguageView: View { // MARK: View var body: some View { - VStack(spacing: 0) { + ContentBlock(dividerLeadingPadding: 16) { ForEach(LanguageOption.allCases) { languageOption in languageOptionRow(languageOption) } } - .background(Asset.Colors.backgroundPrimary.swiftUIColor) - .cornerRadius(10) .scrollView() .navigationBar(title: Localizations.selectLanguage, titleDisplayMode: .inline) .toolbar { @@ -45,7 +44,6 @@ struct SelectLanguageView: View { private func languageOptionRow(_ languageOption: LanguageOption) -> some View { SettingsListItem( languageOption.title, - hasDivider: !languageOption.isLast, ) { store.send(.languageTapped(languageOption)) } trailingContent: { diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsListItem.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsListItem.swift deleted file mode 100644 index 3e3c52876..000000000 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsListItem.swift +++ /dev/null @@ -1,112 +0,0 @@ -import BitwardenResources -import SwiftUI - -// MARK: - SettingsListItem - -/// A list item that appears across settings screens. -/// -struct SettingsListItem: View { - // MARK: Properties - - /// The accessibility ID for the list item. - let accessibilityIdentifier: String? - - /// The action to perform when the list item is tapped. - let action: () -> Void - - /// Whether or not the list item should have a divider on the bottom. - let hasDivider: Bool - - /// The name of the list item. - let name: String - - /// The accessibility ID for the list item name. - let nameAccessibilityID: String? - - /// Content that appears on the trailing edge of the list item. - let trailingContent: () -> Content? - - // MARK: View - - var body: some View { - Button { - action() - } label: { - VStack(spacing: 0) { - HStack { - Text(name) - .styleGuide(.body) - .accessibilityIdentifier(nameAccessibilityID ?? "") - .foregroundColor(Asset.Colors.textPrimary.swiftUIColor) - .multilineTextAlignment(.leading) - .padding(.vertical, 19) - - Spacer() - - trailingContent() - .styleGuide(.body) - .foregroundColor(Asset.Colors.textSecondary.swiftUIColor) - .multilineTextAlignment(.trailing) - } - .padding(.horizontal, 16) - - if hasDivider { - Divider() - .padding(.leading, 16) - } - } - } - .accessibilityIdentifier(accessibilityIdentifier ?? "") - .background(Asset.Colors.backgroundPrimary.swiftUIColor) - } - - // MARK: Initialization - - /// Initializes a new `SettingsListItem`. - /// - /// - Parameters: - /// - name: The name of the list item. - /// - hasDivider: Whether or not the list item should have a divider on the bottom. - /// - accessibilityIdentifier: The accessibility ID for the list item. - /// - nameAccessibilityID: The accessibility ID for the list item name. - /// - action: The action to perform when the list item is tapped. - /// - trailingContent: Content that appears on the trailing edge of the list item. - /// - /// - Returns: The list item. - /// - init( - _ name: String, - hasDivider: Bool = true, - accessibilityIdentifier: String? = nil, - nameAccessibilityID: String? = nil, - action: @escaping () -> Void, - @ViewBuilder trailingContent: @escaping () -> Content? = { EmptyView() }, - ) { - self.accessibilityIdentifier = accessibilityIdentifier - self.name = name - self.hasDivider = hasDivider - self.nameAccessibilityID = nameAccessibilityID - self.trailingContent = trailingContent - self.action = action - } -} - -// MARK: Previews - -#if DEBUG -#Preview { - ScrollView { - VStack(spacing: 0) { - SettingsListItem("Account Security") {} trailingContent: { - Text("Trailing content") - } - - SettingsListItem("Account Security") {} trailingContent: { - Image(asset: SharedAsset.Icons.externalLink16) - } - - SettingsListItem("Account Security") {} - } - } -} -#endif diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView.swift index 6a9a299bb..a39f7211d 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView.swift @@ -93,20 +93,21 @@ struct SettingsView: View { /// The language picker view private var language: some View { - VStack(alignment: .leading, spacing: 8) { - SettingsListItem( - Localizations.language, - hasDivider: false, + Button { + store.send(.languageTapped) + } label: { + BitwardenField( + title: Localizations.language, + footer: Localizations.languageChangeRequiresAppRestart, ) { - store.send(.languageTapped) - } trailingContent: { Text(store.state.currentLanguage.title) + .styleGuide(.body) + .foregroundColor(Color(asset: SharedAsset.Colors.textPrimary)) + .multilineTextAlignment(.leading) + } accessoryContent: { + SharedAsset.Icons.chevronDown24.swiftUIImage + .imageStyle(.rowIcon) } - .cornerRadius(10) - - Text(Localizations.languageChangeRequiresAppRestart) - .styleGuide(.subheadline) - .foregroundColor(Color(asset: Asset.Colors.textSecondary)) } } @@ -115,27 +116,24 @@ struct SettingsView: View { VStack(spacing: 0) { biometricsSetting - SectionView(Localizations.data, contentSpacing: 0) { - VStack(spacing: 0) { - SettingsListItem(Localizations.import) { - store.send(.importItemsTapped) - } - - SettingsListItem(Localizations.export) { - store.send(.exportItemsTapped) - } - - SettingsListItem(Localizations.backup) { - store.send(.backupTapped) - } - - syncWithPasswordManagerRow(hasDivider: store.state.shouldShowDefaultSaveOption) - - if store.state.shouldShowDefaultSaveOption { - defaultSaveOption - } + ContentBlock(dividerLeadingPadding: 16) { + SettingsListItem(Localizations.import) { + store.send(.importItemsTapped) + } + + SettingsListItem(Localizations.export) { + store.send(.exportItemsTapped) + } + + SettingsListItem(Localizations.backup) { + store.send(.backupTapped) + } + + syncWithPasswordManagerRow(hasDivider: store.state.shouldShowDefaultSaveOption) + + if store.state.shouldShowDefaultSaveOption { + defaultSaveOption } - .cornerRadius(10) } .padding(.bottom, 32) @@ -145,30 +143,24 @@ struct SettingsView: View { } .padding(.bottom, 32) - SectionView(Localizations.help, contentSpacing: 0) { - VStack(spacing: 0) { - SettingsListItem(Localizations.launchTutorial) { - store.send(.tutorialTapped) - } - - externalLinkRow(Localizations.bitwardenHelpCenter, action: .helpCenterTapped, hasDivider: false) + ContentBlock(dividerLeadingPadding: 16) { + SettingsListItem(Localizations.launchTutorial) { + store.send(.tutorialTapped) } - .cornerRadius(10) + + externalLinkRow(Localizations.bitwardenHelpCenter, action: .helpCenterTapped) } .padding(.bottom, 32) - SectionView(Localizations.about, contentSpacing: 0) { - VStack(spacing: 0) { - externalLinkRow(Localizations.privacyPolicy, action: .privacyPolicyTapped) + ContentBlock(dividerLeadingPadding: 16) { + externalLinkRow(Localizations.privacyPolicy, action: .privacyPolicyTapped) - SettingsListItem(store.state.version, hasDivider: false) { - store.send(.versionTapped) - } trailingContent: { - SharedAsset.Icons.copy16.swiftUIImage - .imageStyle(.rowIcon) - } + SettingsListItem(store.state.version) { + store.send(.versionTapped) + } trailingContent: { + SharedAsset.Icons.copy24.swiftUIImage + .imageStyle(.rowIcon) } - .cornerRadius(10) } .padding(.bottom, 16) @@ -193,23 +185,16 @@ struct SettingsView: View { /// The application's color theme picker view private var theme: some View { - VStack(alignment: .leading, spacing: 8) { - SettingsMenuField( - title: Localizations.theme, - options: AppTheme.allCases, - hasDivider: false, - selection: store.binding( - get: \.appTheme, - send: SettingsAction.appThemeChanged, - ), - ) - .cornerRadius(10) - .accessibilityIdentifier("ThemeChooser") - - Text(Localizations.themeDescription) - .styleGuide(.subheadline) - .foregroundColor(Color(asset: Asset.Colors.textSecondary)) - } + BitwardenMenuField( + title: Localizations.theme, + footer: Localizations.themeDescription, + accessibilityIdentifier: "ThemeChooser", + options: AppTheme.allCases, + selection: store.binding( + get: \.appTheme, + send: SettingsAction.appThemeChanged, + ), + ) } /// A toggle for the user's biometric unlock preference. @@ -245,15 +230,11 @@ struct SettingsView: View { /// - action: An action to send when the row is tapped. /// - Returns: A `SettingsListItem` configured for an external web link. /// - private func externalLinkRow( - _ name: String, - action: SettingsAction, - hasDivider: Bool = true, - ) -> some View { - SettingsListItem(name, hasDivider: hasDivider) { + private func externalLinkRow(_ name: String, action: SettingsAction) -> some View { + SettingsListItem(name) { store.send(action) } trailingContent: { - SharedAsset.Icons.externalLink16.swiftUIImage + SharedAsset.Icons.externalLink24.swiftUIImage .imageStyle(.rowIcon) } } diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift index 265710217..cc52586c5 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift @@ -40,7 +40,7 @@ class SettingsViewTests: BitwardenTestCase { @MainActor func test_appThemeChanged_updateValue() throws { processor.state.appTheme = .light - let menuField = try subject.inspect().find(settingsMenuField: Localizations.theme) + let menuField = try subject.inspect().find(bitwardenMenuField: Localizations.theme) try menuField.select(newValue: AppTheme.dark) XCTAssertEqual(processor.dispatchedActions.last, .appThemeChanged(.dark)) } diff --git a/BitwardenShared/UI/Platform/Application/Views/BitwardenBadge.swift b/BitwardenKit/UI/Platform/Application/Views/BitwardenBadge.swift similarity index 85% rename from BitwardenShared/UI/Platform/Application/Views/BitwardenBadge.swift rename to BitwardenKit/UI/Platform/Application/Views/BitwardenBadge.swift index 6869de79e..0ed47016b 100644 --- a/BitwardenShared/UI/Platform/Application/Views/BitwardenBadge.swift +++ b/BitwardenKit/UI/Platform/Application/Views/BitwardenBadge.swift @@ -5,7 +5,7 @@ import SwiftUI /// A view that displays some text surrounded by a circular background, similar to an iOS icon badge. /// -struct BitwardenBadge: View { +public struct BitwardenBadge: View { // MARK: Properties /// Padding applied between the text and the circular background. Scales with dynamic type) @@ -30,7 +30,7 @@ struct BitwardenBadge: View { // MARK: View - var body: some View { + public var body: some View { Text(badgeValue) .styleGuide(.callout, weight: .bold, includeLinePadding: false, includeLineSpacing: false) .foregroundStyle(SharedAsset.Colors.iconBadgeForeground.swiftUIColor) @@ -44,6 +44,16 @@ struct BitwardenBadge: View { .background(SharedAsset.Colors.iconBadgeBackground.swiftUIColor) .clipShape(Circle()) } + + // MARK: Initializers + + /// Public version of synthesized initializer. + /// + /// - Parameters: + /// - badgeValue: The value to display in the badge. + public init(badgeValue: String) { + self.badgeValue = badgeValue + } } // MARK: Previews diff --git a/BitwardenShared/UI/Platform/Application/Views/BitwardenField.swift b/BitwardenKit/UI/Platform/Application/Views/BitwardenField.swift similarity index 95% rename from BitwardenShared/UI/Platform/Application/Views/BitwardenField.swift rename to BitwardenKit/UI/Platform/Application/Views/BitwardenField.swift index 5aefed8d6..7af4edefc 100644 --- a/BitwardenShared/UI/Platform/Application/Views/BitwardenField.swift +++ b/BitwardenKit/UI/Platform/Application/Views/BitwardenField.swift @@ -5,7 +5,7 @@ import SwiftUI /// A standardized view used to wrap some content into a row of a list. This is commonly used in /// forms. -struct BitwardenField: View { +public struct BitwardenField: View { // MARK: Properties /// The (optional) title of the field. @@ -29,7 +29,7 @@ struct BitwardenField Content, @@ -139,7 +139,7 @@ struct BitwardenField: View { +public struct SettingsListItem: View { // MARK: Properties /// The accessibility ID for the list item. @@ -32,7 +31,7 @@ struct SettingsListItem: View { // MARK: View - var body: some View { + public var body: some View { Button { action() } label: { @@ -83,7 +82,7 @@ struct SettingsListItem: View { /// /// - Returns: The list item. /// - init( + public init( _ name: String, accessibilityIdentifier: String? = nil, badgeValue: String? = nil, diff --git a/BitwardenShared/UI/Platform/Application/Views/SettingsMenuField.swift b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuField.swift similarity index 97% rename from BitwardenShared/UI/Platform/Application/Views/SettingsMenuField.swift rename to BitwardenKit/UI/Platform/Application/Views/SettingsMenuField.swift index ca5f0180c..3d44a1fa9 100644 --- a/BitwardenShared/UI/Platform/Application/Views/SettingsMenuField.swift +++ b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuField.swift @@ -1,4 +1,3 @@ -import BitwardenKit import BitwardenResources import SwiftUI @@ -7,7 +6,7 @@ import SwiftUI /// A standard input field that allows the user to select between a predefined set of /// options. /// -struct SettingsMenuField: View where T: Menuable { +public struct SettingsMenuField: View where T: Menuable { // MARK: Properties /// The accessibility ID for the menu field. @@ -33,7 +32,7 @@ struct SettingsMenuField: View where T: Menuable { // MARK: View - var body: some View { + public var body: some View { VStack(spacing: 0) { Menu { Picker(selection: $selection) { @@ -92,7 +91,7 @@ struct SettingsMenuField: View where T: Menuable { /// - selectionAccessibilityID: The accessibility ID for the picker selection. /// - selection: A `Binding` for the currently selected option. /// - init( + public init( title: String, options: [T], hasDivider: Bool = true, diff --git a/BitwardenShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift similarity index 97% rename from BitwardenShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift rename to BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift index 1ee09a6ba..372af09ea 100644 --- a/BitwardenShared/UI/Platform/Application/Views/SettingsMenuFieldTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift @@ -3,8 +3,6 @@ import SwiftUI import ViewInspector import XCTest -@testable import BitwardenShared - class SettingsMenuFieldTests: BitwardenTestCase { // MARK: Types diff --git a/BitwardenShared/UI/Platform/Application/Views/SettingsPickerField.swift b/BitwardenKit/UI/Platform/Application/Views/SettingsPickerField.swift similarity index 97% rename from BitwardenShared/UI/Platform/Application/Views/SettingsPickerField.swift rename to BitwardenKit/UI/Platform/Application/Views/SettingsPickerField.swift index d543db40b..432ac2a29 100644 --- a/BitwardenShared/UI/Platform/Application/Views/SettingsPickerField.swift +++ b/BitwardenKit/UI/Platform/Application/Views/SettingsPickerField.swift @@ -5,7 +5,7 @@ import SwiftUI /// A field that displays a `CountdownDatePicker` when interacted with. /// -struct SettingsPickerField: View { +public struct SettingsPickerField: View { // MARK: Properties /// The accessibility label used for the custom timeout value. @@ -28,7 +28,7 @@ struct SettingsPickerField: View { // MARK: View - var body: some View { + public var body: some View { VStack(spacing: 0) { Button { withAnimation { @@ -83,7 +83,7 @@ struct SettingsPickerField: View { /// - hasDivider: Whether or not the field has a bottom edge divider. /// - customTimeoutAccessibilityLabel: The accessibility label used for the custom timeout value. /// - init( + public init( title: String, customTimeoutValue: String, pickerValue: Binding, diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift index 490cdc998..d2dc4b959 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift @@ -1,3 +1,4 @@ +import BitwardenKit import BitwardenResources import SnapshotTesting import ViewInspector diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift index 161a3a80e..bdcfa408d 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift @@ -1,3 +1,4 @@ +import BitwardenKit import BitwardenResources import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView.swift index 5ee815439..06d755ae3 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView.swift @@ -1,3 +1,4 @@ +import BitwardenKit import BitwardenResources import SwiftUI diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift index 14d9e3886..e36a6af21 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift @@ -1,3 +1,4 @@ +import BitwardenKit import BitwardenResources import SnapshotTesting import XCTest diff --git a/GlobalTestHelpers-bwa/Extensions/InspectableView.swift b/GlobalTestHelpers-bwa/Extensions/InspectableView.swift index 0f1d07741..3099aa91a 100644 --- a/GlobalTestHelpers-bwa/Extensions/InspectableView.swift +++ b/GlobalTestHelpers-bwa/Extensions/InspectableView.swift @@ -54,7 +54,7 @@ struct SettingsMenuFieldType: BaseViewType { static var typePrefix: String = "SettingsMenuField" static var namespacedPrefixes: [String] = [ - "AuthenticatorShared.SettingsMenuField", + "BitwardenKit.SettingsMenuField", ] }