SimpleX-Chat/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift

107 lines
4.4 KiB
Swift
Raw Normal View History

//
// LocalAuthView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 10/04/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct LocalAuthView: View {
@EnvironmentObject var m: ChatModel
var authRequest: LocalAuthRequest
@State private var password = ""
@State private var allowToReact = true
var body: some View {
PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit",
buttonsEnabled: $allowToReact) {
if let sdPassword = kcSelfDestructPassword.get(), authRequest.selfDestruct && password == sdPassword {
allowToReact = false
deleteStorageAndRestart(sdPassword) { r in
m.laRequest = nil
authRequest.completed(r)
}
return
}
let r: LAResult
if password == authRequest.password {
if authRequest.selfDestruct && kcSelfDestructPassword.get() != nil && !m.chatInitialized {
initChatAndMigrate()
}
r = .success
} else {
r = .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry"))
}
m.laRequest = nil
authRequest.completed(r)
} cancel: {
m.laRequest = nil
authRequest.completed(.failed(authError: NSLocalizedString("Authentication cancelled", comment: "PIN entry")))
}
}
private func deleteStorageAndRestart(_ password: String, completed: @escaping (LAResult) -> Void) {
Task {
do {
/** Waiting until [initializeChat] finishes */
while (m.ctrlInitInProgress) {
try await Task.sleep(nanoseconds: 50_000000)
}
if m.chatRunning == true {
try await stopChatAsync()
}
if m.chatInitialized {
/**
* The following sequence can bring a user here:
* the user opened the app, entered app passcode, went to background, returned back, entered self-destruct code.
* In this case database should be closed to prevent possible situation when OS can deny database removal command
* */
chatCloseStore()
}
deleteAppDatabaseAndFiles()
// Clear sensitive data on screen just in case app fails to hide its views while new database is created
m.chatId = nil
ItemsModel.shared.reversedChatItems = []
ios: open chat on first unread, "scroll" to quoted items that were not loaded (#5392) * ios: open chat on first unread, "scroll" to quoted items that were not loaded * more changes * changes * unused * fix reveal logic * debug * changes * test * Revert "test" This reverts commit 553be124d5233c6afad18ef37f81fce659958101. * change * change * changes * changes * changes * commented deceleration logic * changes * fixes * optimized item identifiers to use merged item directly * fixed counters * encreased initial and preload counters * fix initial loading and trimming items * optimize * allow marking read * 10 instead of 5 * performance * one more parameter in hash * disable trimming * performance * performance - in background * optimization * next/prev * changes * markread * finally * less logs * read * change after merge * trimming, edge cases * wait until items loaded * Revert "wait until items loaded" This reverts commit 895218b97802669c10d22028d22b9da8a8c1f01a. * progress indicator * optimization * disable scroll helper * experiment * Revert "experiment" This reverts commit c952c9e6230a05b639ab812431781f1353c94c5d. * jump * no read * layoutIfNeeded * changes * EndlessScrollView * read * changes * changes * changes * reduce time to open a chat (by ~300ms) * open from the first unread when clicking member chat * refactored and removed unused code * handling search emptiness to scroll to correct position * changes * read state maintain * remove protocol * avoid parsing chatId * pass chat * changes * remove reveal * refactor spaghetti * remove ItemsScrollModel * rename * remove setUpdateListener * unused * optimization * scrollToTop * fix * scrollbar working again * scrollToBottom * fix * scrollBar hiding when not many items on screen * small safer change --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2025-02-18 01:21:40 +07:00
ItemsModel.shared.chatItemsChangesListener.cleared()
m.updateChats([])
m.users = []
_ = kcAppPassword.set(password)
_ = kcSelfDestructPassword.remove()
await NtfManager.shared.removeAllNotifications()
let displayName = UserDefaults.standard.string(forKey: DEFAULT_LA_SELF_DESTRUCT_DISPLAY_NAME)
UserDefaults.standard.removeObject(forKey: DEFAULT_LA_SELF_DESTRUCT)
UserDefaults.standard.removeObject(forKey: DEFAULT_LA_SELF_DESTRUCT_DISPLAY_NAME)
await MainActor.run {
m.chatDbChanged = true
m.chatInitialized = false
}
resetChatCtrl()
try initializeChat(start: true)
m.chatDbChanged = false
AppChatState.shared.set(.active)
if m.currentUser != nil || !m.chatInitialized { return }
var profile: Profile? = nil
if let displayName = displayName, displayName != "" {
profile = Profile(displayName: displayName, fullName: "")
}
m.currentUser = try apiCreateActiveUser(profile, pastTimestamp: true)
onboardingStageDefault.set(.onboardingComplete)
m.onboardingStage = .onboardingComplete
try startChat()
completed(.success)
} catch {
completed(.failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry")))
}
}
}
}
struct LocalAuthView_Previews: PreviewProvider {
static var previews: some View {
LocalAuthView(authRequest: LocalAuthRequest.sample)
}
}