Improved locking

This commit is contained in:
Peter 2019-10-25 23:06:31 +04:00
parent 7d465b0f93
commit f75a73d257
27 changed files with 570 additions and 201 deletions

1
BUCK
View File

@ -247,6 +247,7 @@ apple_binary(
deps = [
"//submodules/BuildConfig:BuildConfig",
"//submodules/WidgetItems:WidgetItems",
"//submodules/AppLockState:AppLockState",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/UIKit.framework",

View File

@ -99,7 +99,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
let encryptionParameters = ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: deviceSpecificEncryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: deviceSpecificEncryptionParameters.salt)!)
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: .single(buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), encryptionProvider: OpenSSLEncryptionProvider()), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods, encryptionParameters: encryptionParameters)
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: .single(buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider()), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods, encryptionParameters: encryptionParameters)
|> mapToSignal { account -> Signal<Account?, NoError> in
if let account = account {
switch account {

View File

@ -2,6 +2,7 @@ import UIKit
import NotificationCenter
import BuildConfig
import WidgetItems
import AppLockState
private func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
@ -13,14 +14,11 @@ class TodayViewController: UIViewController, NCWidgetProviding {
private var buildConfig: BuildConfig?
private var appLockedLabel: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
if self.initializedInterface {
return
}
self.initializedInterface = true
let appBundleIdentifier = Bundle.main.bundleIdentifier!
guard let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
return
@ -38,6 +36,23 @@ class TodayViewController: UIViewController, NCWidgetProviding {
}
let rootPath = rootPathForBasePath(appGroupUrl.path)
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
let appLockedLabel = UILabel()
appLockedLabel.textColor = .black
appLockedLabel.font = UIFont.systemFont(ofSize: 16.0)
appLockedLabel.text = "Unlock the app to use widget"
appLockedLabel.sizeToFit()
self.appLockedLabel = appLockedLabel
self.view.addSubview(appLockedLabel)
return
}
if self.initializedInterface {
return
}
self.initializedInterface = true
let dataPath = rootPath + "/widget-data"
if let data = try? Data(contentsOf: URL(fileURLWithPath: dataPath)), let widgetData = try? JSONDecoder().decode(WidgetData.self, from: data) {
@ -97,6 +112,10 @@ class TodayViewController: UIViewController, NCWidgetProviding {
private func updateLayout(size: CGSize) {
self.validLayout = size
if let appLockedLabel = self.appLockedLabel {
appLockedLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - appLockedLabel.bounds.width) / 2.0), y: floor((size.height - appLockedLabel.bounds.height) / 2.0)), size: appLockedLabel.bounds.size)
}
let peerSize = CGSize(width: 70.0, height: 100.0)
var peerFrames: [CGRect] = []

View File

@ -384,10 +384,19 @@ public enum CreateGroupMode {
case locatedGroup(latitude: Double, longitude: Double, address: String?)
}
public protocol AppLockContext: class {
var invalidAttempts: Signal<AccessChallengeAttempts?, NoError> { get }
func lock()
func unlock()
func failedUnlockAttempt()
}
public protocol SharedAccountContext: class {
var basePath: String { get }
var mainWindow: Window1? { get }
var accountManager: AccountManager { get }
var appLockContext: AppLockContext { get }
var currentPresentationData: Atomic<PresentationData> { get }
var presentationData: Signal<PresentationData, NoError> { get }

25
submodules/AppLock/BUCK Normal file
View File

@ -0,0 +1,25 @@
load("//Config:buck_rule_macros.bzl", "static_library")
static_library(
name = "AppLock",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit#shared",
"//submodules/Display:Display#shared",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared",
"//submodules/Postbox:Postbox#shared",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/MonotonicTime:MonotonicTime",
"//submodules/PasscodeUI:PasscodeUI",
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/ImageBlur:ImageBlur",
"//submodules/AccountContext:AccountContext",
"//submodules/AppLockState:AppLockState",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
],
)

View File

@ -0,0 +1,247 @@
import Foundation
import UIKit
import Postbox
import Display
import SwiftSignalKit
import MonotonicTime
import AccountContext
import TelegramPresentationData
import PasscodeUI
import TelegramUIPreferences
import ImageBlur
import AppLockState
private func isLocked(passcodeSettings: PresentationPasscodeSettings, state: LockState, isApplicationActive: Bool) -> Bool {
if state.isManuallyLocked {
return true
} else if let autolockTimeout = passcodeSettings.autolockTimeout {
var bootTimestamp: Int32 = 0
let uptime = getDeviceUptimeSeconds(&bootTimestamp)
let timestamp = MonotonicTimestamp(bootTimestap: bootTimestamp, uptime: uptime)
let applicationActivityTimestamp = state.applicationActivityTimestamp
if let applicationActivityTimestamp = applicationActivityTimestamp {
if timestamp.bootTimestap != applicationActivityTimestamp.bootTimestap {
return true
}
if timestamp.uptime >= applicationActivityTimestamp.uptime + autolockTimeout {
return true
}
} else {
return true
}
}
return false
}
private func getCoveringViewSnaphot(window: Window1) -> UIImage? {
let scale: CGFloat = 0.5
let unscaledSize = window.hostView.containerView.frame.size
return generateImage(CGSize(width: floor(unscaledSize.width * scale), height: floor(unscaledSize.height * scale)), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.scaleBy(x: scale, y: scale)
UIGraphicsPushContext(context)
window.hostView.containerView.drawHierarchy(in: CGRect(origin: CGPoint(), size: unscaledSize), afterScreenUpdates: false)
UIGraphicsPopContext()
}).flatMap(applyScreenshotEffectToImage)
}
public final class AppLockContextImpl: AppLockContext {
private let rootPath: String
private let syncQueue = Queue()
private let applicationBindings: TelegramApplicationBindings
private let accountManager: AccountManager
private let presentationDataSignal: Signal<PresentationData, NoError>
private let window: Window1?
private var coveringView: LockedWindowCoveringView?
private var passcodeController: PasscodeEntryController?
private var timestampRenewTimer: SwiftSignalKit.Timer?
private var currentStateValue: LockState
private let currentState = Promise<LockState>()
public init(rootPath: String, window: Window1?, applicationBindings: TelegramApplicationBindings, accountManager: AccountManager, presentationDataSignal: Signal<PresentationData, NoError>, lockIconInitialFrame: @escaping () -> CGRect?) {
assert(Queue.mainQueue().isCurrent())
self.applicationBindings = applicationBindings
self.accountManager = accountManager
self.presentationDataSignal = presentationDataSignal
self.rootPath = rootPath
self.window = window
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: self.rootPath))), let current = try? JSONDecoder().decode(LockState.self, from: data) {
self.currentStateValue = current
} else {
self.currentStateValue = LockState()
}
let _ = (combineLatest(queue: .mainQueue(),
accountManager.accessChallengeData(),
accountManager.sharedData(keys: Set([ApplicationSpecificSharedDataKeys.presentationPasscodeSettings])),
presentationDataSignal,
applicationBindings.applicationIsActive,
self.currentState.get()
)
|> deliverOnMainQueue).start(next: { [weak self] accessChallengeData, sharedData, presentationData, appInForeground, state in
guard let strongSelf = self else {
return
}
let passcodeSettings: PresentationPasscodeSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationPasscodeSettings] as? PresentationPasscodeSettings ?? .defaultSettings
var shouldDisplayCoveringView = false
if !accessChallengeData.data.isLockable {
if let passcodeController = strongSelf.passcodeController {
strongSelf.passcodeController = nil
passcodeController.dismiss()
}
} else {
if let autolockTimeout = passcodeSettings.autolockTimeout, !appInForeground {
shouldDisplayCoveringView = true
}
if isLocked(passcodeSettings: passcodeSettings, state: state, isApplicationActive: appInForeground) {
if strongSelf.passcodeController == nil {
let biometrics: PasscodeEntryControllerBiometricsMode
if passcodeSettings.enableBiometrics {
biometrics = .enabled(passcodeSettings.biometricsDomainState)
} else {
biometrics = .none
}
let passcodeController = PasscodeEntryController(applicationBindings: strongSelf.applicationBindings, accountManager: strongSelf.accountManager, appLockContext: strongSelf, presentationData: presentationData, presentationDataSignal: strongSelf.presentationDataSignal, challengeData: accessChallengeData.data, biometrics: biometrics, arguments: PasscodeEntryControllerPresentationArguments(animated: true, lockIconInitialFrame: { [weak self] in
if let lockViewFrame = lockIconInitialFrame() {
return lockViewFrame
} else {
return CGRect()
}
}))
passcodeController.presentedOverCoveringView = true
strongSelf.passcodeController = passcodeController
strongSelf.window?.present(passcodeController, on: .passcode)
}
} else if let passcodeController = strongSelf.passcodeController {
strongSelf.passcodeController = nil
passcodeController.dismiss()
}
}
strongSelf.updateTimestampRenewTimer(shouldRun: appInForeground && accessChallengeData.data.isLockable)
if shouldDisplayCoveringView {
if strongSelf.coveringView == nil, let window = strongSelf.window {
let coveringView = LockedWindowCoveringView(theme: presentationData.theme)
coveringView.updateSnapshot(getCoveringViewSnaphot(window: window))
strongSelf.coveringView = coveringView
window.coveringView = coveringView
}
} else {
if let coveringView = strongSelf.coveringView {
strongSelf.coveringView = nil
strongSelf.window?.coveringView = nil
}
}
})
self.currentState.set(.single(self.currentStateValue))
}
private func updateTimestampRenewTimer(shouldRun: Bool) {
if shouldRun {
if self.timestampRenewTimer == nil {
let timestampRenewTimer = SwiftSignalKit.Timer(timeout: 5.0, repeat: true, completion: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.updateApplicationActivityTimestamp()
}, queue: .mainQueue())
self.timestampRenewTimer = timestampRenewTimer
timestampRenewTimer.start()
}
} else {
if let timestampRenewTimer = self.timestampRenewTimer {
self.timestampRenewTimer = nil
timestampRenewTimer.invalidate()
}
}
}
private func updateApplicationActivityTimestamp() {
self.updateLockState { state in
var bootTimestamp: Int32 = 0
let uptime = getDeviceUptimeSeconds(&bootTimestamp)
var state = state
state.applicationActivityTimestamp = MonotonicTimestamp(bootTimestap: bootTimestamp, uptime: uptime)
return state
}
}
private func updateLockState(_ f: @escaping (LockState) -> LockState) {
Queue.mainQueue().async {
let updatedState = f(self.currentStateValue)
if updatedState != self.currentStateValue {
self.currentStateValue = updatedState
self.currentState.set(.single(updatedState))
let path = appLockStatePath(rootPath: self.rootPath)
self.syncQueue.async {
if let data = try? JSONEncoder().encode(updatedState) {
let _ = try? data.write(to: URL(fileURLWithPath: path), options: .atomic)
}
}
}
}
}
public var invalidAttempts: Signal<AccessChallengeAttempts?, NoError> {
return self.currentState.get()
|> map { state in
return state.unlockAttemts.flatMap { unlockAttemts in
return AccessChallengeAttempts(count: unlockAttemts.count, timestamp: unlockAttemts.wallClockTimestamp)
}
}
}
public func lock() {
self.updateLockState { state in
var state = state
state.isManuallyLocked = true
return state
}
}
public func unlock() {
self.updateLockState { state in
var state = state
state.unlockAttemts = nil
state.isManuallyLocked = false
var bootTimestamp: Int32 = 0
let uptime = getDeviceUptimeSeconds(&bootTimestamp)
let timestamp = MonotonicTimestamp(bootTimestap: bootTimestamp, uptime: uptime)
state.applicationActivityTimestamp = timestamp
return state
}
}
public func failedUnlockAttempt() {
self.updateLockState { state in
var state = state
var unlockAttemts = state.unlockAttemts ?? UnlockAttempts(count: 0, wallClockTimestamp: 0)
unlockAttemts.count += 1
unlockAttemts.wallClockTimestamp = Int32(CFAbsoluteTimeGetCurrent())
state.unlockAttemts = unlockAttemts
return state
}
}
}

