mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
no message
This commit is contained in:
@@ -3527,6 +3527,128 @@
|
|||||||
};
|
};
|
||||||
name = "Release AppStore";
|
name = "Release AppStore";
|
||||||
};
|
};
|
||||||
|
D0CE6EF5213DC30700BCD44B /* Release AppStore LLC */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D03B0E591D63215200955575 /* TelegramCore.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/third-party/FFmpeg-iOS/include";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = "Release AppStore LLC";
|
||||||
|
};
|
||||||
|
D0CE6EF6213DC30700BCD44B /* Release AppStore LLC */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D03B0E591D63215200955575 /* TelegramCore.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||||
|
COPY_PHASE_STRIP = YES;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = X834Q8SBVP;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = TelegramCore/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
LIBRARY_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"$(PROJECT_DIR)/third-party/FFmpeg-iOS/lib",
|
||||||
|
"$(PROJECT_DIR)/third-party/libwebp/lib",
|
||||||
|
);
|
||||||
|
MODULEMAP_PRIVATE_FILE = "$(SRCROOT)/TelegramCore/module.private.modulemap";
|
||||||
|
OTHER_LDFLAGS = "-Wl,-dead_strip";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.TelegramCore;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_REFLECTION_METADATA_LEVEL = none;
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/third-party/FFmpeg-iOS/include";
|
||||||
|
};
|
||||||
|
name = "Release AppStore LLC";
|
||||||
|
};
|
||||||
|
D0CE6EF7213DC30700BCD44B /* Release AppStore LLC */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D03B0E591D63215200955575 /* TelegramCore.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
INFOPLIST_FILE = TelegramCoreTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.Telegram.TelegramCoreTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = "Release AppStore LLC";
|
||||||
|
};
|
||||||
|
D0CE6EF8213DC30700BCD44B /* Release AppStore LLC */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D03B0E591D63215200955575 /* TelegramCore.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
FRAMEWORK_VERSION = A;
|
||||||
|
INFOPLIST_FILE = TelegramCoreMac/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
|
MODULEMAP_PRIVATE_FILE = "$(SRCROOT)/TelegramCore/module.private-mac.modulemap";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.Telegram.TelegramCoreMac;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
};
|
||||||
|
name = "Release AppStore LLC";
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
@@ -3539,6 +3661,7 @@
|
|||||||
C22069BE1E8EB4A200E82730 /* Release Hockeyapp */,
|
C22069BE1E8EB4A200E82730 /* Release Hockeyapp */,
|
||||||
D0924FE81FE52C12003F693F /* Release Hockeyapp Internal */,
|
D0924FE81FE52C12003F693F /* Release Hockeyapp Internal */,
|
||||||
D06706551D51162400DED3E3 /* Release AppStore */,
|
D06706551D51162400DED3E3 /* Release AppStore */,
|
||||||
|
D0CE6EF5213DC30700BCD44B /* Release AppStore LLC */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = "Debug AppStore";
|
defaultConfigurationName = "Debug AppStore";
|
||||||
@@ -3552,6 +3675,7 @@
|
|||||||
C22069BF1E8EB4A200E82730 /* Release Hockeyapp */,
|
C22069BF1E8EB4A200E82730 /* Release Hockeyapp */,
|
||||||
D0924FE91FE52C12003F693F /* Release Hockeyapp Internal */,
|
D0924FE91FE52C12003F693F /* Release Hockeyapp Internal */,
|
||||||
D06706561D51162400DED3E3 /* Release AppStore */,
|
D06706561D51162400DED3E3 /* Release AppStore */,
|
||||||
|
D0CE6EF6213DC30700BCD44B /* Release AppStore LLC */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = "Debug AppStore";
|
defaultConfigurationName = "Debug AppStore";
|
||||||
@@ -3565,6 +3689,7 @@
|
|||||||
C22069C01E8EB4A200E82730 /* Release Hockeyapp */,
|
C22069C01E8EB4A200E82730 /* Release Hockeyapp */,
|
||||||
D0924FEA1FE52C12003F693F /* Release Hockeyapp Internal */,
|
D0924FEA1FE52C12003F693F /* Release Hockeyapp Internal */,
|
||||||
D06706571D51162400DED3E3 /* Release AppStore */,
|
D06706571D51162400DED3E3 /* Release AppStore */,
|
||||||
|
D0CE6EF7213DC30700BCD44B /* Release AppStore LLC */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = "Debug AppStore";
|
defaultConfigurationName = "Debug AppStore";
|
||||||
@@ -3578,6 +3703,7 @@
|
|||||||
C22069C11E8EB4A200E82730 /* Release Hockeyapp */,
|
C22069C11E8EB4A200E82730 /* Release Hockeyapp */,
|
||||||
D0924FEB1FE52C12003F693F /* Release Hockeyapp Internal */,
|
D0924FEB1FE52C12003F693F /* Release Hockeyapp Internal */,
|
||||||
D0B4186F1D7E03D5004562A4 /* Release AppStore */,
|
D0B4186F1D7E03D5004562A4 /* Release AppStore */,
|
||||||
|
D0CE6EF8213DC30700BCD44B /* Release AppStore LLC */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = "Debug AppStore";
|
defaultConfigurationName = "Debug AppStore";
|
||||||
|
|||||||
@@ -850,7 +850,7 @@ public class Account {
|
|||||||
private let serviceQueue = Queue()
|
private let serviceQueue = Queue()
|
||||||
|
|
||||||
public private(set) var stateManager: AccountStateManager!
|
public private(set) var stateManager: AccountStateManager!
|
||||||
private var contactSyncManager: ContactSyncManager!
|
private(set) var contactSyncManager: ContactSyncManager!
|
||||||
public private(set) var callSessionManager: CallSessionManager!
|
public private(set) var callSessionManager: CallSessionManager!
|
||||||
public private(set) var viewTracker: AccountViewTracker!
|
public private(set) var viewTracker: AccountViewTracker!
|
||||||
public private(set) var pendingMessageManager: PendingMessageManager!
|
public private(set) var pendingMessageManager: PendingMessageManager!
|
||||||
@@ -1183,6 +1183,7 @@ public class Account {
|
|||||||
public func resetStateManagement() {
|
public func resetStateManagement() {
|
||||||
self.stateManager.reset()
|
self.stateManager.reset()
|
||||||
self.contactSyncManager.beginSync(importableContacts: self.importableContacts.get())
|
self.contactSyncManager.beginSync(importableContacts: self.importableContacts.get())
|
||||||
|
self.managedStickerPacksDisposable.set(manageStickerPacks(network: self.network, postbox: self.postbox).start())
|
||||||
}
|
}
|
||||||
|
|
||||||
public func peerInputActivities(peerId: PeerId) -> Signal<[(PeerId, PeerInputActivity)], NoError> {
|
public func peerInputActivities(peerId: PeerId) -> Signal<[(PeerId, PeerInputActivity)], NoError> {
|
||||||
@@ -1246,5 +1247,4 @@ public func setupAccount(_ account: Account, fetchCachedResourceRepresentation:
|
|||||||
|
|
||||||
account.transformOutgoingMessageMedia = transformOutgoingMessageMedia
|
account.transformOutgoingMessageMedia = transformOutgoingMessageMedia
|
||||||
account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia
|
account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia
|
||||||
account.managedStickerPacksDisposable.set(manageStickerPacks(network: account.network, postbox: account.postbox).start())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ enum AccountStateMutationOperation {
|
|||||||
case UpdateGlobalNotificationSettings(AccountStateGlobalNotificationSettingsSubject, MessageNotificationSettings)
|
case UpdateGlobalNotificationSettings(AccountStateGlobalNotificationSettingsSubject, MessageNotificationSettings)
|
||||||
case MergeApiChats([Api.Chat])
|
case MergeApiChats([Api.Chat])
|
||||||
case UpdatePeer(PeerId, (Peer?) -> Peer?)
|
case UpdatePeer(PeerId, (Peer?) -> Peer?)
|
||||||
|
case UpdateIsContact(PeerId, Bool)
|
||||||
case UpdateCachedPeerData(PeerId, (CachedPeerData?) -> CachedPeerData?)
|
case UpdateCachedPeerData(PeerId, (CachedPeerData?) -> CachedPeerData?)
|
||||||
case MergeApiUsers([Api.User])
|
case MergeApiUsers([Api.User])
|
||||||
case MergePeerPresences([PeerId: PeerPresence])
|
case MergePeerPresences([PeerId: PeerPresence])
|
||||||
@@ -246,6 +247,10 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.UpdatePeer(id, f))
|
self.addOperation(.UpdatePeer(id, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func updatePeerIsContact(_ id: PeerId, isContact: Bool) {
|
||||||
|
self.addOperation(.UpdateIsContact(id, isContact))
|
||||||
|
}
|
||||||
|
|
||||||
mutating func updateCachedPeerData(_ id: PeerId, _ f: @escaping (CachedPeerData?) -> CachedPeerData?) {
|
mutating func updateCachedPeerData(_ id: PeerId, _ f: @escaping (CachedPeerData?) -> CachedPeerData?) {
|
||||||
self.addOperation(.UpdateCachedPeerData(id, f))
|
self.addOperation(.UpdateCachedPeerData(id, f))
|
||||||
}
|
}
|
||||||
@@ -328,7 +333,7 @@ struct AccountMutableState {
|
|||||||
|
|
||||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact:
|
||||||
break
|
break
|
||||||
case let .AddMessages(messages, _):
|
case let .AddMessages(messages, _):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
@@ -399,6 +404,7 @@ struct AccountReplayedFinalState {
|
|||||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||||
let updatedCalls: [Api.PhoneCall]
|
let updatedCalls: [Api.PhoneCall]
|
||||||
|
let isContactUpdates: [(PeerId, Bool)]
|
||||||
let delayNotificatonsUntil: Int32?
|
let delayNotificatonsUntil: Int32?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,11 +413,12 @@ struct AccountFinalStateEvents {
|
|||||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||||
let updatedCalls: [Api.PhoneCall]
|
let updatedCalls: [Api.PhoneCall]
|
||||||
|
let isContactUpdates: [(PeerId, Bool)]
|
||||||
let displayAlerts: [String]
|
let displayAlerts: [String]
|
||||||
let delayNotificatonsUntil: Int32?
|
let delayNotificatonsUntil: Int32?
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
return self.addedIncomingMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil
|
return self.addedIncomingMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -419,15 +426,17 @@ struct AccountFinalStateEvents {
|
|||||||
self.updatedTypingActivities = [:]
|
self.updatedTypingActivities = [:]
|
||||||
self.updatedWebpages = [:]
|
self.updatedWebpages = [:]
|
||||||
self.updatedCalls = []
|
self.updatedCalls = []
|
||||||
|
self.isContactUpdates = []
|
||||||
self.displayAlerts = []
|
self.displayAlerts = []
|
||||||
self.delayNotificatonsUntil = nil
|
self.delayNotificatonsUntil = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
init(addedIncomingMessageIds: [MessageId], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]], updatedWebpages: [MediaId: TelegramMediaWebpage], updatedCalls: [Api.PhoneCall], displayAlerts: [String], delayNotificatonsUntil: Int32?) {
|
init(addedIncomingMessageIds: [MessageId], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]], updatedWebpages: [MediaId: TelegramMediaWebpage], updatedCalls: [Api.PhoneCall], isContactUpdates: [(PeerId, Bool)], displayAlerts: [String], delayNotificatonsUntil: Int32?) {
|
||||||
self.addedIncomingMessageIds = addedIncomingMessageIds
|
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
self.updatedTypingActivities = updatedTypingActivities
|
self.updatedTypingActivities = updatedTypingActivities
|
||||||
self.updatedWebpages = updatedWebpages
|
self.updatedWebpages = updatedWebpages
|
||||||
self.updatedCalls = updatedCalls
|
self.updatedCalls = updatedCalls
|
||||||
|
self.isContactUpdates = isContactUpdates
|
||||||
self.displayAlerts = displayAlerts
|
self.displayAlerts = displayAlerts
|
||||||
self.delayNotificatonsUntil = delayNotificatonsUntil
|
self.delayNotificatonsUntil = delayNotificatonsUntil
|
||||||
}
|
}
|
||||||
@@ -437,6 +446,7 @@ struct AccountFinalStateEvents {
|
|||||||
self.updatedTypingActivities = state.updatedTypingActivities
|
self.updatedTypingActivities = state.updatedTypingActivities
|
||||||
self.updatedWebpages = state.updatedWebpages
|
self.updatedWebpages = state.updatedWebpages
|
||||||
self.updatedCalls = state.updatedCalls
|
self.updatedCalls = state.updatedCalls
|
||||||
|
self.isContactUpdates = state.isContactUpdates
|
||||||
self.displayAlerts = state.state.state.displayAlerts
|
self.displayAlerts = state.state.state.displayAlerts
|
||||||
self.delayNotificatonsUntil = state.delayNotificatonsUntil
|
self.delayNotificatonsUntil = state.delayNotificatonsUntil
|
||||||
}
|
}
|
||||||
@@ -448,6 +458,6 @@ struct AccountFinalStateEvents {
|
|||||||
delayNotificatonsUntil = other
|
delayNotificatonsUntil = other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil)
|
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1081,6 +1081,15 @@ private func finalStateWithUpdatesAndServerTime(account: Account, state: Account
|
|||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
case let .updateContactLink(userId, myLink, _):
|
||||||
|
let isContact: Bool
|
||||||
|
switch myLink {
|
||||||
|
case .contactLinkContact:
|
||||||
|
isContact = true
|
||||||
|
default:
|
||||||
|
isContact = false
|
||||||
|
}
|
||||||
|
updatedState.updatePeerIsContact(PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), isContact: isContact)
|
||||||
case let .updateEncryption(chat, date):
|
case let .updateEncryption(chat, date):
|
||||||
updatedState.updateSecretChat(chat: chat, timestamp: date)
|
updatedState.updateSecretChat(chat: chat, timestamp: date)
|
||||||
case let .updateNewEncryptedMessage(message, _):
|
case let .updateNewEncryptedMessage(message, _):
|
||||||
@@ -1813,7 +1822,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||||||
var currentAddMessages: OptimizeAddMessagesState?
|
var currentAddMessages: OptimizeAddMessagesState?
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact:
|
||||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||||
}
|
}
|
||||||
@@ -1864,6 +1873,7 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, transaction: Tr
|
|||||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||||
var updatedCalls: [Api.PhoneCall] = []
|
var updatedCalls: [Api.PhoneCall] = []
|
||||||
|
var isContactUpdates: [(PeerId, Bool)] = []
|
||||||
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
||||||
var recentlyUsedStickers: [MediaId: (MessageIndex, TelegramMediaFile)] = [:]
|
var recentlyUsedStickers: [MediaId: (MessageIndex, TelegramMediaFile)] = [:]
|
||||||
var recentlyUsedGifs: [MediaId: (MessageIndex, TelegramMediaFile)] = [:]
|
var recentlyUsedGifs: [MediaId: (MessageIndex, TelegramMediaFile)] = [:]
|
||||||
@@ -2221,6 +2231,8 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, transaction: Tr
|
|||||||
} else {
|
} else {
|
||||||
pollLangPack = true
|
pollLangPack = true
|
||||||
}
|
}
|
||||||
|
case let .UpdateIsContact(peerId, value):
|
||||||
|
isContactUpdates.append((peerId, value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2445,5 +2457,5 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, transaction: Tr
|
|||||||
|
|
||||||
addedIncomingMessageIds.append(contentsOf: addedSecretMessageIds)
|
addedIncomingMessageIds.append(contentsOf: addedSecretMessageIds)
|
||||||
|
|
||||||
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, addedSecretMessageIds: addedSecretMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, delayNotificatonsUntil: delayNotificatonsUntil)
|
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, addedSecretMessageIds: addedSecretMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Foundation
|
|||||||
import MtProtoKitDynamic
|
import MtProtoKitDynamic
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private enum AccountStateManagerOperation {
|
private enum AccountStateManagerOperationContent {
|
||||||
case pollDifference(AccountFinalStateEvents)
|
case pollDifference(AccountFinalStateEvents)
|
||||||
case collectUpdateGroups([UpdateGroup], Double)
|
case collectUpdateGroups([UpdateGroup], Double)
|
||||||
case processUpdateGroups([UpdateGroup])
|
case processUpdateGroups([UpdateGroup])
|
||||||
@@ -19,6 +19,20 @@ private enum AccountStateManagerOperation {
|
|||||||
case replayAsynchronouslyBuiltFinalState(AccountFinalState, () -> Void)
|
case replayAsynchronouslyBuiltFinalState(AccountFinalState, () -> Void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class AccountStateManagerOperation {
|
||||||
|
var isRunning: Bool = false
|
||||||
|
let content: AccountStateManagerOperationContent
|
||||||
|
|
||||||
|
init(content: AccountStateManagerOperationContent) {
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum AccountStateManagerAddOperationPosition {
|
||||||
|
case first
|
||||||
|
case last
|
||||||
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
||||||
#else
|
#else
|
||||||
@@ -137,22 +151,17 @@ public final class AccountStateManager {
|
|||||||
func addUpdateGroups(_ groups: [UpdateGroup]) {
|
func addUpdateGroups(_ groups: [UpdateGroup]) {
|
||||||
self.queue.async {
|
self.queue.async {
|
||||||
if let last = self.operations.last {
|
if let last = self.operations.last {
|
||||||
switch last {
|
switch last.content {
|
||||||
case .pollDifference, .processUpdateGroups, .custom, .pollCompletion, .processEvents, .replayAsynchronouslyBuiltFinalState:
|
case .pollDifference, .processUpdateGroups, .custom, .pollCompletion, .processEvents, .replayAsynchronouslyBuiltFinalState:
|
||||||
self.operations.append(.collectUpdateGroups(groups, 0.0))
|
self.addOperation(.collectUpdateGroups(groups, 0.0), position: .last)
|
||||||
case let .collectUpdateGroups(currentGroups, timeout):
|
case let .collectUpdateGroups(currentGroups, timeout):
|
||||||
if timeout.isEqual(to: 0.0) {
|
let operation = AccountStateManagerOperation(content: .collectUpdateGroups(currentGroups + groups, timeout))
|
||||||
self.operations[self.operations.count - 1] = .collectUpdateGroups(currentGroups + groups, timeout)
|
operation.isRunning = last.isRunning
|
||||||
} else {
|
self.operations[self.operations.count - 1] = operation
|
||||||
self.operations[self.operations.count - 1] = .processUpdateGroups(currentGroups + groups)
|
self.startFirstOperation()
|
||||||
if self.operations.count == 1 {
|
|
||||||
self.startFirstOperation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.operations.append(.collectUpdateGroups(groups, 0.0))
|
self.addOperation(.collectUpdateGroups(groups, 0.0), position: .last)
|
||||||
self.startFirstOperation()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,14 +169,10 @@ public final class AccountStateManager {
|
|||||||
func addReplayAsynchronouslyBuiltFinalState(_ finalState: AccountFinalState) -> Signal<Bool, NoError> {
|
func addReplayAsynchronouslyBuiltFinalState(_ finalState: AccountFinalState) -> Signal<Bool, NoError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
self.queue.async {
|
self.queue.async {
|
||||||
let begin = self.operations.isEmpty
|
self.addOperation(.replayAsynchronouslyBuiltFinalState(finalState, {
|
||||||
self.operations.append(.replayAsynchronouslyBuiltFinalState(finalState, {
|
|
||||||
subscriber.putNext(true)
|
subscriber.putNext(true)
|
||||||
subscriber.putCompletion()
|
subscriber.putCompletion()
|
||||||
}))
|
}), position: .last)
|
||||||
if begin {
|
|
||||||
self.startFirstOperation()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
}
|
}
|
||||||
@@ -199,60 +204,78 @@ public final class AccountStateManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addOperation(.custom(self.getNextId(), signal))
|
self.addOperation(.custom(self.getNextId(), signal), position: .last)
|
||||||
|
|
||||||
return disposable
|
return disposable
|
||||||
} |> runOn(self.queue)
|
} |> runOn(self.queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func replaceOperations(with operation: AccountStateManagerOperation) {
|
private func replaceOperations(with content: AccountStateManagerOperationContent) {
|
||||||
var collectedProcessUpdateGroups: [(AccountStateManagerOperation, Bool)] = []
|
var collectedProcessUpdateGroups: [AccountStateManagerOperationContent] = []
|
||||||
var collectedMessageIds: [MessageId] = []
|
var collectedMessageIds: [MessageId] = []
|
||||||
var collectedPollCompletionSubscribers: [(Int32, ([MessageId]) -> Void)] = []
|
var collectedPollCompletionSubscribers: [(Int32, ([MessageId]) -> Void)] = []
|
||||||
var collectedReplayAsynchronouslyBuiltFinalState: [(AccountFinalState, () -> Void)] = []
|
var collectedReplayAsynchronouslyBuiltFinalState: [(AccountFinalState, () -> Void)] = []
|
||||||
var processEvents: [(Int32, AccountFinalStateEvents)] = []
|
var processEvents: [(Int32, AccountFinalStateEvents)] = []
|
||||||
|
|
||||||
|
var replacedOperations: [AccountStateManagerOperation] = []
|
||||||
|
|
||||||
for i in 0 ..< self.operations.count {
|
for i in 0 ..< self.operations.count {
|
||||||
switch self.operations[i] {
|
if self.operations[i].isRunning {
|
||||||
case .processUpdateGroups:
|
replacedOperations.append(self.operations[i])
|
||||||
collectedProcessUpdateGroups.append((self.operations[i], i == 0))
|
} else {
|
||||||
case let .pollCompletion(_, messageIds, subscribers):
|
switch self.operations[i].content {
|
||||||
collectedMessageIds.append(contentsOf: messageIds)
|
case .processUpdateGroups:
|
||||||
collectedPollCompletionSubscribers.append(contentsOf: subscribers)
|
collectedProcessUpdateGroups.append(self.operations[i].content)
|
||||||
case let .replayAsynchronouslyBuiltFinalState(finalState, completion):
|
case let .pollCompletion(_, messageIds, subscribers):
|
||||||
collectedReplayAsynchronouslyBuiltFinalState.append((finalState, completion))
|
collectedMessageIds.append(contentsOf: messageIds)
|
||||||
case let .processEvents(operationId, events):
|
collectedPollCompletionSubscribers.append(contentsOf: subscribers)
|
||||||
processEvents.append((operationId, events))
|
case let .replayAsynchronouslyBuiltFinalState(finalState, completion):
|
||||||
default:
|
collectedReplayAsynchronouslyBuiltFinalState.append((finalState, completion))
|
||||||
break
|
case let .processEvents(operationId, events):
|
||||||
|
processEvents.append((operationId, events))
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.operations.removeAll()
|
replacedOperations.append(contentsOf: collectedProcessUpdateGroups.map { AccountStateManagerOperation(content: $0) })
|
||||||
|
|
||||||
self.operations.append(contentsOf: collectedProcessUpdateGroups.map { $0.0 })
|
replacedOperations.append(AccountStateManagerOperation(content: content))
|
||||||
|
|
||||||
self.operations.append(operation)
|
|
||||||
|
|
||||||
if !collectedPollCompletionSubscribers.isEmpty || !collectedMessageIds.isEmpty {
|
if !collectedPollCompletionSubscribers.isEmpty || !collectedMessageIds.isEmpty {
|
||||||
self.operations.append(.pollCompletion(self.getNextId(), collectedMessageIds, collectedPollCompletionSubscribers))
|
replacedOperations.append(AccountStateManagerOperation(content: .pollCompletion(self.getNextId(), collectedMessageIds, collectedPollCompletionSubscribers)))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (finalState, completion) in collectedReplayAsynchronouslyBuiltFinalState {
|
for (finalState, completion) in collectedReplayAsynchronouslyBuiltFinalState {
|
||||||
self.operations.append(.replayAsynchronouslyBuiltFinalState(finalState, completion))
|
replacedOperations.append(AccountStateManagerOperation(content: .replayAsynchronouslyBuiltFinalState(finalState, completion)))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (operationId, events) in processEvents {
|
for (operationId, events) in processEvents {
|
||||||
self.operations.append(.processEvents(operationId, events))
|
replacedOperations.append(AccountStateManagerOperation(content: .processEvents(operationId, events)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.operations.removeAll()
|
||||||
|
self.operations.append(contentsOf: replacedOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addOperation(_ operation: AccountStateManagerOperation) {
|
private func addOperation(_ content: AccountStateManagerOperationContent, position: AccountStateManagerAddOperationPosition) {
|
||||||
self.queue.async {
|
self.queue.async {
|
||||||
let begin = self.operations.isEmpty
|
let operation = AccountStateManagerOperation(content: content)
|
||||||
self.operations.append(operation)
|
switch position {
|
||||||
if begin {
|
case .first:
|
||||||
self.startFirstOperation()
|
if self.operations.isEmpty || !self.operations[0].isRunning {
|
||||||
|
self.operations.insert(operation, at: 0)
|
||||||
|
self.startFirstOperation()
|
||||||
|
} else {
|
||||||
|
self.operations.insert(operation, at: 1)
|
||||||
|
}
|
||||||
|
case .last:
|
||||||
|
let begin = self.operations.isEmpty
|
||||||
|
self.operations.append(operation)
|
||||||
|
if begin {
|
||||||
|
self.startFirstOperation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,7 +284,11 @@ public final class AccountStateManager {
|
|||||||
guard let operation = self.operations.first else {
|
guard let operation = self.operations.first else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch operation {
|
guard !operation.isRunning else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
operation.isRunning = true
|
||||||
|
switch operation.content {
|
||||||
case let .pollDifference(currentEvents):
|
case let .pollDifference(currentEvents):
|
||||||
self.operationTimer?.invalidate()
|
self.operationTimer?.invalidate()
|
||||||
self.currentIsUpdatingValue = true
|
self.currentIsUpdatingValue = true
|
||||||
@@ -270,71 +297,73 @@ public final class AccountStateManager {
|
|||||||
let accountPeerId = account.peerId
|
let accountPeerId = account.peerId
|
||||||
let auxiliaryMethods = self.auxiliaryMethods
|
let auxiliaryMethods = self.auxiliaryMethods
|
||||||
let signal = account.postbox.stateView()
|
let signal = account.postbox.stateView()
|
||||||
|> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
|
|> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
|
||||||
if let state = view.state as? AuthorizedAccountState {
|
if let state = view.state as? AuthorizedAccountState {
|
||||||
return .single(state)
|
return .single(state)
|
||||||
} else {
|
} else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|> take(1)
|
}
|
||||||
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
|> take(1)
|
||||||
if let authorizedState = state.state {
|
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
||||||
let request = account.network.request(Api.functions.updates.getDifference(flags: 1 << 0, pts: authorizedState.pts, ptsTotalLimit: 1000, date: authorizedState.date, qts: authorizedState.qts))
|
if let authorizedState = state.state {
|
||||||
|> retryRequest
|
let request = account.network.request(Api.functions.updates.getDifference(flags: 1 << 0, pts: authorizedState.pts, ptsTotalLimit: 1000, date: authorizedState.date, qts: authorizedState.qts))
|
||||||
return request |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
|> retryRequest
|
||||||
switch difference {
|
|
||||||
case .differenceTooLong:
|
return request
|
||||||
return accountStateReset(postbox: account.postbox, network: account.network) |> mapToSignal { _ -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
|> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
||||||
return .complete()
|
switch difference {
|
||||||
} |> then(.single((nil, nil)))
|
case .differenceTooLong:
|
||||||
default:
|
return accountStateReset(postbox: account.postbox, network: account.network) |> mapToSignal { _ -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
||||||
return initialStateWithDifference(account, difference: difference)
|
return .complete()
|
||||||
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
} |> then(.single((nil, nil)))
|
||||||
if state.initialState.state != authorizedState {
|
default:
|
||||||
Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)")
|
return initialStateWithDifference(account, difference: difference)
|
||||||
return .single((nil, nil))
|
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
||||||
} else {
|
if state.initialState.state != authorizedState {
|
||||||
return finalStateWithDifference(account: account, state: state, difference: difference)
|
Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)")
|
||||||
|> mapToSignal { finalState -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
return .single((nil, nil))
|
||||||
if !finalState.state.preCachedResources.isEmpty {
|
} else {
|
||||||
for (resource, data) in finalState.state.preCachedResources {
|
return finalStateWithDifference(account: account, state: state, difference: difference)
|
||||||
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
|> mapToSignal { finalState -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
|
||||||
}
|
if !finalState.state.preCachedResources.isEmpty {
|
||||||
}
|
for (resource, data) in finalState.state.preCachedResources {
|
||||||
return account.postbox.transaction { transaction -> (Api.updates.Difference?, AccountReplayedFinalState?) in
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
if let replayedState = replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, transaction: transaction, auxiliaryMethods: auxiliaryMethods, finalState: finalState) {
|
}
|
||||||
return (difference, replayedState)
|
}
|
||||||
} else {
|
return account.postbox.transaction { transaction -> (Api.updates.Difference?, AccountReplayedFinalState?) in
|
||||||
return (nil, nil)
|
if let replayedState = replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, transaction: transaction, auxiliaryMethods: auxiliaryMethods, finalState: finalState) {
|
||||||
}
|
return (difference, replayedState)
|
||||||
}
|
} else {
|
||||||
|
return (nil, nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let appliedState = account.network.request(Api.functions.updates.getState())
|
|
||||||
|> retryRequest
|
|
||||||
|> mapToSignal { state in
|
|
||||||
return account.postbox.transaction { transaction -> (Api.updates.Difference?, AccountReplayedFinalState?) in
|
|
||||||
if let currentState = transaction.getState() as? AuthorizedAccountState {
|
|
||||||
switch state {
|
|
||||||
case let .state(pts, qts, date, seq, _):
|
|
||||||
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: qts, date: date, seq: seq)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (nil, nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return appliedState
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let appliedState = account.network.request(Api.functions.updates.getState())
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { state in
|
||||||
|
return account.postbox.transaction { transaction -> (Api.updates.Difference?, AccountReplayedFinalState?) in
|
||||||
|
if let currentState = transaction.getState() as? AuthorizedAccountState {
|
||||||
|
switch state {
|
||||||
|
case let .state(pts, qts, date, seq, _):
|
||||||
|
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: qts, date: date, seq: seq)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appliedState
|
||||||
}
|
}
|
||||||
|> deliverOn(self.queue)
|
}
|
||||||
|
|> deliverOn(self.queue)
|
||||||
let _ = signal.start(next: { [weak self] difference, finalState in
|
let _ = signal.start(next: { [weak self] difference, finalState in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if case .pollDifference = strongSelf.operations.removeFirst() {
|
if case .pollDifference = strongSelf.operations.removeFirst().content {
|
||||||
let events: AccountFinalStateEvents
|
let events: AccountFinalStateEvents
|
||||||
if let finalState = finalState {
|
if let finalState = finalState {
|
||||||
events = currentEvents.union(with: AccountFinalStateEvents(state: finalState))
|
events = currentEvents.union(with: AccountFinalStateEvents(state: finalState))
|
||||||
@@ -344,7 +373,7 @@ public final class AccountStateManager {
|
|||||||
if let difference = difference {
|
if let difference = difference {
|
||||||
switch difference {
|
switch difference {
|
||||||
case .differenceSlice:
|
case .differenceSlice:
|
||||||
strongSelf.operations.insert(.pollDifference(events), at: 0)
|
strongSelf.addOperation(.pollDifference(events), position: .first)
|
||||||
default:
|
default:
|
||||||
if !events.isEmpty {
|
if !events.isEmpty {
|
||||||
strongSelf.insertProcessEvents(events)
|
strongSelf.insertProcessEvents(events)
|
||||||
@@ -370,9 +399,10 @@ public final class AccountStateManager {
|
|||||||
self.operationTimer?.invalidate()
|
self.operationTimer?.invalidate()
|
||||||
let operationTimer = SignalKitTimer(timeout: timeout, repeat: false, completion: { [weak self] in
|
let operationTimer = SignalKitTimer(timeout: timeout, repeat: false, completion: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let firstOperation = strongSelf.operations.first, case let .collectUpdateGroups(groups, _) = firstOperation {
|
let firstOperation = strongSelf.operations.removeFirst()
|
||||||
|
if case let .collectUpdateGroups(groups, _) = firstOperation.content {
|
||||||
if timeout.isEqual(to: 0.0) {
|
if timeout.isEqual(to: 0.0) {
|
||||||
strongSelf.operations[0] = .processUpdateGroups(groups)
|
strongSelf.addOperation(.processUpdateGroups(groups), position: .first)
|
||||||
} else {
|
} else {
|
||||||
Logger.shared.log("AccountStateManager", "timeout while waiting for updates")
|
Logger.shared.log("AccountStateManager", "timeout while waiting for updates")
|
||||||
strongSelf.replaceOperations(with: .pollDifference(AccountFinalStateEvents()))
|
strongSelf.replaceOperations(with: .pollDifference(AccountFinalStateEvents()))
|
||||||
@@ -393,32 +423,32 @@ public final class AccountStateManager {
|
|||||||
let mediaBox = account.postbox.mediaBox
|
let mediaBox = account.postbox.mediaBox
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
let signal = initialStateWithUpdateGroups(account, groups: groups)
|
let signal = initialStateWithUpdateGroups(account, groups: groups)
|
||||||
|> mapToSignal { state -> Signal<(AccountReplayedFinalState?, AccountFinalState), NoError> in
|
|> mapToSignal { state -> Signal<(AccountReplayedFinalState?, AccountFinalState), NoError> in
|
||||||
return finalStateWithUpdateGroups(account, state: state, groups: groups)
|
return finalStateWithUpdateGroups(account, state: state, groups: groups)
|
||||||
|> mapToSignal { finalState in
|
|> mapToSignal { finalState in
|
||||||
if !finalState.state.preCachedResources.isEmpty {
|
if !finalState.state.preCachedResources.isEmpty {
|
||||||
for (resource, data) in finalState.state.preCachedResources {
|
for (resource, data) in finalState.state.preCachedResources {
|
||||||
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return account.postbox.transaction { transaction -> AccountReplayedFinalState? in
|
|
||||||
return replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, transaction: transaction, auxiliaryMethods: auxiliaryMethods, finalState: finalState)
|
|
||||||
}
|
|
||||||
|> map({ ($0, finalState) })
|
|
||||||
|> deliverOn(queue)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.postbox.transaction { transaction -> AccountReplayedFinalState? in
|
||||||
|
return replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, transaction: transaction, auxiliaryMethods: auxiliaryMethods, finalState: finalState)
|
||||||
|
}
|
||||||
|
|> map({ ($0, finalState) })
|
||||||
|
|> deliverOn(queue)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let _ = signal.start(next: { [weak self] replayedState, finalState in
|
let _ = signal.start(next: { [weak self] replayedState, finalState in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if case let .processUpdateGroups(groups) = strongSelf.operations.removeFirst() {
|
if case let .processUpdateGroups(groups) = strongSelf.operations.removeFirst().content {
|
||||||
if let replayedState = replayedState, !finalState.shouldPoll {
|
if let replayedState = replayedState, !finalState.shouldPoll {
|
||||||
let events = AccountFinalStateEvents(state: replayedState)
|
let events = AccountFinalStateEvents(state: replayedState)
|
||||||
if !events.isEmpty {
|
if !events.isEmpty {
|
||||||
strongSelf.insertProcessEvents(events)
|
strongSelf.insertProcessEvents(events)
|
||||||
}
|
}
|
||||||
if finalState.incomplete {
|
if finalState.incomplete {
|
||||||
strongSelf.operations.append(.collectUpdateGroups(groups, 2.0))
|
strongSelf.addOperation(.collectUpdateGroups(groups, 2.0), position: .last)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strongSelf.replaceOperations(with: .pollDifference(AccountFinalStateEvents()))
|
strongSelf.replaceOperations(with: .pollDifference(AccountFinalStateEvents()))
|
||||||
@@ -436,8 +466,8 @@ public final class AccountStateManager {
|
|||||||
self.operationTimer?.invalidate()
|
self.operationTimer?.invalidate()
|
||||||
let completed: () -> Void = { [weak self] in
|
let completed: () -> Void = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let topOperation = strongSelf.operations.first, case .custom(operationId, _) = topOperation {
|
let topOperation = strongSelf.operations.removeFirst()
|
||||||
strongSelf.operations.removeFirst()
|
if case .custom(operationId, _) = topOperation.content {
|
||||||
strongSelf.startFirstOperation()
|
strongSelf.startFirstOperation()
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
@@ -453,7 +483,8 @@ public final class AccountStateManager {
|
|||||||
self.operationTimer?.invalidate()
|
self.operationTimer?.invalidate()
|
||||||
let completed: () -> Void = { [weak self] in
|
let completed: () -> Void = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let topOperation = strongSelf.operations.first, case .processEvents(operationId, _) = topOperation {
|
let topOperation = strongSelf.operations.removeFirst()
|
||||||
|
if case .processEvents(operationId, _) = topOperation.content {
|
||||||
if !events.updatedTypingActivities.isEmpty {
|
if !events.updatedTypingActivities.isEmpty {
|
||||||
strongSelf.peerInputActivityManager.transaction { manager in
|
strongSelf.peerInputActivityManager.transaction { manager in
|
||||||
for (chatPeerId, peerActivities) in events.updatedTypingActivities {
|
for (chatPeerId, peerActivities) in events.updatedTypingActivities {
|
||||||
@@ -475,14 +506,18 @@ public final class AccountStateManager {
|
|||||||
strongSelf.account.callSessionManager.updateSession(call)
|
strongSelf.account.callSessionManager.updateSession(call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strongSelf.operations.removeFirst()
|
if !events.isContactUpdates.isEmpty {
|
||||||
|
strongSelf.account.contactSyncManager.addIsContactUpdates(events.isContactUpdates)
|
||||||
|
}
|
||||||
var pollCount = 0
|
var pollCount = 0
|
||||||
for i in 0 ..< strongSelf.operations.count {
|
for i in 0 ..< strongSelf.operations.count {
|
||||||
if case let .pollCompletion(pollId, messageIds, subscribers) = strongSelf.operations[i] {
|
if case let .pollCompletion(pollId, messageIds, subscribers) = strongSelf.operations[i].content {
|
||||||
pollCount += 1
|
pollCount += 1
|
||||||
var updatedMessageIds = messageIds
|
var updatedMessageIds = messageIds
|
||||||
updatedMessageIds.append(contentsOf: events.addedIncomingMessageIds)
|
updatedMessageIds.append(contentsOf: events.addedIncomingMessageIds)
|
||||||
strongSelf.operations[i] = .pollCompletion(pollId, updatedMessageIds, subscribers)
|
let operation = AccountStateManagerOperation(content: .pollCompletion(pollId, updatedMessageIds, subscribers))
|
||||||
|
operation.isRunning = strongSelf.operations[i].isRunning
|
||||||
|
strongSelf.operations[i] = operation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(pollCount <= 1)
|
assert(pollCount <= 1)
|
||||||
@@ -508,7 +543,8 @@ public final class AccountStateManager {
|
|||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = (signal |> deliverOn(self.queue)).start(next: { [weak self] messages in
|
let _ = (signal
|
||||||
|
|> deliverOn(self.queue)).start(next: { [weak self] messages in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.notificationMessagesPipe.putNext(messages)
|
strongSelf.notificationMessagesPipe.putNext(messages)
|
||||||
}
|
}
|
||||||
@@ -529,13 +565,13 @@ public final class AccountStateManager {
|
|||||||
} else {
|
} else {
|
||||||
self.operationTimer?.invalidate()
|
self.operationTimer?.invalidate()
|
||||||
let signal = self.account.network.request(Api.functions.help.test())
|
let signal = self.account.network.request(Api.functions.help.test())
|
||||||
|> deliverOn(self.queue)
|
|> deliverOn(self.queue)
|
||||||
let completed: () -> Void = { [weak self] in
|
let completed: () -> Void = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let topOperation = strongSelf.operations.first, case let .pollCompletion(topPollId, messageIds, subscribers) = topOperation {
|
let topOperation = strongSelf.operations.removeFirst()
|
||||||
|
if case let .pollCompletion(topPollId, messageIds, subscribers) = topOperation.content {
|
||||||
assert(topPollId == pollId)
|
assert(topPollId == pollId)
|
||||||
|
|
||||||
strongSelf.operations.removeFirst()
|
|
||||||
if strongSelf.operations.isEmpty {
|
if strongSelf.operations.isEmpty {
|
||||||
for (_, f) in subscribers {
|
for (_, f) in subscribers {
|
||||||
f(messageIds)
|
f(messageIds)
|
||||||
@@ -573,7 +609,7 @@ public final class AccountStateManager {
|
|||||||
|
|
||||||
let _ = signal.start(next: { [weak self] replayedState, finalState in
|
let _ = signal.start(next: { [weak self] replayedState, finalState in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if case .replayAsynchronouslyBuiltFinalState = strongSelf.operations.removeFirst() {
|
if case .replayAsynchronouslyBuiltFinalState = strongSelf.operations.removeFirst().content {
|
||||||
if let replayedState = replayedState {
|
if let replayedState = replayedState {
|
||||||
let events = AccountFinalStateEvents(state: replayedState)
|
let events = AccountFinalStateEvents(state: replayedState)
|
||||||
if !events.isEmpty {
|
if !events.isEmpty {
|
||||||
@@ -596,21 +632,30 @@ public final class AccountStateManager {
|
|||||||
|
|
||||||
private func insertProcessEvents(_ events: AccountFinalStateEvents) {
|
private func insertProcessEvents(_ events: AccountFinalStateEvents) {
|
||||||
if !events.isEmpty {
|
if !events.isEmpty {
|
||||||
var index = 0
|
let operation = AccountStateManagerOperation(content: .processEvents(self.getNextId(), events))
|
||||||
if !self.operations.isEmpty {
|
var inserted = false
|
||||||
while case .processEvents = self.operations[index] {
|
for i in 0 ..< self.operations.count {
|
||||||
index += 1
|
if self.operations[i].isRunning {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
if case .processEvents = self.operations[i].content {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
self.operations.insert(operation, at: i)
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !inserted {
|
||||||
|
self.operations.append(operation)
|
||||||
}
|
}
|
||||||
self.operations.insert(.processEvents(self.getNextId(), events), at: 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func postponePollCompletionOperation(messageIds: [MessageId], subscribers: [(Int32, ([MessageId]) -> Void)]) {
|
private func postponePollCompletionOperation(messageIds: [MessageId], subscribers: [(Int32, ([MessageId]) -> Void)]) {
|
||||||
self.operations.append(.pollCompletion(self.getNextId(), messageIds, subscribers))
|
self.addOperation(.pollCompletion(self.getNextId(), messageIds, subscribers), position: .last)
|
||||||
|
|
||||||
for i in 0 ..< self.operations.count {
|
for i in 0 ..< self.operations.count {
|
||||||
if case .pollCompletion = self.operations[i] {
|
if case .pollCompletion = self.operations[i].content {
|
||||||
if i != self.operations.count - 1 {
|
if i != self.operations.count - 1 {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
@@ -624,31 +669,32 @@ public final class AccountStateManager {
|
|||||||
let updatedId: Int32 = self.getNextId()
|
let updatedId: Int32 = self.getNextId()
|
||||||
|
|
||||||
for i in 0 ..< self.operations.count {
|
for i in 0 ..< self.operations.count {
|
||||||
if case let .pollCompletion(pollId, messageIds, subscribers) = self.operations[i] {
|
if case let .pollCompletion(pollId, messageIds, subscribers) = self.operations[i].content {
|
||||||
var subscribers = subscribers
|
var subscribers = subscribers
|
||||||
subscribers.append((updatedId, f))
|
subscribers.append((updatedId, f))
|
||||||
self.operations[i] = .pollCompletion(pollId, messageIds, subscribers)
|
let operation = AccountStateManagerOperation(content: .pollCompletion(pollId, messageIds, subscribers))
|
||||||
|
operation.isRunning = self.operations[i].isRunning
|
||||||
|
self.operations[i] = operation
|
||||||
return updatedId
|
return updatedId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let beginFirst = self.operations.isEmpty
|
let beginFirst = self.operations.isEmpty
|
||||||
self.operations.append(.pollCompletion(self.getNextId(), [], [(updatedId, f)]))
|
self.addOperation(.pollCompletion(self.getNextId(), [], [(updatedId, f)]), position: .last)
|
||||||
if beginFirst {
|
|
||||||
self.startFirstOperation()
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedId
|
return updatedId
|
||||||
}
|
}
|
||||||
|
|
||||||
private func removePollCompletion(_ id: Int32) {
|
private func removePollCompletion(_ id: Int32) {
|
||||||
for i in 0 ..< self.operations.count {
|
for i in 0 ..< self.operations.count {
|
||||||
if case let .pollCompletion(pollId, messages, subscribers) = self.operations[i] {
|
if case let .pollCompletion(pollId, messages, subscribers) = self.operations[i].content {
|
||||||
for j in 0 ..< subscribers.count {
|
for j in 0 ..< subscribers.count {
|
||||||
if subscribers[j].0 == id {
|
if subscribers[j].0 == id {
|
||||||
var subscribers = subscribers
|
var subscribers = subscribers
|
||||||
subscribers.remove(at: j)
|
subscribers.remove(at: j)
|
||||||
self.operations[i] = .pollCompletion(pollId, messages, subscribers)
|
let operation = AccountStateManagerOperation(content: .pollCompletion(pollId, messages, subscribers))
|
||||||
|
operation.isRunning = self.operations[i].isRunning
|
||||||
|
self.operations[i] = operation
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,15 +37,15 @@ private func updatedRemoteContactPeers(network: Network, hash: Int32) -> Signal<
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func hashForCountAndIds(count: Int32, ids: [Int32]) -> Int32 {
|
private func hashForCountAndIds(count: Int32, ids: [Int32]) -> Int32 {
|
||||||
var acc: UInt32 = 0
|
var acc: Int64 = 0
|
||||||
|
|
||||||
acc = (acc &* 20261) &+ UInt32(bitPattern: count)
|
acc = (acc &* 20261) &+ Int64(count)
|
||||||
|
|
||||||
for id in ids {
|
for id in ids {
|
||||||
let low = UInt32(bitPattern: id)
|
acc = (acc &* 20261) &+ Int64(id)
|
||||||
acc = (acc &* 20261) &+ low
|
acc = acc & Int64(0x7FFFFFFF)
|
||||||
}
|
}
|
||||||
return Int32(bitPattern: acc & UInt32(0x7FFFFFFF))
|
return Int32(acc & Int64(0x7FFFFFFF))
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncContactsOnce(network: Network, postbox: Postbox) -> Signal<Never, NoError> {
|
func syncContactsOnce(network: Network, postbox: Postbox) -> Signal<Never, NoError> {
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ private final class ContactSyncOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum ContactSyncOperationContent {
|
private enum ContactSyncOperationContent {
|
||||||
|
case waitForUpdatedState
|
||||||
case sync(importableContacts: [DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData]?)
|
case sync(importableContacts: [DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData]?)
|
||||||
case updateIsContact(peerId: PeerId, isContact: Bool)
|
case updateIsContact([(PeerId, Bool)])
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ContactSyncManagerImpl {
|
private final class ContactSyncManagerImpl {
|
||||||
@@ -53,15 +54,22 @@ private final class ContactSyncManagerImpl {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
strongSelf.addOperation(.waitForUpdatedState)
|
||||||
strongSelf.addOperation(.sync(importableContacts: importableContacts))
|
strongSelf.addOperation(.sync(importableContacts: importableContacts))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addIsContactUpdates(_ updates: [(PeerId, Bool)]) {
|
||||||
|
self.addOperation(.updateIsContact(updates))
|
||||||
|
}
|
||||||
|
|
||||||
func addOperation(_ content: ContactSyncOperationContent) {
|
func addOperation(_ content: ContactSyncOperationContent) {
|
||||||
let id = self.nextId
|
let id = self.nextId
|
||||||
self.nextId += 1
|
self.nextId += 1
|
||||||
let operation = ContactSyncOperation(id: id, content: content)
|
let operation = ContactSyncOperation(id: id, content: content)
|
||||||
switch content {
|
switch content {
|
||||||
|
case .waitForUpdatedState:
|
||||||
|
self.operations.append(operation)
|
||||||
case .sync:
|
case .sync:
|
||||||
for i in (0 ..< self.operations.count).reversed() {
|
for i in (0 ..< self.operations.count).reversed() {
|
||||||
if case .sync = self.operations[i].content {
|
if case .sync = self.operations[i].content {
|
||||||
@@ -70,10 +78,28 @@ private final class ContactSyncManagerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
self.operations.append(operation)
|
||||||
break
|
case let .updateIsContact(updates):
|
||||||
|
var mergedUpdates: [(PeerId, Bool)] = []
|
||||||
|
var removeIndices: [Int] = []
|
||||||
|
for i in 0 ..< self.operations.count {
|
||||||
|
if case let .updateIsContact(operationUpdates) = self.operations[i].content {
|
||||||
|
if !self.operations[i].isRunning {
|
||||||
|
mergedUpdates.append(contentsOf: operationUpdates)
|
||||||
|
removeIndices.append(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mergedUpdates.append(contentsOf: updates)
|
||||||
|
for index in removeIndices.reversed() {
|
||||||
|
self.operations.remove(at: index)
|
||||||
|
}
|
||||||
|
if self.operations.isEmpty || !self.operations[0].isRunning {
|
||||||
|
self.operations.insert(operation, at: 0)
|
||||||
|
} else {
|
||||||
|
self.operations.insert(operation, at: 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.operations.append(operation)
|
|
||||||
self.updateOperations()
|
self.updateOperations()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +126,11 @@ private final class ContactSyncManagerImpl {
|
|||||||
|
|
||||||
func startOperation(_ operation: ContactSyncOperationContent, disposable: DisposableSet, completion: @escaping () -> Void) {
|
func startOperation(_ operation: ContactSyncOperationContent, disposable: DisposableSet, completion: @escaping () -> Void) {
|
||||||
switch operation {
|
switch operation {
|
||||||
|
case .waitForUpdatedState:
|
||||||
|
disposable.add((self.stateManager.pollStateUpdateCompletion()
|
||||||
|
|> deliverOn(self.queue)).start(next: { _ in
|
||||||
|
completion()
|
||||||
|
}))
|
||||||
case let .sync(importableContacts):
|
case let .sync(importableContacts):
|
||||||
let importSignal: Signal<PushDeviceContactsResult, NoError>
|
let importSignal: Signal<PushDeviceContactsResult, NoError>
|
||||||
if let importableContacts = importableContacts {
|
if let importableContacts = importableContacts {
|
||||||
@@ -107,18 +138,14 @@ private final class ContactSyncManagerImpl {
|
|||||||
} else {
|
} else {
|
||||||
importSignal = .single(PushDeviceContactsResult(addedReimportAttempts: [:]))
|
importSignal = .single(PushDeviceContactsResult(addedReimportAttempts: [:]))
|
||||||
}
|
}
|
||||||
disposable.add((self.stateManager.pollStateUpdateCompletion()
|
disposable.add(
|
||||||
|> mapToSignal { _ -> Signal<PushDeviceContactsResult, NoError> in
|
(syncContactsOnce(network: self.network, postbox: self.postbox)
|
||||||
return .complete()
|
|
||||||
}
|
|
||||||
|> then(
|
|
||||||
syncContactsOnce(network: self.network, postbox: self.postbox)
|
|
||||||
|> mapToSignal { _ -> Signal<PushDeviceContactsResult, NoError> in
|
|> mapToSignal { _ -> Signal<PushDeviceContactsResult, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|> then(importSignal)
|
|> then(importSignal)
|
||||||
)
|
|> deliverOn(self.queue)
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] result in
|
).start(next: { [weak self] result in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -128,17 +155,17 @@ private final class ContactSyncManagerImpl {
|
|||||||
|
|
||||||
completion()
|
completion()
|
||||||
}))
|
}))
|
||||||
case let .updateIsContact(peerId, isContact):
|
case let .updateIsContact(updates):
|
||||||
disposable.add((self.postbox.transaction { transaction -> Void in
|
disposable.add((self.postbox.transaction { transaction -> Void in
|
||||||
if transaction.isPeerContact(peerId: peerId) != isContact {
|
var contactPeerIds = transaction.getContactPeerIds()
|
||||||
var contactPeerIds = transaction.getContactPeerIds()
|
for (peerId, isContact) in updates {
|
||||||
if isContact {
|
if isContact {
|
||||||
contactPeerIds.insert(peerId)
|
contactPeerIds.insert(peerId)
|
||||||
} else {
|
} else {
|
||||||
contactPeerIds.remove(peerId)
|
contactPeerIds.remove(peerId)
|
||||||
}
|
}
|
||||||
transaction.replaceContactPeerIds(contactPeerIds)
|
|
||||||
}
|
}
|
||||||
|
transaction.replaceContactPeerIds(contactPeerIds)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
completion()
|
completion()
|
||||||
@@ -320,4 +347,10 @@ final class ContactSyncManager {
|
|||||||
impl.beginSync(importableContacts: importableContacts)
|
impl.beginSync(importableContacts: importableContacts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addIsContactUpdates(_ updates: [(PeerId, Bool)]) {
|
||||||
|
self.impl.with { impl in
|
||||||
|
impl.addIsContactUpdates(updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public final class Localization: PostboxCoding, Equatable {
|
|||||||
public let version: Int32
|
public let version: Int32
|
||||||
public let entries: [LocalizationEntry]
|
public let entries: [LocalizationEntry]
|
||||||
|
|
||||||
init(version: Int32, entries: [LocalizationEntry]) {
|
public init(version: Int32, entries: [LocalizationEntry]) {
|
||||||
self.version = version
|
self.version = version
|
||||||
self.entries = entries
|
self.entries = entries
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public final class LocalizationSettings: PreferencesEntry, Equatable {
|
|||||||
public let languageCode: String
|
public let languageCode: String
|
||||||
public let localization: Localization
|
public let localization: Localization
|
||||||
|
|
||||||
init(languageCode: String, localization: Localization) {
|
public init(languageCode: String, localization: Localization) {
|
||||||
self.languageCode = languageCode
|
self.languageCode = languageCode
|
||||||
self.localization = localization
|
self.localization = localization
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,13 @@ func managedSynchronizeInstalledStickerPacksOperations(postbox: Postbox, network
|
|||||||
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in
|
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in
|
||||||
if let entry = entry {
|
if let entry = entry {
|
||||||
if let operation = entry.contents as? SynchronizeInstalledStickerPacksOperation {
|
if let operation = entry.contents as? SynchronizeInstalledStickerPacksOperation {
|
||||||
return synchronizeInstalledStickerPacks(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, namespace: namespace, operation: operation)
|
return stateManager.pollStateUpdateCompletion()
|
||||||
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
|
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
|
return synchronizeInstalledStickerPacks(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, namespace: namespace, operation: operation)
|
||||||
|
}
|
||||||
|
|> switchToLatest
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -866,6 +866,7 @@ public final class PendingMessageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sendMessageRequest
|
return sendMessageRequest
|
||||||
|
|> deliverOn(queue)
|
||||||
|> mapToSignal { result -> Signal<Void, MTRpcError> in
|
|> mapToSignal { result -> Signal<Void, MTRpcError> in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
return strongSelf.applySentMessage(postbox: postbox, stateManager: stateManager, message: message, result: result)
|
return strongSelf.applySentMessage(postbox: postbox, stateManager: stateManager, message: message, result: result)
|
||||||
|
|||||||
Reference in New Issue
Block a user