Update notification service

This commit is contained in:
Ali 2021-09-13 20:40:09 +04:00
parent e4d277daf9
commit 0553a14eb3
50 changed files with 600 additions and 796 deletions

View File

@ -15,7 +15,8 @@ swift_library(
"//submodules/EncryptionProvider:EncryptionProvider", "//submodules/EncryptionProvider:EncryptionProvider",
"//submodules/AppLockState:AppLockState", "//submodules/AppLockState:AppLockState",
"//submodules/NotificationsPresentationData:NotificationsPresentationData", "//submodules/NotificationsPresentationData:NotificationsPresentationData",
"//Telegram/NotificationService/NotificationServiceObjC:NotificationServiceObjC", "//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider"
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -1,17 +0,0 @@
import Foundation
/*import ValueBox
private func applicationSpecificSharedDataKey(_ value: Int32) -> ValueBoxKey {
let key = ValueBoxKey(length: 4)
key.setInt32(0, value: value + 1000)
return key
}
private enum ApplicationSpecificSharedDataKeyValues: Int32 {
case inAppNotificationSettings = 0
}
public struct ApplicationSpecificSharedDataKeys {
public static let inAppNotificationSettings = applicationSpecificSharedDataKey(ApplicationSpecificSharedDataKeyValues.inAppNotificationSettings.rawValue)
}
*/

View File

@ -1 +0,0 @@
import Foundation

View File

@ -1,55 +0,0 @@
/*import PostboxDataTypes
struct LegacyPeerSummaryCounterTags: OptionSet, Sequence, Hashable {
var rawValue: Int32
init(rawValue: Int32) {
self.rawValue = rawValue
}
static let regularChatsAndPrivateGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 0)
static let publicGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 1)
static let channels = LegacyPeerSummaryCounterTags(rawValue: 1 << 2)
public func makeIterator() -> AnyIterator<LegacyPeerSummaryCounterTags> {
var index = 0
return AnyIterator { () -> LegacyPeerSummaryCounterTags? in
while index < 31 {
let currentTags = self.rawValue >> UInt32(index)
let tag = LegacyPeerSummaryCounterTags(rawValue: 1 << UInt32(index))
index += 1
if currentTags == 0 {
break
}
if (currentTags & 1) != 0 {
return tag
}
}
return nil
}
}
}
extension PeerSummaryCounterTags {
static let privateChat = PeerSummaryCounterTags(rawValue: 1 << 3)
static let secretChat = PeerSummaryCounterTags(rawValue: 1 << 4)
static let privateGroup = PeerSummaryCounterTags(rawValue: 1 << 5)
static let bot = PeerSummaryCounterTags(rawValue: 1 << 6)
static let channel = PeerSummaryCounterTags(rawValue: 1 << 7)
static let publicGroup = PeerSummaryCounterTags(rawValue: 1 << 8)
}
struct Namespaces {
struct Message {
static let Cloud: Int32 = 0
}
struct Peer {
static let CloudUser: Int32 = 0
static let CloudGroup: Int32 = 1
static let CloudChannel: Int32 = 2
static let SecretChat: Int32 = 3
}
}
*/

View File

@ -1,53 +1,270 @@
import Foundation import Foundation
import UserNotifications import UserNotifications
import SwiftSignalKit import SwiftSignalKit
import NotificationServiceObjC
import Postbox import Postbox
import TelegramCore import TelegramCore
import BuildConfig
import OpenSSLEncryptionProvider
import TelegramUIPreferences
private let queue = Queue() private let queue = Queue()
private var installedSharedLogger = false
private func setupSharedLogger(rootPath: String, path: String) {
if !installedSharedLogger {
installedSharedLogger = true
Logger.setSharedLogger(Logger(rootPath: rootPath, basePath: path))
}
}
private let accountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResource: { account, resource, ranges, _ in
return nil
}, fetchResourceMediaReferenceHash: { resource in
return .single(nil)
}, prepareSecretThumbnailData: { _ in
return nil
})
private func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
}
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
private struct NotificationContent {
var title: String?
var subtitle: String?
var body: String?
var badge: Int?
func asNotificationContent() -> UNNotificationContent {
let content = UNMutableNotificationContent()
content.title = self.title ?? ""
content.subtitle = self.subtitle ?? ""
content.body = self.body ?? ""
if let badge = self.badge {
content.badge = badge as NSNumber
}
return content
}
}
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
private final class NotificationServiceHandler {
private let queue: Queue
private let accountManager: AccountManager<TelegramAccountManagerTypes>
private let encryptionParameters: ValueBoxEncryptionParameters
private var stateManager: AccountStateManager?
private let notificationKeyDisposable = MetaDisposable()
private let pollDisposable = MetaDisposable()
init?(queue: Queue, updateCurrentContent: @escaping (UNNotificationContent) -> Void, completed: @escaping () -> Void, payload: [AnyHashable: Any]) {
self.queue = queue
guard let appBundleIdentifier = Bundle.main.bundleIdentifier, let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
return nil
}
let baseAppBundleId = String(appBundleIdentifier[..<lastDotRange.lowerBound])
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
let apiId: Int32 = buildConfig.apiId
let apiHash: String = buildConfig.apiHash
let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)"
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
guard let appGroupUrl = maybeAppGroupUrl else {
return nil
}
let rootPath = rootPathForBasePath(appGroupUrl.path)
TempBox.initializeShared(basePath: rootPath, processType: "notification", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
let logsPath = rootPath + "/notification-logs"
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
setupSharedLogger(rootPath: rootPath, path: logsPath)
initializeAccountManagement()
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
self.accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false, useCaches: false)
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
self.encryptionParameters = ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: deviceSpecificEncryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: deviceSpecificEncryptionParameters.salt)!)
let networkArguments = NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(buildConfig.bundleData(withAppToken: nil, signatureDict: nil)), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider())
guard var encryptedPayload = payload["p"] as? String else {
return nil
}
encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+")
encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/")
while encryptedPayload.count % 4 != 0 {
encryptedPayload.append("=")
}
guard let payloadData = Data(base64Encoded: encryptedPayload) else {
return nil
}
let _ = (self.accountManager.currentAccountRecord(allocateIfNotExists: false)
|> take(1)
|> deliverOn(self.queue)).start(next: { [weak self] records in
guard let strongSelf = self, let record = records else {
return
}
let _ = (standaloneStateManager(
accountManager: strongSelf.accountManager,
networkArguments: networkArguments,
id: record.0,
encryptionParameters: strongSelf.encryptionParameters,
rootPath: rootPath,
auxiliaryMethods: accountAuxiliaryMethods
)
|> deliverOn(strongSelf.queue)).start(next: { stateManager in
guard let strongSelf = self else {
return
}
guard let stateManager = stateManager else {
completed()
return
}
strongSelf.stateManager = stateManager
strongSelf.notificationKeyDisposable.set((existingMasterNotificationsKey(postbox: stateManager.postbox)
|> deliverOn(strongSelf.queue)).start(next: { notificationsKey in
guard let strongSelf = self else {
return
}
guard let notificationsKey = notificationsKey else {
completed()
return
}
guard let decryptedPayload = decryptedNotificationPayload(key: notificationsKey, data: payloadData) else {
completed()
return
}
guard let payloadJson = try? JSONSerialization.jsonObject(with: decryptedPayload, options: []) as? [String: Any] else {
completed()
return
}
guard let aps = payloadJson["aps"] as? [String: Any] else {
completed()
return
}
var content: NotificationContent = NotificationContent()
if let alert = aps["alert"] as? [String: Any] {
content.title = alert["title"] as? String
content.subtitle = alert["subtitle"] as? String
content.body = alert["body"] as? String
} else if let alert = aps["alert"] as? String {
content.body = alert
} else {
completed()
return
}
updateCurrentContent(content.asNotificationContent())
if let stateManager = strongSelf.stateManager {
stateManager.network.shouldKeepConnection.set(.single(true))
strongSelf.pollDisposable.set(stateManager.pollStateUpdateCompletion().start(completed: {
queue.async {
guard let strongSelf = self, let stateManager = strongSelf.stateManager else {
completed()
return
}
let _ = (renderedTotalUnreadCount(
accountManager: strongSelf.accountManager,
postbox: stateManager.postbox
)
|> deliverOn(strongSelf.queue)).start(next: { value in
content.badge = Int(value.0)
updateCurrentContent(content.asNotificationContent())
completed()
})
}
}))
stateManager.reset()
} else {
completed()
}
}))
})
})
}
deinit {
self.pollDisposable.dispose()
self.stateManager?.network.shouldKeepConnection.set(.single(false))
}
}
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
private final class BoxedNotificationServiceHandler {
let value: NotificationServiceHandler?
init(value: NotificationServiceHandler?) {
self.value = value
}
}
@available(iOSApplicationExtension 10.0, iOS 10.0, *) @available(iOSApplicationExtension 10.0, iOS 10.0, *)
@objc(NotificationService) @objc(NotificationService)
final class NotificationService: UNNotificationServiceExtension { final class NotificationService: UNNotificationServiceExtension {
private let impl: QueueLocalObject<NotificationServiceImpl> private var impl: QueueLocalObject<BoxedNotificationServiceHandler>?
private let content = Atomic<UNNotificationContent?>(value: nil)
private var contentHandler: ((UNNotificationContent) -> Void)?
override init() { override init() {
self.impl = QueueLocalObject(queue: queue, generate: {
var completion: ((Int32) -> Void)?
let impl = NotificationServiceImpl(serialDispatch: { f in
queue.async {
f()
}
}, countIncomingMessage: { rootPath, accountId, encryptionParameters, peerId, messageId in
completion?(0)
}, isLocked: { rootPath in
return SyncProviderImpl.isLocked(withRootPath: rootPath)
}, lockedMessageText: { rootPath in
return SyncProviderImpl.lockedMessageText(withRootPath: rootPath)
})
completion = { [weak impl] count in
queue.async {
impl?.updateUnreadCount(count)
}
}
return impl
})
super.init() super.init()
} }
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.impl.with { impl in let _ = self.content.swap(request.content)
impl.didReceive(request, withContentHandler: contentHandler) self.contentHandler = contentHandler
}
self.impl = nil
let content = self.content
self.impl = QueueLocalObject(queue: queue, generate: { [weak self] in
return BoxedNotificationServiceHandler(value: NotificationServiceHandler(
queue: queue,
updateCurrentContent: { value in
let _ = content.swap(value)
},
completed: {
guard let strongSelf = self else {
return
}
strongSelf.impl = nil
if let content = content.with({ $0 }), let contentHandler = strongSelf.contentHandler {
contentHandler(content)
}
},
payload: request.content.userInfo
))
})
} }
override func serviceExtensionTimeWillExpire() { override func serviceExtensionTimeWillExpire() {
self.impl.with { impl in if let content = self.content.with({ $0 }), let contentHandler = self.contentHandler {
impl.serviceExtensionTimeWillExpire() contentHandler(content)
} }
} }
} }

View File