View File

@ -0,0 +1,35 @@
import Foundation
import Display
import TelegramPresentationData
import AsyncDisplayKit
final class LockedWindowCoveringView: WindowCoveringView {
private let contentView: UIImageView
init(theme: PresentationTheme) {
self.contentView = UIImageView()
super.init(frame: CGRect())
self.backgroundColor = theme.chatList.backgroundColor
self.addSubview(self.contentView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateTheme(_ theme: PresentationTheme) {
self.backgroundColor = theme.chatList.backgroundColor
}
func updateSnapshot(_ image: UIImage?) {
if image != nil {
self.contentView.image = image
}
}
override func updateLayout(_ size: CGSize) {
self.contentView.frame = CGRect(origin: CGPoint(), size: size)
}
}

View File

@ -0,0 +1,14 @@
load("//Config:buck_rule_macros.bzl", "static_library")
static_library(
name = "AppLockState",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/MonotonicTime:MonotonicTime",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
],
)

View File

@ -0,0 +1,62 @@
import Foundation
import MonotonicTime
public struct MonotonicTimestamp: Codable, Equatable {
public var bootTimestap: Int32
public var uptime: Int32
public init(bootTimestap: Int32, uptime: Int32) {
self.bootTimestap = bootTimestap
self.uptime = uptime
}
}
public struct UnlockAttempts: Codable, Equatable {
public var count: Int32
public var wallClockTimestamp: Int32
public init(count: Int32, wallClockTimestamp: Int32) {
self.count = count
self.wallClockTimestamp = wallClockTimestamp
}
}
public struct LockState: Codable, Equatable {
public var isManuallyLocked: Bool
public var autolockTimeout: Int32?
public var unlockAttemts: UnlockAttempts?
public var applicationActivityTimestamp: MonotonicTimestamp?
public init(isManuallyLocked: Bool = false, autolockTimeout: Int32? = nil, unlockAttemts: UnlockAttempts? = nil, applicationActivityTimestamp: MonotonicTimestamp? = nil) {
self.isManuallyLocked = isManuallyLocked
self.autolockTimeout = autolockTimeout
self.unlockAttemts = unlockAttemts
self.applicationActivityTimestamp = applicationActivityTimestamp
}
}
public func appLockStatePath(rootPath: String) -> String {
return rootPath + "/lockState.json"
}
public func isAppLocked(state: LockState) -> Bool {
if state.isManuallyLocked {
return true
} else if let autolockTimeout = state.autolockTimeout {
var bootTimestamp: Int32 = 0
let uptime = getDeviceUptimeSeconds(&bootTimestamp)
let timestamp = MonotonicTimestamp(bootTimestap: bootTimestamp, uptime: uptime)
if let applicationActivityTimestamp = state.applicationActivityTimestamp {
if timestamp.bootTimestap != applicationActivityTimestamp.bootTimestap {
return true
}
if timestamp.uptime >= applicationActivityTimestamp.uptime + autolockTimeout {
return true
}
} else {
return true
}
}
return false
}

View File

@ -249,7 +249,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
let passcode = context.sharedContext.accountManager.accessChallengeData()
|> map { view -> (Bool, Bool) in
let data = view.data
return (data.isLockable, data.autolockDeadline == 0)
return (data.isLockable, false)
}
if !self.hideNetworkActivityStatus {
@ -338,17 +338,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
self.titleView.toggleIsLocked = { [weak self] in
if let strongSelf = self {
let _ = (strongSelf.context.sharedContext.accountManager.transaction({ transaction -> Void in
var data = transaction.getAccessChallengeData()
if data.isLockable {
if data.autolockDeadline != 0 {
data = data.withUpdatedAutolockDeadline(0)
} else {
data = data.withUpdatedAutolockDeadline(nil)
}
transaction.setAccessChallengeData(data)
}
}) |> deliverOnMainQueue).start()
strongSelf.context.sharedContext.appLockContext.lock()
}
}

View File

@ -149,9 +149,9 @@ func importLegacyPreferences(accountManager: AccountManager, account: TemporaryA
}
if mode == 3 {
passcodeChallenge = .numericalPassword(value: passwordText, timeout: lockTimeout, attempts: nil)
passcodeChallenge = .numericalPassword(value: passwordText)
} else if mode == 4 {
passcodeChallenge = PostboxAccessChallengeData.plaintextPassword(value: passwordText, timeout: lockTimeout, attempts: nil)
passcodeChallenge = PostboxAccessChallengeData.plaintextPassword(value: passwordText)
}
}
}
@ -288,14 +288,6 @@ func importLegacyPreferences(accountManager: AccountManager, account: TemporaryA
var settings: PresentationPasscodeSettings = current as? PresentationPasscodeSettings ?? .defaultSettings
if let passcodeChallenge = passcodeChallenge {
transaction.setAccessChallengeData(passcodeChallenge)
switch passcodeChallenge {
case .none:
break
case let .numericalPassword(_, timeout, _):
settings.autolockTimeout = timeout
case let .plaintextPassword(_, timeout, _):
settings.autolockTimeout = timeout
}
settings.enableBiometrics = passcodeEnableBiometrics
}
return settings

View File

@ -0,0 +1,19 @@
load("//Config:buck_rule_macros.bzl", "static_library")
static_library(
name = "MonotonicTime",
srcs = glob([
"Sources/**/*.m",
]),
headers = glob([
"Sources/**/*.h",
]),
exported_headers = glob([
"Sources/**/*.h",
]),
deps = [
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
],
)

View File

@ -0,0 +1,3 @@
#import <Foundation/Foundation.h>
int32_t getDeviceUptimeSeconds(int32_t *bootTime);

View File

@ -0,0 +1,22 @@
#import "DeviceUptime.h"
#include <sys/sysctl.h>
int32_t getDeviceUptimeSeconds(int32_t *bootTime) {
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t now;
time_t uptime = -1;
(void)time(&now);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
uptime = now - boottime.tv_sec;
if (bootTime != NULL) {
*bootTime = boottime.tv_sec;
}
}
return uptime;
}

