Skip to content

Commit

Permalink
sync connect (#1062)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/0/1204266236802307/f
Tech Design URL:
CC:

**Description**:

Add sync connect flow.

**Steps to test this PR**:
See duckduckgo/BrowserServicesKit#281 for
details.

<!--
Tagging instructions
If this PR isn't ready to be merged for whatever reason it should be
marked with the `DO NOT MERGE` label (particularly if it's a draft)
If it's pending Product Review/PFR, please add the `Pending Product
Review` label.

If at any point it isn't actively being worked on/ready for
review/otherwise moving forward (besides the above PR/PFR exception)
strongly consider closing it (or not opening it in the first place). If
you decide not to close it, make sure it's labelled to make it clear the
PRs state and comment with more information.
-->

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
**When ready for review, remember to post the PR in MM**
  • Loading branch information
brindy authored Mar 31, 2023
1 parent 7d92092 commit f2dfe00
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 20 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8615,7 +8615,7 @@
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 53.2.1;
version = 54.0.0;
};
};
AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "aa5b5ff4b76e7f1334b66118c414d774e3eb677b",
"version" : "53.2.1"
"revision" : "0f0e20970a54c0fb570734111f0f15c3de4b4de8",
"version" : "54.0.0"
}
},
{
Expand Down Expand Up @@ -113,8 +113,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/sync_crypto",
"state" : {
"revision" : "df751674ee842d129c50a183668b033d02c2980d",
"version" : "0.0.1"
"revision" : "2ab6ab6f0f96b259c14c2de3fc948935fc16ac78",
"version" : "0.2.0"
}
},
{
Expand Down
44 changes: 37 additions & 7 deletions DuckDuckGo/Preferences/Model/SyncPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ final class SyncPreferences: ObservableObject, SyncUI.ManagementViewModel {
}

onEndFlow = {
self.connector?.stopPolling()
self.connector = nil

guard let window = syncWindowController.window, let sheetParent = window.sheetParent else {
assertionFailure("window or sheet parent not present")
return
Expand All @@ -144,19 +147,32 @@ final class SyncPreferences: ObservableObject, SyncUI.ManagementViewModel {

private let syncService: DDGSyncing
private var cancellables = Set<AnyCancellable>()
private var connector: RemoteConnecting?
}

extension SyncPreferences: ManagementDialogModelDelegate {

private func deviceInfo() -> (name: String, type: String) {
let hostname = SCDynamicStoreCopyComputerName(nil, nil) as? String ?? ProcessInfo.processInfo.hostName
return (name: hostname, type: "desktop")
}

@MainActor
private func login(_ recoveryKey: SyncCode.RecoveryKey) async throws {
let device = deviceInfo()
try await syncService.login(recoveryKey, deviceName: device.name, deviceType: device.type)
managementDialogModel.endFlow()
}

func turnOnSync() {
presentDialog(for: .askToSyncAnotherDevice)
}

func dontSyncAnotherDeviceNow() {
Task { @MainActor in
do {
let hostname = SCDynamicStoreCopyComputerName(nil, nil) as? String ?? ProcessInfo.processInfo.hostName
try await syncService.createAccount(deviceName: hostname, deviceType: "desktop")
let device = deviceInfo()
try await syncService.createAccount(deviceName: device.name, deviceType: device.type)
} catch {
managementDialogModel.errorMessage = String(describing: error)
}
Expand All @@ -171,20 +187,33 @@ extension SyncPreferences: ManagementDialogModelDelegate {
return
}

let hostname = SCDynamicStoreCopyComputerName(nil, nil) as? String ?? ProcessInfo.processInfo.hostName
try await syncService.login(recoveryKey, deviceName: hostname, deviceType: "desktop")
managementDialogModel.endFlow()
try await login(recoveryKey)
} catch {
managementDialogModel.errorMessage = String(describing: error)
}
}
}

func presentSyncAnotherDeviceDialog() {
presentDialog(for: .syncAnotherDevice)
Task { @MainActor in
do {
self.connector = try syncService.remoteConnect()
managementDialogModel.connectCode = connector?.code
presentDialog(for: .syncAnotherDevice)
if let recoveryKey = try await connector?.pollForRecoveryKey() {
try await login(recoveryKey)
} else {
// Polling was likeley cancelled elsewhere (e.g. dialog closed)
return
}
managementDialogModel.endFlow()
} catch {
managementDialogModel.errorMessage = String(describing: error)
}
}
}

func addAnotherDevice(using recoveryCode: String) {
func addAnotherDevice() {
presentDialog(for: .deviceSynced)
}

Expand All @@ -195,4 +224,5 @@ extension SyncPreferences: ManagementDialogModelDelegate {
func saveRecoveryPDF() {
managementDialogModel.endFlow()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public protocol ManagementDialogModelDelegate: AnyObject {
func dontSyncAnotherDeviceNow()
func recoverDevice(using recoveryCode: String)
func presentSyncAnotherDeviceDialog()
func addAnotherDevice(using recoveryCode: String)
func addAnotherDevice()
func confirmSetupComplete()
func saveRecoveryPDF()
}
Expand All @@ -33,6 +33,7 @@ public final class ManagementDialogModel: ObservableObject {

@Published public var currentDialog: ManagementDialogKind?
public var recoveryCode: String?
public var connectCode: String?

@Published public var shouldShowErrorMessage: Bool = false
@Published public var errorMessage: String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ final public class RecoveryCodeViewModel: ObservableObject {
}
}

public func setCode(_ newCode: String) {
if CharacterSet.base64.isSuperset(of: CharacterSet(charactersIn: newCode)) {
recoveryCode = newCode
func setCode(_ code: String) {
if CharacterSet.base64.isSuperset(of: CharacterSet(charactersIn: code)) {
recoveryCode = code
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct SyncAnotherDeviceView: View {
model.endFlow()
}
Button(UserText.submit) {
model.delegate?.addAnotherDevice(using: recoveryCodeModel.recoveryCode)
model.delegate?.addAnotherDevice()
}
.buttonStyle(DefaultActionButtonStyle(enabled: !recoveryCodeModel.shouldDisableSubmitButton))
.disabled(recoveryCodeModel.shouldDisableSubmitButton)
Expand All @@ -81,18 +81,18 @@ private struct ShowCodeView: View {
.multilineTextAlignment(.center)

HStack(alignment: .top, spacing: 20) {
QRCode(string: model.recoveryCode ?? "", size: .init(width: 164, height: 164))
QRCode(string: model.connectCode ?? "", size: .init(width: 164, height: 164))

VStack {
SyncKeyView(text: model.recoveryCode ?? "")
SyncKeyView(text: model.connectCode ?? "")

Spacer()

HStack {
Spacer()
Button {
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(model.recoveryCode ?? "", forType: .string)
NSPasteboard.general.setString(model.connectCode ?? "", forType: .string)
} label: {
HStack {
Image("Copy")
Expand Down

0 comments on commit f2dfe00

Please sign in to comment.