mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update notification service
This commit is contained in:
parent
e4d277daf9
commit
0553a14eb3
@ -15,7 +15,8 @@ swift_library(
|
||||
"//submodules/EncryptionProvider:EncryptionProvider",
|
||||
"//submodules/AppLockState:AppLockState",
|
||||
"//submodules/NotificationsPresentationData:NotificationsPresentationData",
|
||||
"//Telegram/NotificationService/NotificationServiceObjC:NotificationServiceObjC",
|
||||
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
|
||||
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider"
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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)
|
||||
}
|
||||
*/
|
@ -1 +0,0 @@
|
||||
import Foundation
|
@ -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
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,53 +1,270 @@
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
import SwiftSignalKit
|
||||
import NotificationServiceObjC
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import BuildConfig
|
||||
import OpenSSLEncryptionProvider
|
||||
import TelegramUIPreferences
|
||||
|
||||
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, *)
|
||||
@objc(NotificationService)
|
||||
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() {
|
||||
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()
|
||||
}
|
||||
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
self.impl.with { impl in
|
||||
impl.didReceive(request, withContentHandler: contentHandler)
|
||||
}
|
||||
let _ = self.content.swap(request.content)
|
||||
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() {
|
||||
self.impl.with { impl in
|
||||
impl.serviceExtensionTimeWillExpire()
|
||||
if let content = self.content.with({ $0 }), let contentHandler = self.contentHandler {
|
||||
contentHandler(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
*/
|
@ -121,7 +121,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
||||
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
||||
|
||||
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
|
||||
|
||||
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
|
||||
|
@ -386,14 +386,14 @@ static int32_t fixedTimeDifferenceValue = 0;
|
||||
NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"];
|
||||
if (datacenterAuthInfoById != nil) {
|
||||
_datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById];
|
||||
#if DEBUG
|
||||
/*#if DEBUG
|
||||
NSArray<NSNumber *> *keys = [_datacenterAuthInfoById allKeys];
|
||||
for (NSNumber *key in keys) {
|
||||
if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) {
|
||||
[_datacenterAuthInfoById removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif*/
|
||||
}
|
||||
|
||||
NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"];
|
||||
|
@ -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()
|
||||
|
||||
self.queue = queue
|
||||
@ -77,19 +77,19 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
self.atomicStatePath = "\(basePath)/atomic-state"
|
||||
self.temporarySessionId = temporarySessionId
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
self.valueBox = valueBox
|
||||
|
||||
self.legacyMetadataTable = AccountManagerMetadataTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerMetadataTable<Types.Attribute>.tableSpec(0))
|
||||
self.legacyRecordTable = AccountManagerRecordTable<Types.Attribute>(valueBox: self.valueBox, table: AccountManagerRecordTable<Types.Attribute>.tableSpec(1))
|
||||
self.sharedDataTable = AccountManagerSharedDataTable(valueBox: self.valueBox, table: AccountManagerSharedDataTable.tableSpec(2))
|
||||
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(3))
|
||||
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), useCaches: useCaches)
|
||||
self.sharedDataTable = AccountManagerSharedDataTable(valueBox: self.valueBox, table: AccountManagerSharedDataTable.tableSpec(2), useCaches: useCaches)
|
||||
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(3), useCaches: useCaches)
|
||||
|
||||
do {
|
||||
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)
|
||||
}
|
||||
|
||||
public init(basePath: String, isTemporary: Bool, isReadOnly: Bool) {
|
||||
public init(basePath: String, isTemporary: Bool, isReadOnly: Bool, useCaches: Bool) {
|
||||
self.queue = sharedQueue
|
||||
self.basePath = basePath
|
||||
var temporarySessionId: Int64 = 0
|
||||
@ -480,7 +480,7 @@ public final class AccountManager<Types: AccountManagerTypes> {
|
||||
self.temporarySessionId = temporarySessionId
|
||||
let queue = self.queue
|
||||
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
|
||||
} else {
|
||||
preconditionFailure()
|
||||
|
@ -11,8 +11,8 @@ final class CachedPeerDataTable: Table {
|
||||
private var cachedDatas: [PeerId: CachedPeerData] = [:]
|
||||
private var updatedPeerIds = Set<PeerId>()
|
||||
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable) {
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ id: PeerId) -> ValueBoxKey {
|
||||
@ -54,5 +54,8 @@ final class CachedPeerDataTable: Table {
|
||||
}
|
||||
|
||||
self.updatedPeerIds.removeAll()
|
||||
if !self.useCaches {
|
||||
self.cachedDatas.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ final class ChatListIndexTable: Table {
|
||||
|
||||
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.metadataTable = metadataTable
|
||||
self.readStateTable = readStateTable
|
||||
self.notificationSettingsTable = notificationSettingsTable
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ peerId: PeerId) -> ValueBoxKey {
|
||||
@ -554,6 +554,10 @@ final class ChatListIndexTable: Table {
|
||||
|
||||
override func beforeCommit() {
|
||||
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
||||
|
||||
if !self.useCaches {
|
||||
self.cachedPeerIndices.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
func debugReindexUnreadCounts(postbox: Postbox, currentTransaction: Transaction) -> ([PeerGroupId: ChatListTotalUnreadState], [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) {
|
||||
|
@ -133,12 +133,12 @@ final class ChatListTable: Table {
|
||||
let metadataTable: MessageHistoryMetadataTable
|
||||
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.metadataTable = metadataTable
|
||||
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 {
|
||||
|
@ -10,10 +10,10 @@ final class ContactTable: Table {
|
||||
private var peerIdsBeforeModification: 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
|
||||
|
||||
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 {
|
||||
@ -98,5 +98,9 @@ final class ContactTable: Table {
|
||||
|
||||
self.peerIdsBeforeModification = nil
|
||||
}
|
||||
|
||||
if !self.useCaches {
|
||||
self.peerIds = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ final class GlobalMessageIdsTable: Table {
|
||||
private let sharedKey = ValueBoxKey(length: 8)
|
||||
private let sharedBuffer = WriteBuffer()
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, 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 {
|
||||
|
@ -63,9 +63,9 @@ final class ItemCollectionItemTable: Table {
|
||||
|
||||
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
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(collectionId: ItemCollectionId, index: ItemCollectionItemIndex) -> ValueBoxKey {
|
||||
|
@ -49,11 +49,11 @@ final class MessageHistoryHoleIndexTable: Table {
|
||||
let metadataTable: MessageHistoryMetadataTable
|
||||
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.metadataTable = metadataTable
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(id: MessageId, space: MessageHistoryHoleSpace) -> ValueBoxKey {
|
||||
|
@ -47,13 +47,13 @@ final class MessageHistoryIndexTable: Table {
|
||||
|
||||
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.globalMessageIdsTable = globalMessageIdsTable
|
||||
self.seedConfiguration = seedConfiguration
|
||||
self.metadataTable = metadataTable
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ id: MessageId) -> ValueBoxKey {
|
||||
|
@ -32,10 +32,10 @@ final class MessageHistoryReadStateTable: Table {
|
||||
return self.sharedKey
|
||||
}
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, 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? {
|
||||
@ -567,6 +567,10 @@ final class MessageHistoryReadStateTable: Table {
|
||||
}
|
||||
}
|
||||
self.updatedInitialPeerReadStates.removeAll()
|
||||
|
||||
if !self.useCaches {
|
||||
self.cachedPeerReadStates.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ final class MessageHistoryTable: Table {
|
||||
let summaryTable: MessageHistoryTagsSummaryTable
|
||||
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.messageHistoryIndexTable = messageHistoryIndexTable
|
||||
self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable
|
||||
@ -110,7 +110,7 @@ final class MessageHistoryTable: Table {
|
||||
self.summaryTable = summaryTable
|
||||
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 {
|
||||
|
@ -82,10 +82,10 @@ class MessageHistoryTagsSummaryTable: Table {
|
||||
|
||||
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
|
||||
|
||||
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 {
|
||||
@ -172,5 +172,9 @@ class MessageHistoryTagsSummaryTable: Table {
|
||||
}
|
||||
self.updatedKeys.removeAll()
|
||||
}
|
||||
|
||||
if !self.useCaches {
|
||||
self.cachedSummaries.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,11 @@ class MessageHistoryTagsTable: Table {
|
||||
private let summaryTable: MessageHistoryTagsSummaryTable
|
||||
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.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 {
|
||||
|
@ -25,11 +25,11 @@ final class MessageHistoryThreadHoleIndexTable: Table {
|
||||
let metadataTable: MessageHistoryMetadataTable
|
||||
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.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 {
|
||||
|
@ -11,8 +11,8 @@ class MessageHistoryThreadsTable: Table {
|
||||
|
||||
private let sharedKey = ValueBoxKey(length: 8 + 8 + 4 + 4 + 4)
|
||||
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable) {
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
|
||||
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 {
|
||||
|
@ -19,8 +19,8 @@ final class MetadataTable: Table {
|
||||
|
||||
private let sharedBuffer = WriteBuffer()
|
||||
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable) {
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
override init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool) {
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ key: MetadataKey) -> ValueBoxKey {
|
||||
|
@ -19,10 +19,10 @@ final class OrderedItemListTable: Table {
|
||||
|
||||
private let indexTable: OrderedItemListIndexTable
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: OrderedItemListIndexTable) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: OrderedItemListIndexTable) {
|
||||
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 {
|
||||
|
@ -7,10 +7,10 @@ final class PeerMergedOperationLogIndexTable: Table {
|
||||
|
||||
private let metadataTable: PeerOperationLogMetadataTable
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: PeerOperationLogMetadataTable) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PeerOperationLogMetadataTable) {
|
||||
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 {
|
||||
|
@ -140,11 +140,11 @@ final class PeerNameIndexTable: Table {
|
||||
|
||||
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.peerNameTokenIndexTable = peerNameTokenIndexTable
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ peerId: PeerId) -> ValueBoxKey {
|
||||
|
@ -11,10 +11,10 @@ final class PeerNotificationSettingsBehaviorTable: Table {
|
||||
|
||||
private let indexTable: PeerNotificationSettingsBehaviorIndexTable
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: PeerNotificationSettingsBehaviorIndexTable) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: PeerNotificationSettingsBehaviorIndexTable) {
|
||||
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 {
|
||||
|
@ -63,11 +63,11 @@ final class PeerNotificationSettingsTable: Table {
|
||||
private var cachedSettings: [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.behaviorTable = behaviorTable
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ id: PeerId) -> ValueBoxKey {
|
||||
@ -301,6 +301,10 @@ final class PeerNotificationSettingsTable: Table {
|
||||
}
|
||||
|
||||
self.updatedInitialSettings.removeAll()
|
||||
|
||||
if !self.useCaches {
|
||||
self.cachedSettings.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,11 +112,11 @@ final class PeerOperationLogTable: Table {
|
||||
private let metadataTable: PeerOperationLogMetadataTable
|
||||
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.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 {
|
||||
|
@ -13,10 +13,10 @@ final class PeerTable: Table {
|
||||
private var cachedPeers: [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
|
||||
|
||||
super.init(valueBox: valueBox, table: table)
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
||||
private func key(_ id: PeerId) -> ValueBoxKey {
|
||||
@ -87,6 +87,9 @@ final class PeerTable: Table {
|
||||
}
|
||||
|
||||
self.updatedInitialPeers.removeAll()
|
||||
if !self.useCaches {
|
||||
self.cachedPeers.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ final class PendingMessageActionsTable: Table {
|
||||
|
||||
private let metadataTable: PendingMessageActionsMetadataTable
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, metadataTable: PendingMessageActionsMetadataTable) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PendingMessageActionsMetadataTable) {
|
||||
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 {
|
||||
|
@ -1165,7 +1165,7 @@ func debugRestoreState(basePath:String, name: String) {
|
||||
|
||||
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
|
||||
return Signal { subscriber in
|
||||
queue.async {
|
||||
@ -1209,7 +1209,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
|
||||
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)")
|
||||
subscriber.putNext(.upgrading(progress))
|
||||
}) else {
|
||||
@ -1219,7 +1219,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
}
|
||||
|
||||
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 currentUserVersion: Int32 = 25
|
||||
@ -1237,7 +1237,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
postboxLog("Version \(userVersion) is newer than supported")
|
||||
assertionFailure("Version \(userVersion) is newer than supported")
|
||||
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))
|
||||
}) else {
|
||||
subscriber.putNext(.error)
|
||||
@ -1261,7 +1261,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
valueBox.internalClose()
|
||||
let _ = try? FileManager.default.removeItem(atPath: 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))
|
||||
}) else {
|
||||
subscriber.putNext(.error)
|
||||
@ -1275,7 +1275,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
assertionFailure("Couldn't find any upgrade for \(userVersion)")
|
||||
postboxLog("Couldn't find any upgrade for \(userVersion)")
|
||||
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))
|
||||
}) else {
|
||||
subscriber.putNext(.error)
|
||||
@ -1293,7 +1293,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
let endTime = CFAbsoluteTimeGetCurrent()
|
||||
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")
|
||||
|
||||
@ -1450,7 +1450,7 @@ public final class Postbox {
|
||||
|
||||
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())
|
||||
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
@ -1465,67 +1465,67 @@ public final class Postbox {
|
||||
self.mediaBox = MediaBox(basePath: self.basePath + "/media")
|
||||
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.reverseAssociatedPeerTable = ReverseAssociatedPeerTable(valueBox: self.valueBox, table:ReverseAssociatedPeerTable.tableSpec(40))
|
||||
self.peerTable = PeerTable(valueBox: self.valueBox, table: PeerTable.tableSpec(2), reverseAssociatedTable: self.reverseAssociatedPeerTable)
|
||||
self.globalMessageIdsTable = GlobalMessageIdsTable(valueBox: self.valueBox, table: GlobalMessageIdsTable.tableSpec(3), seedConfiguration: seedConfiguration)
|
||||
self.globallyUniqueMessageIdsTable = MessageGloballyUniqueIdTable(valueBox: self.valueBox, table: MessageGloballyUniqueIdTable.tableSpec(32))
|
||||
self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10))
|
||||
self.messageHistoryHoleIndexTable = MessageHistoryHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryHoleIndexTable.tableSpec(56), metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||
self.messageHistoryUnsentTable = MessageHistoryUnsentTable(valueBox: self.valueBox, table: MessageHistoryUnsentTable.tableSpec(11))
|
||||
self.messageHistoryFailedTable = MessageHistoryFailedTable(valueBox: self.valueBox, table: MessageHistoryFailedTable.tableSpec(49))
|
||||
self.invalidatedMessageHistoryTagsSummaryTable = InvalidatedMessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: InvalidatedMessageHistoryTagsSummaryTable.tableSpec(47))
|
||||
self.messageHistoryTagsSummaryTable = MessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: MessageHistoryTagsSummaryTable.tableSpec(44), invalidateTable: self.invalidatedMessageHistoryTagsSummaryTable)
|
||||
self.pendingMessageActionsMetadataTable = PendingMessageActionsMetadataTable(valueBox: self.valueBox, table: PendingMessageActionsMetadataTable.tableSpec(45))
|
||||
self.pendingMessageActionsTable = PendingMessageActionsTable(valueBox: self.valueBox, table: PendingMessageActionsTable.tableSpec(46), metadataTable: self.pendingMessageActionsMetadataTable)
|
||||
self.messageHistoryTagsTable = MessageHistoryTagsTable(valueBox: self.valueBox, table: MessageHistoryTagsTable.tableSpec(12), seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
||||
self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62))
|
||||
self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||
self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39))
|
||||
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52))
|
||||
self.messageHistoryIndexTable = MessageHistoryIndexTable(valueBox: self.valueBox, table: MessageHistoryIndexTable.tableSpec(4), messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, globalMessageIdsTable: self.globalMessageIdsTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||
self.mediaTable = MessageMediaTable(valueBox: self.valueBox, table: MessageMediaTable.tableSpec(6))
|
||||
self.readStateTable = MessageHistoryReadStateTable(valueBox: self.valueBox, table: MessageHistoryReadStateTable.tableSpec(14), seedConfiguration: seedConfiguration)
|
||||
self.synchronizeReadStateTable = MessageHistorySynchronizeReadStateTable(valueBox: self.valueBox, table: MessageHistorySynchronizeReadStateTable.tableSpec(15))
|
||||
self.synchronizeGroupMessageStatsTable = InvalidatedGroupMessageStatsTable(valueBox: self.valueBox, table: InvalidatedGroupMessageStatsTable.tableSpec(59))
|
||||
self.timestampBasedMessageAttributesIndexTable = TimestampBasedMessageAttributesIndexTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(33))
|
||||
self.timestampBasedMessageAttributesTable = TimestampBasedMessageAttributesTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(34), indexTable: self.timestampBasedMessageAttributesIndexTable)
|
||||
self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1), useCaches: useCaches)
|
||||
self.reverseAssociatedPeerTable = ReverseAssociatedPeerTable(valueBox: self.valueBox, table:ReverseAssociatedPeerTable.tableSpec(40), useCaches: useCaches)
|
||||
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), useCaches: useCaches, seedConfiguration: seedConfiguration)
|
||||
self.globallyUniqueMessageIdsTable = MessageGloballyUniqueIdTable(valueBox: self.valueBox, table: MessageGloballyUniqueIdTable.tableSpec(32), useCaches: useCaches)
|
||||
self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.messageHistoryFailedTable = MessageHistoryFailedTable(valueBox: self.valueBox, table: MessageHistoryFailedTable.tableSpec(49), useCaches: useCaches)
|
||||
self.invalidatedMessageHistoryTagsSummaryTable = InvalidatedMessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: InvalidatedMessageHistoryTagsSummaryTable.tableSpec(47), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
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), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
||||
self.messageHistoryThreadsTable = MessageHistoryThreadsTable(valueBox: self.valueBox, table: MessageHistoryThreadsTable.tableSpec(62), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.readStateTable = MessageHistoryReadStateTable(valueBox: self.valueBox, table: MessageHistoryReadStateTable.tableSpec(14), useCaches: useCaches, seedConfiguration: seedConfiguration)
|
||||
self.synchronizeReadStateTable = MessageHistorySynchronizeReadStateTable(valueBox: self.valueBox, table: MessageHistorySynchronizeReadStateTable.tableSpec(15), useCaches: useCaches)
|
||||
self.synchronizeGroupMessageStatsTable = InvalidatedGroupMessageStatsTable(valueBox: self.valueBox, table: InvalidatedGroupMessageStatsTable.tableSpec(59), useCaches: useCaches)
|
||||
self.timestampBasedMessageAttributesIndexTable = TimestampBasedMessageAttributesIndexTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(33), useCaches: useCaches)
|
||||
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.additionalChatListItemsTable = AdditionalChatListItemsTable(valueBox: self.valueBox, table: AdditionalChatListItemsTable.tableSpec(55))
|
||||
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.peerChatStateTable = PeerChatStateTable(valueBox: self.valueBox, table: PeerChatStateTable.tableSpec(13))
|
||||
self.peerNameTokenIndexTable = ReverseIndexReferenceTable<PeerIdReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<PeerIdReverseIndexReference>.tableSpec(26))
|
||||
self.peerNameIndexTable = PeerNameIndexTable(valueBox: self.valueBox, table: PeerNameIndexTable.tableSpec(27), peerTable: self.peerTable, peerNameTokenIndexTable: self.peerNameTokenIndexTable)
|
||||
self.contactsTable = ContactTable(valueBox: self.valueBox, table: ContactTable.tableSpec(16), peerNameIndexTable: self.peerNameIndexTable)
|
||||
self.peerRatingTable = RatingTable<PeerId>(valueBox: self.valueBox, table: RatingTable<PeerId>.tableSpec(17))
|
||||
self.cachedPeerDataTable = CachedPeerDataTable(valueBox: self.valueBox, table: CachedPeerDataTable.tableSpec(18))
|
||||
self.pendingPeerNotificationSettingsIndexTable = PendingPeerNotificationSettingsIndexTable(valueBox: self.valueBox, table: PendingPeerNotificationSettingsIndexTable.tableSpec(48))
|
||||
self.peerNotificationSettingsBehaviorIndexTable = PeerNotificationSettingsBehaviorIndexTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorIndexTable.tableSpec(60))
|
||||
self.peerNotificationSettingsBehaviorTable = PeerNotificationSettingsBehaviorTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorTable.tableSpec(61), indexTable: self.peerNotificationSettingsBehaviorIndexTable)
|
||||
self.peerNotificationSettingsTable = PeerNotificationSettingsTable(valueBox: self.valueBox, table: PeerNotificationSettingsTable.tableSpec(19), pendingIndexTable: self.pendingPeerNotificationSettingsIndexTable, behaviorTable: self.peerNotificationSettingsBehaviorTable)
|
||||
self.peerPresenceTable = PeerPresenceTable(valueBox: self.valueBox, table: PeerPresenceTable.tableSpec(20))
|
||||
self.itemCollectionInfoTable = ItemCollectionInfoTable(valueBox: self.valueBox, table: ItemCollectionInfoTable.tableSpec(21))
|
||||
self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36))
|
||||
self.itemCollectionItemTable = ItemCollectionItemTable(valueBox: self.valueBox, table: ItemCollectionItemTable.tableSpec(22), reverseIndexTable: self.itemCollectionReverseIndexTable)
|
||||
self.peerChatInterfaceStateTable = PeerChatInterfaceStateTable(valueBox: self.valueBox, table: PeerChatInterfaceStateTable.tableSpec(67))
|
||||
self.peerChatThreadInterfaceStateTable = PeerChatThreadInterfaceStateTable(valueBox: self.valueBox, table: PeerChatThreadInterfaceStateTable.tableSpec(68))
|
||||
self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24))
|
||||
self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25))
|
||||
self.chatListIndexTable = ChatListIndexTable(valueBox: self.valueBox, table: ChatListIndexTable.tableSpec(8), 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.peerChatTopTaggedMessageIdsTable = PeerChatTopTaggedMessageIdsTable(valueBox: self.valueBox, table: PeerChatTopTaggedMessageIdsTable.tableSpec(28))
|
||||
self.peerOperationLogMetadataTable = PeerOperationLogMetadataTable(valueBox: self.valueBox, table: PeerOperationLogMetadataTable.tableSpec(29))
|
||||
self.peerMergedOperationLogIndexTable = PeerMergedOperationLogIndexTable(valueBox: self.valueBox, table: PeerMergedOperationLogIndexTable.tableSpec(30), metadataTable: self.peerOperationLogMetadataTable)
|
||||
self.peerOperationLogTable = PeerOperationLogTable(valueBox: self.valueBox, table: PeerOperationLogTable.tableSpec(31), metadataTable: self.peerOperationLogMetadataTable, mergedIndexTable: self.peerMergedOperationLogIndexTable)
|
||||
self.preferencesTable = PreferencesTable(valueBox: self.valueBox, table: PreferencesTable.tableSpec(35))
|
||||
self.orderedItemListIndexTable = OrderedItemListIndexTable(valueBox: self.valueBox, table: OrderedItemListIndexTable.tableSpec(37))
|
||||
self.orderedItemListTable = OrderedItemListTable(valueBox: self.valueBox, table: OrderedItemListTable.tableSpec(38), indexTable: self.orderedItemListIndexTable)
|
||||
self.unorderedItemListTable = UnorderedItemListTable(valueBox: self.valueBox, table: UnorderedItemListTable.tableSpec(42))
|
||||
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(43))
|
||||
self.deviceContactImportInfoTable = DeviceContactImportInfoTable(valueBox: self.valueBox, table: DeviceContactImportInfoTable.tableSpec(54))
|
||||
self.groupMessageStatsTable = GroupMessageStatsTable(valueBox: self.valueBox, table: GroupMessageStatsTable.tableSpec(58))
|
||||
self.additionalChatListItemsTable = AdditionalChatListItemsTable(valueBox: self.valueBox, table: AdditionalChatListItemsTable.tableSpec(55), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.peerNameTokenIndexTable = ReverseIndexReferenceTable<PeerIdReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<PeerIdReverseIndexReference>.tableSpec(26), useCaches: useCaches)
|
||||
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), useCaches: useCaches, peerNameIndexTable: self.peerNameIndexTable)
|
||||
self.peerRatingTable = RatingTable<PeerId>(valueBox: self.valueBox, table: RatingTable<PeerId>.tableSpec(17), useCaches: useCaches)
|
||||
self.cachedPeerDataTable = CachedPeerDataTable(valueBox: self.valueBox, table: CachedPeerDataTable.tableSpec(18), useCaches: useCaches)
|
||||
self.pendingPeerNotificationSettingsIndexTable = PendingPeerNotificationSettingsIndexTable(valueBox: self.valueBox, table: PendingPeerNotificationSettingsIndexTable.tableSpec(48), useCaches: useCaches)
|
||||
self.peerNotificationSettingsBehaviorIndexTable = PeerNotificationSettingsBehaviorIndexTable(valueBox: self.valueBox, table: PeerNotificationSettingsBehaviorIndexTable.tableSpec(60), useCaches: useCaches)
|
||||
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), useCaches: useCaches, pendingIndexTable: self.pendingPeerNotificationSettingsIndexTable, behaviorTable: self.peerNotificationSettingsBehaviorTable)
|
||||
self.peerPresenceTable = PeerPresenceTable(valueBox: self.valueBox, table: PeerPresenceTable.tableSpec(20), useCaches: useCaches)
|
||||
self.itemCollectionInfoTable = ItemCollectionInfoTable(valueBox: self.valueBox, table: ItemCollectionInfoTable.tableSpec(21), useCaches: useCaches)
|
||||
self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.peerChatThreadInterfaceStateTable = PeerChatThreadInterfaceStateTable(valueBox: self.valueBox, table: PeerChatThreadInterfaceStateTable.tableSpec(68), useCaches: useCaches)
|
||||
self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24), useCaches: useCaches)
|
||||
self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25), useCaches: useCaches)
|
||||
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), useCaches: useCaches, indexTable: self.chatListIndexTable, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||
self.peerChatTopTaggedMessageIdsTable = PeerChatTopTaggedMessageIdsTable(valueBox: self.valueBox, table: PeerChatTopTaggedMessageIdsTable.tableSpec(28), useCaches: useCaches)
|
||||
self.peerOperationLogMetadataTable = PeerOperationLogMetadataTable(valueBox: self.valueBox, table: PeerOperationLogMetadataTable.tableSpec(29), useCaches: useCaches)
|
||||
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), useCaches: useCaches, metadataTable: self.peerOperationLogMetadataTable, mergedIndexTable: self.peerMergedOperationLogIndexTable)
|
||||
self.preferencesTable = PreferencesTable(valueBox: self.valueBox, table: PreferencesTable.tableSpec(35), useCaches: useCaches)
|
||||
self.orderedItemListIndexTable = OrderedItemListIndexTable(valueBox: self.valueBox, table: OrderedItemListIndexTable.tableSpec(37), useCaches: useCaches)
|
||||
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), useCaches: useCaches)
|
||||
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(43), useCaches: useCaches)
|
||||
self.deviceContactImportInfoTable = DeviceContactImportInfoTable(valueBox: self.valueBox, table: DeviceContactImportInfoTable.tableSpec(54), useCaches: useCaches)
|
||||
self.groupMessageStatsTable = GroupMessageStatsTable(valueBox: self.valueBox, table: GroupMessageStatsTable.tableSpec(58), useCaches: useCaches)
|
||||
|
||||
var tables: [Table] = []
|
||||
tables.append(self.metadataTable)
|
||||
|
@ -5,7 +5,7 @@ import SwiftSignalKit
|
||||
func postboxUpgrade_21to22(queue: Queue, basePath: String, valueBox: ValueBox, encryptionParameters: ValueBoxEncryptionParameters, progress: (Float) -> Void) -> String? {
|
||||
postboxLog("Upgrade 21->22 started")
|
||||
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)
|
||||
valueBox.commit()
|
||||
return nil
|
||||
|
@ -163,6 +163,7 @@ public final class SqliteValueBox: ValueBox {
|
||||
fileprivate let basePath: String
|
||||
private let isTemporary: Bool
|
||||
private let isReadOnly: Bool
|
||||
private let useCaches: Bool
|
||||
private let inMemory: Bool
|
||||
private let encryptionParameters: ValueBoxEncryptionParameters?
|
||||
private let databasePath: String
|
||||
@ -201,10 +202,11 @@ public final class SqliteValueBox: ValueBox {
|
||||
|
||||
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.isTemporary = isTemporary
|
||||
self.isReadOnly = isReadOnly
|
||||
self.useCaches = useCaches
|
||||
self.inMemory = inMemory
|
||||
self.encryptionParameters = encryptionParameters
|
||||
self.databasePath = basePath + "/db_sqlite"
|
||||
@ -420,8 +422,11 @@ public final class SqliteValueBox: ValueBox {
|
||||
}
|
||||
|
||||
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")
|
||||
assert(resultCode)
|
||||
resultCode = database.execute("PRAGMA synchronous=NORMAL")
|
||||
|
@ -3,10 +3,12 @@ import Foundation
|
||||
open class Table {
|
||||
public final let valueBox: ValueBox
|
||||
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.table = table
|
||||
self.useCaches = useCaches
|
||||
}
|
||||
|
||||
open func clearMemoryCache() {
|
||||
|
@ -26,10 +26,10 @@ final class TimestampBasedMessageAttributesTable: Table {
|
||||
|
||||
private let indexTable: TimestampBasedMessageAttributesIndexTable
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, indexTable: TimestampBasedMessageAttributesIndexTable) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, indexTable: TimestampBasedMessageAttributesIndexTable) {
|
||||
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 {
|
||||
|
@ -33,6 +33,13 @@ final public class AdaptedPostboxDecoder {
|
||||
}
|
||||
|
||||
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)
|
||||
return try T(from: decoder)
|
||||
}
|
||||
|
@ -21,30 +21,30 @@ private func makeExclusiveKeychain(id: AccountRecordId, postbox: Postbox) -> Key
|
||||
}
|
||||
return dict
|
||||
}
|
||||
return Keychain(get: { key in
|
||||
return Keychain(get: { [weak postbox] key in
|
||||
let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in
|
||||
return dict[id] == keychainId
|
||||
}
|
||||
if enabled {
|
||||
if enabled, let postbox = postbox {
|
||||
return postbox.keychainEntryForKey(key)
|
||||
} else {
|
||||
Logger.shared.log("Keychain", "couldn't get \(key) — not current")
|
||||
return nil
|
||||
}
|
||||
}, set: { (key, data) in
|
||||
}, set: { [weak postbox] key, data in
|
||||
let enabled = accountRecordToActiveKeychainId.with { dict -> Bool in
|
||||
return dict[id] == keychainId
|
||||
}
|
||||
if enabled {
|
||||
if enabled, let postbox = postbox {
|
||||
postbox.setKeychainEntryForKey(key, value: data)
|
||||
} else {
|
||||
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
|
||||
return dict[id] == keychainId
|
||||
}
|
||||
if enabled {
|
||||
if enabled, let postbox = postbox {
|
||||
postbox.removeKeychainEntryForKey(key)
|
||||
} else {
|
||||
Logger.shared.log("Keychain", "couldn't remove \(key) — not current")
|
||||
@ -162,85 +162,19 @@ public enum AccountResult {
|
||||
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> {
|
||||
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
|
||||
|> mapToSignal { result -> Signal<AccountResult, NoError> in
|
||||
@ -251,7 +185,11 @@ public func accountWithId(accountManager: AccountManager<TelegramAccountManagerT
|
||||
return .single(.upgrading(0.0))
|
||||
case let .postbox(postbox):
|
||||
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
|
||||
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> {
|
||||
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 }) {
|
||||
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 {
|
||||
let authKeyHash = sha1Digest(value)
|
||||
let authKeyId = authKeyHash.subdata(in: authKeyHash.count - 8 ..< authKeyHash.count)
|
||||
let keyData = MasterNotificationKey(id: authKeyId, data: value)
|
||||
let _ = masterNotificationKeyValue.swap(keyData)
|
||||
return keyData
|
||||
} else {
|
||||
} else if createIfNotExists {
|
||||
var secretData = Data(count: 256)
|
||||
let secretDataCount = secretData.count
|
||||
if !secretData.withUnsafeMutableBytes({ rawBytes -> Bool in
|
||||
@ -772,6 +718,8 @@ private func masterNotificationsKey(masterNotificationKeyValue: Atomic<MasterNot
|
||||
let keyData = MasterNotificationKey(id: authKeyId, data: secretData)
|
||||
let _ = masterNotificationKeyValue.swap(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> {
|
||||
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
|
||||
guard let secret = secret else {
|
||||
return nil
|
||||
}
|
||||
return decryptedNotificationPayload(key: secret, data: data)
|
||||
}
|
||||
}
|
||||
@ -969,12 +920,8 @@ public class Account {
|
||||
|
||||
let networkStateQueue = Queue()
|
||||
|
||||
let networkStateSignal = combineLatest(queue: networkStateQueue, self.stateManager.isUpdating, network.connectionStatus/*, delayNetworkStatus*/)
|
||||
|> map { isUpdating, connectionStatus/*, delayNetworkStatus*/ -> AccountNetworkState in
|
||||
/*if delayNetworkStatus {
|
||||
return .online(proxy: nil)
|
||||
}*/
|
||||
|
||||
let networkStateSignal = combineLatest(queue: networkStateQueue, self.stateManager.isUpdating, network.connectionStatus)
|
||||
|> map { isUpdating, connectionStatus -> AccountNetworkState in
|
||||
switch connectionStatus {
|
||||
case .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(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(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>] = [
|
||||
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(managedNotificationSettingsBehaviors(postbox: self.postbox).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())
|
||||
}
|
||||
|
||||
@ -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()
|
||||
if let data = try? encoder.encode(key) {
|
||||
let _ = try? data.write(to: URL(fileURLWithPath: "\(basePath)/notificationsKey"))
|
||||
@ -1301,3 +1251,95 @@ public func setupAccount(_ account: Account, fetchCachedResourceRepresentation:
|
||||
account.pendingMessageManager.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
return manager.currentAccountRecord(allocateIfNotExists: allocateIfNotExists)
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
|
@ -423,16 +423,6 @@ public struct NetworkInitializationArguments {
|
||||
private let cloudDataContext = Atomic<CloudDataContext?>(value: nil)
|
||||
#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> {
|
||||
return Signal { subscriber in
|
||||
let queue = Queue()
|
||||
@ -475,19 +465,7 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
|
||||
|
||||
let useTempAuthKeys: Bool = true
|
||||
|
||||
var contextValue: MTContext?
|
||||
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 context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys)
|
||||
|
||||
let seedAddressList: [Int: [String]]
|
||||
|
||||
@ -539,10 +517,6 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
|
||||
#endif
|
||||
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)!
|
||||
mtProto.useTempAuthKeys = context.useTempAuthKeys
|
||||
mtProto.checkForProxyConnectionIssues = true
|
||||
|
@ -52,15 +52,15 @@ public enum DeletedMessageId: Hashable {
|
||||
|
||||
public final class AccountStateManager {
|
||||
private let queue = Queue()
|
||||
private let accountPeerId: PeerId
|
||||
public let accountPeerId: PeerId
|
||||
private let accountManager: AccountManager<TelegramAccountManagerTypes>
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let callSessionManager: CallSessionManager
|
||||
public let postbox: Postbox
|
||||
public let network: Network
|
||||
private let callSessionManager: CallSessionManager?
|
||||
private let addIsContactUpdates: ([(PeerId, Bool)]) -> Void
|
||||
private let shouldKeepOnlinePresence: Signal<Bool, NoError>
|
||||
|
||||
private let peerInputActivityManager: PeerInputActivityManager
|
||||
private let peerInputActivityManager: PeerInputActivityManager?
|
||||
let auxiliaryMethods: AccountAuxiliaryMethods
|
||||
var transformOutgoingMessageMedia: TransformOutgoingMessageMedia?
|
||||
|
||||
@ -166,7 +166,7 @@ public final class AccountStateManager {
|
||||
private let appliedQtsPromise = Promise<Int32?>(nil)
|
||||
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.accountManager = accountManager
|
||||
self.postbox = postbox
|
||||
@ -183,9 +183,14 @@ public final class AccountStateManager {
|
||||
self.operationDisposable.dispose()
|
||||
self.appliedMaxMessageIdDisposable.dispose()
|
||||
self.appliedQtsDisposable.dispose()
|
||||
|
||||
var postbox: Postbox? = self.postbox
|
||||
postbox?.queue.async {
|
||||
postbox = nil
|
||||
}
|
||||
}
|
||||
|
||||
func reset() {
|
||||
public func reset() {
|
||||
self.queue.async {
|
||||
if self.updateService == nil {
|
||||
self.updateService = UpdateMessageService(peerId: self.accountPeerId)
|
||||
@ -641,7 +646,7 @@ public final class AccountStateManager {
|
||||
let topOperation = strongSelf.operations.removeFirst()
|
||||
if case .processEvents(operationId, _) = topOperation.content {
|
||||
if !events.updatedTypingActivities.isEmpty {
|
||||
strongSelf.peerInputActivityManager.transaction { manager in
|
||||
strongSelf.peerInputActivityManager?.transaction { manager in
|
||||
for (chatPeerId, peerActivities) in events.updatedTypingActivities {
|
||||
for (peerId, activity) in peerActivities {
|
||||
if let activity = activity {
|
||||
@ -661,12 +666,12 @@ public final class AccountStateManager {
|
||||
}
|
||||
if !events.updatedCalls.isEmpty {
|
||||
for call in events.updatedCalls {
|
||||
strongSelf.callSessionManager.updateSession(call, completion: { _ in })
|
||||
strongSelf.callSessionManager?.updateSession(call, completion: { _ in })
|
||||
}
|
||||
}
|
||||
if !events.addedCallSignalingData.isEmpty {
|
||||
for (id, data) in events.addedCallSignalingData {
|
||||
strongSelf.callSessionManager.addCallSignalingData(id: id, data: data)
|
||||
strongSelf.callSessionManager?.addCallSignalingData(id: id, data: data)
|
||||
}
|
||||
}
|
||||
if !events.updatedGroupCallParticipants.isEmpty {
|
||||
@ -1046,9 +1051,13 @@ public final class AccountStateManager {
|
||||
for update in updates {
|
||||
switch update {
|
||||
case let .updatePhoneCall(phoneCall):
|
||||
self.callSessionManager.updateSession(phoneCall, completion: { result in
|
||||
completion(result)
|
||||
})
|
||||
if let callSessionManager = self.callSessionManager {
|
||||
callSessionManager.updateSession(phoneCall, completion: { result in
|
||||
completion(result)
|
||||
})
|
||||
} else {
|
||||
completion(nil)
|
||||
}
|
||||
return
|
||||
default:
|
||||
break
|
||||
|
@ -97,9 +97,9 @@ public enum AccountTransactionError {
|
||||
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 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
|
||||
|> castError(AccountTransactionError.self)
|
||||
|> mapToSignal { value -> Signal<T, AccountTransactionError> in
|
||||
|
@ -677,7 +677,7 @@ final class SharedApplicationContext {
|
||||
})
|
||||
|
||||
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)
|
||||
|> deliverOnMainQueue).start(next: { progress in
|
||||
if self.dataImportSplash == nil {
|
||||
@ -1489,6 +1489,10 @@ final class SharedApplicationContext {
|
||||
}
|
||||
|
||||
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
|
||||
if "".isEmpty {
|
||||
return;
|
||||
}
|
||||
|
||||
if #available(iOS 9.0, *) {
|
||||
/*guard var encryptedPayload = payload.dictionaryPayload["p"] as? String else {
|
||||
return
|
||||
|
@ -94,7 +94,7 @@ public final class NotificationViewControllerImpl {
|
||||
|
||||
if sharedAccountContext == nil {
|
||||
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?
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
|
@ -624,10 +624,10 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
||||
game = value
|
||||
} else if queryItem.name == "post" {
|
||||
post = value
|
||||
} else if queryItem.name == "voicechat" {
|
||||
} else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
|
||||
voiceChat = value
|
||||
}
|
||||
} else if queryItem.name == "voicechat" {
|
||||
} else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
|
||||
voiceChat = ""
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ public class ShareRootControllerImpl {
|
||||
|
||||
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 {
|
||||
internalContext = globalInternalContext
|
||||
|
@ -111,204 +111,11 @@ public func upgradedAccounts(accountManager: AccountManager<TelegramAccountManag
|
||||
return (transaction.getVersion(), transaction.getCurrent()?.0)
|
||||
}
|
||||
|> mapToSignal { version, currentId -> Signal<Float, NoError> in
|
||||
guard let version = version else {
|
||||
return accountManager.transaction { transaction -> Void in
|
||||
transaction.setVersion(4)
|
||||
}
|
||||
|> ignoreValues
|
||||
|> mapToSignal { _ -> Signal<Float, NoError> in
|
||||
}
|
||||
return accountManager.transaction { transaction -> Void in
|
||||
transaction.setVersion(4)
|
||||
}
|
||||
var signal: Signal<Float, NoError> = .complete()
|
||||
if version < 1 {
|
||||
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)
|
||||
|> ignoreValues
|
||||
|> mapToSignal { _ -> Signal<Float, NoError> in
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -136,10 +136,10 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
|
||||
return .peerName(peerName, .groupBotStart(value))
|
||||
} else if queryItem.name == "game" {
|
||||
return nil
|
||||
} else if queryItem.name == "voicechat" {
|
||||
} else if queryItem.name == "voicechat" || queryItem.name == "videochat" || queryItem.name == "livestream" {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user