View File

@ -34,7 +34,11 @@ public final class PasscodeEntryController: ViewController {
return self.displayNode as! PasscodeEntryControllerNode
}
private let context: AccountContext
private let applicationBindings: TelegramApplicationBindings
private let accountManager: AccountManager
private let appLockContext: AppLockContext
private let presentationDataSignal: Signal<PresentationData, NoError>
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
@ -52,9 +56,12 @@ public final class PasscodeEntryController: ViewController {
private var inBackground: Bool = false
private var inBackgroundDisposable: Disposable?
public init(context: AccountContext, challengeData: PostboxAccessChallengeData, biometrics: PasscodeEntryControllerBiometricsMode, arguments: PasscodeEntryControllerPresentationArguments) {
self.context = context
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
public init(applicationBindings: TelegramApplicationBindings, accountManager: AccountManager, appLockContext: AppLockContext, presentationData: PresentationData, presentationDataSignal: Signal<PresentationData, NoError>, challengeData: PostboxAccessChallengeData, biometrics: PasscodeEntryControllerBiometricsMode, arguments: PasscodeEntryControllerPresentationArguments) {
self.applicationBindings = applicationBindings
self.accountManager = accountManager
self.appLockContext = appLockContext
self.presentationData = presentationData
self.presentationDataSignal = presentationDataSignal
self.challengeData = challengeData
self.biometrics = biometrics
self.arguments = arguments
@ -64,14 +71,14 @@ public final class PasscodeEntryController: ViewController {
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
self.statusBar.statusBarStyle = .White
self.presentationDataDisposable = (context.sharedContext.presentationData
self.presentationDataDisposable = (presentationDataSignal
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self, strongSelf.isNodeLoaded {
strongSelf.controllerNode.updatePresentationData(presentationData)
}
})
self.inBackgroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground
self.inBackgroundDisposable = (applicationBindings.applicationInForeground
|> deliverOnMainQueue).start(next: { [weak self] value in
guard let strongSelf = self else {
return
@ -96,7 +103,7 @@ public final class PasscodeEntryController: ViewController {
override public func loadDisplayNode() {
let passcodeType: PasscodeEntryFieldType
switch self.challengeData {
case let .numericalPassword(value, _, _):
case let .numericalPassword(value):
passcodeType = value.count == 6 ? .digits6 : .digits4
default:
passcodeType = .alphanumeric
@ -104,7 +111,7 @@ public final class PasscodeEntryController: ViewController {
let biometricsType: LocalAuthBiometricAuthentication?
if case let .enabled(data) = self.biometrics {
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
if data == LocalAuth.evaluatedPolicyDomainState || (data == nil && !self.context.sharedContext.applicationBindings.isMainApp) {
if data == LocalAuth.evaluatedPolicyDomainState || (data == nil && !self.applicationBindings.isMainApp) {
biometricsType = LocalAuth.biometricAuthentication
} else {
biometricsType = nil
@ -115,12 +122,11 @@ public final class PasscodeEntryController: ViewController {
} else {
biometricsType = nil
}
self.displayNode = PasscodeEntryControllerNode(context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, passcodeType: passcodeType, biometricsType: biometricsType, arguments: self.arguments, statusBar: self.statusBar)
self.displayNode = PasscodeEntryControllerNode(accountManager: self.accountManager, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, passcodeType: passcodeType, biometricsType: biometricsType, arguments: self.arguments, statusBar: self.statusBar)
self.displayNodeDidLoad()
let _ = (self.context.sharedContext.accountManager.transaction({ transaction -> AccessChallengeAttempts? in
return transaction.getAccessChallengeData().attempts
}) |> deliverOnMainQueue).start(next: { [weak self] attempts in
let _ = (self.appLockContext.invalidAttempts
|> deliverOnMainQueue).start(next: { [weak self] attempts in
guard let strongSelf = self else {
return
}
@ -136,9 +142,9 @@ public final class PasscodeEntryController: ViewController {
switch strongSelf.challengeData {
case .none:
succeed = true
case let .numericalPassword(code, _, _):
case let .numericalPassword(code):
succeed = passcode == normalizeArabicNumeralString(code, type: .western)
case let .plaintextPassword(code, _, _):
case let .plaintextPassword(code):
succeed = passcode == code
}
@ -146,22 +152,11 @@ public final class PasscodeEntryController: ViewController {
if let completed = strongSelf.completed {
completed()
} else {
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction -> Void in
var data = transaction.getAccessChallengeData().withUpdatedAutolockDeadline(nil)
switch data {
case .none:
break
case let .numericalPassword(value, timeout, _):
data = .numericalPassword(value: value, timeout: timeout, attempts: nil)
case let .plaintextPassword(value, timeout, _):
data = .plaintextPassword(value: value, timeout: timeout, attempts: nil)
}
transaction.setAccessChallengeData(data)
}).start()
strongSelf.appLockContext.unlock()
}
let isMainApp = strongSelf.context.sharedContext.applicationBindings.isMainApp
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { settings in
let isMainApp = strongSelf.applicationBindings.isMainApp
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: strongSelf.accountManager, { settings in
if isMainApp {
return settings.withUpdatedBiometricsDomainState(LocalAuth.evaluatedPolicyDomainState)
} else {
@ -169,36 +164,7 @@ public final class PasscodeEntryController: ViewController {
}
}).start()
} else {
let _ = (strongSelf.context.sharedContext.accountManager.transaction({ transaction -> AccessChallengeAttempts in
var data = transaction.getAccessChallengeData()
let updatedAttempts: AccessChallengeAttempts
if let attempts = data.attempts {
var count = attempts.count + 1
if count > 6 {
count = 1
}
updatedAttempts = AccessChallengeAttempts(count: count, timestamp: Int32(CFAbsoluteTimeGetCurrent()))
} else {
updatedAttempts = AccessChallengeAttempts(count: 1, timestamp: Int32(CFAbsoluteTimeGetCurrent()))
}
switch data {
case .none:
break
case let .numericalPassword(value, timeout, _):
data = .numericalPassword(value: value, timeout: timeout, attempts: updatedAttempts)
case let .plaintextPassword(value, timeout, _):
data = .plaintextPassword(value: value, timeout: timeout, attempts: updatedAttempts)
}
transaction.setAccessChallengeData(data)
return updatedAttempts
})
|> deliverOnMainQueue).start(next: { [weak self] attempts in
if let strongSelf = self {
strongSelf.controllerNode.updateInvalidAttempts(attempts, animated: true)
}
})
strongSelf.appLockContext.failedUnlockAttempt()
strongSelf.controllerNode.animateError()
}
}
@ -231,7 +197,7 @@ public final class PasscodeEntryController: ViewController {
}
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
if data == nil && self.context.sharedContext.applicationBindings.isMainApp {
if data == nil && self.applicationBindings.isMainApp {
return
}
}
@ -258,8 +224,8 @@ public final class PasscodeEntryController: ViewController {
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
if case let .enabled(storedDomainState) = strongSelf.biometrics, evaluatedPolicyDomainState != nil {
if !strongSelf.context.sharedContext.applicationBindings.isMainApp && storedDomainState == nil {
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { settings in
if !strongSelf.applicationBindings.isMainApp && storedDomainState == nil {
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: strongSelf.accountManager, { settings in
return settings.withUpdatedShareBiometricsDomainState(LocalAuth.evaluatedPolicyDomainState)
}).start()
} else if storedDomainState != evaluatedPolicyDomainState {
@ -278,14 +244,8 @@ public final class PasscodeEntryController: ViewController {
}
strongSelf.hasOngoingBiometricsRequest = false
} else {
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction -> Void in
let data = transaction.getAccessChallengeData().withUpdatedAutolockDeadline(nil)
transaction.setAccessChallengeData(data)
}).start(completed: { [weak self] in
if let strongSelf = self {
strongSelf.hasOngoingBiometricsRequest = false
}
})
strongSelf.appLockContext.unlock()
strongSelf.hasOngoingBiometricsRequest = false
}
} else {
strongSelf.hasOngoingBiometricsRequest = false

View File

@ -17,7 +17,7 @@ private let subtitleFont = Font.regular(15.0)
private let buttonFont = Font.regular(17.0)
final class PasscodeEntryControllerNode: ASDisplayNode {
private let context: AccountContext
private let accountManager: AccountManager
private var theme: PresentationTheme
private var strings: PresentationStrings
private var wallpaper: TelegramWallpaper
@ -49,8 +49,8 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
var checkPasscode: ((String) -> Void)?
var requestBiometrics: (() -> Void)?
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, passcodeType: PasscodeEntryFieldType, biometricsType: LocalAuthBiometricAuthentication?, arguments: PasscodeEntryControllerPresentationArguments, statusBar: StatusBar) {
self.context = context
init(accountManager: AccountManager, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, passcodeType: PasscodeEntryFieldType, biometricsType: LocalAuthBiometricAuthentication?, arguments: PasscodeEntryControllerPresentationArguments, statusBar: StatusBar) {
self.accountManager = accountManager
self.theme = theme
self.strings = strings
self.wallpaper = wallpaper
@ -174,7 +174,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
switch self.wallpaper {
case .image, .file:
if let image = chatControllerBackgroundImage(theme: self.theme, wallpaper: self.wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, composed: false, knockoutMode: false) {
if let image = chatControllerBackgroundImage(theme: self.theme, wallpaper: self.wallpaper, mediaBox: self.accountManager.mediaBox, composed: false, knockoutMode: false) {
self.background = ImageBasedPasscodeBackground(image: image, size: size)
} else {
self.background = GradientPasscodeBackground(size: size, backgroundColors: self.theme.passcode.backgroundColors.colors, buttonColor: self.theme.passcode.buttonColor)

View File

@ -75,7 +75,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
switch self.mode {
case let .entry(challenge):
switch challenge {
case let .numericalPassword(value, _, _):
case let .numericalPassword(value):
passcodeType = value.count == 6 ? .digits6 : .digits4
default:
passcodeType = .alphanumeric

View File

@ -1151,6 +1151,9 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
}
})
self.emptyQueryListNode.beganInteractiveDragging = { [weak self] in
self?.dismissInput?()
}
self.listNode.beganInteractiveDragging = { [weak self] in
self?.dismissInput?()
}

View File

@ -22,17 +22,17 @@ public struct AccessChallengeAttempts: PostboxCoding, Equatable {
public enum PostboxAccessChallengeData: PostboxCoding, Equatable {
case none
case numericalPassword(value: String, timeout: Int32?, attempts: AccessChallengeAttempts?)
case plaintextPassword(value: String, timeout: Int32?, attempts: AccessChallengeAttempts?)
case numericalPassword(value: String)
case plaintextPassword(value: String)
public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("r", orElse: 0) {
case 0:
self = .none
case 1:
self = .numericalPassword(value: decoder.decodeStringForKey("t", orElse: ""), timeout: decoder.decodeOptionalInt32ForKey("a"), attempts: decoder.decodeObjectForKey("att", decoder: { AccessChallengeAttempts(decoder: $0) }) as? AccessChallengeAttempts)
self = .numericalPassword(value: decoder.decodeStringForKey("t", orElse: ""))
case 2:
self = .plaintextPassword(value: decoder.decodeStringForKey("t", orElse: ""), timeout: decoder.decodeOptionalInt32ForKey("a"), attempts: decoder.decodeObjectForKey("att", decoder: { AccessChallengeAttempts(decoder: $0) }) as? AccessChallengeAttempts)
self = .plaintextPassword(value: decoder.decodeStringForKey("t", orElse: ""))
default:
assertionFailure()
self = .none
@ -43,32 +43,12 @@ public enum PostboxAccessChallengeData: PostboxCoding, Equatable {
switch self {
case .none:
encoder.encodeInt32(0, forKey: "r")
case let .numericalPassword(text, timeout, attempts):
case let .numericalPassword(text):
encoder.encodeInt32(1, forKey: "r")
encoder.encodeString(text, forKey: "t")
if let timeout = timeout {
encoder.encodeInt32(timeout, forKey: "a")
} else {
encoder.encodeNil(forKey: "a")
}
if let attempts = attempts {
encoder.encodeObject(attempts, forKey: "att")
} else {
encoder.encodeNil(forKey: "att")
}
case let .plaintextPassword(text, timeout, attempts):
case let .plaintextPassword(text):
encoder.encodeInt32(2, forKey: "r")
encoder.encodeString(text, forKey: "t")
if let timeout = timeout {
encoder.encodeInt32(timeout, forKey: "a")
} else {
encoder.encodeNil(forKey: "a")
}
if let attempts = attempts {
encoder.encodeObject(attempts, forKey: "att")
} else {
encoder.encodeNil(forKey: "att")
}
}
}
@ -79,39 +59,6 @@ public enum PostboxAccessChallengeData: PostboxCoding, Equatable {
return true
}
}
public var autolockDeadline: Int32? {
switch self {
case .none:
return nil
case let .numericalPassword(_, timeout, _):
return timeout
case let .plaintextPassword(_, timeout, _):
return timeout
}
}
public var attempts: AccessChallengeAttempts? {
switch self {
case .none:
return nil
case let .numericalPassword(_, _, attempts):
return attempts
case let .plaintextPassword(_, _, attempts):
return attempts
}
}
public func withUpdatedAutolockDeadline(_ autolockDeadline: Int32?) -> PostboxAccessChallengeData {
switch self {
case .none:
return self
case let .numericalPassword(value, _, attempts):
return .numericalPassword(value: value, timeout: autolockDeadline, attempts: attempts)
case let .plaintextPassword(value, _, attempts):
return .plaintextPassword(value: value, timeout: autolockDeadline, attempts: attempts)
}
}
}
public struct AuthAccountRecord: PostboxCoding, Codable {

View File

@ -254,9 +254,9 @@ func passcodeOptionsController(context: AccountContext) -> ViewController {
let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in
var data = transaction.getAccessChallengeData()
if numerical {
data = PostboxAccessChallengeData.numericalPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.numericalPassword(value: passcode)
} else {
data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.plaintextPassword(value: passcode)
}
transaction.setAccessChallengeData(data)
@ -298,9 +298,9 @@ func passcodeOptionsController(context: AccountContext) -> ViewController {
let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in
var data = transaction.getAccessChallengeData()
if numerical {
data = PostboxAccessChallengeData.numericalPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.numericalPassword(value: passcode)
} else {
data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.plaintextPassword(value: passcode)
}
transaction.setAccessChallengeData(data)
}) |> deliverOnMainQueue).start(next: { _ in
@ -403,9 +403,9 @@ public func passcodeOptionsAccessController(context: AccountContext, animateIn:
let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in
var data = transaction.getAccessChallengeData()
if numerical {
data = PostboxAccessChallengeData.numericalPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.numericalPassword(value: passcode)
} else {
data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil)
data = PostboxAccessChallengeData.plaintextPassword(value: passcode)
}
transaction.setAccessChallengeData(data)
@ -426,9 +426,9 @@ public func passcodeOptionsAccessController(context: AccountContext, animateIn:
switch challenge {
case .none:
succeed = true
case let .numericalPassword(code, _, _):
case let .numericalPassword(code):
succeed = passcode == normalizeArabicNumeralString(code, type: .western)
case let .plaintextPassword(code, _, _):
case let .plaintextPassword(code):
succeed = passcode == code
}
if succeed {
@ -463,7 +463,7 @@ public func passcodeEntryController(context: AccountContext, animateIn: Bool = t
} else {
biometrics = .none
}
let controller = PasscodeEntryController(context: context, challengeData: challenge, biometrics: biometrics, arguments: PasscodeEntryControllerPresentationArguments(animated: false, fadeIn: true, cancel: {
let controller = PasscodeEntryController(applicationBindings: context.sharedContext.applicationBindings, accountManager: context.sharedContext.accountManager, appLockContext: context.sharedContext.appLockContext, presentationData: context.sharedContext.currentPresentationData.with { $0 }, presentationDataSignal: context.sharedContext.presentationData, challengeData: challenge, biometrics: biometrics, arguments: PasscodeEntryControllerPresentationArguments(animated: false, fadeIn: true, cancel: {
completion(false)
}))
controller.presentationCompleted = { [weak controller] in

View File

@ -910,13 +910,7 @@ public class Account {
}).start()
self.notificationAutolockReportManager = NotificationAutolockReportManager(deadline: self.autolockReportDeadline.get(), network: network)
self.autolockReportDeadline.set(
accountManager.accessChallengeData()
|> map { dataView -> Int32? in
guard let autolockDeadline = dataView.data.autolockDeadline else {
return nil
}
return autolockDeadline
}
networkArguments.autolockDeadine
|> distinctUntilChanged
)

View File

@ -410,14 +410,16 @@ public struct NetworkInitializationArguments {
public let appVersion: String
public let voipMaxLayer: Int32
public let appData: Signal<Data?, NoError>
public let autolockDeadine: Signal<Int32?, NoError>
public let encryptionProvider: EncryptionProvider
public init(apiId: Int32, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, appData: Signal<Data?, NoError>, encryptionProvider: EncryptionProvider) {
public init(apiId: Int32, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, appData: Signal<Data?, NoError>, autolockDeadine: Signal<Int32?, NoError>, encryptionProvider: EncryptionProvider) {
self.apiId = apiId
self.languagesCategory = languagesCategory
self.appVersion = appVersion
self.voipMaxLayer = voipMaxLayer
self.appData = appData
self.autolockDeadine = autolockDeadine
self.encryptionProvider = encryptionProvider
}
}

View File

@ -31,6 +31,7 @@ import UrlHandling
import WalletUrl
import WalletCore
import OpenSSLEncryptionProvider
import AppLock
#if canImport(BackgroundTasks)
import BackgroundTasks
@ -362,7 +363,7 @@ final class SharedApplicationContext {
Logger.shared.log("data", "can't deserialize")
}
return data
}, encryptionProvider: OpenSSLEncryptionProvider())
}, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider())
guard let appGroupUrl = maybeAppGroupUrl else {
UIAlertView(title: nil, message: "Error 2", delegate: nil, cancelButtonTitle: "OK").show()
@ -725,8 +726,13 @@ final class SharedApplicationContext {
let legacyBasePath = appGroupUrl.path
let legacyCache = LegacyCache(path: legacyBasePath + "/Caches")
let presentationDataPromise = Promise<PresentationData>()
let appLockContext = AppLockContextImpl(rootPath: rootPath, window: self.mainWindow!, applicationBindings: applicationBindings, accountManager: accountManager, presentationDataSignal: presentationDataPromise.get(), lockIconInitialFrame: {
return (self.mainWindow?.viewController as? TelegramRootController)?.chatListController?.lockViewFrame
})
var setPresentationCall: ((PresentationCall?) -> Void)?
let sharedContext = SharedAccountContextImpl(mainWindow: self.mainWindow, basePath: rootPath, encryptionParameters: encryptionParameters, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in
let sharedContext = SharedAccountContextImpl(mainWindow: self.mainWindow, basePath: rootPath, encryptionParameters: encryptionParameters, accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in
setPresentationCall?(call)
}, navigateToChat: { accountId, peerId, messageId in
self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId)
@ -748,6 +754,8 @@ final class SharedApplicationContext {
}
})
presentationDataPromise.set(sharedContext.presentationData)
let rawAccounts = sharedContext.activeAccounts
|> map { _, accounts, _ -> [Account] in
return accounts.map({ $0.1 })

View File

@ -22,14 +22,6 @@ import ImageBlur
import WatchBridge
import SettingsUI
func isAccessLocked(data: PostboxAccessChallengeData, at timestamp: Int32) -> Bool {
if data.isLockable, let autolockDeadline = data.autolockDeadline, autolockDeadline <= timestamp {
return true
} else {
return false
}
}
final class UnauthorizedApplicationContext {
let sharedContext: SharedAccountContextImpl
let account: UnauthorizedAccount
@ -56,14 +48,6 @@ final class UnauthorizedApplicationContext {
}
}
private struct PasscodeState: Equatable {
let isActive: Bool
let challengeData: PostboxAccessChallengeData
let autolockTimeout: Int32?
let enableBiometrics: Bool
let biometricsDomainState: Data?
}
final class AuthorizedApplicationContext {
let sharedApplicationContext: SharedApplicationContext
let mainWindow: Window1
@ -166,7 +150,7 @@ final class AuthorizedApplicationContext {
context.keyShortcutsController = keyShortcutsController
}
let previousPasscodeState = Atomic<PasscodeState?>(value: nil)
/*let previousPasscodeState = Atomic<PasscodeState?>(value: nil)
let passcodeStatusData = combineLatest(queue: Queue.mainQueue(), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), context.sharedContext.accountManager.accessChallengeData(), context.sharedContext.applicationBindings.applicationIsActive)
let passcodeState = passcodeStatusData
|> map { sharedData, accessChallengeDataView, isActive -> PasscodeState in
@ -331,7 +315,21 @@ final class AuthorizedApplicationContext {
} else {
strongSelf.isReady.set(.single(true))
}
}))
}))*/
if self.rootController.rootTabController == nil {
self.rootController.addRootControllers(showCallsTab: self.showCallsTab)
}
if let tabsController = self.rootController.viewControllers.first as? TabBarController, !tabsController.controllers.isEmpty, tabsController.selectedIndex >= 0 {
let controller = tabsController.controllers[tabsController.selectedIndex]
let combinedReady = combineLatest(tabsController.ready.get(), controller.ready.get())
|> map { $0 && $1 }
|> filter { $0 }
|> take(1)
self.isReady.set(combinedReady)
} else {
self.isReady.set(.single(true))
}
let accountId = context.account.id
self.loggedOutDisposable.set((context.account.loggedOut

View File

@ -15,6 +15,7 @@ import PhotoResources
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import OpenSSLEncryptionProvider
import AppLock
private enum NotificationContentAuthorizationError {
case unauthorized
@ -145,7 +146,15 @@ public final class NotificationViewControllerImpl {
f(false)
})
sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, appData: .single(self.initializationData.bundleData), encryptionProvider: OpenSSLEncryptionProvider()), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
let presentationDataPromise = Promise<PresentationData>()
let appLockContext = AppLockContextImpl(rootPath: rootPath, window: nil, applicationBindings: applicationBindings, accountManager: accountManager, presentationDataSignal: presentationDataPromise.get(), lockIconInitialFrame: {
return nil
})
sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider()), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
presentationDataPromise.set(sharedAccountContext!.presentationData)
}
}

View File

@ -13,6 +13,7 @@ import PeerInfoUI
import ShareItems
import SettingsUI
import OpenSSLEncryptionProvider
import AppLock
private let inForeground = ValuePromise<Bool>(false, ignoreRepeated: true)
@ -173,7 +174,14 @@ public class ShareRootControllerImpl {
})
semaphore.wait()
let sharedContext = SharedAccountContextImpl(mainWindow: nil, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, appData: .single(self.initializationData.bundleData), encryptionProvider: OpenSSLEncryptionProvider()), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
let presentationDataPromise = Promise<PresentationData>()
let appLockContext = AppLockContextImpl(rootPath: rootPath, window: nil, applicationBindings: applicationBindings, accountManager: accountManager, presentationDataSignal: presentationDataPromise.get(), lockIconInitialFrame: {
return nil
})
let sharedContext = SharedAccountContextImpl(mainWindow: nil, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider()), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
presentationDataPromise.set(sharedContext.presentationData)
internalContext = InternalContext(sharedContext: sharedContext)
globalInternalContext = internalContext
}

View File

@ -60,6 +60,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
public let applicationBindings: TelegramApplicationBindings
public let basePath: String
public let accountManager: AccountManager
public let appLockContext: AppLockContext
private let navigateToChatImpl: (AccountRecordId, PeerId, MessageId?) -> Void
@ -146,7 +147,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
private var widgetDataContext: WidgetDataContext?
public init(mainWindow: Window1?, basePath: String, encryptionParameters: ValueBoxEncryptionParameters, accountManager: AccountManager, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, rootPath: String, legacyBasePath: String?, legacyCache: LegacyCache?, apsNotificationToken: Signal<Data?, NoError>, voipNotificationToken: Signal<Data?, NoError>, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) {
public init(mainWindow: Window1?, basePath: String, encryptionParameters: ValueBoxEncryptionParameters, accountManager: AccountManager, appLockContext: AppLockContext, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, rootPath: String, legacyBasePath: String?, legacyCache: LegacyCache?, apsNotificationToken: Signal<Data?, NoError>, voipNotificationToken: Signal<Data?, NoError>, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) {
assert(Queue.mainQueue().isCurrent())
precondition(!testHasInstance)
@ -158,6 +159,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
self.accountManager = accountManager
self.navigateToChatImpl = navigateToChat
self.displayUpgradeProgress = displayUpgradeProgress
self.appLockContext = appLockContext
self.accountManager.mediaBox.fetchCachedResourceRepresentation = { (resource, representation) -> Signal<CachedMediaResourceRepresentationResult, NoError> in
return fetchCachedSharedResourceRepresentation(accountManager: accountManager, resource: resource, representation: representation)