@ -1,148 +0,0 @@
import Foundation
import SwiftSignalKit
//import ValueBox
//import PostboxDataTypes
//import MessageHistoryReadStateTable
//import MessageHistoryMetadataTable
//import PreferencesTable
//import PeerTable
//import PostboxCoding
import AppLockState
import NotificationsPresentationData
import BuildConfig
/*private let registeredTypes: Void = {
declareEncodable(InAppNotificationSettings.self, f: InAppNotificationSettings.init(decoder:))
declareEncodable(TelegramChannel.self, f: TelegramChannel.init(decoder:))
}()*/
private func accountRecordIdPathName(_ id: Int64) -> String {
return "account-\(UInt64(bitPattern: id))"
}
/*private final class ValueBoxLoggerImpl: ValueBoxLogger {
func log(_ what: String) {
print("ValueBox: \(what)")
}
}*/
enum SyncProviderImpl {
static func isLocked(withRootPath rootPath: String) -> Bool {
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
return true
} else {
return false
}
}
static func lockedMessageText(withRootPath rootPath: String) -> String {
if let data = try? Data(contentsOf: URL(fileURLWithPath: notificationsPresentationDataPath(rootPath: rootPath))), let value = try? JSONDecoder().decode(NotificationsPresentationData.self, from: data) {
return value.applicationLockedMessageString
} else {
return "You have a new message"
}
}
/*static func addIncomingMessage(queue: Queue, withRootPath rootPath: String, accountId: Int64, encryptionParameters: DeviceSpecificEncryptionParameters, peerId: Int64, messageId: Int32, completion: @escaping (Int32) -> Void) {
queue.async {
let _ = registeredTypes
let sharedBasePath = rootPath + "/accounts-metadata"
let basePath = rootPath + "/" + accountRecordIdPathName(accountId) + "/postbox"
let sharedValueBox = SqliteValueBox(basePath: sharedBasePath + "/db", queue: queue, logger: ValueBoxLoggerImpl(), encryptionParameters: nil, disableCache: true, upgradeProgress: { _ in
})
let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, logger: ValueBoxLoggerImpl(), encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: encryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: encryptionParameters.salt)!), disableCache: true, upgradeProgress: { _ in
})
let metadataTable = MessageHistoryMetadataTable(valueBox: valueBox, table: MessageHistoryMetadataTable.tableSpec(10))
let readStateTable = MessageHistoryReadStateTable(valueBox: valueBox, table: MessageHistoryReadStateTable.tableSpec(14), defaultMessageNamespaceReadStates: [:])
let peerTable = PeerTable(valueBox: valueBox, table: PeerTable.tableSpec(2), reverseAssociatedTable: nil)
let preferencesTable = PreferencesTable(valueBox: sharedValueBox, table: PreferencesTable.tableSpec(2))
let peerId = PeerId(peerId)
let initialCombinedState = readStateTable.getCombinedState(peerId)
let combinedState = initialCombinedState.flatMap { state -> CombinedPeerReadState in
var state = state
for i in 0 ..< state.states.count {
if state.states[i].0 == Namespaces.Message.Cloud {
switch state.states[i].1 {
case .idBased(let maxIncomingReadId, let maxOutgoingReadId, var maxKnownId, var count, let markedUnread):
if messageId > maxIncomingReadId {
count += 1
}
maxKnownId = max(maxKnownId, messageId)
state.states[i] = (state.states[i].0, .idBased(maxIncomingReadId: maxIncomingReadId, maxOutgoingReadId: maxOutgoingReadId, maxKnownId: maxKnownId, count: count, markedUnread: markedUnread))
default:
break
}
}
}
return state
}
if let combinedState = combinedState {
let initialCount = initialCombinedState?.count ?? 0
let updatedCount = combinedState.count
let deltaCount = max(0, updatedCount - initialCount)
let tag: PeerSummaryCounterTags
if peerId.namespace == Namespaces.Peer.CloudChannel {
if let channel = peerTable.get(peerId) as? TelegramChannel {
switch channel.info {
case .broadcast:
tag = .channel
case .group:
if channel.username != nil {
tag = .publicGroup
} else {
tag = .privateGroup
}
}
} else {
tag = .channel
}
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
tag = .privateGroup
} else {
tag = .privateChat
}
var totalCount: Int32 = -1
var totalUnreadState = metadataTable.getChatListTotalUnreadState()
if var counters = totalUnreadState.absoluteCounters[tag] {
if initialCount == 0 && updatedCount > 0 {
counters.chatCount += 1
}
counters.messageCount += deltaCount
totalUnreadState.absoluteCounters[tag] = counters
}
if var counters = totalUnreadState.filteredCounters[tag] {
if initialCount == 0 && updatedCount > 0 {
counters.chatCount += 1
}
counters.messageCount += deltaCount
totalUnreadState.filteredCounters[tag] = counters
}
let inAppSettings = preferencesTable.get(key: ApplicationSpecificSharedDataKeys.inAppNotificationSettings) as? InAppNotificationSettings ?? InAppNotificationSettings.defaultSettings
totalCount = totalUnreadState.count(for: inAppSettings.totalUnreadCountDisplayStyle.category, in: inAppSettings.totalUnreadCountDisplayCategory.statsType, with: inAppSettings.totalUnreadCountIncludeTags)
metadataTable.setChatListTotalUnreadState(totalUnreadState)
metadataTable.setShouldReindexUnreadCounts(value: true)
metadataTable.beforeCommit()
readStateTable.beforeCommit()
completion(totalCount)
} else {
completion(-1)
}
}
}*/
}

View File

@ -1,39 +0,0 @@
/*import PostboxDataTypes
import PostboxCoding
public enum TelegramChannelInfo: Int32 {
case broadcast = 0
case group = 1
}
public final class TelegramChannel: Peer {
public let id: PeerId
public let username: String?
public let info: TelegramChannelInfo
public let associatedPeerId: PeerId? = nil
public let notificationSettingsPeerId: PeerId? = nil
public init(decoder: PostboxDecoder) {
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
self.username = decoder.decodeOptionalStringForKey("un")
self.info = TelegramChannelInfo(rawValue: decoder.decodeInt32ForKey("i.t", orElse: 0)) ?? .broadcast
}
public func encode(_ encoder: PostboxEncoder) {
preconditionFailure()
}
public func isEqual(_ other: Peer) -> Bool {
guard let other = other as? TelegramChannel else {
return false
}
if self.username != other.username {
return false
}
return true
}
}
*/

View File

@ -121,7 +121,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
initializeAccountManagement() initializeAccountManagement()
let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false, useCaches: false)
self.accountManager = accountManager self.accountManager = accountManager
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId) let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)

View File

@ -386,14 +386,14 @@ static int32_t fixedTimeDifferenceValue = 0;
NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"]; NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"];
if (datacenterAuthInfoById != nil) { if (datacenterAuthInfoById != nil) {
_datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById]; _datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById];
#if DEBUG /*#if DEBUG
NSArray<NSNumber *> *keys = [_datacenterAuthInfoById allKeys]; NSArray<NSNumber *> *keys = [_datacenterAuthInfoById allKeys];
for (NSNumber *key in keys) { for (NSNumber *key in keys) {
if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) { if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) {
[_datacenterAuthInfoById removeObjectForKey:key]; [_datacenterAuthInfoById removeObjectForKey:key];
} }
} }
#endif #endif*/
} }
NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"]; NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"];

View File

