From 9959f6db49b3ed615d15337d28dbac374d110d51 Mon Sep 17 00:00:00 2001 From: Bruno Muniz Azevedo Filho <bruno@elixxir.io> Date: Thu, 22 Sep 2022 14:31:19 -0300 Subject: [PATCH] Continued w/ migration --- App/client-ios.xcodeproj/project.pbxproj | 8 +- App/client-ios/Resources/Info.plist | 2 +- Package.swift | 3 +- .../BackupFeature/Service/BackupService.swift | 61 +++- .../ViewModels/BackupConfigViewModel.swift | 19 +- .../ViewModels/SingleChatViewModel.swift | 50 ++- .../ViewModels/ContactViewModel.swift | 42 ++- .../Controllers/CreateGroupController.swift | 3 +- Sources/LaunchFeature/LaunchViewModel.swift | 301 ++++++++++-------- Sources/Models/Backup.swift | 2 +- Sources/Models/BackupSettings.swift | 8 +- .../ViewModels/ProfileCodeViewModel.swift | 4 + .../ViewModels/RequestsFailedViewModel.swift | 23 +- .../ViewModels/RequestsSentViewModel.swift | 22 +- .../ViewModels/RestoreListViewModel.swift | 6 +- .../ViewModels/RestoreViewModel.swift | 163 +--------- .../RestoreFeature/Views/RestoreView.swift | 2 +- .../ActionHandlers/SFTPUploader.swift | 2 +- .../ViewModels/SearchLeftViewModel.swift | 38 ++- Sources/iCloudFeature/iCloudService.swift | 5 +- 20 files changed, 427 insertions(+), 337 deletions(-) diff --git a/App/client-ios.xcodeproj/project.pbxproj b/App/client-ios.xcodeproj/project.pbxproj index dfd5b05c..7985bef1 100644 --- a/App/client-ios.xcodeproj/project.pbxproj +++ b/App/client-ios.xcodeproj/project.pbxproj @@ -448,7 +448,7 @@ CODE_SIGN_ENTITLEMENTS = "client-ios/Resources/client-ios.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 251; + CURRENT_PROJECT_VERSION = 256; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = S6JDM2WW29; ENABLE_BITCODE = NO; @@ -487,7 +487,7 @@ CODE_SIGN_ENTITLEMENTS = "client-ios/Resources/client-ios.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 251; + CURRENT_PROJECT_VERSION = 256; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = S6JDM2WW29; ENABLE_BITCODE = NO; @@ -522,7 +522,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 251; + CURRENT_PROJECT_VERSION = 256; DEVELOPMENT_TEAM = S6JDM2WW29; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -553,7 +553,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 251; + CURRENT_PROJECT_VERSION = 256; DEVELOPMENT_TEAM = S6JDM2WW29; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/App/client-ios/Resources/Info.plist b/App/client-ios/Resources/Info.plist index ee4d813d..d8cb845b 100644 --- a/App/client-ios/Resources/Info.plist +++ b/App/client-ios/Resources/Info.plist @@ -105,6 +105,6 @@ <key>UIViewControllerBasedStatusBarAppearance</key> <true/> <key>isReportingOptional</key> - <true/> + <false/> </dict> </plist> diff --git a/Package.swift b/Package.swift index 9f965571..c00b4df2 100644 --- a/Package.swift +++ b/Package.swift @@ -117,7 +117,7 @@ let package = Package( .package( path: "../elixxir-dapps-sdk-swift" // url: "https://git.xx.network/elixxir/elixxir-dapps-sdk-swift", -// branch: "development" +// branch: "feature/messenger-restore-from-backup" ), .package( url: "https://git.xx.network/elixxir/client-ios-db.git", @@ -554,6 +554,7 @@ let package = Package( .target(name: "Permissions"), .target(name: "Presentation"), .target(name: "DrawerFeature"), + .target(name: "BackupFeature"), .target(name: "DependencyInjection"), .product(name: "CombineSchedulers", package: "combine-schedulers"), .product(name: "ScrollViewController", package: "ScrollViewController"), diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift index 626adba5..f0fcaf7e 100644 --- a/Sources/BackupFeature/Service/BackupService.swift +++ b/Sources/BackupFeature/Service/BackupService.swift @@ -9,18 +9,25 @@ import DropboxFeature import NetworkMonitor import GoogleDriveFeature import DependencyInjection +import XXClient +import XXMessengerClient public final class BackupService { - @Dependency private var sftpService: SFTPService - @Dependency private var icloudService: iCloudInterface - @Dependency private var dropboxService: DropboxInterface - @Dependency private var networkManager: NetworkMonitoring - @Dependency private var keychainHandler: KeychainHandling - @Dependency private var driveService: GoogleDriveInterface + @Dependency var messenger: Messenger + @Dependency var sftpService: SFTPService + @Dependency var icloudService: iCloudInterface + @Dependency var dropboxService: DropboxInterface + @Dependency var networkManager: NetworkMonitoring + @Dependency var keychainHandler: KeychainHandling + @Dependency var driveService: GoogleDriveInterface - @KeyObject(.backupSettings, defaultValue: Data()) private var storedSettings: Data + @KeyObject(.email, defaultValue: nil) var email: String? + @KeyObject(.phone, defaultValue: nil) var phone: String? + @KeyObject(.username, defaultValue: nil) var username: String? + + var manager: XXClient.Backup? - public var passphrase: String? + @KeyObject(.backupSettings, defaultValue: Data()) private var storedSettings: Data public var settingsPublisher: AnyPublisher<BackupSettings, Never> { settings.handleEvents(receiveSubscription: { [weak self] _ in @@ -56,6 +63,36 @@ public final class BackupService { } extension BackupService { + public func initializeBackup(passphrase: String) { + manager = try! InitializeBackup.live( + e2eId: messenger.e2e.get()!.getId(), + udId: messenger.ud.get()!.getId(), + password: passphrase, + callback: .init(handle: { [weak self] backupData in + self?.updateBackup(data: backupData) + }) + ) + + didUpdateFacts() + } + + public func didUpdateFacts() { + if let manager = manager { + let currentFacts = try! JSONEncoder().encode( + BackupParams( + username: username!, + email: email, + phone: phone + ) + ) + + manager.addJSON(String(data: currentFacts, encoding: .utf8)!) + } + + guard settings.value.automaticBackups == true else { return } + performBackup() + } + public func performBackupIfAutomaticIsEnabled() { guard settings.value.automaticBackups == true else { return } performBackup() @@ -207,7 +244,7 @@ extension BackupService { return } - settings.value.backups[.icloud] = Backup( + settings.value.backups[.icloud] = BackupModel( id: metadata.path, date: metadata.modifiedDate, size: metadata.size @@ -224,7 +261,7 @@ extension BackupService { return } - settings.value.backups[.sftp] = Backup( + settings.value.backups[.sftp] = BackupModel( id: metadata.id, date: metadata.date, size: metadata.size @@ -241,7 +278,7 @@ extension BackupService { return } - settings.value.backups[.dropbox] = Backup( + settings.value.backups[.dropbox] = BackupModel( id: metadata.path, date: metadata.modifiedDate, size: metadata.size @@ -256,7 +293,7 @@ extension BackupService { self.driveService.downloadMetadata { guard let metadata = try? $0.get() else { return } - settings.value.backups[.drive] = Backup( + settings.value.backups[.drive] = BackupModel( id: metadata.identifier, date: metadata.modifiedDate, size: metadata.size diff --git a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift index 0731bc4a..757f3046 100644 --- a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift +++ b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift @@ -1,10 +1,13 @@ +import HUD import UIKit import Models import Shared import Combine +import XXClient +import Defaults import Foundation + import DependencyInjection -import HUD enum BackupActionState { case backupFinished @@ -21,7 +24,7 @@ struct BackupConfigViewModel { var wifiOnly: () -> AnyPublisher<Bool, Never> var automatic: () -> AnyPublisher<Bool, Never> - var lastBackup: () -> AnyPublisher<Backup?, Never> + var lastBackup: () -> AnyPublisher<BackupModel?, Never> var actionState: () -> AnyPublisher<BackupActionState, Never> var enabledService: () -> AnyPublisher<CloudService?, Never> var connectedServices: () -> AnyPublisher<Set<CloudService>, Never> @@ -49,17 +52,25 @@ extension BackupConfigViewModel { didChooseAutomatic: context.service.setBackupAutomatically(_:), didToggleService: { controller, service, enabling in guard enabling == true else { - context.service.toggle(service: service, enabling: enabling) + context.service.toggle(service: service, enabling: false) + if let manager = context.service.manager { + if manager.isRunning() { + try! manager.stop() + } + + context.service.manager = nil + } + return } context.coordinator.toPassphrase(from: controller, cancelClosure: { context.service.toggle(service: service, enabling: false) }, passphraseClosure: { passphrase in - context.service.passphrase = passphrase context.hud.update(with: .onTitle("Initializing and securing your backup file will take few seconds, please keep the app open.")) DispatchQueue.global().async { context.service.toggle(service: service, enabling: enabling) + context.service.initializeBackup(passphrase: passphrase) DispatchQueue.main.async { context.hud.update(with: .none) diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift index 78df0880..0b348894 100644 --- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift +++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift @@ -172,17 +172,16 @@ final class SingleChatViewModel: NSObject { } func didSend(image: UIImage) { - guard let imageData = image.orientedUp().jpegData(compressionQuality: 1.0) else { - return - } - + guard let imageData = image.orientedUp().jpegData(compressionQuality: 1.0) else { return } hudRelay.send(.on) + let transferName = UUID().uuidString + do { - let _ = try transferManager.send( + let tid = try transferManager.send( params: .init( payload: .init( - name: "abc", + name: transferName, type: "jpeg", preview: Data(), contents: imageData @@ -194,13 +193,48 @@ final class SingleChatViewModel: NSObject { callback: .init(handle: { switch $0 { case .success(let progressCallback): - print(progressCallback.progress.total) + + if progressCallback.progress.completed { + print(">>> Outgoing transfer finished successfully") + } else { + print(">>> Outgoing transfer. (\(progressCallback.progress.transmitted)/\(progressCallback.progress.total))") + } + + /// THIS IS TOO COMPLEX, NEEDS HELP FROM DARIUSZ + case .failure(let error): - print(error.localizedDescription) + print(">>> Transfer.error: \(error.localizedDescription)") } }) ) + let transferModel = FileTransfer( + id: tid, + contactId: contact.id, + name: transferName, + type: "jpeg", + data: imageData, + progress: 0.0, + isIncoming: false, + createdAt: Date() + ) + + let transferMessage = Message( + senderId: myId, + recipientId: contact.id, + groupId: nil, + date: Date(), + status: .sending, + isUnread: false, + text: "", + replyMessageId: nil, + roundURL: nil, + fileTransferId: tid + ) + + try database.saveFileTransfer(transferModel) + try database.saveMessage(transferMessage) + hudRelay.send(.none) } catch { hudRelay.send(.error(.init(with: error))) diff --git a/Sources/ContactFeature/ViewModels/ContactViewModel.swift b/Sources/ContactFeature/ViewModels/ContactViewModel.swift index c14131fe..5e4b3d71 100644 --- a/Sources/ContactFeature/ViewModels/ContactViewModel.swift +++ b/Sources/ContactFeature/ViewModels/ContactViewModel.swift @@ -25,6 +25,8 @@ final class ContactViewModel { @Dependency var getFactsFromContact: GetFactsFromContact @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool + @KeyObject(.sharingPhone, defaultValue: false) var sharingPhone: Bool var contact: XXModels.Contact @@ -111,12 +113,24 @@ final class ContactViewModel { do { try self.database.saveContact(self.contact) - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( - partner: XXClient.Contact.live(self.contact.marshaled!), - myFacts: myFacts + partner: .live(self.contact.marshaled!), + myFacts: includedFacts ) self.contact.authStatus = .requested @@ -143,12 +157,24 @@ final class ContactViewModel { do { try self.database.saveContact(self.contact) - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( - partner: XXClient.Contact.live(self.contact.marshaled!), - myFacts: myFacts + partner: .live(self.contact.marshaled!), + myFacts: includedFacts ) self.contact.authStatus = .requested diff --git a/Sources/ContactListFeature/Controllers/CreateGroupController.swift b/Sources/ContactListFeature/Controllers/CreateGroupController.swift index cde81579..bc4efdef 100644 --- a/Sources/ContactListFeature/Controllers/CreateGroupController.swift +++ b/Sources/ContactListFeature/Controllers/CreateGroupController.swift @@ -32,10 +32,11 @@ public final class CreateGroupController: UIViewController { attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color) attString.addAttributes(attributes: [ .foregroundColor: Asset.neutralDisabled.color, - .font: Fonts.Mulish.regular.font(size: 15.0) as Any + .font: Fonts.Mulish.regular.font(size: 14.0) as Any ], betweenCharacters: "#") titleLabel.attributedText = attString + titleLabel.sizeToFit() } } diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift index d1ebfb8c..ad65cc9e 100644 --- a/Sources/LaunchFeature/LaunchViewModel.swift +++ b/Sources/LaunchFeature/LaunchViewModel.swift @@ -60,6 +60,7 @@ final class LaunchViewModel { var authCallbacksCancellable: Cancellable? var networkCallbacksCancellable: Cancellable? + var messageListenerCallbacksCancellable: Cancellable? var routePublisher: AnyPublisher<LaunchRoute, Never> { routeSubject.eraseToAnyPublisher() @@ -106,46 +107,13 @@ final class LaunchViewModel { do { try self.setupDatabase() - _ = try SetLogLevel.live(.fatal) - - RegisterLogWriter.live(.init(handle: { - XXLogger.live().debug($0) - })) - - var environment: MessengerEnvironment = .live() - environment.ndfEnvironment = .mainnet - environment.udAddress = "46.101.98.49:18001" - environment.udCert = """ - -----BEGIN CERTIFICATE----- - MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV - BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx - GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp - cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT - MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV - BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw - DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh - Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs - WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE - tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA - m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9 - bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA - AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA - neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf - U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2 - qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4 - cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R - tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5 - 6m52PyzMNV+2N21IPppKwA== - -----END CERTIFICATE----- - """.data(using: .utf8)! - environment.udContact = """ - <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc> - """.data(using: .utf8) - - let messenger = Messenger.live(environment) - + let messenger = makeMessenger() DependencyInjection.Container.shared.register(messenger) + setupLogWriter() + setupAuthCallback(messenger) + setupMessageCallback(messenger) + if messenger.isLoaded() == false { if messenger.isCreated() == false { try messenger.create() @@ -156,99 +124,32 @@ final class LaunchViewModel { try messenger.start() - authCallbacksCancellable = messenger.registerAuthCallbacks( - AuthCallbacks(handle: { - switch $0 { - case .confirm(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): - self.handleConfirm(from: contact) - case .request(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): - self.handleDirectRequest(from: contact) - case .reset(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): - self.handleReset(from: contact) - } - }) - ) - if messenger.isConnected() == false { try messenger.connect() + try messenger.listenForMessages() } - try messenger.e2e.get()?.registerListener( - senderId: nil, - messageType: 2, - callback: .init(handle: { - guard let payload = try? Payload(with: $0.payload) else { - fatalError("Couldn't decode payload: \(String(data: $0.payload, encoding: .utf8) ?? "nil")") - } - - try! self.database.saveMessage(.init( - networkId: $0.id, - senderId: $0.sender, - recipientId: messenger.e2e.get()!.getContact().getId(), - groupId: nil, - date: Date.fromTimestamp($0.timestamp), - status: .received, - isUnread: true, - text: payload.text, - replyMessageId: payload.reply?.messageId, - roundURL: $0.roundURL, - fileTransferId: nil - )) - - if var contact = try? self.database.fetchContacts(.init(id: [$0.sender])).first { - contact.isRecent = false - try! self.database.saveContact(contact) - } - }) - ) - - try generateGroupManager(messenger: messenger) - try generateTrafficManager(messenger: messenger) - try generateTransferManager(messenger: messenger) - - networkMonitor.start() - - networkCallbacksCancellable = messenger.cMix.get()!.addHealthCallback(.init(handle: { [weak self] in - guard let self = self else { return } - self.networkMonitor.update($0) - })) + try generateGroupManager(messenger) + try generateTrafficManager(messenger) + try generateTransferManager(messenger) + listenToNetworkUpdates(messenger) if messenger.isLoggedIn() == false { - if try messenger.isRegistered() == false { + if try messenger.isRegistered() { + try messenger.logIn() hudSubject.send(.none) - routeSubject.send(.onboarding) + routeSubject.send(.chats) } else { hudSubject.send(.none) - checkBiometrics { [weak self] bioResult in - - switch bioResult { - case .success(let granted): - if granted { - try! messenger.logIn() - self?.routeSubject.send(.chats) - } else { - // WHAT SHOULD HAPPEN HERE? - } - case .failure(let error): - print(">>> Bio auth failed: \(error.localizedDescription)") - } - } + routeSubject.send(.onboarding) } } else { hudSubject.send(.none) - checkBiometrics { [weak self] bioResult in - switch bioResult { - case .success(let granted): - if granted { - self?.routeSubject.send(.chats) - } else { - // WHAT SHOULD HAPPEN HERE? - } - case .failure(let error): - print(">>> Bio auth failed: \(error.localizedDescription)") - } - } + routeSubject.send(.chats) } + + // TODO: Biometric auth + } catch { let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription) hudSubject.send(.error(.init(content: xxError))) @@ -470,7 +371,7 @@ final class LaunchViewModel { } extension LaunchViewModel { - private func generateGroupManager(messenger: Messenger) throws { + private func generateGroupManager(_ messenger: Messenger) throws { let manager = try NewGroupChat.live( e2eId: messenger.e2e()!.getId(), groupRequest: .init(handle: { [weak self] group in @@ -527,13 +428,15 @@ extension LaunchViewModel { DependencyInjection.Container.shared.register(manager) } - private func generateTransferManager(messenger: Messenger) throws { + private func generateTransferManager(_ messenger: Messenger) throws { let manager = try InitFileTransfer.live( e2eId: messenger.e2e()!.getId(), - callback: .init(handle: { + callback: .init(handle: { [weak self] in + guard let self = self else { return } + switch $0 { case .success(let receivedFile): - print(receivedFile.name) + self.handleIncomingTransfer(receivedFile, messenger: messenger) case .failure(let error): print(error.localizedDescription) } @@ -543,7 +446,7 @@ extension LaunchViewModel { DependencyInjection.Container.shared.register(manager) } - private func generateTrafficManager(messenger: Messenger) throws { + private func generateTrafficManager(_ messenger: Messenger) throws { let manager = try NewDummyTrafficManager.live( cMixId: messenger.e2e()!.getId() ) @@ -584,15 +487,15 @@ extension LaunchViewModel { do { let messenger: Messenger = try DependencyInjection.Container.shared.resolve() - print(">>> [messenger.verifyContact] will start") + try messenger.waitForNetwork() if try messenger.verifyContact(contact) { - print(">>> [messenger.verifyContact] verified") + print(">>> [messenger.verifyContact \(#file):\(#line)]") model.authStatus = .verified model = try database.saveContact(model) } else { - print(">>> [messenger.verifyContact] is fake") + print(">>> [messenger.verifyContact \(#file):\(#line)]") try database.deleteContact(model) } } catch { @@ -715,3 +618,149 @@ extension LaunchViewModel { } } } + +extension LaunchViewModel { + private func handleIncomingTransfer(_ receivedFile: ReceivedFile, messenger: Messenger) { + if var model = try? database.saveFileTransfer(.init( + id: receivedFile.transferId, + contactId: receivedFile.senderId, + name: receivedFile.name, + type: receivedFile.type, + data: nil, + progress: 0.0, + isIncoming: true, + createdAt: Date() + )) { + try! database.saveMessage(.init( + networkId: nil, + senderId: receivedFile.senderId, + recipientId: messenger.e2e.get()!.getContact().getId(), + groupId: nil, + date: Date(), + status: .receiving, + isUnread: false, + text: "", + replyMessageId: nil, + roundURL: nil, + fileTransferId: model.id + )) + + if let manager: XXClient.FileTransfer = try? DependencyInjection.Container.shared.resolve() { + print(">>> registerReceivedProgressCallback") + + try! manager.registerReceivedProgressCallback( + transferId: receivedFile.transferId, + period: 1_000, + callback: .init(handle: { [weak self] in + guard let self = self else { return } + switch $0 { + case .success(let cb): + if cb.progress.completed { + model.progress = 100 + model.data = try! manager.receive(transferId: receivedFile.transferId) + } else { + model.progress = Float(cb.progress.transmitted/cb.progress.total) + } + + model = try! self.database.saveFileTransfer(model) + + case .failure(let error): + print(error.localizedDescription) + } + }) + ) + } else { +// print(DependencyInjection.Container.shared.dependencies) + } + } + } + + private func setupLogWriter() { + _ = try! SetLogLevel.live(.debug) + RegisterLogWriter.live(.init(handle: { XXLogger.live().debug($0) })) + } + + private func makeMessenger() -> Messenger { + var environment: MessengerEnvironment = .live() + environment.ndfEnvironment = .mainnet + environment.udAddress = "46.101.98.49:18001" + environment.udCert = """ + -----BEGIN CERTIFICATE----- + MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV + BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx + GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp + cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT + MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV + BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw + DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh + Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs + WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE + tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA + m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9 + bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA + AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA + neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf + U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2 + qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4 + cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R + tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5 + 6m52PyzMNV+2N21IPppKwA== + -----END CERTIFICATE----- + """.data(using: .utf8)! + environment.udContact = """ + <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc> + """.data(using: .utf8) + + return Messenger.live(environment) + } + + private func setupAuthCallback(_ messenger: Messenger) { + authCallbacksCancellable = messenger.registerAuthCallbacks( + AuthCallbacks(handle: { + switch $0 { + case .confirm(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): + self.handleConfirm(from: contact) + case .request(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): + self.handleDirectRequest(from: contact) + case .reset(contact: let contact, receptionId: _, ephemeralId: _, roundId: _): + self.handleReset(from: contact) + } + }) + ) + } + + private func setupMessageCallback(_ messenger: Messenger) { + messageListenerCallbacksCancellable = messenger.registerMessageListener(.init(handle: { + guard let payload = try? Payload(with: $0.payload) else { + fatalError("Couldn't decode payload: \(String(data: $0.payload, encoding: .utf8) ?? "nil")") + } + + try! self.database.saveMessage(.init( + networkId: $0.id, + senderId: $0.sender, + recipientId: messenger.e2e.get()!.getContact().getId(), + groupId: nil, + date: Date.fromTimestamp($0.timestamp), + status: .received, + isUnread: true, + text: payload.text, + replyMessageId: payload.reply?.messageId, + roundURL: $0.roundURL, + fileTransferId: nil + )) + + if var contact = try? self.database.fetchContacts(.init(id: [$0.sender])).first { + contact.isRecent = false + try! self.database.saveContact(contact) + } + })) + } + + private func listenToNetworkUpdates(_ messenger: Messenger) { + networkMonitor.start() + networkCallbacksCancellable = messenger.cMix.get()!.addHealthCallback(.init(handle: { [weak self] in + guard let self = self else { return } + self.networkMonitor.update($0) + })) + } +} diff --git a/Sources/Models/Backup.swift b/Sources/Models/Backup.swift index a3518af4..104462f0 100644 --- a/Sources/Models/Backup.swift +++ b/Sources/Models/Backup.swift @@ -1,6 +1,6 @@ import Foundation -public struct Backup: Equatable, Codable { +public struct BackupModel: Equatable, Codable { public var id: String public var date: Date public var size: Float diff --git a/Sources/Models/BackupSettings.swift b/Sources/Models/BackupSettings.swift index 1ec2883f..89194c24 100644 --- a/Sources/Models/BackupSettings.swift +++ b/Sources/Models/BackupSettings.swift @@ -5,14 +5,14 @@ public struct BackupSettings: Equatable, Codable { public var automaticBackups: Bool public var enabledService: CloudService? public var connectedServices: Set<CloudService> - public var backups: [CloudService: Backup] + public var backups: [CloudService: BackupModel] public init( wifiOnlyBackup: Bool = false, automaticBackups: Bool = false, enabledService: CloudService? = nil, connectedServices: Set<CloudService> = [], - backups: [CloudService: Backup] = [:] + backups: [CloudService: BackupModel] = [:] ) { self.wifiOnlyBackup = wifiOnlyBackup self.automaticBackups = automaticBackups @@ -38,11 +38,11 @@ public struct BackupSettings: Equatable, Codable { } public struct RestoreSettings { - public var backup: Backup? + public var backup: BackupModel? public var cloudService: CloudService public init( - backup: Backup? = nil, + backup: BackupModel? = nil, cloudService: CloudService ) { self.backup = backup diff --git a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift index f2c0d8a5..7e6f3751 100644 --- a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift +++ b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift @@ -9,6 +9,7 @@ import InputField import CombineSchedulers import DependencyInjection import XXMessengerClient +import BackupFeature struct ProfileCodeViewState: Equatable { var input: String = "" @@ -18,6 +19,7 @@ struct ProfileCodeViewState: Equatable { final class ProfileCodeViewModel { @Dependency var messenger: Messenger + @Dependency var backupService: BackupService @KeyObject(.email, defaultValue: nil) var email: String? @KeyObject(.phone, defaultValue: nil) var phone: String? @@ -80,6 +82,8 @@ final class ProfileCodeViewModel { self.phone = self.confirmation.content } + self.backupService.didUpdateFacts() + self.timer?.invalidate() self.hudRelay.send(.none) self.completionRelay.send(self.confirmation) diff --git a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift index 497dac0a..1a3fb575 100644 --- a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift +++ b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift @@ -14,6 +14,8 @@ final class RequestsFailedViewModel { @Dependency var messenger: Messenger @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool + @KeyObject(.sharingPhone, defaultValue: false) var sharingPhone: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() @@ -54,12 +56,25 @@ final class RequestsFailedViewModel { do { if request.status == .failedToRequest { - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( - partner: XXClient.Contact.live(contact.marshaled!), - myFacts: myFacts + partner: .live(contact.marshaled!), + myFacts: includedFacts ) contact.authStatus = .requested diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift index bbee533c..6d9457b5 100644 --- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift +++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift @@ -25,6 +25,8 @@ final class RequestsSentViewModel { @Dependency var toastController: ToastController @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool + @KeyObject(.sharingPhone, defaultValue: false) var sharingPhone: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() @@ -77,12 +79,24 @@ final class RequestsSentViewModel { guard let self = self else { return } do { - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( - partner: XXClient.Contact.live(contact.marshaled!), - myFacts: myFacts + partner: .live(contact.marshaled!), + myFacts: includedFacts ) self.hudSubject.send(.none) diff --git a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift index 438207bb..e02adb2d 100644 --- a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift +++ b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift @@ -76,7 +76,7 @@ final class RestoreListViewModel { self.googleDriveService.downloadMetadata { downloadResult in switch downloadResult { case .success(let metadata): - var backup: Backup? + var backup: BackupModel? if let metadata = metadata { backup = .init(id: metadata.identifier, date: metadata.modifiedDate, size: metadata.size) @@ -102,7 +102,7 @@ final class RestoreListViewModel { icloudService.downloadMetadata { result in switch result { case .success(let metadata): - var backup: Backup? + var backup: BackupModel? if let metadata = metadata { backup = .init(id: metadata.path, date: metadata.modifiedDate, size: metadata.size) @@ -133,7 +133,7 @@ final class RestoreListViewModel { dropboxService.downloadMetadata { metadataResult in switch metadataResult { case .success(let metadata): - var backup: Backup? + var backup: BackupModel? if let metadata = metadata { backup = .init(id: metadata.path, date: metadata.modifiedDate, size: metadata.size) diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift index bec2e6c6..ec1895dc 100644 --- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift +++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift @@ -13,10 +13,10 @@ import DropboxFeature import GoogleDriveFeature import XXClient -import struct Models.Backup +import XXMessengerClient enum RestorationStep { - case idle(CloudService, Backup?) + case idle(CloudService, BackupModel?) case downloading(Float, Float) case failDownload(Error) case wrongPass @@ -41,8 +41,7 @@ extension RestorationStep: Equatable { } final class RestoreViewModel { - @Dependency var cMixManager: CMixManager - + @Dependency var messenger: Messenger @Dependency private var sftpService: SFTPService @Dependency private var iCloudService: iCloudInterface @Dependency private var dropboxService: DropboxInterface @@ -93,7 +92,7 @@ final class RestoreViewModel { } } - private func downloadBackupForSFTP(_ backup: Backup) { + private func downloadBackupForSFTP(_ backup: BackupModel) { sftpService.downloadBackup(path: backup.id) { [weak self] in guard let self = self else { return } self.stepRelay.send(.downloading(backup.size, backup.size)) @@ -107,7 +106,7 @@ final class RestoreViewModel { } } - private func downloadBackupForDropbox(_ backup: Backup) { + private func downloadBackupForDropbox(_ backup: BackupModel) { dropboxService.downloadBackup(backup.id) { [weak self] in guard let self = self else { return } self.stepRelay.send(.downloading(backup.size, backup.size)) @@ -121,7 +120,7 @@ final class RestoreViewModel { } } - private func downloadBackupForiCloud(_ backup: Backup) { + private func downloadBackupForiCloud(_ backup: BackupModel) { iCloudService.downloadBackup(backup.id) { [weak self] in guard let self = self else { return } self.stepRelay.send(.downloading(backup.size, backup.size)) @@ -135,7 +134,7 @@ final class RestoreViewModel { } } - private func downloadBackupForDrive(_ backup: Backup) { + private func downloadBackupForDrive(_ backup: BackupModel) { googleService.downloadBackup(backup.id) { [weak self] in if let stepRelay = self?.stepRelay { stepRelay.send(.downloading($0, backup.size)) @@ -159,152 +158,22 @@ final class RestoreViewModel { guard let self = self else { return } do { - let report = try self.cMixManager.restore( - backup: data, - passphrase: self.passphrase - ) - - struct BackupParameters: Codable { - var email: String? - var phone: String? - var username: String - } - - guard let paramsData = report.params.data(using: .utf8) else { - fatalError("Couldn't parse parameters from backup to byte array") - } - - let facts = try JSONDecoder().decode( - BackupParameters.self, - from: paramsData - ) - - self.phone = facts.phone - self.email = facts.email - - var emailFact: Fact? - var phoneFact: Fact? - - if let email = self.email { emailFact = .init(type: .email, value: email) } - if let phone = self.phone { phoneFact = .init(type: .phone, value: phone) } - - let cMix = try self.cMixManager.load() - - DependencyInjection.Container.shared.register(cMix) - - let e2e = try Login.live( - cMixId: cMix.getId(), - authCallbacks: .init( - handle: { callbacks in - switch callbacks { - case .reset( - contact: _, - receptionId: _, - ephemeralId: _, - roundId: _ - ): - break - case .confirm( - contact: _, - receptionId: _, - ephemeralId: _, - roundId: _ - ): - break - case .request( - contact: _, - receptionId: _, - ephemeralId: _, - roundId: _ - ): - break - } - } - ), - identity: try cMix.makeReceptionIdentity() - ) - - let udAddress = "46.101.98.49:18001" - let udCert = """ - -----BEGIN CERTIFICATE----- - MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV - BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx - GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp - cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT - MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV - BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw - DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh - Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs - WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE - tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA - m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9 - bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA - AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA - neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf - U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2 - qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4 - cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R - tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5 - 6m52PyzMNV+2N21IPppKwA== - -----END CERTIFICATE----- - """.data(using: .utf8)! - let udContact = """ - <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc> - """.data(using: .utf8) - - let userDiscovery = try NewUdManagerFromBackup.live( - params: .init( - e2eId: e2e.getId(), - username: .init(type: .username, value: facts.username), - email: emailFact, - phone: phoneFact, - cert: udCert, - contact: udContact!, - address: udAddress - ), - follower: .init(handle: { cMix.networkFollowerStatus() }) + let result = try self.messenger.restoreBackup( + backupData: data, + backupPassphrase: self.passphrase ) - DependencyInjection.Container.shared.register(userDiscovery) - - try e2e.registerListener( - senderId: nil, - messageType: 2, - callback: .init(handle: { message in - print(message.timestamp) - }) - ) + print(">>> Finished restoring on bindings") - DependencyInjection.Container.shared.register(e2e) - - let groupManager = try NewGroupChat.live( - e2eId: e2e.getId(), - groupRequest: .init(handle: { - print($0) - }), - groupChatProcessor: .init(handle: { - print($0) - }) - ) - - DependencyInjection.Container.shared.register(groupManager) - - let transferManager = try InitFileTransfer.live( - e2eId: e2e.getId(), - callback: .init(handle: { - switch $0 { - case .success(let receivedFile): - print(receivedFile.name) - case .failure(let error): - print(error.localizedDescription) - } - }) - ) + self.username = result.restoredParams.username + self.email = result.restoredParams.email + self.phone = result.restoredParams.phone - DependencyInjection.Container.shared.register(transferManager) + //let restoreContacts = result.restoredContacts self.stepRelay.send(.done) } catch { + print(">>> Error on restoration: \(error.localizedDescription)") self.pendingData = data self.stepRelay.send(.wrongPass) } diff --git a/Sources/RestoreFeature/Views/RestoreView.swift b/Sources/RestoreFeature/Views/RestoreView.swift index ba2e643c..de449911 100644 --- a/Sources/RestoreFeature/Views/RestoreView.swift +++ b/Sources/RestoreFeature/Views/RestoreView.swift @@ -104,7 +104,7 @@ final class RestoreView: UIView { } } - private func showBackup(_ backup: Backup, fromCloud cloud: CloudService) { + private func showBackup(_ backup: BackupModel, fromCloud cloud: CloudService) { titleLabel.text = Localized.AccountRestore.Found.title subtitleLabel.text = Localized.AccountRestore.Found.subtitle diff --git a/Sources/SFTPFeature/ActionHandlers/SFTPUploader.swift b/Sources/SFTPFeature/ActionHandlers/SFTPUploader.swift index 0c39386e..4217d837 100644 --- a/Sources/SFTPFeature/ActionHandlers/SFTPUploader.swift +++ b/Sources/SFTPFeature/ActionHandlers/SFTPUploader.swift @@ -5,7 +5,7 @@ import Keychain import Foundation import DependencyInjection -public typealias SFTPUploadResult = (Result<Backup, Error>) -> Void +public typealias SFTPUploadResult = (Result<BackupModel, Error>) -> Void public struct SFTPUploader { public var upload: (URL, @escaping SFTPUploadResult) -> Void diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift index 9158e359..67b8d649 100644 --- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift +++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift @@ -33,6 +33,8 @@ final class SearchLeftViewModel { @Dependency var networkMonitor: NetworkMonitoring @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool + @KeyObject(.sharingPhone, defaultValue: false) var sharingPhone: Bool var myId: Data { try! messenger.e2e.get()!.getContact().getId() @@ -209,12 +211,24 @@ final class SearchLeftViewModel { do { try self.database.saveContact(contact) - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( partner: .live(contact.marshaled!), - myFacts: myFacts + myFacts: includedFacts ) contact.authStatus = .requested @@ -243,12 +257,24 @@ final class SearchLeftViewModel { do { try self.database.saveContact(contact) - var myFacts = try self.messenger.ud.get()!.getFacts() - myFacts.append(.init(type: .username, value: self.username!)) + var includedFacts: [Fact] = [] + let myFacts = try self.messenger.ud.get()!.getFacts() + + if let fact = myFacts.get(.username) { + includedFacts.append(fact) + } + + if self.sharingEmail, let fact = myFacts.get(.email) { + includedFacts.append(fact) + } + + if self.sharingPhone, let fact = myFacts.get(.phone) { + includedFacts.append(fact) + } let _ = try self.messenger.e2e.get()!.requestAuthenticatedChannel( partner: .live(contact.marshaled!), - myFacts: myFacts + myFacts: includedFacts ) contact.authStatus = .requested diff --git a/Sources/iCloudFeature/iCloudService.swift b/Sources/iCloudFeature/iCloudService.swift index 2ccf20ba..0c766b9f 100644 --- a/Sources/iCloudFeature/iCloudService.swift +++ b/Sources/iCloudFeature/iCloudService.swift @@ -17,7 +17,10 @@ public struct iCloudService: iCloudInterface { } public func downloadMetadata(_ completion: @escaping (Result<iCloudMetadata?, Error>) -> Void) { - guard let documentsProvider = documentsProvider else { fatalError() } + guard let documentsProvider = documentsProvider else { + // TODO: Use some generic error + fatalError() + } documentsProvider.contentsOfDirectory(path: "/", completionHandler: { contents, error in guard error == nil else { -- GitLab