mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
8fe68fd1ed
@ -55,7 +55,25 @@ enum IntentHandlingError {
|
|||||||
|
|
||||||
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
||||||
@objc(IntentHandler)
|
@objc(IntentHandler)
|
||||||
class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling, INSearchCallHistoryIntentHandling {
|
class IntentHandler: INExtension {
|
||||||
|
override public func handler(for intent: INIntent) -> Any {
|
||||||
|
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
|
||||||
|
if intent is SelectAvatarFriendsIntent {
|
||||||
|
return AvatarsIntentHandler()
|
||||||
|
} else if intent is SelectFriendsIntent {
|
||||||
|
return FriendsIntentHandler()
|
||||||
|
} else {
|
||||||
|
return DefaultIntentHandler()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return DefaultIntentHandler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
||||||
|
@objc(IntentHandler)
|
||||||
|
class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling, INSearchCallHistoryIntentHandling {
|
||||||
private let accountPromise = Promise<Account?>()
|
private let accountPromise = Promise<Account?>()
|
||||||
private let allAccounts = Promise<[(AccountRecordId, PeerId, Bool)]>()
|
private let allAccounts = Promise<[(AccountRecordId, PeerId, Bool)]>()
|
||||||
|
|
||||||
@ -106,7 +124,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
|||||||
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
||||||
|
|
||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true)
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false)
|
||||||
self.accountManager = accountManager
|
self.accountManager = accountManager
|
||||||
|
|
||||||
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
|
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
|
||||||
@ -195,20 +213,6 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
|||||||
self.searchDisposable.dispose()
|
self.searchDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func handler(for intent: INIntent) -> Any {
|
|
||||||
if #available(iOSApplicationExtension 12.0, iOS 12.0, *) {
|
|
||||||
if intent is SelectAvatarFriendsIntent {
|
|
||||||
return AvatarsIntentHandler()
|
|
||||||
} else if intent is SelectFriendsIntent {
|
|
||||||
return FriendsIntentHandler()
|
|
||||||
} else {
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ResolveResult {
|
enum ResolveResult {
|
||||||
case success(INPerson)
|
case success(INPerson)
|
||||||
case disambiguation([INPerson])
|
case disambiguation([INPerson])
|
||||||
@ -789,7 +793,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
|||||||
var accountResults: [Signal<INObjectSection<Friend>, Error>] = []
|
var accountResults: [Signal<INObjectSection<Friend>, Error>] = []
|
||||||
|
|
||||||
for (accountId, accountPeerId, _) in accounts {
|
for (accountId, accountPeerId, _) in accounts {
|
||||||
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> INObjectSection<Friend> in
|
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> INObjectSection<Friend> in
|
||||||
var accountTitle: String = ""
|
var accountTitle: String = ""
|
||||||
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
||||||
if let username = peer.username, !username.isEmpty {
|
if let username = peer.username, !username.isEmpty {
|
||||||
@ -958,7 +962,7 @@ private final class WidgetIntentHandler {
|
|||||||
var accountResults: [Signal<INObjectSection<Friend>, Error>] = []
|
var accountResults: [Signal<INObjectSection<Friend>, Error>] = []
|
||||||
|
|
||||||
for (accountId, accountPeerId, _) in accounts {
|
for (accountId, accountPeerId, _) in accounts {
|
||||||
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> INObjectSection<Friend> in
|
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> INObjectSection<Friend> in
|
||||||
var accountTitle: String = ""
|
var accountTitle: String = ""
|
||||||
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
||||||
if let username = peer.username, !username.isEmpty {
|
if let username = peer.username, !username.isEmpty {
|
||||||
@ -1041,7 +1045,7 @@ private final class WidgetIntentHandler {
|
|||||||
if !isActive {
|
if !isActive {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [Friend] in
|
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [Friend] in
|
||||||
var peers: [Peer] = []
|
var peers: [Peer] = []
|
||||||
|
|
||||||
for id in getRecentPeers(transaction: transaction) {
|
for id in getRecentPeers(transaction: transaction) {
|
||||||
|
@ -59,22 +59,6 @@ private let accountAuxiliaryMethods = AccountAuxiliaryMethods(updatePeerChatInpu
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
private struct ApplicationSettings {
|
|
||||||
let logging: LoggingSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
private func applicationSettings(accountManager: AccountManager) -> Signal<ApplicationSettings, NoError> {
|
|
||||||
return accountManager.transaction { transaction -> ApplicationSettings in
|
|
||||||
let loggingSettings: LoggingSettings
|
|
||||||
if let value = transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings {
|
|
||||||
loggingSettings = value
|
|
||||||
} else {
|
|
||||||
loggingSettings = LoggingSettings.defaultSettings
|
|
||||||
}
|
|
||||||
return ApplicationSettings(logging: loggingSettings)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func rootPathForBasePath(_ appGroupPath: String) -> String {
|
private func rootPathForBasePath(_ appGroupPath: String) -> String {
|
||||||
return appGroupPath + "/telegram-data"
|
return appGroupPath + "/telegram-data"
|
||||||
}
|
}
|
||||||
@ -155,7 +139,7 @@ struct Provider: IntentTimelineProvider {
|
|||||||
|
|
||||||
var friendsByAccount: [Signal<[ParsedPeer], NoError>] = []
|
var friendsByAccount: [Signal<[ParsedPeer], NoError>] = []
|
||||||
for (accountId, items) in itemsByAccount {
|
for (accountId, items) in itemsByAccount {
|
||||||
friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [ParsedPeer] in
|
friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [ParsedPeer] in
|
||||||
guard let state = transaction.getState() as? AuthorizedAccountState else {
|
guard let state = transaction.getState() as? AuthorizedAccountState else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -313,7 +297,7 @@ struct AvatarsProvider: IntentTimelineProvider {
|
|||||||
|
|
||||||
var friendsByAccount: [Signal<[ParsedPeer], NoError>] = []
|
var friendsByAccount: [Signal<[ParsedPeer], NoError>] = []
|
||||||
for (accountId, items) in itemsByAccount {
|
for (accountId, items) in itemsByAccount {
|
||||||
friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [ParsedPeer] in
|
friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [ParsedPeer] in
|
||||||
guard let state = transaction.getState() as? AuthorizedAccountState else {
|
guard let state = transaction.getState() as? AuthorizedAccountState else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ final class AccountManagerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, temporarySessionId: Int64) {
|
fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, isReadOnly: Bool, temporarySessionId: Int64) {
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
let startTime = CFAbsoluteTimeGetCurrent()
|
||||||
|
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
@ -73,11 +73,11 @@ final class AccountManagerImpl {
|
|||||||
self.atomicStatePath = "\(basePath)/atomic-state"
|
self.atomicStatePath = "\(basePath)/atomic-state"
|
||||||
self.temporarySessionId = temporarySessionId
|
self.temporarySessionId = temporarySessionId
|
||||||
let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
|
let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
|
||||||
guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, encryptionParameters: nil, upgradeProgress: { _ in }) else {
|
guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, isReadOnly: false, encryptionParameters: nil, upgradeProgress: { _ in }) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
self.guardValueBox = guardValueBox
|
self.guardValueBox = guardValueBox
|
||||||
guard let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: nil, upgradeProgress: { _ in }) else {
|
guard let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: nil, upgradeProgress: { _ in }) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
self.valueBox = valueBox
|
self.valueBox = valueBox
|
||||||
@ -468,7 +468,7 @@ public final class AccountManager {
|
|||||||
return AccountManagerImpl.getCurrentRecords(basePath: basePath)
|
return AccountManagerImpl.getCurrentRecords(basePath: basePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(basePath: String, isTemporary: Bool) {
|
public init(basePath: String, isTemporary: Bool, isReadOnly: Bool) {
|
||||||
self.queue = sharedQueue
|
self.queue = sharedQueue
|
||||||
self.basePath = basePath
|
self.basePath = basePath
|
||||||
var temporarySessionId: Int64 = 0
|
var temporarySessionId: Int64 = 0
|
||||||
@ -476,7 +476,7 @@ public final class AccountManager {
|
|||||||
self.temporarySessionId = temporarySessionId
|
self.temporarySessionId = temporarySessionId
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||||
if let value = AccountManagerImpl(queue: queue, basePath: basePath, isTemporary: isTemporary, temporarySessionId: temporarySessionId) {
|
if let value = AccountManagerImpl(queue: queue, basePath: basePath, isTemporary: isTemporary, isReadOnly: isReadOnly, temporarySessionId: temporarySessionId) {
|
||||||
return value
|
return value
|
||||||
} else {
|
} else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
|
@ -28,11 +28,16 @@ import sqlcipher
|
|||||||
public final class Database {
|
public final class Database {
|
||||||
internal var handle: OpaquePointer? = nil
|
internal var handle: OpaquePointer? = nil
|
||||||
|
|
||||||
public init?(_ location: String) {
|
public init?(_ location: String, readOnly: Bool) {
|
||||||
if location != ":memory:" {
|
if location != ":memory:" {
|
||||||
let _ = open(location + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
let _ = open(location + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
||||||
}
|
}
|
||||||
let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
|
let flags: Int32
|
||||||
|
if readOnly {
|
||||||
|
flags = SQLITE_OPEN_READONLY
|
||||||
|
} else {
|
||||||
|
flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
|
||||||
|
}
|
||||||
let res = sqlite3_open_v2(location, &self.handle, flags, nil)
|
let res = sqlite3_open_v2(location, &self.handle, flags, nil)
|
||||||
if res != SQLITE_OK {
|
if res != SQLITE_OK {
|
||||||
postboxLog("sqlite3_open_v2: \(res)")
|
postboxLog("sqlite3_open_v2: \(res)")
|
||||||
|
@ -1125,7 +1125,7 @@ func debugRestoreState(basePath:String, name: String) {
|
|||||||
|
|
||||||
private let sharedQueue = Queue(name: "org.telegram.postbox.Postbox")
|
private let sharedQueue = Queue(name: "org.telegram.postbox.Postbox")
|
||||||
|
|
||||||
public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool) -> Signal<PostboxResult, NoError> {
|
public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, isReadOnly: Bool) -> Signal<PostboxResult, NoError> {
|
||||||
let queue = sharedQueue
|
let queue = sharedQueue
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
queue.async {
|
queue.async {
|
||||||
@ -1138,7 +1138,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
|||||||
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
let startTime = CFAbsoluteTimeGetCurrent()
|
||||||
|
|
||||||
guard var valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
guard var valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
||||||
subscriber.putNext(.upgrading(progress))
|
subscriber.putNext(.upgrading(progress))
|
||||||
}) else {
|
}) else {
|
||||||
subscriber.putNext(.error)
|
subscriber.putNext(.error)
|
||||||
@ -1161,7 +1161,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
|||||||
postboxLog("Version \(userVersion) is newer than supported")
|
postboxLog("Version \(userVersion) is newer than supported")
|
||||||
assertionFailure("Version \(userVersion) is newer than supported")
|
assertionFailure("Version \(userVersion) is newer than supported")
|
||||||
valueBox.drop()
|
valueBox.drop()
|
||||||
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
||||||
subscriber.putNext(.upgrading(progress))
|
subscriber.putNext(.upgrading(progress))
|
||||||
}) else {
|
}) else {
|
||||||
subscriber.putNext(.error)
|
subscriber.putNext(.error)
|
||||||
@ -1185,7 +1185,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
|||||||
valueBox.internalClose()
|
valueBox.internalClose()
|
||||||
let _ = try? FileManager.default.removeItem(atPath: basePath + "/db")
|
let _ = try? FileManager.default.removeItem(atPath: basePath + "/db")
|
||||||
let _ = try? FileManager.default.moveItem(atPath: updatedPath, toPath: basePath + "/db")
|
let _ = try? FileManager.default.moveItem(atPath: updatedPath, toPath: basePath + "/db")
|
||||||
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
||||||
subscriber.putNext(.upgrading(progress))
|
subscriber.putNext(.upgrading(progress))
|
||||||
}) else {
|
}) else {
|
||||||
subscriber.putNext(.error)
|
subscriber.putNext(.error)
|
||||||
@ -1199,7 +1199,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
|||||||
assertionFailure("Couldn't find any upgrade for \(userVersion)")
|
assertionFailure("Couldn't find any upgrade for \(userVersion)")
|
||||||
postboxLog("Couldn't find any upgrade for \(userVersion)")
|
postboxLog("Couldn't find any upgrade for \(userVersion)")
|
||||||
valueBox.drop()
|
valueBox.drop()
|
||||||
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
|
||||||
subscriber.putNext(.upgrading(progress))
|
subscriber.putNext(.upgrading(progress))
|
||||||
}) else {
|
}) else {
|
||||||
subscriber.putNext(.error)
|
subscriber.putNext(.error)
|
||||||
@ -1538,10 +1538,12 @@ public final class Postbox {
|
|||||||
self.messageHistoryMetadataTable.setShouldReindexUnreadCountsState(value: reindexUnreadVersion)
|
self.messageHistoryMetadataTable.setShouldReindexUnreadCountsState(value: reindexUnreadVersion)
|
||||||
}
|
}
|
||||||
//#if DEBUG
|
//#if DEBUG
|
||||||
|
if !isTemporary {
|
||||||
self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true)
|
self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true)
|
||||||
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
if self.messageHistoryMetadataTable.shouldReindexUnreadCounts() {
|
if !isTemporary && self.messageHistoryMetadataTable.shouldReindexUnreadCounts() {
|
||||||
self.groupMessageStatsTable.removeAll()
|
self.groupMessageStatsTable.removeAll()
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
let startTime = CFAbsoluteTimeGetCurrent()
|
||||||
let (totalStates, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
let (totalStates, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||||
|
@ -162,6 +162,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
|
|
||||||
fileprivate let basePath: String
|
fileprivate let basePath: String
|
||||||
private let isTemporary: Bool
|
private let isTemporary: Bool
|
||||||
|
private let isReadOnly: Bool
|
||||||
private let inMemory: Bool
|
private let inMemory: Bool
|
||||||
private let encryptionParameters: ValueBoxEncryptionParameters?
|
private let encryptionParameters: ValueBoxEncryptionParameters?
|
||||||
private let databasePath: String
|
private let databasePath: String
|
||||||
@ -200,14 +201,15 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
|
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
|
|
||||||
public init?(basePath: String, queue: Queue, isTemporary: Bool, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) {
|
public init?(basePath: String, queue: Queue, isTemporary: Bool, isReadOnly: Bool, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) {
|
||||||
self.basePath = basePath
|
self.basePath = basePath
|
||||||
self.isTemporary = isTemporary
|
self.isTemporary = isTemporary
|
||||||
|
self.isReadOnly = isReadOnly
|
||||||
self.inMemory = inMemory
|
self.inMemory = inMemory
|
||||||
self.encryptionParameters = encryptionParameters
|
self.encryptionParameters = encryptionParameters
|
||||||
self.databasePath = basePath + "/db_sqlite"
|
self.databasePath = basePath + "/db_sqlite"
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
if let database = self.openDatabase(encryptionParameters: encryptionParameters, isTemporary: isTemporary, upgradeProgress: upgradeProgress) {
|
if let database = self.openDatabase(encryptionParameters: encryptionParameters, isTemporary: isTemporary, isReadOnly: isReadOnly, upgradeProgress: upgradeProgress) {
|
||||||
self.database = database
|
self.database = database
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -224,7 +226,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
self.database = nil
|
self.database = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func openDatabase(encryptionParameters: ValueBoxEncryptionParameters?, isTemporary: Bool, upgradeProgress: (Float) -> Void) -> Database? {
|
private func openDatabase(encryptionParameters: ValueBoxEncryptionParameters?, isTemporary: Bool, isReadOnly: Bool, upgradeProgress: (Float) -> Void) -> Database? {
|
||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
|
|
||||||
checkpoints.set(nil)
|
checkpoints.set(nil)
|
||||||
@ -261,18 +263,23 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
var database: Database
|
var database: Database
|
||||||
if let result = Database(self.inMemory ? ":memory:" : path) {
|
if let result = Database(self.inMemory ? ":memory:" : path, readOnly: isReadOnly) {
|
||||||
database = result
|
database = result
|
||||||
} else {
|
} else {
|
||||||
postboxLog("Couldn't open DB")
|
postboxLog("Couldn't open DB")
|
||||||
|
|
||||||
|
if isReadOnly {
|
||||||
|
postboxLog("Readonly, exiting")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
let tempPath = basePath + "_test\(arc4random())"
|
let tempPath = basePath + "_test\(arc4random())"
|
||||||
enum TempError: Error {
|
enum TempError: Error {
|
||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
try FileManager.default.createDirectory(atPath: tempPath, withIntermediateDirectories: true, attributes: nil)
|
try FileManager.default.createDirectory(atPath: tempPath, withIntermediateDirectories: true, attributes: nil)
|
||||||
let testDatabase = Database(tempPath + "/test_db")!
|
let testDatabase = Database(tempPath + "/test_db", readOnly: false)!
|
||||||
var resultCode = testDatabase.execute("PRAGMA journal_mode=WAL")
|
var resultCode = testDatabase.execute("PRAGMA journal_mode=WAL")
|
||||||
if !resultCode {
|
if !resultCode {
|
||||||
throw TempError.generic
|
throw TempError.generic
|
||||||
@ -309,7 +316,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
|
|
||||||
if self.isEncrypted(database) {
|
if self.isEncrypted(database) {
|
||||||
if isTemporary {
|
if isTemporary || isReadOnly {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
postboxLog("Encryption key is invalid")
|
postboxLog("Encryption key is invalid")
|
||||||
@ -317,7 +324,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
for fileName in dabaseFileNames {
|
for fileName in dabaseFileNames {
|
||||||
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
||||||
}
|
}
|
||||||
database = Database(path)!
|
database = Database(path, readOnly: false)!
|
||||||
|
|
||||||
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
@ -329,11 +336,15 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
postboxLog("Encryption key is required")
|
postboxLog("Encryption key is required")
|
||||||
|
if isReadOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
assert(false)
|
assert(false)
|
||||||
for fileName in dabaseFileNames {
|
for fileName in dabaseFileNames {
|
||||||
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
||||||
}
|
}
|
||||||
database = Database(path)!
|
database = Database(path, readOnly: false)!
|
||||||
|
|
||||||
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
@ -344,6 +355,10 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
let hexKey = hexString(encryptionParameters.key.data + encryptionParameters.salt.data)
|
let hexKey = hexString(encryptionParameters.key.data + encryptionParameters.salt.data)
|
||||||
|
|
||||||
if FileManager.default.fileExists(atPath: path) {
|
if FileManager.default.fileExists(atPath: path) {
|
||||||
|
if isReadOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
postboxLog("Reencrypting database")
|
postboxLog("Reencrypting database")
|
||||||
database = self.reencryptInPlace(database: database, encryptionParameters: encryptionParameters)
|
database = self.reencryptInPlace(database: database, encryptionParameters: encryptionParameters)
|
||||||
|
|
||||||
@ -353,7 +368,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
for fileName in dabaseFileNames {
|
for fileName in dabaseFileNames {
|
||||||
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
||||||
}
|
}
|
||||||
database = Database(path)!
|
database = Database(path, readOnly: false)!
|
||||||
|
|
||||||
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
@ -373,10 +388,14 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
postboxLog("Encryption setup failed")
|
postboxLog("Encryption setup failed")
|
||||||
//assert(false)
|
//assert(false)
|
||||||
|
|
||||||
|
if isReadOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
for fileName in dabaseFileNames {
|
for fileName in dabaseFileNames {
|
||||||
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)")
|
||||||
}
|
}
|
||||||
database = Database(path)!
|
database = Database(path, readOnly: false)!
|
||||||
|
|
||||||
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
@ -459,9 +478,14 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
|
|
||||||
public func begin() {
|
public func begin() {
|
||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
|
if self.isReadOnly {
|
||||||
|
let resultCode = self.database.execute("BEGIN DEFERRED")
|
||||||
|
assert(resultCode)
|
||||||
|
} else {
|
||||||
let resultCode = self.database.execute("BEGIN IMMEDIATE")
|
let resultCode = self.database.execute("BEGIN IMMEDIATE")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func commit() {
|
public func commit() {
|
||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
@ -477,9 +501,14 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
|
|
||||||
private func beginInternal(database: Database) {
|
private func beginInternal(database: Database) {
|
||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
|
if self.isReadOnly {
|
||||||
|
let resultCode = database.execute("BEGIN DEFERRED")
|
||||||
|
assert(resultCode)
|
||||||
|
} else {
|
||||||
let resultCode = database.execute("BEGIN IMMEDIATE")
|
let resultCode = database.execute("BEGIN IMMEDIATE")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func commitInternal(database: Database) {
|
private func commitInternal(database: Database) {
|
||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
@ -2074,6 +2103,10 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
precondition(self.queue.isCurrent())
|
precondition(self.queue.isCurrent())
|
||||||
self.clearStatements()
|
self.clearStatements()
|
||||||
|
|
||||||
|
if self.isReadOnly {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
self.lock.lock()
|
self.lock.lock()
|
||||||
self.database = nil
|
self.database = nil
|
||||||
self.lock.unlock()
|
self.lock.unlock()
|
||||||
@ -2084,7 +2117,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
let _ = try? FileManager.default.removeItem(atPath: self.basePath + "/\(fileName)")
|
let _ = try? FileManager.default.removeItem(atPath: self.basePath + "/\(fileName)")
|
||||||
}
|
}
|
||||||
|
|
||||||
self.database = self.openDatabase(encryptionParameters: self.encryptionParameters, isTemporary: self.isTemporary, upgradeProgress: { _ in })
|
self.database = self.openDatabase(encryptionParameters: self.encryptionParameters, isTemporary: self.isTemporary, isReadOnly: false, upgradeProgress: { _ in })
|
||||||
|
|
||||||
tables.removeAll()
|
tables.removeAll()
|
||||||
}
|
}
|
||||||
@ -2119,6 +2152,10 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func reencryptInPlace(database: Database, encryptionParameters: ValueBoxEncryptionParameters) -> Database {
|
private func reencryptInPlace(database: Database, encryptionParameters: ValueBoxEncryptionParameters) -> Database {
|
||||||
|
if self.isReadOnly {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
let targetPath = self.basePath + "/db_export"
|
let targetPath = self.basePath + "/db_export"
|
||||||
let _ = try? FileManager.default.removeItem(atPath: targetPath)
|
let _ = try? FileManager.default.removeItem(atPath: targetPath)
|
||||||
|
|
||||||
@ -2130,7 +2167,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
}
|
}
|
||||||
let _ = try? FileManager.default.removeItem(atPath: targetPath)
|
let _ = try? FileManager.default.removeItem(atPath: targetPath)
|
||||||
|
|
||||||
let updatedDatabase = Database(self.databasePath)!
|
let updatedDatabase = Database(self.databasePath, readOnly: false)!
|
||||||
|
|
||||||
var resultCode = updatedDatabase.execute("PRAGMA cipher_plaintext_header_size=32")
|
var resultCode = updatedDatabase.execute("PRAGMA cipher_plaintext_header_size=32")
|
||||||
assert(resultCode)
|
assert(resultCode)
|
||||||
|
@ -73,9 +73,9 @@ public enum AccountTransactionError {
|
|||||||
case couldNotOpen
|
case couldNotOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, transaction: @escaping (Postbox, Transaction) -> T) -> Signal<T, AccountTransactionError> {
|
public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, isReadOnly: Bool, transaction: @escaping (Postbox, Transaction) -> T) -> Signal<T, AccountTransactionError> {
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true)
|
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: isReadOnly)
|
||||||
return postbox
|
return postbox
|
||||||
|> castError(AccountTransactionError.self)
|
|> castError(AccountTransactionError.self)
|
||||||
|> mapToSignal { value -> Signal<T, AccountTransactionError> in
|
|> mapToSignal { value -> Signal<T, AccountTransactionError> in
|
||||||
|
@ -160,7 +160,7 @@ public enum AccountPreferenceEntriesResult {
|
|||||||
|
|
||||||
public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set<ValueBoxKey>, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountPreferenceEntriesResult, NoError> {
|
public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set<ValueBoxKey>, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountPreferenceEntriesResult, NoError> {
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true)
|
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true)
|
||||||
return postbox
|
return postbox
|
||||||
|> mapToSignal { value -> Signal<AccountPreferenceEntriesResult, NoError> in
|
|> mapToSignal { value -> Signal<AccountPreferenceEntriesResult, NoError> in
|
||||||
switch value {
|
switch value {
|
||||||
@ -189,7 +189,7 @@ public enum AccountNoticeEntriesResult {
|
|||||||
|
|
||||||
public func accountNoticeEntries(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountNoticeEntriesResult, NoError> {
|
public func accountNoticeEntries(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountNoticeEntriesResult, NoError> {
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true)
|
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true)
|
||||||
return postbox
|
return postbox
|
||||||
|> mapToSignal { value -> Signal<AccountNoticeEntriesResult, NoError> in
|
|> mapToSignal { value -> Signal<AccountNoticeEntriesResult, NoError> in
|
||||||
switch value {
|
switch value {
|
||||||
@ -212,7 +212,7 @@ public enum LegacyAccessChallengeDataResult {
|
|||||||
|
|
||||||
public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<LegacyAccessChallengeDataResult, NoError> {
|
public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<LegacyAccessChallengeDataResult, NoError> {
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true)
|
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true)
|
||||||
return postbox
|
return postbox
|
||||||
|> mapToSignal { value -> Signal<LegacyAccessChallengeDataResult, NoError> in
|
|> mapToSignal { value -> Signal<LegacyAccessChallengeDataResult, NoError> in
|
||||||
switch value {
|
switch value {
|
||||||
@ -231,7 +231,7 @@ public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecord
|
|||||||
public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, backupData: AccountBackupData?, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
|
public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, backupData: AccountBackupData?, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
|
|
||||||
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false)
|
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false, isReadOnly: false)
|
||||||
|
|
||||||
return postbox
|
return postbox
|
||||||
|> mapToSignal { result -> Signal<AccountResult, NoError> in
|
|> mapToSignal { result -> Signal<AccountResult, NoError> in
|
||||||
|
@ -214,7 +214,7 @@ public func temporaryAccount(manager: AccountManager, rootPath: String, encrypti
|
|||||||
return manager.allocatedTemporaryAccountId()
|
return manager.allocatedTemporaryAccountId()
|
||||||
|> mapToSignal { id -> Signal<TemporaryAccount, NoError> in
|
|> mapToSignal { id -> Signal<TemporaryAccount, NoError> in
|
||||||
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
|
||||||
return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false)
|
return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false, isReadOnly: false)
|
||||||
|> mapToSignal { result -> Signal<TemporaryAccount, NoError> in
|
|> mapToSignal { result -> Signal<TemporaryAccount, NoError> in
|
||||||
switch result {
|
switch result {
|
||||||
case .upgrading:
|
case .upgrading:
|
||||||
|
@ -664,7 +664,7 @@ final class SharedApplicationContext {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let accountManagerSignal = Signal<AccountManager, NoError> { subscriber in
|
let accountManagerSignal = Signal<AccountManager, NoError> { subscriber in
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: false)
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: false, isReadOnly: false)
|
||||||
return (upgradedAccounts(accountManager: accountManager, rootPath: rootPath, encryptionParameters: encryptionParameters)
|
return (upgradedAccounts(accountManager: accountManager, rootPath: rootPath, encryptionParameters: encryptionParameters)
|
||||||
|> deliverOnMainQueue).start(next: { progress in
|
|> deliverOnMainQueue).start(next: { progress in
|
||||||
if self.dataImportSplash == nil {
|
if self.dataImportSplash == nil {
|
||||||
|
@ -113,7 +113,7 @@ public final class NotificationViewControllerImpl {
|
|||||||
|
|
||||||
if sharedAccountContext == nil {
|
if sharedAccountContext == nil {
|
||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true)
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false)
|
||||||
|
|
||||||
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
|
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
|
||||||
let semaphore = DispatchSemaphore(value: 0)
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
|
@ -202,7 +202,7 @@ public class ShareRootControllerImpl {
|
|||||||
|
|
||||||
let internalContext: InternalContext
|
let internalContext: InternalContext
|
||||||
|
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true)
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false)
|
||||||
|
|
||||||
if let globalInternalContext = globalInternalContext {
|
if let globalInternalContext = globalInternalContext {
|
||||||
internalContext = globalInternalContext
|
internalContext = globalInternalContext
|
||||||
|
@ -290,7 +290,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e
|
|||||||
|> mapToSignal { globalSettings, ids -> Signal<Never, NoError> in
|
|> mapToSignal { globalSettings, ids -> Signal<Never, NoError> in
|
||||||
var importSignal: Signal<Never, NoError> = .complete()
|
var importSignal: Signal<Never, NoError> = .complete()
|
||||||
for id in ids {
|
for id in ids {
|
||||||
let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, transaction: { _, transaction -> Void in
|
let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, isReadOnly: false, transaction: { _, transaction -> Void in
|
||||||
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
|
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
|
||||||
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
|
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||||
settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts
|
settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts
|
||||||
|
Loading…
x
Reference in New Issue
Block a user