@ -69,7 +69,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
} }
} }
fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, isReadOnly: Bool, temporarySessionId: Int64) { fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, isReadOnly: Bool, useCaches: Bool, temporarySessionId: Int64) {
let startTime = CFAbsoluteTimeGetCurrent() let startTime = CFAbsoluteTimeGetCurrent()
self.queue = queue self.queue = queue
@ -77,19 +77,19 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
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, isReadOnly: false, encryptionParameters: nil, upgradeProgress: { _ in }) else { guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, isReadOnly: false, useCaches: useCaches, 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, isReadOnly: isReadOnly, encryptionParameters: nil, upgradeProgress: { _ in }) else { guard let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, encryptionParameters: nil, upgradeProgress: { _ in }) else {
return nil return nil
} }
self.valueBox = valueBox self.valueBox = valueBox
self.legacyMetadataTable = AccountManagerMetadataTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerMetadataTable<Types.Attribute>.tableSpec(0)) self.legacyMetadataTable = AccountManagerMetadataTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerMetadataTable<Types.Attribute>.tableSpec(0), useCaches: useCaches)
self.legacyRecordTable = AccountManagerRecordTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerRecordTable<Types.Attribute>.tableSpec(1)) self.legacyRecordTable = AccountManagerRecordTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerRecordTable<Types.Attribute>.tableSpec(1), useCaches: useCaches)
self.sharedDataTable = AccountManagerSharedDataTable(valueBox: self.valueBox, table: AccountManagerSharedDataTable.tableSpec(2)) self.sharedDataTable = AccountManagerSharedDataTable(valueBox: self.valueBox, table: AccountManagerSharedDataTable.tableSpec(2), useCaches: useCaches)
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(3)) self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(3), useCaches: useCaches)
do { do {
let data = try Data(contentsOf: URL(fileURLWithPath: self.atomicStatePath)) let data = try Data(contentsOf: URL(fileURLWithPath: self.atomicStatePath))
@ -472,7 +472,7 @@ public final class AccountManager<Types: AccountManagerTypes> {
return AccountManagerImpl<Types>.getCurrentRecords(basePath: basePath) return AccountManagerImpl<Types>.getCurrentRecords(basePath: basePath)
} }
public init(basePath: String, isTemporary: Bool, isReadOnly: Bool) { public init(basePath: String, isTemporary: Bool, isReadOnly: Bool, useCaches: Bool) {
self.queue = sharedQueue self.queue = sharedQueue
self.basePath = basePath self.basePath = basePath
var temporarySessionId: Int64 = 0 var temporarySessionId: Int64 = 0
@ -480,7 +480,7 @@ public final class AccountManager<Types: AccountManagerTypes> {
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<Types>(queue: queue, basePath: basePath, isTemporary: isTemporary, isReadOnly: isReadOnly, temporarySessionId: temporarySessionId) { if let value = AccountManagerImpl<Types>(queue: queue, basePath: basePath, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, temporarySessionId: temporarySessionId) {
return value return value
} else { } else {
preconditionFailure() preconditionFailure()

View File

@ -11,8 +11,8 @@ final class CachedPeerDataTable: Table {
private var cachedDatas: [PeerId: CachedPeerData] = [:] private var cachedDatas: [PeerId: CachedPeerData] = [:]
private var updatedPeerIds = Set<PeerId>() private var updatedPeerIds = Set<PeerId>()
override init(valueBox: ValueBox, table: ValueBoxTable) { override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: PeerId) -> ValueBoxKey { private func key(_ id: PeerId) -> ValueBoxKey {
@ -54,5 +54,8 @@ final class CachedPeerDataTable: Table {
} }
self.updatedPeerIds.removeAll() self.updatedPeerIds.removeAll()
if !self.useCaches {
self.cachedDatas.removeAll()
}
} }
} }

View File

@ -52,13 +52,13 @@ final class ChatListIndexTable: Table {
private var updatedPreviousPeerCachedIndices: [PeerId: ChatListPeerInclusionIndex] = [:] private var updatedPreviousPeerCachedIndices: [PeerId: ChatListPeerInclusionIndex] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, peerNameIndexTable: PeerNameIndexTable, metadataTable: MessageHistoryMetadataTable, readStateTable: MessageHistoryReadStateTable, notificationSettingsTable: PeerNotificationSettingsTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, peerNameIndexTable: PeerNameIndexTable, metadataTable: MessageHistoryMetadataTable, readStateTable: MessageHistoryReadStateTable, notificationSettingsTable: PeerNotificationSettingsTable) {
self.peerNameIndexTable = peerNameIndexTable self.peerNameIndexTable = peerNameIndexTable
self.metadataTable = metadataTable self.metadataTable = metadataTable
self.readStateTable = readStateTable self.readStateTable = readStateTable
self.notificationSettingsTable = notificationSettingsTable self.notificationSettingsTable = notificationSettingsTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ peerId: PeerId) -> ValueBoxKey { private func key(_ peerId: PeerId) -> ValueBoxKey {
@ -554,6 +554,10 @@ final class ChatListIndexTable: Table {
override func beforeCommit() { override func beforeCommit() {
assert(self.updatedPreviousPeerCachedIndices.isEmpty) assert(self.updatedPreviousPeerCachedIndices.isEmpty)
if !self.useCaches {
self.cachedPeerIndices.removeAll()
}
} }
func debugReindexUnreadCounts(postbox: Postbox, currentTransaction: Transaction) -> ([PeerGroupId: ChatListTotalUnreadState], [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) { func debugReindexUnreadCounts(postbox: Postbox, currentTransaction: Transaction) -> ([PeerGroupId: ChatListTotalUnreadState], [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) {

View File

@ -133,12 +133,12 @@ final class ChatListTable: Table {
let metadataTable: MessageHistoryMetadataTable let metadataTable: MessageHistoryMetadataTable
let seedConfiguration: SeedConfiguration let seedConfiguration: SeedConfiguration
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: ChatListIndexTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: ChatListIndexTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) {
self.indexTable = indexTable self.indexTable = indexTable
self.metadataTable = metadataTable self.metadataTable = metadataTable
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(groupId: PeerGroupId, index: ChatListIndex, type: ChatListEntryType) -> ValueBoxKey { private func key(groupId: PeerGroupId, index: ChatListIndex, type: ChatListEntryType) -> ValueBoxKey {

View File

@ -10,10 +10,10 @@ final class ContactTable: Table {
private var peerIdsBeforeModification: Set<PeerId>? private var peerIdsBeforeModification: Set<PeerId>?
private var peerIds: Set<PeerId>? private var peerIds: Set<PeerId>?
init(valueBox: ValueBox, table: ValueBoxTable, peerNameIndexTable: PeerNameIndexTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, peerNameIndexTable: PeerNameIndexTable) {
self.peerNameIndexTable = peerNameIndexTable self.peerNameIndexTable = peerNameIndexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: PeerId, sharedKey: ValueBoxKey = ValueBoxKey(length: 8)) -> ValueBoxKey { private func key(_ id: PeerId, sharedKey: ValueBoxKey = ValueBoxKey(length: 8)) -> ValueBoxKey {
@ -98,5 +98,9 @@ final class ContactTable: Table {
self.peerIdsBeforeModification = nil self.peerIdsBeforeModification = nil
} }
if !self.useCaches {
self.peerIds = nil
}
} }
} }

View File

@ -10,10 +10,10 @@ final class GlobalMessageIdsTable: Table {
private let sharedKey = ValueBoxKey(length: 8) private let sharedKey = ValueBoxKey(length: 8)
private let sharedBuffer = WriteBuffer() private let sharedBuffer = WriteBuffer()
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, seedConfiguration: SeedConfiguration) {
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: Int32) -> ValueBoxKey { private func key(_ id: Int32) -> ValueBoxKey {

View File

@ -63,9 +63,9 @@ final class ItemCollectionItemTable: Table {
private let sharedKey = ValueBoxKey(length: 4 + 8 + 4 + 8) private let sharedKey = ValueBoxKey(length: 4 + 8 + 4 + 8)
init(valueBox: ValueBox, table: ValueBoxTable, reverseIndexTable: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, reverseIndexTable: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>) {
self.reverseIndexTable = reverseIndexTable self.reverseIndexTable = reverseIndexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(collectionId: ItemCollectionId, index: ItemCollectionItemIndex) -> ValueBoxKey { private func key(collectionId: ItemCollectionId, index: ItemCollectionItemIndex) -> ValueBoxKey {

View File

@ -49,11 +49,11 @@ final class MessageHistoryHoleIndexTable: Table {
let metadataTable: MessageHistoryMetadataTable let metadataTable: MessageHistoryMetadataTable
let seedConfiguration: SeedConfiguration let seedConfiguration: SeedConfiguration
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) {
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
self.metadataTable = metadataTable self.metadataTable = metadataTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(id: MessageId, space: MessageHistoryHoleSpace) -> ValueBoxKey { private func key(id: MessageId, space: MessageHistoryHoleSpace) -> ValueBoxKey {

View File

@ -47,13 +47,13 @@ final class MessageHistoryIndexTable: Table {
private var cachedExistingNamespaces: [PeerId: Set<MessageId.Namespace>] = [:] private var cachedExistingNamespaces: [PeerId: Set<MessageId.Namespace>] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, globalMessageIdsTable: GlobalMessageIdsTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, globalMessageIdsTable: GlobalMessageIdsTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) {
self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable
self.globalMessageIdsTable = globalMessageIdsTable self.globalMessageIdsTable = globalMessageIdsTable
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
self.metadataTable = metadataTable self.metadataTable = metadataTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: MessageId) -> ValueBoxKey { private func key(_ id: MessageId) -> ValueBoxKey {

View File

@ -32,10 +32,10 @@ final class MessageHistoryReadStateTable: Table {
return self.sharedKey return self.sharedKey
} }
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, seedConfiguration: SeedConfiguration) {
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func get(_ id: PeerId) -> InternalPeerReadStates? { private func get(_ id: PeerId) -> InternalPeerReadStates? {
@ -567,6 +567,10 @@ final class MessageHistoryReadStateTable: Table {
} }
} }
self.updatedInitialPeerReadStates.removeAll() self.updatedInitialPeerReadStates.removeAll()
if !self.useCaches {
self.cachedPeerReadStates.removeAll()
}
} }
} }
} }

View File

@ -90,7 +90,7 @@ final class MessageHistoryTable: Table {
let summaryTable: MessageHistoryTagsSummaryTable let summaryTable: MessageHistoryTagsSummaryTable
let pendingActionsTable: PendingMessageActionsTable let pendingActionsTable: PendingMessageActionsTable
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration, messageHistoryIndexTable: MessageHistoryIndexTable, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, messageMediaTable: MessageMediaTable, historyMetadataTable: MessageHistoryMetadataTable, globallyUniqueMessageIdsTable: MessageGloballyUniqueIdTable, unsentTable: MessageHistoryUnsentTable, failedTable: MessageHistoryFailedTable, tagsTable: MessageHistoryTagsTable, threadsTable: MessageHistoryThreadsTable, globalTagsTable: GlobalMessageHistoryTagsTable, localTagsTable: LocalMessageHistoryTagsTable, timeBasedAttributesTable: TimestampBasedMessageAttributesTable, readStateTable: MessageHistoryReadStateTable, synchronizeReadStateTable: MessageHistorySynchronizeReadStateTable, textIndexTable: MessageHistoryTextIndexTable, summaryTable: MessageHistoryTagsSummaryTable, pendingActionsTable: PendingMessageActionsTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, seedConfiguration: SeedConfiguration, messageHistoryIndexTable: MessageHistoryIndexTable, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, messageMediaTable: MessageMediaTable, historyMetadataTable: MessageHistoryMetadataTable, globallyUniqueMessageIdsTable: MessageGloballyUniqueIdTable, unsentTable: MessageHistoryUnsentTable, failedTable: MessageHistoryFailedTable, tagsTable: MessageHistoryTagsTable, threadsTable: MessageHistoryThreadsTable, globalTagsTable: GlobalMessageHistoryTagsTable, localTagsTable: LocalMessageHistoryTagsTable, timeBasedAttributesTable: TimestampBasedMessageAttributesTable, readStateTable: MessageHistoryReadStateTable, synchronizeReadStateTable: MessageHistorySynchronizeReadStateTable, textIndexTable: MessageHistoryTextIndexTable, summaryTable: MessageHistoryTagsSummaryTable, pendingActionsTable: PendingMessageActionsTable) {
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
self.messageHistoryIndexTable = messageHistoryIndexTable self.messageHistoryIndexTable = messageHistoryIndexTable
self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable
@ -110,7 +110,7 @@ final class MessageHistoryTable: Table {
self.summaryTable = summaryTable self.summaryTable = summaryTable
self.pendingActionsTable = pendingActionsTable self.pendingActionsTable = pendingActionsTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 4 + 4 + 4)) -> ValueBoxKey { private func key(_ index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 4 + 4 + 4)) -> ValueBoxKey {

View File

@ -82,10 +82,10 @@ class MessageHistoryTagsSummaryTable: Table {
private let sharedKey = ValueBoxKey(length: 4 + 8 + 4) private let sharedKey = ValueBoxKey(length: 4 + 8 + 4)
init(valueBox: ValueBox, table: ValueBoxTable, invalidateTable: InvalidatedMessageHistoryTagsSummaryTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, invalidateTable: InvalidatedMessageHistoryTagsSummaryTable) {
self.invalidateTable = invalidateTable self.invalidateTable = invalidateTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(key: MessageHistoryTagsSummaryKey, sharedKey: ValueBoxKey = ValueBoxKey(length: 4 + 8 + 4)) -> ValueBoxKey { private func key(key: MessageHistoryTagsSummaryKey, sharedKey: ValueBoxKey = ValueBoxKey(length: 4 + 8 + 4)) -> ValueBoxKey {
@ -172,5 +172,9 @@ class MessageHistoryTagsSummaryTable: Table {
} }
self.updatedKeys.removeAll() self.updatedKeys.removeAll()
} }
if !self.useCaches {
self.cachedSummaries.removeAll()
}
} }
} }

View File

@ -14,11 +14,11 @@ class MessageHistoryTagsTable: Table {
private let summaryTable: MessageHistoryTagsSummaryTable private let summaryTable: MessageHistoryTagsSummaryTable
private let summaryTags: MessageTags private let summaryTags: MessageTags
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration, summaryTable: MessageHistoryTagsSummaryTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, seedConfiguration: SeedConfiguration, summaryTable: MessageHistoryTagsSummaryTable) {
self.summaryTable = summaryTable self.summaryTable = summaryTable
self.summaryTags = seedConfiguration.messageTagsWithSummary self.summaryTags = seedConfiguration.messageTagsWithSummary
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(tag: MessageTags, index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 4 + 4 + 4 + 4)) -> ValueBoxKey { private func key(tag: MessageTags, index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 4 + 4 + 4 + 4)) -> ValueBoxKey {

View File

@ -25,11 +25,11 @@ final class MessageHistoryThreadHoleIndexTable: Table {
let metadataTable: MessageHistoryMetadataTable let metadataTable: MessageHistoryMetadataTable
let seedConfiguration: SeedConfiguration let seedConfiguration: SeedConfiguration
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: MessageHistoryMetadataTable, seedConfiguration: SeedConfiguration) {
self.seedConfiguration = seedConfiguration self.seedConfiguration = seedConfiguration
self.metadataTable = metadataTable self.metadataTable = metadataTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(threadId: Int64, id: MessageId, space: MessageHistoryHoleSpace) -> ValueBoxKey { private func key(threadId: Int64, id: MessageId, space: MessageHistoryHoleSpace) -> ValueBoxKey {

View File

@ -11,8 +11,8 @@ class MessageHistoryThreadsTable: Table {
private let sharedKey = ValueBoxKey(length: 8 + 8 + 4 + 4 + 4) private let sharedKey = ValueBoxKey(length: 8 + 8 + 4 + 4 + 4)
override init(valueBox: ValueBox, table: ValueBoxTable) { override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(threadId: Int64, index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 8 + 4 + 4 + 4)) -> ValueBoxKey { private func key(threadId: Int64, index: MessageIndex, key: ValueBoxKey = ValueBoxKey(length: 8 + 8 + 4 + 4 + 4)) -> ValueBoxKey {

View File

@ -19,8 +19,8 @@ final class MetadataTable: Table {
private let sharedBuffer = WriteBuffer() private let sharedBuffer = WriteBuffer()
override init(valueBox: ValueBox, table: ValueBoxTable) { override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ key: MetadataKey) -> ValueBoxKey { private func key(_ key: MetadataKey) -> ValueBoxKey {

View File

@ -19,10 +19,10 @@ final class OrderedItemListTable: Table {
private let indexTable: OrderedItemListIndexTable private let indexTable: OrderedItemListIndexTable
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: OrderedItemListIndexTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: OrderedItemListIndexTable) {
self.indexTable = indexTable self.indexTable = indexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func keyIndexToId(collectionId: Int32, itemIndex: UInt32) -> ValueBoxKey { private func keyIndexToId(collectionId: Int32, itemIndex: UInt32) -> ValueBoxKey {

View File

@ -7,10 +7,10 @@ final class PeerMergedOperationLogIndexTable: Table {
private let metadataTable: PeerOperationLogMetadataTable private let metadataTable: PeerOperationLogMetadataTable
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: PeerOperationLogMetadataTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PeerOperationLogMetadataTable) {
self.metadataTable = metadataTable self.metadataTable = metadataTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(tag: PeerOperationLogTag, index: Int32) -> ValueBoxKey { private func key(tag: PeerOperationLogTag, index: Int32) -> ValueBoxKey {

View File

@ -140,11 +140,11 @@ final class PeerNameIndexTable: Table {
private var entryUpdates: [PeerId: PeerNameIndexCategoriesEntryUpdate] = [:] private var entryUpdates: [PeerId: PeerNameIndexCategoriesEntryUpdate] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, peerTable: PeerTable, peerNameTokenIndexTable: ReverseIndexReferenceTable<PeerIdReverseIndexReference>) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, peerTable: PeerTable, peerNameTokenIndexTable: ReverseIndexReferenceTable<PeerIdReverseIndexReference>) {
self.peerTable = peerTable self.peerTable = peerTable
self.peerNameTokenIndexTable = peerNameTokenIndexTable self.peerNameTokenIndexTable = peerNameTokenIndexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ peerId: PeerId) -> ValueBoxKey { private func key(_ peerId: PeerId) -> ValueBoxKey {

View File

@ -11,10 +11,10 @@ final class PeerNotificationSettingsBehaviorTable: Table {
private let indexTable: PeerNotificationSettingsBehaviorIndexTable private let indexTable: PeerNotificationSettingsBehaviorIndexTable
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: PeerNotificationSettingsBehaviorIndexTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: PeerNotificationSettingsBehaviorIndexTable) {
self.indexTable = indexTable self.indexTable = indexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(peerId: PeerId, timestamp: Int32) -> ValueBoxKey { private func key(peerId: PeerId, timestamp: Int32) -> ValueBoxKey {

View File

@ -63,11 +63,11 @@ final class PeerNotificationSettingsTable: Table {
private var cachedSettings: [PeerId: PeerNotificationSettingsTableEntry] = [:] private var cachedSettings: [PeerId: PeerNotificationSettingsTableEntry] = [:]
private var updatedInitialSettings: [PeerId: PeerNotificationSettingsTableEntry] = [:] private var updatedInitialSettings: [PeerId: PeerNotificationSettingsTableEntry] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, pendingIndexTable: PendingPeerNotificationSettingsIndexTable, behaviorTable: PeerNotificationSettingsBehaviorTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, pendingIndexTable: PendingPeerNotificationSettingsIndexTable, behaviorTable: PeerNotificationSettingsBehaviorTable) {
self.pendingIndexTable = pendingIndexTable self.pendingIndexTable = pendingIndexTable
self.behaviorTable = behaviorTable self.behaviorTable = behaviorTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: PeerId) -> ValueBoxKey { private func key(_ id: PeerId) -> ValueBoxKey {
@ -301,6 +301,10 @@ final class PeerNotificationSettingsTable: Table {
} }
self.updatedInitialSettings.removeAll() self.updatedInitialSettings.removeAll()
if !self.useCaches {
self.cachedSettings.removeAll()
}
} }
} }
} }

View File

@ -112,11 +112,11 @@ final class PeerOperationLogTable: Table {
private let metadataTable: PeerOperationLogMetadataTable private let metadataTable: PeerOperationLogMetadataTable
private let mergedIndexTable: PeerMergedOperationLogIndexTable private let mergedIndexTable: PeerMergedOperationLogIndexTable
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: PeerOperationLogMetadataTable, mergedIndexTable: PeerMergedOperationLogIndexTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PeerOperationLogMetadataTable, mergedIndexTable: PeerMergedOperationLogIndexTable) {
self.metadataTable = metadataTable self.metadataTable = metadataTable
self.mergedIndexTable = mergedIndexTable self.mergedIndexTable = mergedIndexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(peerId: PeerId, tag: PeerOperationLogTag, index: Int32) -> ValueBoxKey { private func key(peerId: PeerId, tag: PeerOperationLogTag, index: Int32) -> ValueBoxKey {

View File

@ -13,10 +13,10 @@ final class PeerTable: Table {
private var cachedPeers: [PeerId: Peer] = [:] private var cachedPeers: [PeerId: Peer] = [:]
private var updatedInitialPeers: [PeerId: Peer?] = [:] private var updatedInitialPeers: [PeerId: Peer?] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, reverseAssociatedTable: ReverseAssociatedPeerTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, reverseAssociatedTable: ReverseAssociatedPeerTable) {
self.reverseAssociatedTable = reverseAssociatedTable self.reverseAssociatedTable = reverseAssociatedTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(_ id: PeerId) -> ValueBoxKey { private func key(_ id: PeerId) -> ValueBoxKey {
@ -87,6 +87,9 @@ final class PeerTable: Table {
} }
self.updatedInitialPeers.removeAll() self.updatedInitialPeers.removeAll()
if !self.useCaches {
self.cachedPeers.removeAll()
}
} }
} }
} }

View File

@ -53,10 +53,10 @@ final class PendingMessageActionsTable: Table {
private let metadataTable: PendingMessageActionsMetadataTable private let metadataTable: PendingMessageActionsMetadataTable
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: PendingMessageActionsMetadataTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PendingMessageActionsMetadataTable) {
self.metadataTable = metadataTable self.metadataTable = metadataTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func forwardKey(id: MessageId, actionType: PendingMessageActionType) -> ValueBoxKey { private func forwardKey(id: MessageId, actionType: PendingMessageActionType) -> ValueBoxKey {

View File

@ -1165,7 +1165,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, isReadOnly: Bool, useCopy: Bool) -> Signal<PostboxResult, NoError> { public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, isReadOnly: Bool, useCopy: Bool, useCaches: Bool) -> Signal<PostboxResult, NoError> {
let queue = sharedQueue let queue = sharedQueue
return Signal { subscriber in return Signal { subscriber in
queue.async { queue.async {
@ -1209,7 +1209,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
postboxLog("openPostbox, initialize SqliteValueBox") postboxLog("openPostbox, initialize SqliteValueBox")
guard var valueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in guard var valueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
postboxLog("openPostbox, SqliteValueBox upgrading progress \(progress)") postboxLog("openPostbox, SqliteValueBox upgrading progress \(progress)")
subscriber.putNext(.upgrading(progress)) subscriber.putNext(.upgrading(progress))
}) else { }) else {
@ -1219,7 +1219,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
} }
loop: while true { loop: while true {
let metadataTable = MetadataTable(valueBox: valueBox, table: MetadataTable.tableSpec(0)) let metadataTable = MetadataTable(valueBox: valueBox, table: MetadataTable.tableSpec(0), useCaches: useCaches)
let userVersion: Int32? = metadataTable.userVersion() let userVersion: Int32? = metadataTable.userVersion()
let currentUserVersion: Int32 = 25 let currentUserVersion: Int32 = 25
@ -1237,7 +1237,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: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in guard let updatedValueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
subscriber.putNext(.upgrading(progress)) subscriber.putNext(.upgrading(progress))
}) else { }) else {
subscriber.putNext(.error) subscriber.putNext(.error)
@ -1261,7 +1261,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
valueBox.internalClose() valueBox.internalClose()
let _ = try? FileManager.default.removeItem(atPath: dbBasePath) let _ = try? FileManager.default.removeItem(atPath: dbBasePath)
let _ = try? FileManager.default.moveItem(atPath: updatedPath, toPath: dbBasePath) let _ = try? FileManager.default.moveItem(atPath: updatedPath, toPath: dbBasePath)
guard let updatedValueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in guard let updatedValueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
subscriber.putNext(.upgrading(progress)) subscriber.putNext(.upgrading(progress))
}) else { }) else {
subscriber.putNext(.error) subscriber.putNext(.error)
@ -1275,7 +1275,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: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in guard let updatedValueBox = SqliteValueBox(basePath: dbBasePath, queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, useCaches: useCaches, encryptionParameters: encryptionParameters, upgradeProgress: { progress in
subscriber.putNext(.upgrading(progress)) subscriber.putNext(.upgrading(progress))
}) else { }) else {
subscriber.putNext(.error) subscriber.putNext(.error)
@ -1293,7 +1293,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
let endTime = CFAbsoluteTimeGetCurrent() let endTime = CFAbsoluteTimeGetCurrent()
postboxLog("Postbox load took \((endTime - startTime) * 1000.0) ms") postboxLog("Postbox load took \((endTime - startTime) * 1000.0) ms")
subscriber.putNext(.postbox(Postbox(queue: queue, basePath: basePath, seedConfiguration: seedConfiguration, valueBox: valueBox, timestampForAbsoluteTimeBasedOperations: timestampForAbsoluteTimeBasedOperations, isTemporary: isTemporary, tempDir: tempDir))) subscriber.putNext(.postbox(Postbox(queue: queue, basePath: basePath, seedConfiguration: seedConfiguration, valueBox: valueBox, timestampForAbsoluteTimeBasedOperations: timestampForAbsoluteTimeBasedOperations, isTemporary: isTemporary, tempDir: tempDir, useCaches: useCaches)))
postboxLog("openPostbox, putCompletion") postboxLog("openPostbox, putCompletion")
@ -1450,7 +1450,7 @@ public final class Postbox {
var installedMessageActionsByPeerId: [PeerId: Bag<([StoreMessage], Transaction) -> Void>] = [:] var installedMessageActionsByPeerId: [PeerId: Bag<([StoreMessage], Transaction) -> Void>] = [:]
init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, tempDir: TempBoxDirectory?) { init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, tempDir: TempBoxDirectory?, useCaches: Bool) {
assert(queue.isCurrent()) assert(queue.isCurrent())
let startTime = CFAbsoluteTimeGetCurrent() let startTime = CFAbsoluteTimeGetCurrent()
@ -1465,67 +1465,67 @@ public final class Postbox {
self.mediaBox = MediaBox(basePath: self.basePath + "/media") self.mediaBox = MediaBox(basePath: self.basePath + "/media")
self.valueBox = valueBox self.valueBox = valueBox
self.metadataTable = MetadataTable(valueBox: self.valueBox, table: MetadataTable.tableSpec(0)) self.metadataTable = MetadataTable(valueBox: self.valueBox, table: MetadataTable.tableSpec(0), useCaches: useCaches)
self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1)) self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1), useCaches: useCaches)
self.reverseAssociatedPeerTable = ReverseAssociatedPeerTable(valueBox: self.valueBox, table:ReverseAssociatedPeerTable.tableSpec(40)) self.reverseAssociatedPeerTable = ReverseAssociatedPeerTable(valueBox: self.valueBox, table:ReverseAssociatedPeerTable.tableSpec(40), useCaches: useCaches)
self.peerTable = PeerTable(valueBox: self.valueBox, table: PeerTable.tableSpec(2), reverseAssociatedTable: self.reverseAssociatedPeerTable) self.peerTable = PeerTable(valueBox: self.valueBox, table: PeerTable.tableSpec(2), useCaches: useCaches, reverseAssociatedTable: self.reverseAssociatedPeerTable)
self.globalMessageIdsTable = GlobalMessageIdsTable(valueBox: self.valueBox, table: GlobalMessageIdsTable.tableSpec(3), seedConfiguration: seedConfiguration) self.globalMessageIdsTable = GlobalMessageIdsTable(valueBox: self.valueBox, table: GlobalMessageIdsTable.tableSpec(3), useCaches: useCaches, seedConfiguration: seedConfiguration)
self.globallyUniqueMessageIdsTable = MessageGloballyUniqueIdTable(valueBox: self.valueBox, table: MessageGloballyUniqueIdTable.tableSpec(32)) self.globallyUniqueMessageIdsTable = MessageGloballyUniqueIdTable(valueBox: self.valueBox, table: MessageGloballyUniqueIdTable.tableSpec(32), useCaches: useCaches)
self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10)) self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10), useCaches: useCaches)
self.messageHistoryHoleIndexTable = MessageHistoryHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryHoleIndexTable.tableSpec(56), metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration) self.messageHistoryHoleIndexTable = MessageHistoryHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryHoleIndexTable.tableSpec(56), useCaches: useCaches, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
self.messageHistoryUnsentTable = MessageHistoryUnsentTable(valueBox: self.valueBox, table: MessageHistoryUnsentTable.tableSpec(11)) self.messageHistoryUnsentTable = MessageHistoryUnsentTable(valueBox: self.valueBox, table: MessageHistoryUnsentTable.tableSpec(11), useCaches: useCaches)
self.messageHistoryFailedTable = MessageHistoryFailedTable(valueBox: self.valueBox, table: MessageHistoryFailedTable.tableSpec(49)) self.messageHistoryFailedTable = MessageHistoryFailedTable(valueBox: self.valueBox, table: MessageHistoryFailedTable.tableSpec(49), useCaches: useCaches)
self.invalidatedMessageHistoryTagsSummaryTable = InvalidatedMessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: InvalidatedMessageHistoryTagsSummaryTable.tableSpec(47)) self.invalidatedMessageHistoryTagsSummaryTable = InvalidatedMessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: InvalidatedMessageHistoryTagsSummaryTable.tableSpec(47), useCaches: useCaches)
self.messageHistoryTagsSummaryTable = MessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: MessageHistoryTagsSummaryTable.tableSpec(44), invalidateTable: self.invalidatedMessageHistoryTagsSummaryTable) self.messageHistoryTagsSummaryTable = MessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: MessageHistoryTagsSummaryTable.tableSpec(44), useCaches: useCaches, invalidateTable: self.invalidatedMessageHistoryTagsSummaryTable)
self.pendingMessageActionsMetadataTable = PendingMessageActionsMetadataTable(valueBox: self.valueBox, table: PendingMessageActionsMetadataTable.tableSpec(45)) self.pendingMessageActionsMetadataTable = PendingMessageActionsMetadataTable(valueBox: self.valueBox, table: PendingMessageActionsMetadataTable.tableSpec(45), useCaches: useCaches)
self.pendingMessageActionsTable = PendingMessageActionsTable(valueBox: self.valueBox, table: PendingMessageActionsTable.tableSpec(46), metadataTable: self.pendingMessageActionsMetadataTable) self.pendingMessageActionsTable = PendingMessageActionsTable(valueBox: self.valueBox, table: PendingMessageActionsTable.tableSpec(46), useCaches: useCaches, metadataTable: self.pendingMessageActionsMetadataTable)
self.messageHistoryTagsTable = MessageHistoryTagsTable(valueBox: self.valueBox, table: MessageHistoryTagsTable.tableSpec(12), seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable) self.messageHistoryTagsTable = MessageHistoryTagsTable(valueBox: self.valueBox, table: MessageHistoryTagsTable.tableSpec(12), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62)) self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62), useCaches: useCaches)
self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration) self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), useCaches: useCaches, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39)) self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39), useCaches: useCaches)
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52)) self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52), useCaches: useCaches)
self.messageHistoryIndexTable = MessageHistoryIndexTable(valueBox: self.valueBox, table: MessageHistoryIndexTable.tableSpec(4), messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, globalMessageIdsTable: self.globalMessageIdsTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration) self.messageHistoryIndexTable = MessageHistoryIndexTable(valueBox: self.valueBox, table: MessageHistoryIndexTable.tableSpec(4), useCaches: useCaches, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, globalMessageIdsTable: self.globalMessageIdsTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
self.mediaTable = MessageMediaTable(valueBox: self.valueBox, table: MessageMediaTable.tableSpec(6)) self.mediaTable = MessageMediaTable(valueBox: self.valueBox, table: MessageMediaTable.tableSpec(6), useCaches: useCaches)
self.readStateTable = MessageHistoryReadStateTable(valueBox: self.valueBox, table: MessageHistoryReadStateTable.tableSpec(14), seedConfiguration: seedConfiguration) self.readStateTable = MessageHistoryReadStateTable(valueBox: self.valueBox, table: MessageHistoryReadStateTable.tableSpec(14), useCaches: useCaches, seedConfiguration: seedConfiguration)
self.synchronizeReadStateTable = MessageHistorySynchronizeReadStateTable(valueBox: self.valueBox, table: MessageHistorySynchronizeReadStateTable.tableSpec(15)) self.synchronizeReadStateTable = MessageHistorySynchronizeReadStateTable(valueBox: self.valueBox, table: MessageHistorySynchronizeReadStateTable.tableSpec(15), useCaches: useCaches)
self.synchronizeGroupMessageStatsTable = InvalidatedGroupMessageStatsTable(valueBox: self.valueBox, table: InvalidatedGroupMessageStatsTable.tableSpec(59)) self.synchronizeGroupMessageStatsTable = InvalidatedGroupMessageStatsTable(valueBox: self.valueBox, table: InvalidatedGroupMessageStatsTable.tableSpec(59), useCaches: useCaches)
self.timestampBasedMessageAttributesIndexTable = TimestampBasedMessageAttributesIndexTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(33)) self.timestampBasedMessageAttributesIndexTable = TimestampBasedMessageAttributesIndexTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(33), useCaches: useCaches)
self.timestampBasedMessageAttributesTable = TimestampBasedMessageAttributesTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(34), indexTable: self.timestampBasedMessageAttributesIndexTable) self.timestampBasedMessageAttributesTable = TimestampBasedMessageAttributesTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(34), useCaches: useCaches, indexTable: self.timestampBasedMessageAttributesIndexTable)
self.textIndexTable = MessageHistoryTextIndexTable(valueBox: self.valueBox, table: MessageHistoryTextIndexTable.tableSpec(41)) self.textIndexTable = MessageHistoryTextIndexTable(valueBox: self.valueBox, table: MessageHistoryTextIndexTable.tableSpec(41))
self.additionalChatListItemsTable = AdditionalChatListItemsTable(valueBox: self.valueBox, table: AdditionalChatListItemsTable.tableSpec(55)) self.additionalChatListItemsTable = AdditionalChatListItemsTable(valueBox: self.valueBox, table: AdditionalChatListItemsTable.tableSpec(55), useCaches: useCaches)
self.messageHistoryTable = MessageHistoryTable(valueBox: self.valueBox, table: MessageHistoryTable.tableSpec(7), seedConfiguration: seedConfiguration, messageHistoryIndexTable: self.messageHistoryIndexTable, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, messageMediaTable: self.mediaTable, historyMetadataTable: self.messageHistoryMetadataTable, globallyUniqueMessageIdsTable: self.globallyUniqueMessageIdsTable, unsentTable: self.messageHistoryUnsentTable, failedTable: self.messageHistoryFailedTable, tagsTable: self.messageHistoryTagsTable, threadsTable: self.messageHistoryThreadsTable, globalTagsTable: self.globalMessageHistoryTagsTable, localTagsTable: self.localMessageHistoryTagsTable, timeBasedAttributesTable: self.timestampBasedMessageAttributesTable, readStateTable: self.readStateTable, synchronizeReadStateTable: self.synchronizeReadStateTable, textIndexTable: self.textIndexTable, summaryTable: self.messageHistoryTagsSummaryTable, pendingActionsTable: self.pendingMessageActionsTable) self.messageHistoryTable = MessageHistoryTable(valueBox: self.valueBox, table: MessageHistoryTable.tableSpec(7), useCaches: useCaches, seedConfiguration: seedConfiguration, messageHistoryIndexTable: self.messageHistoryIndexTable, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, messageMediaTable: self.mediaTable, historyMetadataTable: self.messageHistoryMetadataTable, globallyUniqueMessageIdsTable: self.globallyUniqueMessageIdsTable, unsentTable: self.messageHistoryUnsentTable, failedTable: self.messageHistoryFailedTable, tagsTable: self.messageHistoryTagsTable, threadsTable: self.messageHistoryThreadsTable, globalTagsTable: self.globalMessageHistoryTagsTable, localTagsTable: self.localMessageHistoryTagsTable, timeBasedAttributesTable: self.timestampBasedMessageAttributesTable, readStateTable: self.readStateTable, synchronizeReadStateTable: self.synchronizeReadStateTable, textIndexTable: self.textIndexTable, summaryTable: self.messageHistoryTagsSummaryTable, pendingActionsTable: self.pendingMessageActionsTable)
self.peerChatStateTable = PeerChatStateTable(valueBox: self.valueBox, table: PeerChatStateTable.tableSpec(13)) self.peerChatStateTable = PeerChatStateTable(valueBox: self.valueBox, table: PeerChatStateTable.tableSpec(13), useCaches: useCaches)
self.peerNameTokenIndexTable = ReverseIndexReferenceTable<PeerIdReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<PeerIdReverseIndexReference>.tableSpec(26)) self.peerNameTokenIndexTable = ReverseIndexReferenceTable<PeerIdReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<PeerIdReverseIndexReference>.tableSpec(26), useCaches: useCaches)
self.peerNameIndexTable = PeerNameIndexTable(valueBox: self.valueBox, table: PeerNameIndexTable.tableSpec(27), peerTable: self.peerTable, peerNameTokenIndexTable: self.peerNameTokenIndexTable) self.peerNameIndexTable = PeerNameIndexTable(valueBox: self.valueBox, table: PeerNameIndexTable.tableSpec(27), useCaches: useCaches, peerTable: self.peerTable, peerNameTokenIndexTable: self.peerNameTokenIndexTable)
self.contactsTable = ContactTable(valueBox: self.valueBox, table: ContactTable.tableSpec(16), peerNameIndexTable: self.peerNameIndexTable) self.contactsTable = ContactTable(valueBox: self.valueBox, table: ContactTable.tableSpec(16), useCaches: useCaches, peerNameIndexTable: self.peerNameIndexTable)
self.peerRatingTable = RatingTable<PeerId>(valueBox: self.valueBox, table: RatingTable<PeerId>.tableSpec(17)) self.peerRatingTable = RatingTable<PeerId>(valueBox: self.valueBox, table: RatingTable<PeerId>.tableSpec(17), useCaches: useCaches)
self.cachedPeerDataTable = CachedPeerDataTable(valueBox: self.valueBox, table: CachedPeerDataTable.tableSpec(18)) self.cachedPeerDataTable = CachedPeerDataTable(valueBox: self.valueBox, table: CachedPeerDataTable.tableSpec(18), useCaches: useCaches)
self.pendingPeerNotificationSettingsIndexTable = PendingPeerNotificationSettingsIndexTable(valueBox: self.valueBox, table: PendingPeerNotificationSettingsIndexTable.tableSpec(48)) self.pendingPeerNotificationSettingsIndexTable = PendingPeerNotificationSettingsIndexTable(valueBox: self.valueBox, table: PendingPeerNotificationSettingsIndexTable.tableSpec(48), useCaches: useCaches)
self.peerNotificationSettingsBehaviorIndexTable = PeerNotificationSettingsBehaviorIndexTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorIndexTable.tableSpec(60)) self.peerNotificationSettingsBehaviorIndexTable = PeerNotificationSettingsBehaviorIndexTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorIndexTable.tableSpec(60), useCaches: useCaches)
self.peerNotificationSettingsBehaviorTable = PeerNotificationSettingsBehaviorTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorTable.tableSpec(61), indexTable: self.peerNotificationSettingsBehaviorIndexTable) self.peerNotificationSettingsBehaviorTable = PeerNotificationSettingsBehaviorTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorTable.tableSpec(61), useCaches: useCaches, indexTable: self.peerNotificationSettingsBehaviorIndexTable)
self.peerNotificationSettingsTable = PeerNotificationSettingsTable(valueBox: self.valueBox, table: PeerNotificationSettingsTable.tableSpec(19), pendingIndexTable: self.pendingPeerNotificationSettingsIndexTable, behaviorTable: self.peerNotificationSettingsBehaviorTable) self.peerNotificationSettingsTable = PeerNotificationSettingsTable(valueBox: self.valueBox, table: PeerNotificationSettingsTable.tableSpec(19), useCaches: useCaches, pendingIndexTable: self.pendingPeerNotificationSettingsIndexTable, behaviorTable: self.peerNotificationSettingsBehaviorTable)
self.peerPresenceTable = PeerPresenceTable(valueBox: self.valueBox, table: PeerPresenceTable.tableSpec(20)) self.peerPresenceTable = PeerPresenceTable(valueBox: self.valueBox, table: PeerPresenceTable.tableSpec(20), useCaches: useCaches)
self.itemCollectionInfoTable = ItemCollectionInfoTable(valueBox: self.valueBox, table: ItemCollectionInfoTable.tableSpec(21)) self.itemCollectionInfoTable = ItemCollectionInfoTable(valueBox: self.valueBox, table: ItemCollectionInfoTable.tableSpec(21), useCaches: useCaches)
self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36)) self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36), useCaches: useCaches)
self.itemCollectionItemTable = ItemCollectionItemTable(valueBox: self.valueBox, table: ItemCollectionItemTable.tableSpec(22), reverseIndexTable: self.itemCollectionReverseIndexTable) self.itemCollectionItemTable = ItemCollectionItemTable(valueBox: self.valueBox, table: ItemCollectionItemTable.tableSpec(22), useCaches: useCaches, reverseIndexTable: self.itemCollectionReverseIndexTable)
self.peerChatInterfaceStateTable = PeerChatInterfaceStateTable(valueBox: self.valueBox, table: PeerChatInterfaceStateTable.tableSpec(67)) self.peerChatInterfaceStateTable = PeerChatInterfaceStateTable(valueBox: self.valueBox, table: PeerChatInterfaceStateTable.tableSpec(67), useCaches: useCaches)
self.peerChatThreadInterfaceStateTable = PeerChatThreadInterfaceStateTable(valueBox: self.valueBox, table: PeerChatThreadInterfaceStateTable.tableSpec(68)) self.peerChatThreadInterfaceStateTable = PeerChatThreadInterfaceStateTable(valueBox: self.valueBox, table: PeerChatThreadInterfaceStateTable.tableSpec(68), useCaches: useCaches)
self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24)) self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24), useCaches: useCaches)
self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25)) self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25), useCaches: useCaches)
self.chatListIndexTable = ChatListIndexTable(valueBox: self.valueBox, table: ChatListIndexTable.tableSpec(8), peerNameIndexTable: self.peerNameIndexTable, metadataTable: self.messageHistoryMetadataTable, readStateTable: self.readStateTable, notificationSettingsTable: self.peerNotificationSettingsTable) self.chatListIndexTable = ChatListIndexTable(valueBox: self.valueBox, table: ChatListIndexTable.tableSpec(8), useCaches: useCaches, peerNameIndexTable: self.peerNameIndexTable, metadataTable: self.messageHistoryMetadataTable, readStateTable: self.readStateTable, notificationSettingsTable: self.peerNotificationSettingsTable)
self.chatListTable = ChatListTable(valueBox: self.valueBox, table: ChatListTable.tableSpec(9), indexTable: self.chatListIndexTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration) self.chatListTable = ChatListTable(valueBox: self.valueBox, table: ChatListTable.tableSpec(9), useCaches: useCaches, indexTable: self.chatListIndexTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
self.peerChatTopTaggedMessageIdsTable = PeerChatTopTaggedMessageIdsTable(valueBox: self.valueBox, table: PeerChatTopTaggedMessageIdsTable.tableSpec(28)) self.peerChatTopTaggedMessageIdsTable = PeerChatTopTaggedMessageIdsTable(valueBox: self.valueBox, table: PeerChatTopTaggedMessageIdsTable.tableSpec(28), useCaches: useCaches)
self.peerOperationLogMetadataTable = PeerOperationLogMetadataTable(valueBox: self.valueBox, table: PeerOperationLogMetadataTable.tableSpec(29)) self.peerOperationLogMetadataTable = PeerOperationLogMetadataTable(valueBox: self.valueBox, table: PeerOperationLogMetadataTable.tableSpec(29), useCaches: useCaches)
self.peerMergedOperationLogIndexTable = PeerMergedOperationLogIndexTable(valueBox: self.valueBox, table: PeerMergedOperationLogIndexTable.tableSpec(30), metadataTable: self.peerOperationLogMetadataTable) self.peerMergedOperationLogIndexTable = PeerMergedOperationLogIndexTable(valueBox: self.valueBox, table: PeerMergedOperationLogIndexTable.tableSpec(30), useCaches: useCaches, metadataTable: self.peerOperationLogMetadataTable)
self.peerOperationLogTable = PeerOperationLogTable(valueBox: self.valueBox, table: PeerOperationLogTable.tableSpec(31), metadataTable: self.peerOperationLogMetadataTable, mergedIndexTable: self.peerMergedOperationLogIndexTable) self.peerOperationLogTable = PeerOperationLogTable(valueBox: self.valueBox, table: PeerOperationLogTable.tableSpec(31), useCaches: useCaches, metadataTable: self.peerOperationLogMetadataTable, mergedIndexTable: self.peerMergedOperationLogIndexTable)
self.preferencesTable = PreferencesTable(valueBox: self.valueBox, table: PreferencesTable.tableSpec(35)) self.preferencesTable = PreferencesTable(valueBox: self.valueBox, table: PreferencesTable.tableSpec(35), useCaches: useCaches)
self.orderedItemListIndexTable = OrderedItemListIndexTable(valueBox: self.valueBox, table: OrderedItemListIndexTable.tableSpec(37)) self.orderedItemListIndexTable = OrderedItemListIndexTable(valueBox: self.valueBox, table: OrderedItemListIndexTable.tableSpec(37), useCaches: useCaches)
self.orderedItemListTable = OrderedItemListTable(valueBox: self.valueBox, table: OrderedItemListTable.tableSpec(38), indexTable: self.orderedItemListIndexTable) self.orderedItemListTable = OrderedItemListTable(valueBox: self.valueBox, table: OrderedItemListTable.tableSpec(38), useCaches: useCaches, indexTable: self.orderedItemListIndexTable)
self.unorderedItemListTable = UnorderedItemListTable(valueBox: self.valueBox, table: UnorderedItemListTable.tableSpec(42)) self.unorderedItemListTable = UnorderedItemListTable(valueBox: self.valueBox, table: UnorderedItemListTable.tableSpec(42), useCaches: useCaches)
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(43)) self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(43), useCaches: useCaches)
self.deviceContactImportInfoTable = DeviceContactImportInfoTable(valueBox: self.valueBox, table: DeviceContactImportInfoTable.tableSpec(54)) self.deviceContactImportInfoTable = DeviceContactImportInfoTable(valueBox: self.valueBox, table: DeviceContactImportInfoTable.tableSpec(54), useCaches: useCaches)
self.groupMessageStatsTable = GroupMessageStatsTable(valueBox: self.valueBox, table: GroupMessageStatsTable.tableSpec(58)) self.groupMessageStatsTable = GroupMessageStatsTable(valueBox: self.valueBox, table: GroupMessageStatsTable.tableSpec(58), useCaches: useCaches)
var tables: [Table] = [] var tables: [Table] = []
tables.append(self.metadataTable) tables.append(self.metadataTable)

