generated from bitwarden/template
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PM-11147: Add import logins view (#1019)
- Loading branch information
1 parent
317cb91
commit 621d901
Showing
19 changed files
with
450 additions
and
2 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
...ared/UI/Platform/Application/Support/Images.xcassets/Images/import.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "import.pdf", | ||
"idiom" : "universal" | ||
}, | ||
{ | ||
"appearances" : [ | ||
{ | ||
"appearance" : "luminosity", | ||
"value" : "dark" | ||
} | ||
], | ||
"filename" : "import-dark.pdf", | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
}, | ||
"properties" : { | ||
"preserves-vector-representation" : true | ||
} | ||
} |
Binary file added
BIN
+2.67 KB
...ed/UI/Platform/Application/Support/Images.xcassets/Images/import.imageset/import-dark.pdf
Binary file not shown.
Binary file added
BIN
+2.65 KB
...nShared/UI/Platform/Application/Support/Images.xcassets/Images/import.imageset/import.pdf
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsAction.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// MARK: - ImportLoginsAction | ||
|
||
/// Actions that can be processed by a `ImportLoginsProcessor`. | ||
/// | ||
enum ImportLoginsAction: Equatable { | ||
/// Dismiss the view. | ||
case dismiss | ||
|
||
/// The get started button was tapped. | ||
case getStarted | ||
} |
8 changes: 8 additions & 0 deletions
8
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsEffect.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// MARK: - ImportLoginsEffect | ||
|
||
/// Effects handled by the `ImportLoginsProcessor`. | ||
/// | ||
enum ImportLoginsEffect: Equatable { | ||
/// The import logins button was tapped. | ||
case importLoginsLater | ||
} |
78 changes: 78 additions & 0 deletions
78
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsProcessor.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// MARK: - ImportLoginsProcessor | ||
|
||
/// The processor used to manage state and handle actions for the import logins screen. | ||
/// | ||
class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsAction, ImportLoginsEffect> { | ||
// MARK: Types | ||
|
||
typealias Services = HasErrorReporter | ||
& HasStateService | ||
|
||
// MARK: Private Properties | ||
|
||
/// The coordinator that handles navigation. | ||
private let coordinator: AnyCoordinator<VaultRoute, AuthAction> | ||
|
||
/// The services used by this processor. | ||
private let services: Services | ||
|
||
// MARK: Initialization | ||
|
||
/// Creates a new `ImportLoginsProcessor`. | ||
/// | ||
/// - Parameters: | ||
/// - coordinator: The coordinator that handles navigation. | ||
/// - services: The services required by this processor. | ||
/// - state: The initial state of the processor. | ||
/// | ||
init( | ||
coordinator: AnyCoordinator<VaultRoute, AuthAction>, | ||
services: Services, | ||
state: ImportLoginsState | ||
) { | ||
self.coordinator = coordinator | ||
self.services = services | ||
super.init(state: state) | ||
} | ||
|
||
// MARK: Methods | ||
|
||
override func perform(_ effect: ImportLoginsEffect) async { | ||
switch effect { | ||
case .importLoginsLater: | ||
showImportLoginsLaterAlert() | ||
} | ||
} | ||
|
||
override func receive(_ action: ImportLoginsAction) { | ||
switch action { | ||
case .dismiss: | ||
coordinator.navigate(to: .dismiss) | ||
case .getStarted: | ||
showGetStartAlert() | ||
} | ||
} | ||
|
||
// MARK: Private | ||
|
||
/// Shows the alert confirming the user wants to get started on importing logins. | ||
/// | ||
private func showGetStartAlert() { | ||
coordinator.showAlert(.importLoginsComputerAvailable { | ||
// TODO: PM-11150 Show step 1 | ||
}) | ||
} | ||
|
||
/// Shows the alert confirming the user wants to import logins later. | ||
/// | ||
private func showImportLoginsLaterAlert() { | ||
coordinator.showAlert(.importLoginsLater { | ||
do { | ||
try await self.services.stateService.setAccountSetupImportLogins(.setUpLater) | ||
} catch { | ||
self.services.errorReporter.log(error: error) | ||
} | ||
self.coordinator.navigate(to: .dismiss) | ||
}) | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsProcessorTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import XCTest | ||
|
||
@testable import BitwardenShared | ||
|
||
class ImportLoginsProcessorTests: BitwardenTestCase { | ||
// MARK: Properties | ||
|
||
var coordinator: MockCoordinator<VaultRoute, AuthAction>! | ||
var errorReporter: MockErrorReporter! | ||
var stateService: MockStateService! | ||
var subject: ImportLoginsProcessor! | ||
|
||
// MARK: Setup & Teardown | ||
|
||
override func setUp() { | ||
super.setUp() | ||
|
||
coordinator = MockCoordinator() | ||
errorReporter = MockErrorReporter() | ||
stateService = MockStateService() | ||
|
||
subject = ImportLoginsProcessor( | ||
coordinator: coordinator.asAnyCoordinator(), | ||
services: ServiceContainer.withMocks( | ||
errorReporter: errorReporter, | ||
stateService: stateService | ||
), | ||
state: ImportLoginsState() | ||
) | ||
} | ||
|
||
override func tearDown() { | ||
super.tearDown() | ||
|
||
coordinator = nil | ||
errorReporter = nil | ||
stateService = nil | ||
subject = nil | ||
} | ||
|
||
// MARK: Tests | ||
|
||
/// `perform(_:)` with `.importLoginsLater` shows an alert for confirming the user wants to | ||
/// import logins later. | ||
@MainActor | ||
func test_perform_importLoginsLater() async throws { | ||
stateService.activeAccount = .fixture() | ||
stateService.accountSetupImportLogins["1"] = .incomplete | ||
|
||
await subject.perform(.importLoginsLater) | ||
|
||
let alert = try XCTUnwrap(coordinator.alertShown.last) | ||
XCTAssertEqual(alert, .importLoginsLater {}) | ||
try await alert.tapAction(title: Localizations.confirm) | ||
|
||
XCTAssertEqual(coordinator.routes, [.dismiss]) | ||
XCTAssertEqual(stateService.accountSetupImportLogins["1"], .setUpLater) | ||
} | ||
|
||
/// `perform(_:)` with `.importLoginsLater` logs an error if one occurs. | ||
@MainActor | ||
func test_perform_importLoginsLater_error() async throws { | ||
await subject.perform(.importLoginsLater) | ||
|
||
let alert = try XCTUnwrap(coordinator.alertShown.last) | ||
XCTAssertEqual(alert, .importLoginsLater {}) | ||
try await alert.tapAction(title: Localizations.confirm) | ||
|
||
XCTAssertEqual(coordinator.routes, [.dismiss]) | ||
XCTAssertEqual(errorReporter.errors as? [StateServiceError], [.noActiveAccount]) | ||
} | ||
|
||
/// `receive(_:)` with `.dismiss` dismisses the view. | ||
@MainActor | ||
func test_receive_dismiss() { | ||
subject.receive(.dismiss) | ||
XCTAssertEqual(coordinator.routes.last, .dismiss) | ||
} | ||
|
||
/// `receive(_:)` with `.getStarted` shows an alert for the user to confirm they have a | ||
/// computer available. | ||
@MainActor | ||
func test_receive_getStarted() throws { | ||
subject.receive(.getStarted) | ||
|
||
let alert = try XCTUnwrap(coordinator.alertShown.last) | ||
XCTAssertEqual(alert, .importLoginsComputerAvailable {}) | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsState.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// MARK: - ImportLoginsState | ||
|
||
/// An object that defines the current state of a `ImportLoginsView`. | ||
/// | ||
struct ImportLoginsState: Equatable, Sendable { | ||
// MARK: Properties | ||
} |
54 changes: 54 additions & 0 deletions
54
BitwardenShared/UI/Vault/Vault/ImportLogins/ImportLoginsView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import SwiftUI | ||
|
||
// MARK: - ImportLoginsView | ||
|
||
/// A view that instructs the user how to import their logins from another password manager. | ||
/// | ||
struct ImportLoginsView: View { | ||
// MARK: Properties | ||
|
||
/// The `Store` for this view. | ||
@ObservedObject var store: Store<ImportLoginsState, ImportLoginsAction, ImportLoginsEffect> | ||
|
||
// MARK: View | ||
|
||
var body: some View { | ||
VStack(spacing: 32) { | ||
PageHeaderView( | ||
image: Asset.Images.import, | ||
title: Localizations.giveYourVaultAHeadStart, | ||
message: Localizations.importLoginsDescriptionLong | ||
) | ||
|
||
VStack(spacing: 12) { | ||
Button(Localizations.getStarted) { | ||
store.send(.getStarted) | ||
} | ||
.buttonStyle(.primary()) | ||
|
||
AsyncButton(Localizations.importLoginsLater) { | ||
await store.perform(.importLoginsLater) | ||
} | ||
.buttonStyle(.transparent) | ||
} | ||
} | ||
.padding(.top, 8) | ||
.frame(maxWidth: .infinity) | ||
.scrollView() | ||
.navigationBar(title: Localizations.importLogins, titleDisplayMode: .inline) | ||
.toolbar { | ||
cancelToolbarItem { | ||
store.send(.dismiss) | ||
} | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Previews | ||
|
||
#if DEBUG | ||
#Preview { | ||
ImportLoginsView(store: Store(processor: StateProcessor(state: ImportLoginsState()))) | ||
.navStackWrapped | ||
} | ||
#endif |
Oops, something went wrong.