View File

@ -5,7 +5,7 @@ import SwiftSignalKit
func postboxUpgrade_21to22(queue: Queue, basePath: String, valueBox: ValueBox, encryptionParameters: ValueBoxEncryptionParameters, progress: (Float) -> Void) -> String? { func postboxUpgrade_21to22(queue: Queue, basePath: String, valueBox: ValueBox, encryptionParameters: ValueBoxEncryptionParameters, progress: (Float) -> Void) -> String? {
postboxLog("Upgrade 21->22 started") postboxLog("Upgrade 21->22 started")
valueBox.begin() valueBox.begin()
let metadataTable = MetadataTable(valueBox: valueBox, table: MetadataTable.tableSpec(0)) let metadataTable = MetadataTable(valueBox: valueBox, table: MetadataTable.tableSpec(0), useCaches: false)
metadataTable.setUserVersion(22) metadataTable.setUserVersion(22)
valueBox.commit() valueBox.commit()
return nil return nil

View File

@ -163,6 +163,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 isReadOnly: Bool
private let useCaches: 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
@ -201,10 +202,11 @@ public final class SqliteValueBox: ValueBox {
private let queue: Queue private let queue: Queue
public init?(basePath: String, queue: Queue, isTemporary: Bool, isReadOnly: Bool, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) { public init?(basePath: String, queue: Queue, isTemporary: Bool, isReadOnly: Bool, useCaches: 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.isReadOnly = isReadOnly
self.useCaches = useCaches
self.inMemory = inMemory self.inMemory = inMemory
self.encryptionParameters = encryptionParameters self.encryptionParameters = encryptionParameters
self.databasePath = basePath + "/db_sqlite" self.databasePath = basePath + "/db_sqlite"
@ -421,7 +423,10 @@ public final class SqliteValueBox: ValueBox {
postboxLog("Did set up encryption") postboxLog("Did set up encryption")
//database.execute("PRAGMA cache_size=-2097152") if !self.useCaches {
resultCode = database.execute("PRAGMA cache_size=32")
assert(resultCode)
}
resultCode = database.execute("PRAGMA mmap_size=0") resultCode = database.execute("PRAGMA mmap_size=0")
assert(resultCode) assert(resultCode)
resultCode = database.execute("PRAGMA synchronous=NORMAL") resultCode = database.execute("PRAGMA synchronous=NORMAL")

View File

@ -3,10 +3,12 @@ import Foundation
open class Table { open class Table {
public final let valueBox: ValueBox public final let valueBox: ValueBox
public final let table: ValueBoxTable public final let table: ValueBoxTable
public final let useCaches: Bool
public init(valueBox: ValueBox, table: ValueBoxTable) { public init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
self.valueBox = valueBox self.valueBox = valueBox
self.table = table self.table = table
self.useCaches = useCaches
} }
open func clearMemoryCache() { open func clearMemoryCache() {

View File

@ -26,10 +26,10 @@ final class TimestampBasedMessageAttributesTable: Table {
private let indexTable: TimestampBasedMessageAttributesIndexTable private let indexTable: TimestampBasedMessageAttributesIndexTable
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: TimestampBasedMessageAttributesIndexTable) { init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: TimestampBasedMessageAttributesIndexTable) {
self.indexTable = indexTable self.indexTable = indexTable
super.init(valueBox: valueBox, table: table) super.init(valueBox: valueBox, table: table, useCaches: useCaches)
} }
private func key(tag: UInt16, timestamp: Int32, id: MessageId) -> ValueBoxKey { private func key(tag: UInt16, timestamp: Int32, id: MessageId) -> ValueBoxKey {

View File

@ -33,6 +33,13 @@ final public class AdaptedPostboxDecoder {
} }
func decode<T>(_ type: T.Type, from data: Data, contentType: ContentType) throws -> T where T : Decodable { func decode<T>(_ type: T.Type, from data: Data, contentType: ContentType) throws -> T where T : Decodable {
if type == AdaptedPostboxDecoder.RawObjectData.self {
if case .object = contentType {
return AdaptedPostboxDecoder.RawObjectData(data: data, typeHash: 0) as! T
} else {
preconditionFailure()
}
}
let decoder = _AdaptedPostboxDecoder(data: data, contentType: contentType) let decoder = _AdaptedPostboxDecoder(data: data, contentType: contentType)
return try T(from: decoder) return try T(from: decoder)
} }

View File

@ -21,30 +21,30 @@ private func makeExclusiveKeychain(id: AccountRecordId, postbox: Postbox) -> Key
} }
return dict return dict
} }
return Keychain(get: { key in return Keychain(get: { [weak postbox] key in
let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in
return dict[id] == keychainId return dict[id] == keychainId
} }
if enabled { if enabled, let postbox = postbox {
return postbox.keychainEntryForKey(key) return postbox.keychainEntryForKey(key)
} else { } else {
Logger.shared.log("Keychain", "couldn't get \(key) — not current") Logger.shared.log("Keychain", "couldn't get \(key) — not current")
return nil return nil
} }
}, set: { (key, data) in }, set: { [weak postbox] key, data in
let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in
return dict[id] == keychainId return dict[id] == keychainId
} }
if enabled { if enabled, let postbox = postbox {
postbox.setKeychainEntryForKey(key, value: data) postbox.setKeychainEntryForKey(key, value: data)
} else { } else {
Logger.shared.log("Keychain", "couldn't set \(key) — not current") Logger.shared.log("Keychain", "couldn't set \(key) — not current")
} }
}, remove: { key in }, remove: { [weak postbox] key in
let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in
return dict[id] == keychainId return dict[id] == keychainId
} }
if enabled { if enabled, let postbox = postbox {
postbox.removeKeychainEntryForKey(key) postbox.removeKeychainEntryForKey(key)
} else { } else {
Logger.shared.log("Keychain", "couldn't remove \(key) — not current") Logger.shared.log("Keychain", "couldn't remove \(key) — not current")
@ -162,85 +162,19 @@ public enum AccountResult {
case authorized(Account) case authorized(Account)
} }
public enum AccountPreferenceEntriesResult {
case progress(Float)
case result(String, [ValueBoxKey: PreferencesEntry])
}
public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set<ValueBoxKey>, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountPreferenceEntriesResult, NoError> {
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true, useCopy: false)
return postbox
|> mapToSignal { value -> Signal<AccountPreferenceEntriesResult, NoError> in
switch value {
case let .upgrading(progress):
return .single(.progress(progress))
case let .postbox(postbox):
return postbox.transaction { transaction -> AccountPreferenceEntriesResult in
var result: [ValueBoxKey: PreferencesEntry] = [:]
for key in keys {
if let value = transaction.getPreferencesEntry(key: key) {
result[key] = value
}
}
return .result(path, result)
}
case .error:
return .single(.progress(0.0))
}
}
}
public enum AccountNoticeEntriesResult {
case progress(Float)
case result(String, [ValueBoxKey: NoticeEntry])
}
public func accountNoticeEntries(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountNoticeEntriesResult, NoError> {
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true, useCopy: false)
return postbox
|> mapToSignal { value -> Signal<AccountNoticeEntriesResult, NoError> in
switch value {
case let .upgrading(progress):
return .single(.progress(progress))
case let .postbox(postbox):
return postbox.transaction { transaction -> AccountNoticeEntriesResult in
return .result(path, transaction.getAllNoticeEntries())
}
case .error:
return .single(.progress(0.0))
}
}
}
public enum LegacyAccessChallengeDataResult {
case progress(Float)
case result(PostboxAccessChallengeData)
}
public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<LegacyAccessChallengeDataResult, NoError> {
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true, useCopy: false)
return postbox
|> mapToSignal { value -> Signal<LegacyAccessChallengeDataResult, NoError> in
switch value {
case let .upgrading(progress):
return .single(.progress(progress))
case let .postbox(postbox):
return postbox.transaction { transaction -> LegacyAccessChallengeDataResult in
return .result(transaction.legacyGetAccessChallengeData())
}
case .error:
return .single(.progress(0.0))
}
}
}
public func accountWithId(accountManager: AccountManager<TelegramAccountManagerTypes>, 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<TelegramAccountManagerTypes>, 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, isReadOnly: false, useCopy: false) let postbox = openPostbox(
basePath: path + "/postbox",
seedConfiguration: telegramPostboxSeedConfiguration,
encryptionParameters: encryptionParameters,
timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970),
isTemporary: false,
isReadOnly: false,
useCopy: false,
useCaches: !supplementary
)
return postbox return postbox
|> mapToSignal { result -> Signal<AccountResult, NoError> in |> mapToSignal { result -> Signal<AccountResult, NoError> in
@ -251,7 +185,11 @@ public func accountWithId(accountManager: AccountManager<TelegramAccountManagerT
return .single(.upgrading(0.0)) return .single(.upgrading(0.0))
case let .postbox(postbox): case let .postbox(postbox):
return accountManager.transaction { transaction -> (LocalizationSettings?, ProxySettings?) in return accountManager.transaction { transaction -> (LocalizationSettings?, ProxySettings?) in
return (transaction.getSharedData(SharedDataKeys.localizationSettings)?.get(LocalizationSettings.self), transaction.getSharedData(SharedDataKeys.proxySettings)?.get(ProxySettings.self)) var localizationSettings: LocalizationSettings?
if !supplementary {
localizationSettings = transaction.getSharedData(SharedDataKeys.localizationSettings)?.get(LocalizationSettings.self)
}
return (localizationSettings, transaction.getSharedData(SharedDataKeys.proxySettings)?.get(ProxySettings.self))
} }
|> mapToSignal { localizationSettings, proxySettings -> Signal<AccountResult, NoError> in |> mapToSignal { localizationSettings, proxySettings -> Signal<AccountResult, NoError> in
return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in
@ -740,22 +678,30 @@ public struct MasterNotificationKey: Codable {
} }
public func masterNotificationsKey(account: Account, ignoreDisabled: Bool) -> Signal<MasterNotificationKey, NoError> { public func masterNotificationsKey(account: Account, ignoreDisabled: Bool) -> Signal<MasterNotificationKey, NoError> {
return masterNotificationsKey(masterNotificationKeyValue: account.masterNotificationKey, postbox: account.postbox, ignoreDisabled: ignoreDisabled) return masterNotificationsKey(masterNotificationKeyValue: account.masterNotificationKey, postbox: account.postbox, ignoreDisabled: ignoreDisabled, createIfNotExists: true)
|> map { value -> MasterNotificationKey in
return value!
}
} }
private func masterNotificationsKey(masterNotificationKeyValue: Atomic<MasterNotificationKey?>, postbox: Postbox, ignoreDisabled: Bool) -> Signal<MasterNotificationKey, NoError> { public func existingMasterNotificationsKey(postbox: Postbox) -> Signal<MasterNotificationKey?, NoError> {
let value = Atomic<MasterNotificationKey?>(value: nil)
return masterNotificationsKey(masterNotificationKeyValue: value, postbox: postbox, ignoreDisabled: true, createIfNotExists: false)
}
private func masterNotificationsKey(masterNotificationKeyValue: Atomic<MasterNotificationKey?>, postbox: Postbox, ignoreDisabled: Bool, createIfNotExists: Bool) -> Signal<MasterNotificationKey?, NoError> {
if let key = masterNotificationKeyValue.with({ $0 }) { if let key = masterNotificationKeyValue.with({ $0 }) {
return .single(key) return .single(key)
} }
return postbox.transaction(ignoreDisabled: ignoreDisabled, { transaction -> MasterNotificationKey in return postbox.transaction(ignoreDisabled: ignoreDisabled, { transaction -> MasterNotificationKey? in
if let value = transaction.keychainEntryForKey("master-notification-secret"), !value.isEmpty { if let value = transaction.keychainEntryForKey("master-notification-secret"), !value.isEmpty {
let authKeyHash = sha1Digest(value) let authKeyHash = sha1Digest(value)
let authKeyId = authKeyHash.subdata(in: authKeyHash.count - 8 ..< authKeyHash.count) let authKeyId = authKeyHash.subdata(in: authKeyHash.count - 8 ..< authKeyHash.count)
let keyData = MasterNotificationKey(id: authKeyId, data: value) let keyData = MasterNotificationKey(id: authKeyId, data: value)
let _ = masterNotificationKeyValue.swap(keyData) let _ = masterNotificationKeyValue.swap(keyData)
return keyData return keyData
} else { } else if createIfNotExists {
var secretData = Data(count: 256) var secretData = Data(count: 256)
let secretDataCount = secretData.count let secretDataCount = secretData.count
if !secretData.withUnsafeMutableBytes({ rawBytes -> Bool in if !secretData.withUnsafeMutableBytes({ rawBytes -> Bool in
@ -772,6 +718,8 @@ private func masterNotificationsKey(masterNotificationKeyValue: Atomic<MasterNot
let keyData = MasterNotificationKey(id: authKeyId, data: secretData) let keyData = MasterNotificationKey(id: authKeyId, data: secretData)
let _ = masterNotificationKeyValue.swap(keyData) let _ = masterNotificationKeyValue.swap(keyData)
return keyData return keyData
} else {
return nil
} }
}) })
} }
@ -818,8 +766,11 @@ public func decryptedNotificationPayload(key: MasterNotificationKey, data: Data)
} }
public func decryptedNotificationPayload(account: Account, data: Data) -> Signal<Data?, NoError> { public func decryptedNotificationPayload(account: Account, data: Data) -> Signal<Data?, NoError> {
return masterNotificationsKey(masterNotificationKeyValue: account.masterNotificationKey, postbox: account.postbox, ignoreDisabled: true) return masterNotificationsKey(masterNotificationKeyValue: account.masterNotificationKey, postbox: account.postbox, ignoreDisabled: true, createIfNotExists: false)
|> map { secret -> Data? in |> map { secret -> Data? in
guard let secret = secret else {
return nil
}
return decryptedNotificationPayload(key: secret, data: data) return decryptedNotificationPayload(key: secret, data: data)
} }
} }
@ -969,12 +920,8 @@ public class Account {
let networkStateQueue = Queue() let networkStateQueue = Queue()
let networkStateSignal = combineLatest(queue: networkStateQueue, self.stateManager.isUpdating, network.connectionStatus/*, delayNetworkStatus*/) let networkStateSignal = combineLatest(queue: networkStateQueue, self.stateManager.isUpdating, network.connectionStatus)
|> map { isUpdating, connectionStatus/*, delayNetworkStatus*/ -> AccountNetworkState in |> map { isUpdating, connectionStatus -> AccountNetworkState in
/*if delayNetworkStatus {
return .online(proxy: nil)
}*/
switch connectionStatus { switch connectionStatus {
case .waitingForNetwork: case .waitingForNetwork:
return .waitingForNetwork return .waitingForNetwork
@ -1076,7 +1023,10 @@ public class Account {
self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network, accountPeerId: self.peerId).start())
if !supplementary {
self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network, accountPeerId: self.peerId).start())
}
let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = [ let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = [
managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] }, managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] },
@ -1140,7 +1090,7 @@ public class Account {
self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedNotificationSettingsBehaviors(postbox: self.postbox).start()) self.managedOperationsDisposable.add(managedNotificationSettingsBehaviors(postbox: self.postbox).start())
self.managedOperationsDisposable.add(managedThemesUpdates(accountManager: accountManager, postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedThemesUpdates(accountManager: accountManager, postbox: self.postbox, network: self.network).start())
if !self.testingEnvironment { if !self.testingEnvironment && !supplementary {
self.managedOperationsDisposable.add(managedChatThemesUpdates(accountManager: accountManager, network: self.network).start()) self.managedOperationsDisposable.add(managedChatThemesUpdates(accountManager: accountManager, network: self.network).start())
} }
@ -1161,7 +1111,7 @@ public class Account {
}) })
} }
let _ = masterNotificationsKey(masterNotificationKeyValue: self.masterNotificationKey, postbox: self.postbox, ignoreDisabled: false).start(next: { key in let _ = masterNotificationsKey(masterNotificationKeyValue: self.masterNotificationKey, postbox: self.postbox, ignoreDisabled: false, createIfNotExists: true).start(next: { key in
let encoder = JSONEncoder() let encoder = JSONEncoder()
if let data = try? encoder.encode(key) { if let data = try? encoder.encode(key) {
let _ = try? data.write(to: URL(fileURLWithPath: "\(basePath)/notificationsKey")) let _ = try? data.write(to: URL(fileURLWithPath: "\(basePath)/notificationsKey"))
@ -1301,3 +1251,95 @@ public func setupAccount(_ account: Account, fetchCachedResourceRepresentation:
account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia
account.pendingUpdateMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia account.pendingUpdateMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia
} }
public func standaloneStateManager(
accountManager: AccountManager<TelegramAccountManagerTypes>,
networkArguments: NetworkInitializationArguments,
id: AccountRecordId,
encryptionParameters: ValueBoxEncryptionParameters,
rootPath: String,
auxiliaryMethods: AccountAuxiliaryMethods
) -> Signal<AccountStateManager?, NoError> {
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
let postbox = openPostbox(
basePath: path + "/postbox",
seedConfiguration: telegramPostboxSeedConfiguration,
encryptionParameters: encryptionParameters,
timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970),
isTemporary: false,
isReadOnly: false,
useCopy: false,
useCaches: false
)
return postbox
|> take(1)
|> mapToSignal { result -> Signal<AccountStateManager?, NoError> in
switch result {
case .upgrading:
return .single(nil)
case .error:
return .single(nil)
case let .postbox(postbox):
return accountManager.transaction { transaction -> (LocalizationSettings?, ProxySettings?) in
return (nil, transaction.getSharedData(SharedDataKeys.proxySettings)?.get(ProxySettings.self))
}
|> mapToSignal { localizationSettings, proxySettings -> Signal<AccountStateManager?, NoError> in
return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in
let state = transaction.getState()
return (state, localizationSettings, proxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings)?.get(NetworkSettings.self))
}
|> mapToSignal { accountState, localizationSettings, proxySettings, networkSettings -> Signal<AccountStateManager?, NoError> in
let keychain = makeExclusiveKeychain(id: id, postbox: postbox)
if let accountState = accountState {
switch accountState {
case _ as UnauthorizedAccountState:
return .single(nil)
case let authorizedState as AuthorizedAccountState:
return postbox.transaction { transaction -> String? in
return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone
}
|> mapToSignal { phoneNumber in
return initializedNetwork(
accountId: id,
arguments: networkArguments,
supplementary: true,
datacenterId: Int(authorizedState.masterDatacenterId),
keychain: keychain,
basePath: path,
testingEnvironment: authorizedState.isTestingEnvironment,
languageCode: localizationSettings?.primaryComponent.languageCode,
proxySettings: proxySettings,
networkSettings: networkSettings,
phoneNumber: phoneNumber
)
|> map { network -> AccountStateManager? in
return AccountStateManager(
accountPeerId: authorizedState.peerId,
accountManager: accountManager,
postbox: postbox,
network: network,
callSessionManager: nil,
addIsContactUpdates: { _ in
},
shouldKeepOnlinePresence: .single(false),
peerInputActivityManager: nil,
auxiliaryMethods: auxiliaryMethods
)
}
}
default:
assertionFailure("Unexpected accountState \(accountState)")
return .single(nil)
}
} else {
return .single(nil)
}
}
}
}
}
}

View File

@ -282,36 +282,6 @@ public func performAppGroupUpgrades(appGroupPath: String, rootPath: String) {
} }
} }
public final class TemporaryAccount {
public let id: AccountRecordId
public let basePath: String
public let postbox: Postbox
init(id: AccountRecordId, basePath: String, postbox: Postbox) {
self.id = id
self.basePath = basePath
self.postbox = postbox
}
}
public func temporaryAccount(manager: AccountManager<TelegramAccountManagerTypes>, rootPath: String, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<TemporaryAccount, NoError> {
return manager.allocatedTemporaryAccountId()
|> mapToSignal { id -> Signal<TemporaryAccount, NoError> in
let path = "\(rootPath)/\(accountRecordIdPathName(id))"
return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false, isReadOnly: false, useCopy: false)
|> mapToSignal { result -> Signal<TemporaryAccount, NoError> in
switch result {
case .upgrading:
return .complete()
case .error:
return .complete()
case let .postbox(postbox):
return .single(TemporaryAccount(id: id, basePath: path, postbox: postbox))
}
}
}
}
public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager<TelegramAccountManagerTypes>, rootPath: String, auxiliaryMethods: AccountAuxiliaryMethods, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountResult?, NoError> { public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager<TelegramAccountManagerTypes>, rootPath: String, auxiliaryMethods: AccountAuxiliaryMethods, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<AccountResult?, NoError> {
return manager.currentAccountRecord(allocateIfNotExists: allocateIfNotExists) return manager.currentAccountRecord(allocateIfNotExists: allocateIfNotExists)
|> distinctUntilChanged(isEqual: { lhs, rhs in |> distinctUntilChanged(isEqual: { lhs, rhs in

View File

@ -423,16 +423,6 @@ public struct NetworkInitializationArguments {
private let cloudDataContext = Atomic<CloudDataContext?>(value: nil) private let cloudDataContext = Atomic<CloudDataContext?>(value: nil)
#endif #endif
private final class SharedContextStore {
struct Key: Hashable {
var accountId: AccountRecordId
}
var contexts: [Key: MTContext] = [:]
}
private let sharedContexts = Atomic<SharedContextStore>(value: SharedContextStore())
func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializationArguments, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?, proxySettings: ProxySettings?, networkSettings: NetworkSettings?, phoneNumber: String?) -> Signal<Network, NoError> { func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializationArguments, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?, proxySettings: ProxySettings?, networkSettings: NetworkSettings?, phoneNumber: String?) -> Signal<Network, NoError> {
return Signal { subscriber in return Signal { subscriber in
let queue = Queue() let queue = Queue()
@ -475,19 +465,7 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
let useTempAuthKeys: Bool = true let useTempAuthKeys: Bool = true
var contextValue: MTContext? let context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys)
sharedContexts.with { store in
let key = SharedContextStore.Key(accountId: accountId)
let context: MTContext
context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys)
store.contexts[key] = context
contextValue = context
}
let context = contextValue!
let seedAddressList: [Int: [String]] let seedAddressList: [Int: [String]]
@ -539,10 +517,6 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
#endif #endif
context.setDiscoverBackupAddressListSignal(MTBackupAddressSignals.fetchBackupIps(testingEnvironment, currentContext: context, additionalSource: wrappedAdditionalSource, phoneNumber: phoneNumber)) context.setDiscoverBackupAddressListSignal(MTBackupAddressSignals.fetchBackupIps(testingEnvironment, currentContext: context, additionalSource: wrappedAdditionalSource, phoneNumber: phoneNumber))
#if DEBUG
//let _ = MTBackupAddressSignals.fetchBackupIps(testingEnvironment, currentContext: context, additionalSource: wrappedAdditionalSource, phoneNumber: phoneNumber).start(next: nil)
#endif
let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: usageCalculationInfo(basePath: basePath, category: nil), requiredAuthToken: nil, authTokenMasterDatacenterId: 0)! let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: usageCalculationInfo(basePath: basePath, category: nil), requiredAuthToken: nil, authTokenMasterDatacenterId: 0)!
mtProto.useTempAuthKeys = context.useTempAuthKeys mtProto.useTempAuthKeys = context.useTempAuthKeys
mtProto.checkForProxyConnectionIssues = true mtProto.checkForProxyConnectionIssues = true

View File

@ -52,15 +52,15 @@ public enum DeletedMessageId: Hashable {
public final class AccountStateManager { public final class AccountStateManager {
private let queue = Queue() private let queue = Queue()
private let accountPeerId: PeerId public let accountPeerId: PeerId
private let accountManager: AccountManager<TelegramAccountManagerTypes> private let accountManager: AccountManager<TelegramAccountManagerTypes>
private let postbox: Postbox public let postbox: Postbox
private let network: Network public let network: Network
private let callSessionManager: CallSessionManager private let callSessionManager: CallSessionManager?
private let addIsContactUpdates: ([(PeerId, Bool)]) -> Void private let addIsContactUpdates: ([(PeerId, Bool)]) -> Void
private let shouldKeepOnlinePresence: Signal<Bool, NoError> private let shouldKeepOnlinePresence: Signal<Bool, NoError>
private let peerInputActivityManager: PeerInputActivityManager private let peerInputActivityManager: PeerInputActivityManager?
let auxiliaryMethods: AccountAuxiliaryMethods let auxiliaryMethods: AccountAuxiliaryMethods
var transformOutgoingMessageMedia: TransformOutgoingMessageMedia? var transformOutgoingMessageMedia: TransformOutgoingMessageMedia?
@ -166,7 +166,7 @@ public final class AccountStateManager {
private let appliedQtsPromise = Promise<Int32?>(nil) private let appliedQtsPromise = Promise<Int32?>(nil)
private let appliedQtsDisposable = MetaDisposable() private let appliedQtsDisposable = MetaDisposable()
init(accountPeerId: PeerId, accountManager: AccountManager<TelegramAccountManagerTypes>, postbox: Postbox, network: Network, callSessionManager: CallSessionManager, addIsContactUpdates: @escaping ([(PeerId, Bool)]) -> Void, shouldKeepOnlinePresence: Signal<Bool, NoError>, peerInputActivityManager: PeerInputActivityManager, auxiliaryMethods: AccountAuxiliaryMethods) { init(accountPeerId: PeerId, accountManager: AccountManager<TelegramAccountManagerTypes>, postbox: Postbox, network: Network, callSessionManager: CallSessionManager?, addIsContactUpdates: @escaping ([(PeerId, Bool)]) -> Void, shouldKeepOnlinePresence: Signal<Bool, NoError>, peerInputActivityManager: PeerInputActivityManager?, auxiliaryMethods: AccountAuxiliaryMethods) {
self.accountPeerId = accountPeerId self.accountPeerId = accountPeerId
self.accountManager = accountManager self.accountManager = accountManager
self.postbox = postbox self.postbox = postbox
@ -183,9 +183,14 @@ public final class AccountStateManager {
self.operationDisposable.dispose() self.operationDisposable.dispose()
self.appliedMaxMessageIdDisposable.dispose() self.appliedMaxMessageIdDisposable.dispose()
self.appliedQtsDisposable.dispose() self.appliedQtsDisposable.dispose()
var postbox: Postbox? = self.postbox
postbox?.queue.async {
postbox = nil
}
} }
func reset() { public func reset() {
self.queue.async { self.queue.async {
if self.updateService == nil { if self.updateService == nil {
self.updateService = UpdateMessageService(peerId: self.accountPeerId) self.updateService = UpdateMessageService(peerId: self.accountPeerId)
@ -641,7 +646,7 @@ public final class AccountStateManager {
let topOperation = strongSelf.operations.removeFirst() let topOperation = strongSelf.operations.removeFirst()
if case .processEvents(operationId, _) = topOperation.content { if case .processEvents(operationId, _) = topOperation.content {
if !events.updatedTypingActivities.isEmpty { if !events.updatedTypingActivities.isEmpty {
strongSelf.peerInputActivityManager.transaction { manager in strongSelf.peerInputActivityManager?.transaction { manager in
for (chatPeerId, peerActivities) in events.updatedTypingActivities { for (chatPeerId, peerActivities) in events.updatedTypingActivities {
for (peerId, activity) in peerActivities { for (peerId, activity) in peerActivities {
if let activity = activity { if let activity = activity {
@ -661,12 +666,12 @@ public final class AccountStateManager {
} }
if !events.updatedCalls.isEmpty { if !events.updatedCalls.isEmpty {
for call in events.updatedCalls { for call in events.updatedCalls {
strongSelf.callSessionManager.updateSession(call, completion: { _ in }) strongSelf.callSessionManager?.updateSession(call, completion: { _ in })
} }
} }
if !events.addedCallSignalingData.isEmpty { if !events.addedCallSignalingData.isEmpty {
for (id, data) in events.addedCallSignalingData { for (id, data) in events.addedCallSignalingData {
strongSelf.callSessionManager.addCallSignalingData(id: id, data: data) strongSelf.callSessionManager?.addCallSignalingData(id: id, data: data)
} }
} }
if !events.updatedGroupCallParticipants.isEmpty { if !events.updatedGroupCallParticipants.isEmpty {
@ -1046,9 +1051,13 @@ public final class AccountStateManager {
for update in updates { for update in updates {
switch update { switch update {
case let .updatePhoneCall(phoneCall): case let .updatePhoneCall(phoneCall):
self.callSessionManager.updateSession(phoneCall, completion: { result in if let callSessionManager = self.callSessionManager {
completion(result) callSessionManager.updateSession(phoneCall, completion: { result in
}) completion(result)
})
} else {
completion(nil)
}
return return
default: default:
break break

View File

@ -97,9 +97,9 @@ public enum AccountTransactionError {
case couldNotOpen case couldNotOpen
} }
public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, isReadOnly: Bool, useCopy: Bool = false, transaction: @escaping (Postbox, Transaction) -> T) -> Signal<T, AccountTransactionError> { public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, isReadOnly: Bool, useCopy: Bool = false, useCaches: Bool = true, 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, isReadOnly: isReadOnly, useCopy: useCopy) let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: isReadOnly, useCopy: useCopy, useCaches: useCaches)
return postbox return postbox
|> castError(AccountTransactionError.self) |> castError(AccountTransactionError.self)
|> mapToSignal { value -> Signal<T, AccountTransactionError> in |> mapToSignal { value -> Signal<T, AccountTransactionError> in

View File

@ -677,7 +677,7 @@ final class SharedApplicationContext {
}) })
let accountManagerSignal = Signal<AccountManager<TelegramAccountManagerTypes>, NoError> { subscriber in let accountManagerSignal = Signal<AccountManager<TelegramAccountManagerTypes>, NoError> { subscriber in
let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: false, isReadOnly: false) let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: false, isReadOnly: false, useCaches: true)
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 {
@ -1489,6 +1489,10 @@ final class SharedApplicationContext {
} }
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
if "".isEmpty {
return;
}
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
/*guard var encryptedPayload = payload.dictionaryPayload["p"] as? String else { /*guard var encryptedPayload = payload.dictionaryPayload["p"] as? String else {
return return

View File

@ -94,7 +94,7 @@ public final class NotificationViewControllerImpl {
if sharedAccountContext == nil { if sharedAccountContext == nil {
initializeAccountManagement() initializeAccountManagement()
let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false, useCaches: false)
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings? var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
let semaphore = DispatchSemaphore(value: 0) let semaphore = DispatchSemaphore(value: 0)

View File

@ -624,10 +624,10 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
game = value game = value
} else if queryItem.name == "post" { } else if queryItem.name == "post" {
post = value post = value
} else if queryItem.name == "voicechat" { } else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
voiceChat = value voiceChat = value
} }
} else if queryItem.name == "voicechat" { } else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
voiceChat = "" voiceChat = ""
} }
} }

View File

@ -205,7 +205,7 @@ public class ShareRootControllerImpl {
let internalContext: InternalContext let internalContext: InternalContext
let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false, useCaches: false)
if let globalInternalContext = globalInternalContext { if let globalInternalContext = globalInternalContext {
internalContext = globalInternalContext internalContext = globalInternalContext

View File

@ -111,204 +111,11 @@ public func upgradedAccounts(accountManager: AccountManager<TelegramAccountManag
return (transaction.getVersion(), transaction.getCurrent()?.0) return (transaction.getVersion(), transaction.getCurrent()?.0)
} }
|> mapToSignal { version, currentId -> Signal<Float, NoError> in |> mapToSignal { version, currentId -> Signal<Float, NoError> in
guard let version = version else { return accountManager.transaction { transaction -> Void in
return accountManager.transaction { transaction -> Void in transaction.setVersion(4)
transaction.setVersion(4)
}
|> ignoreValues
|> mapToSignal { _ -> Signal<Float, NoError> in
}
} }
var signal: Signal<Float, NoError> = .complete() |> ignoreValues
if version < 1 { |> mapToSignal { _ -> Signal<Float, NoError> in
if let currentId = currentId {
let upgradePreferences = accountPreferenceEntries(rootPath: rootPath, id: currentId, keys: Set(preferencesKeyMapping.keys.map({ $0.key }) + applicationSpecificPreferencesKeyMapping.keys.map({ $0.key })), encryptionParameters: encryptionParameters)
|> mapToSignal { result -> Signal<Float, NoError> in
switch result {
case let .progress(progress):
return .single(progress)
case let .result(path, values):
return accountManager.transaction { transaction -> Void in
for (key, value) in values {
var upgradedKey: ValueBoxKey?
for (k, v) in preferencesKeyMapping {
if k.key == key {
upgradedKey = v.key
break
}
}
for (k, v) in applicationSpecificPreferencesKeyMapping {
if k.key == key {
upgradedKey = v.key
break
}
}
if let upgradedKey = upgradedKey {
transaction.updateSharedData(upgradedKey, { _ in
return upgradedSharedDataValue(value)
})
}
}
if let value = values[LegacyApplicationSpecificPreferencesKeyValues.presentationThemeSettings.key]?.get(PresentationThemeSettings.self) {
let mediaBox = MediaBox(basePath: path + "/postbox/media")
let wallpapers = Array(value.themeSpecificChatWallpapers.values)
for wallpaper in wallpapers {
switch wallpaper {
case let .file(file):
if let path = mediaBox.completedResourcePath(file.file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
accountManager.mediaBox.storeResourceData(file.file.resource.id, data: data)
let _ = accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
if wallpaper.isPattern {
} else {
if file.settings.blur {
let _ = accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true).start()
}
}
}
case let .image(representations, _):
for representation in representations {
let resource = representation.resource
if let path = mediaBox.completedResourcePath(resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
accountManager.mediaBox.storeResourceData(resource.id, data: data)
let _ = mediaBox.cachedResourceRepresentation(resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
}
}
default:
break
}
}
}
transaction.setVersion(1)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
}
}
signal = signal |> then(upgradePreferences)
} else {
let upgradePreferences = accountManager.transaction { transaction -> Void in
transaction.setVersion(1)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
signal = signal |> then(upgradePreferences)
} }
}
if version < 2 {
if let currentId = currentId {
let upgradeNotices = accountNoticeEntries(rootPath: rootPath, id: currentId, encryptionParameters: encryptionParameters)
|> mapToSignal { result -> Signal<Float, NoError> in
switch result {
case let .progress(progress):
return .single(progress)
case let .result(_, values):
return accountManager.transaction { transaction -> Void in
for (key, value) in values {
transaction.setNotice(NoticeEntryKey(namespace: ValueBoxKey(length: 0), key: key), value)
}
transaction.setVersion(2)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
}
}
signal = signal |> then(upgradeNotices)
} else {
let upgradeNotices = accountManager.transaction { transaction -> Void in
transaction.setVersion(2)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
signal = signal |> then(upgradeNotices)
}
let upgradeSortOrder = accountManager.transaction { transaction -> Void in
var index: Int32 = 0
for record in transaction.getRecords() {
transaction.updateRecord(record.id, { _ in
return AccountRecord(id: record.id, attributes: record.attributes + [.sortOrder(AccountSortOrderAttribute(order: index))], temporarySessionId: record.temporarySessionId)
})
index += 1
}
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
signal = signal |> then(upgradeSortOrder)
}
if version < 3 {
if let currentId = currentId {
let upgradeAccessChallengeData = accountLegacyAccessChallengeData(rootPath: rootPath, id: currentId, encryptionParameters: encryptionParameters)
|> mapToSignal { result -> Signal<Float, NoError> in
switch result {
case let .progress(progress):
return .single(progress)
case let .result(accessChallengeData):
return accountManager.transaction { transaction -> Void in
if case .none = transaction.getAccessChallengeData() {
transaction.setAccessChallengeData(accessChallengeData)
}
transaction.setVersion(3)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
}
}
signal = signal |> then(upgradeAccessChallengeData)
} else {
let upgradeAccessChallengeData = accountManager.transaction { transaction -> Void in
transaction.setVersion(3)
}
|> mapToSignal { _ -> Signal<Float, NoError> in
return .complete()
}
signal = signal |> then(upgradeAccessChallengeData)
}
}
if version < 4 {
let updatedContactSynchronizationSettings = accountManager.transaction { transaction -> (ContactSynchronizationSettings, [AccountRecordId]) in
return (transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings)?.get(ContactSynchronizationSettings.self) ?? ContactSynchronizationSettings.defaultSettings, transaction.getRecords().map({ $0.id }))
}
|> mapToSignal { globalSettings, ids -> Signal<Never, NoError> in
var importSignal: Signal<Never, NoError> = .complete()
for id in ids {
let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, isReadOnly: false, transaction: { _, transaction -> Void in
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
var settings = current?.get(ContactsSettings.self) ?? ContactsSettings.defaultSettings
settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts
return PreferencesEntry(settings)
})
})
|> ignoreValues
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()
}
importSignal = importSignal |> then(importInfoAccounttSignal)
}
return importSignal
}
let applyVersion = accountManager.transaction { transaction -> Void in
transaction.setVersion(4)
}
|> ignoreValues
signal = signal |> then(
(updatedContactSynchronizationSettings
|> then(
applyVersion
)) |> mapToSignal { _ -> Signal<Float, NoError> in
}
)
}
return signal
} }
} }

View File

@ -136,10 +136,10 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
return .peerName(peerName, .groupBotStart(value)) return .peerName(peerName, .groupBotStart(value))
} else if queryItem.name == "game" { } else if queryItem.name == "game" {
return nil return nil
} else if queryItem.name == "voicechat" { } else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
return .peerName(peerName, .voiceChat(value)) return .peerName(peerName, .voiceChat(value))
} }
} else if queryItem.name == "voicechat" { } else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
return .peerName(peerName, .voiceChat(nil)) return .peerName(peerName, .voiceChat(nil))
} }
} }