mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 11:00:07 +00:00
no message
This commit is contained in:
parent
59411a3c2e
commit
c2768b07b3
@ -7,7 +7,26 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CFF1D62255C00955575 /* ChannelState.swift */; };
|
||||||
|
D001F3E91E128A1C007A8C60 /* SecretChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */; };
|
||||||
|
D001F3EA1E128A1C007A8C60 /* TelegramPeerNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */; };
|
||||||
|
D001F3EB1E128A1C007A8C60 /* EnqueueMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D001D62255C00955575 /* EnqueueMessage.swift */; };
|
||||||
|
D001F3EC1E128A1C007A8C60 /* Holes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D011D62255C00955575 /* Holes.swift */; };
|
||||||
|
D001F3ED1E128A1C007A8C60 /* SendUnsentMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D021D62255C00955575 /* SendUnsentMessage.swift */; };
|
||||||
|
D001F3EE1E128A1C007A8C60 /* AccountStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495D1E118F790057C89A /* AccountStateManager.swift */; };
|
||||||
|
D001F3EF1E128A1C007A8C60 /* AccountIntermediateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495F1E118FC30057C89A /* AccountIntermediateState.swift */; };
|
||||||
|
D001F3F01E128A1C007A8C60 /* AccountStateManagementUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D031D62255C00955575 /* AccountStateManagementUtils.swift */; };
|
||||||
|
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */; };
|
||||||
|
D001F3F21E128A1C007A8C60 /* UpdateGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D051D62255C00955575 /* UpdateGroup.swift */; };
|
||||||
|
D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D061D62255C00955575 /* UpdateMessageService.swift */; };
|
||||||
|
D001F3F41E128A1C007A8C60 /* UpdatesApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D071D62255C00955575 /* UpdatesApiUtils.swift */; };
|
||||||
|
D001F3F51E128A1C007A8C60 /* PendingMessageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09BB6B31DB02C2B00A905C0 /* PendingMessageManager.swift */; };
|
||||||
|
D001F3F61E128A1C007A8C60 /* PendingMessageUploadedContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09BB6B51DB0428000A905C0 /* PendingMessageUploadedContent.swift */; };
|
||||||
|
D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9221DD5E9A200E8160F /* ApplyUpdateMessage.swift */; };
|
||||||
D003702B1DA42586004308D3 /* PhoneNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = D003702A1DA42586004308D3 /* PhoneNumber.swift */; };
|
D003702B1DA42586004308D3 /* PhoneNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = D003702A1DA42586004308D3 /* PhoneNumber.swift */; };
|
||||||
|
D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01749581E1092BC0057C89A /* RequestStartBot.swift */; };
|
||||||
|
D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495D1E118F790057C89A /* AccountStateManager.swift */; };
|
||||||
|
D01749601E118FC30057C89A /* AccountIntermediateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495F1E118FC30057C89A /* AccountIntermediateState.swift */; };
|
||||||
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */; };
|
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */; };
|
||||||
D01AC91D1DD5DA5E00E8160F /* RequestMessageActionCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */; };
|
D01AC91D1DD5DA5E00E8160F /* RequestMessageActionCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */; };
|
||||||
D01AC9211DD5E7E500E8160F /* RequestEditMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */; };
|
D01AC9211DD5E7E500E8160F /* RequestEditMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */; };
|
||||||
@ -41,7 +60,7 @@
|
|||||||
D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D001D62255C00955575 /* EnqueueMessage.swift */; };
|
D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D001D62255C00955575 /* EnqueueMessage.swift */; };
|
||||||
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D011D62255C00955575 /* Holes.swift */; };
|
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D011D62255C00955575 /* Holes.swift */; };
|
||||||
D03B0D0B1D62255C00955575 /* SendUnsentMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D021D62255C00955575 /* SendUnsentMessage.swift */; };
|
D03B0D0B1D62255C00955575 /* SendUnsentMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D021D62255C00955575 /* SendUnsentMessage.swift */; };
|
||||||
D03B0D0C1D62255C00955575 /* StateManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D031D62255C00955575 /* StateManagement.swift */; };
|
D03B0D0C1D62255C00955575 /* AccountStateManagementUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D031D62255C00955575 /* AccountStateManagementUtils.swift */; };
|
||||||
D03B0D0D1D62255C00955575 /* SynchronizePeerReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */; };
|
D03B0D0D1D62255C00955575 /* SynchronizePeerReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */; };
|
||||||
D03B0D0E1D62255C00955575 /* UpdateGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D051D62255C00955575 /* UpdateGroup.swift */; };
|
D03B0D0E1D62255C00955575 /* UpdateGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D051D62255C00955575 /* UpdateGroup.swift */; };
|
||||||
D03B0D0F1D62255C00955575 /* UpdateMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D061D62255C00955575 /* UpdateMessageService.swift */; };
|
D03B0D0F1D62255C00955575 /* UpdateMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D061D62255C00955575 /* UpdateMessageService.swift */; };
|
||||||
@ -91,8 +110,6 @@
|
|||||||
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5C1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift */; };
|
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5C1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift */; };
|
||||||
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5F1DCB9D14007511FD /* OutgoingMessageInfoAttribute.swift */; };
|
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5F1DCB9D14007511FD /* OutgoingMessageInfoAttribute.swift */; };
|
||||||
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0DE1DB539FC00C6B04F /* StickerPack.swift */; };
|
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0DE1DB539FC00C6B04F /* StickerPack.swift */; };
|
||||||
D073CEA21DCBF3E1007511FD /* PendingMessageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09BB6B31DB02C2B00A905C0 /* PendingMessageManager.swift */; };
|
|
||||||
D073CEA31DCBF3E1007511FD /* PendingMessageUploadedContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09BB6B51DB0428000A905C0 /* PendingMessageUploadedContent.swift */; };
|
|
||||||
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */; };
|
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */; };
|
||||||
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0E11DB5401A00C6B04F /* StickerManagement.swift */; };
|
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0E11DB5401A00C6B04F /* StickerManagement.swift */; };
|
||||||
D07827BB1E00451F00071108 /* SearchPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827BA1E00451F00071108 /* SearchPeers.swift */; };
|
D07827BB1E00451F00071108 /* SearchPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827BA1E00451F00071108 /* SearchPeers.swift */; };
|
||||||
@ -191,16 +208,6 @@
|
|||||||
D0B844341DAB91E0005F29E1 /* NBPhoneNumberDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843AD1DA7FF30005F29E1 /* NBPhoneNumberDefines.m */; };
|
D0B844341DAB91E0005F29E1 /* NBPhoneNumberDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843AD1DA7FF30005F29E1 /* NBPhoneNumberDefines.m */; };
|
||||||
D0B844351DAB91E0005F29E1 /* NBPhoneNumberDesc.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843AF1DA7FF30005F29E1 /* NBPhoneNumberDesc.m */; };
|
D0B844351DAB91E0005F29E1 /* NBPhoneNumberDesc.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843AF1DA7FF30005F29E1 /* NBPhoneNumberDesc.m */; };
|
||||||
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843B11DA7FF30005F29E1 /* NBPhoneNumberUtil.m */; };
|
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B843B11DA7FF30005F29E1 /* NBPhoneNumberUtil.m */; };
|
||||||
D0B844381DAB91EF005F29E1 /* ChannelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CFF1D62255C00955575 /* ChannelState.swift */; };
|
|
||||||
D0B844391DAB91EF005F29E1 /* TelegramPeerNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */; };
|
|
||||||
D0B8443A1DAB91EF005F29E1 /* EnqueueMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D001D62255C00955575 /* EnqueueMessage.swift */; };
|
|
||||||
D0B8443B1DAB91EF005F29E1 /* Holes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D011D62255C00955575 /* Holes.swift */; };
|
|
||||||
D0B8443C1DAB91EF005F29E1 /* SendUnsentMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D021D62255C00955575 /* SendUnsentMessage.swift */; };
|
|
||||||
D0B8443D1DAB91EF005F29E1 /* StateManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D031D62255C00955575 /* StateManagement.swift */; };
|
|
||||||
D0B8443E1DAB91EF005F29E1 /* SynchronizePeerReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */; };
|
|
||||||
D0B8443F1DAB91EF005F29E1 /* UpdateGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D051D62255C00955575 /* UpdateGroup.swift */; };
|
|
||||||
D0B844401DAB91EF005F29E1 /* UpdateMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D061D62255C00955575 /* UpdateMessageService.swift */; };
|
|
||||||
D0B844411DAB91EF005F29E1 /* UpdatesApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D071D62255C00955575 /* UpdatesApiUtils.swift */; };
|
|
||||||
D0B844431DAB91FD005F29E1 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D611D631A8B00955575 /* Account.swift */; };
|
D0B844431DAB91FD005F29E1 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D611D631A8B00955575 /* Account.swift */; };
|
||||||
D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D621D631A8B00955575 /* AccountSettings.swift */; };
|
D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D621D631A8B00955575 /* AccountSettings.swift */; };
|
||||||
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D631D631A8B00955575 /* AccountViewTracker.swift */; };
|
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D631D631A8B00955575 /* AccountViewTracker.swift */; };
|
||||||
@ -256,6 +263,9 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
D003702A1DA42586004308D3 /* PhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumber.swift; sourceTree = "<group>"; };
|
D003702A1DA42586004308D3 /* PhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumber.swift; sourceTree = "<group>"; };
|
||||||
|
D01749581E1092BC0057C89A /* RequestStartBot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestStartBot.swift; sourceTree = "<group>"; };
|
||||||
|
D017495D1E118F790057C89A /* AccountStateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountStateManager.swift; sourceTree = "<group>"; };
|
||||||
|
D017495F1E118FC30057C89A /* AccountIntermediateState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountIntermediateState.swift; sourceTree = "<group>"; };
|
||||||
D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatState.swift; sourceTree = "<group>"; };
|
D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatState.swift; sourceTree = "<group>"; };
|
||||||
D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestMessageActionCallback.swift; sourceTree = "<group>"; };
|
D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestMessageActionCallback.swift; sourceTree = "<group>"; };
|
||||||
D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestEditMessage.swift; sourceTree = "<group>"; };
|
D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestEditMessage.swift; sourceTree = "<group>"; };
|
||||||
@ -289,7 +299,7 @@
|
|||||||
D03B0D001D62255C00955575 /* EnqueueMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnqueueMessage.swift; sourceTree = "<group>"; };
|
D03B0D001D62255C00955575 /* EnqueueMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnqueueMessage.swift; sourceTree = "<group>"; };
|
||||||
D03B0D011D62255C00955575 /* Holes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Holes.swift; sourceTree = "<group>"; };
|
D03B0D011D62255C00955575 /* Holes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Holes.swift; sourceTree = "<group>"; };
|
||||||
D03B0D021D62255C00955575 /* SendUnsentMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendUnsentMessage.swift; sourceTree = "<group>"; };
|
D03B0D021D62255C00955575 /* SendUnsentMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendUnsentMessage.swift; sourceTree = "<group>"; };
|
||||||
D03B0D031D62255C00955575 /* StateManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateManagement.swift; sourceTree = "<group>"; };
|
D03B0D031D62255C00955575 /* AccountStateManagementUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountStateManagementUtils.swift; sourceTree = "<group>"; };
|
||||||
D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePeerReadState.swift; sourceTree = "<group>"; };
|
D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePeerReadState.swift; sourceTree = "<group>"; };
|
||||||
D03B0D051D62255C00955575 /* UpdateGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateGroup.swift; sourceTree = "<group>"; };
|
D03B0D051D62255C00955575 /* UpdateGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateGroup.swift; sourceTree = "<group>"; };
|
||||||
D03B0D061D62255C00955575 /* UpdateMessageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateMessageService.swift; sourceTree = "<group>"; };
|
D03B0D061D62255C00955575 /* UpdateMessageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateMessageService.swift; sourceTree = "<group>"; };
|
||||||
@ -594,7 +604,9 @@
|
|||||||
D03B0D001D62255C00955575 /* EnqueueMessage.swift */,
|
D03B0D001D62255C00955575 /* EnqueueMessage.swift */,
|
||||||
D03B0D011D62255C00955575 /* Holes.swift */,
|
D03B0D011D62255C00955575 /* Holes.swift */,
|
||||||
D03B0D021D62255C00955575 /* SendUnsentMessage.swift */,
|
D03B0D021D62255C00955575 /* SendUnsentMessage.swift */,
|
||||||
D03B0D031D62255C00955575 /* StateManagement.swift */,
|
D017495D1E118F790057C89A /* AccountStateManager.swift */,
|
||||||
|
D017495F1E118FC30057C89A /* AccountIntermediateState.swift */,
|
||||||
|
D03B0D031D62255C00955575 /* AccountStateManagementUtils.swift */,
|
||||||
D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */,
|
D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */,
|
||||||
D03B0D051D62255C00955575 /* UpdateGroup.swift */,
|
D03B0D051D62255C00955575 /* UpdateGroup.swift */,
|
||||||
D03B0D061D62255C00955575 /* UpdateMessageService.swift */,
|
D03B0D061D62255C00955575 /* UpdateMessageService.swift */,
|
||||||
@ -672,6 +684,7 @@
|
|||||||
D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */,
|
D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */,
|
||||||
D0DC354F1DE36900000195EB /* ChatContextResult.swift */,
|
D0DC354F1DE36900000195EB /* ChatContextResult.swift */,
|
||||||
D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */,
|
D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */,
|
||||||
|
D01749581E1092BC0057C89A /* RequestStartBot.swift */,
|
||||||
);
|
);
|
||||||
name = Messages;
|
name = Messages;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1029,12 +1042,14 @@
|
|||||||
D03B0D0F1D62255C00955575 /* UpdateMessageService.swift in Sources */,
|
D03B0D0F1D62255C00955575 /* UpdateMessageService.swift in Sources */,
|
||||||
D03B0CF61D62250800955575 /* TelegramMediaFile.swift in Sources */,
|
D03B0CF61D62250800955575 /* TelegramMediaFile.swift in Sources */,
|
||||||
D03B0CE81D6224AD00955575 /* ViewCountMessageAttribute.swift in Sources */,
|
D03B0CE81D6224AD00955575 /* ViewCountMessageAttribute.swift in Sources */,
|
||||||
D03B0D0C1D62255C00955575 /* StateManagement.swift in Sources */,
|
D03B0D0C1D62255C00955575 /* AccountStateManagementUtils.swift in Sources */,
|
||||||
D073CE5D1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
D073CE5D1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
||||||
D03B0D721D631ABA00955575 /* SearchMessages.swift in Sources */,
|
D03B0D721D631ABA00955575 /* SearchMessages.swift in Sources */,
|
||||||
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */,
|
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */,
|
||||||
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */,
|
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */,
|
||||||
D03B0D5C1D631A6900955575 /* Download.swift in Sources */,
|
D03B0D5C1D631A6900955575 /* Download.swift in Sources */,
|
||||||
|
D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */,
|
||||||
|
D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */,
|
||||||
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
||||||
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
|
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
|
||||||
D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */,
|
D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */,
|
||||||
@ -1051,6 +1066,7 @@
|
|||||||
D03B0CC11D62235000955575 /* StringFormat.swift in Sources */,
|
D03B0CC11D62235000955575 /* StringFormat.swift in Sources */,
|
||||||
D0B843C31DA7FF30005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */,
|
D0B843C31DA7FF30005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */,
|
||||||
D0B843C11DA7FF30005F29E1 /* NBPhoneMetaData.m in Sources */,
|
D0B843C11DA7FF30005F29E1 /* NBPhoneMetaData.m in Sources */,
|
||||||
|
D01749601E118FC30057C89A /* AccountIntermediateState.swift in Sources */,
|
||||||
D03B0D651D631A8B00955575 /* Account.swift in Sources */,
|
D03B0D651D631A8B00955575 /* Account.swift in Sources */,
|
||||||
D0AB0B941D662ECE002C78E7 /* ManagedMessageHistoryHoles.swift in Sources */,
|
D0AB0B941D662ECE002C78E7 /* ManagedMessageHistoryHoles.swift in Sources */,
|
||||||
D03B0CF41D62250800955575 /* TelegramMediaAction.swift in Sources */,
|
D03B0CF41D62250800955575 /* TelegramMediaAction.swift in Sources */,
|
||||||
@ -1075,7 +1091,6 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D0B8443D1DAB91EF005F29E1 /* StateManagement.swift in Sources */,
|
|
||||||
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
|
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||||
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
|
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
|
||||||
D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */,
|
D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */,
|
||||||
@ -1083,38 +1098,42 @@
|
|||||||
D0B844311DAB91E0005F29E1 /* NBPhoneMetaData.m in Sources */,
|
D0B844311DAB91E0005F29E1 /* NBPhoneMetaData.m in Sources */,
|
||||||
D0B418AC1D7E0597004562A4 /* Network.swift in Sources */,
|
D0B418AC1D7E0597004562A4 /* Network.swift in Sources */,
|
||||||
D0B844141DAB91CD005F29E1 /* PhoneNumbers.swift in Sources */,
|
D0B844141DAB91CD005F29E1 /* PhoneNumbers.swift in Sources */,
|
||||||
D0B844391DAB91EF005F29E1 /* TelegramPeerNotificationSettings.swift in Sources */,
|
|
||||||
D0B844491DAB91FD005F29E1 /* ManagedChatListHoles.swift in Sources */,
|
D0B844491DAB91FD005F29E1 /* ManagedChatListHoles.swift in Sources */,
|
||||||
D03C53711DAD5CA9004C17B3 /* CachedGroupParticipants.swift in Sources */,
|
D03C53711DAD5CA9004C17B3 /* CachedGroupParticipants.swift in Sources */,
|
||||||
D03C53671DAD5CA9004C17B3 /* ApiUtils.swift in Sources */,
|
D03C53671DAD5CA9004C17B3 /* ApiUtils.swift in Sources */,
|
||||||
|
D001F3F21E128A1C007A8C60 /* UpdateGroup.swift in Sources */,
|
||||||
D0F7B1EB1E045C87007EB8A5 /* ResolvePeerByName.swift in Sources */,
|
D0F7B1EB1E045C87007EB8A5 /* ResolvePeerByName.swift in Sources */,
|
||||||
|
D001F3EE1E128A1C007A8C60 /* AccountStateManager.swift in Sources */,
|
||||||
D0B844351DAB91E0005F29E1 /* NBPhoneNumberDesc.m in Sources */,
|
D0B844351DAB91E0005F29E1 /* NBPhoneNumberDesc.m in Sources */,
|
||||||
D0B8442F1DAB91E0005F29E1 /* NBMetadataHelper.m in Sources */,
|
D0B8442F1DAB91E0005F29E1 /* NBMetadataHelper.m in Sources */,
|
||||||
D0B8444C1DAB91FD005F29E1 /* UpdateCachedPeerData.swift in Sources */,
|
D0B8444C1DAB91FD005F29E1 /* UpdateCachedPeerData.swift in Sources */,
|
||||||
D0B418A81D7E0597004562A4 /* Api.swift in Sources */,
|
D0B418A81D7E0597004562A4 /* Api.swift in Sources */,
|
||||||
D03C536C1DAD5CA9004C17B3 /* TelegramChannel.swift in Sources */,
|
D03C536C1DAD5CA9004C17B3 /* TelegramChannel.swift in Sources */,
|
||||||
D0B418951D7E0580004562A4 /* TelegramMediaContact.swift in Sources */,
|
D0B418951D7E0580004562A4 /* TelegramMediaContact.swift in Sources */,
|
||||||
D0B8443B1DAB91EF005F29E1 /* Holes.swift in Sources */,
|
|
||||||
D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */,
|
D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */,
|
||||||
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */,
|
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */,
|
||||||
D0E35A141DE4C69C00BC6096 /* FetchHttpResource.swift in Sources */,
|
D0E35A141DE4C69C00BC6096 /* FetchHttpResource.swift in Sources */,
|
||||||
D0B8443E1DAB91EF005F29E1 /* SynchronizePeerReadState.swift in Sources */,
|
|
||||||
D0B8440D1DAB91CD005F29E1 /* ImageRepresentationsUtils.swift in Sources */,
|
D0B8440D1DAB91CD005F29E1 /* ImageRepresentationsUtils.swift in Sources */,
|
||||||
D03C536A1DAD5CA9004C17B3 /* TelegramUser.swift in Sources */,
|
D03C536A1DAD5CA9004C17B3 /* TelegramUser.swift in Sources */,
|
||||||
|
D001F3EA1E128A1C007A8C60 /* TelegramPeerNotificationSettings.swift in Sources */,
|
||||||
|
D001F3EB1E128A1C007A8C60 /* EnqueueMessage.swift in Sources */,
|
||||||
D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */,
|
D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */,
|
||||||
D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */,
|
D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */,
|
||||||
D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */,
|
D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */,
|
||||||
|
D001F3F01E128A1C007A8C60 /* AccountStateManagementUtils.swift in Sources */,
|
||||||
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
|
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
|
||||||
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
|
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
|
||||||
|
D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */,
|
||||||
D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||||
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */,
|
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */,
|
||||||
D0B844401DAB91EF005F29E1 /* UpdateMessageService.swift in Sources */,
|
|
||||||
D0E35A131DE4C69100BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */,
|
D0E35A131DE4C69100BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */,
|
||||||
D0B418961D7E0580004562A4 /* TelegramMediaFile.swift in Sources */,
|
D0B418961D7E0580004562A4 /* TelegramMediaFile.swift in Sources */,
|
||||||
|
D001F3EC1E128A1C007A8C60 /* Holes.swift in Sources */,
|
||||||
D0B4189B1D7E0580004562A4 /* TelegramMediaWebpage.swift in Sources */,
|
D0B4189B1D7E0580004562A4 /* TelegramMediaWebpage.swift in Sources */,
|
||||||
D0B844341DAB91E0005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
D0B844341DAB91E0005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
||||||
D0B8442A1DAB91E0005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
D0B8442A1DAB91E0005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
||||||
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
||||||
|
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||||
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
||||||
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
|
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
|
||||||
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */,
|
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */,
|
||||||
@ -1122,12 +1141,12 @@
|
|||||||
D0E35A151DE4C6A200BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */,
|
D0E35A151DE4C6A200BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */,
|
||||||
D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */,
|
D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */,
|
||||||
D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
||||||
D0B8443F1DAB91EF005F29E1 /* UpdateGroup.swift in Sources */,
|
|
||||||
D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */,
|
D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */,
|
||||||
D0F7AB2D1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */,
|
D0F7AB2D1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */,
|
||||||
D0B844121DAB91CD005F29E1 /* Log.swift in Sources */,
|
D0B844121DAB91CD005F29E1 /* Log.swift in Sources */,
|
||||||
D03C53721DAD5CA9004C17B3 /* CachedUserData.swift in Sources */,
|
D03C53721DAD5CA9004C17B3 /* CachedUserData.swift in Sources */,
|
||||||
D073CE6B1DCBCF17007511FD /* ReplyMessageAttribute.swift in Sources */,
|
D073CE6B1DCBCF17007511FD /* ReplyMessageAttribute.swift in Sources */,
|
||||||
|
D001F3E91E128A1C007A8C60 /* SecretChatState.swift in Sources */,
|
||||||
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
||||||
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
||||||
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
||||||
@ -1137,14 +1156,15 @@
|
|||||||
D0B8440F1DAB91CD005F29E1 /* Either.swift in Sources */,
|
D0B8440F1DAB91CD005F29E1 /* Either.swift in Sources */,
|
||||||
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */,
|
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */,
|
||||||
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */,
|
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */,
|
||||||
|
D001F3EF1E128A1C007A8C60 /* AccountIntermediateState.swift in Sources */,
|
||||||
D03C536E1DAD5CA9004C17B3 /* PhoneNumber.swift in Sources */,
|
D03C536E1DAD5CA9004C17B3 /* PhoneNumber.swift in Sources */,
|
||||||
D0B844111DAB91CD005F29E1 /* Regex.swift in Sources */,
|
D0B844111DAB91CD005F29E1 /* Regex.swift in Sources */,
|
||||||
D0B8443C1DAB91EF005F29E1 /* SendUnsentMessage.swift in Sources */,
|
|
||||||
D0B844321DAB91E0005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */,
|
D0B844321DAB91E0005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */,
|
||||||
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */,
|
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */,
|
||||||
D03C53701DAD5CA9004C17B3 /* ExportedInvitation.swift in Sources */,
|
D03C53701DAD5CA9004C17B3 /* ExportedInvitation.swift in Sources */,
|
||||||
D0F7B1E31E045C7B007EB8A5 /* RichText.swift in Sources */,
|
D0F7B1E31E045C7B007EB8A5 /* RichText.swift in Sources */,
|
||||||
D0B418AA1D7E0597004562A4 /* Download.swift in Sources */,
|
D0B418AA1D7E0597004562A4 /* Download.swift in Sources */,
|
||||||
|
D001F3F41E128A1C007A8C60 /* UpdatesApiUtils.swift in Sources */,
|
||||||
D0B4188E1D7E0578004562A4 /* StoreMessage_Telegram.swift in Sources */,
|
D0B4188E1D7E0578004562A4 /* StoreMessage_Telegram.swift in Sources */,
|
||||||
D0B844461DAB91FD005F29E1 /* RecentPeers.swift in Sources */,
|
D0B844461DAB91FD005F29E1 /* RecentPeers.swift in Sources */,
|
||||||
D03C53681DAD5CA9004C17B3 /* PeerUtils.swift in Sources */,
|
D03C53681DAD5CA9004C17B3 /* PeerUtils.swift in Sources */,
|
||||||
@ -1155,25 +1175,25 @@
|
|||||||
D0B418BA1D7E05BB004562A4 /* NetworkLogging.m in Sources */,
|
D0B418BA1D7E05BB004562A4 /* NetworkLogging.m in Sources */,
|
||||||
D03C536B1DAD5CA9004C17B3 /* TelegramGroup.swift in Sources */,
|
D03C536B1DAD5CA9004C17B3 /* TelegramGroup.swift in Sources */,
|
||||||
D0B418941D7E0580004562A4 /* TelegramMediaAction.swift in Sources */,
|
D0B418941D7E0580004562A4 /* TelegramMediaAction.swift in Sources */,
|
||||||
D0B844411DAB91EF005F29E1 /* UpdatesApiUtils.swift in Sources */,
|
|
||||||
D0B844381DAB91EF005F29E1 /* ChannelState.swift in Sources */,
|
|
||||||
D0B8442C1DAB91E0005F29E1 /* NBMetadataCoreMapper.m in Sources */,
|
D0B8442C1DAB91E0005F29E1 /* NBMetadataCoreMapper.m in Sources */,
|
||||||
D0B8443A1DAB91EF005F29E1 /* EnqueueMessage.swift in Sources */,
|
D001F3ED1E128A1C007A8C60 /* SendUnsentMessage.swift in Sources */,
|
||||||
D073CE6A1DCBCF17007511FD /* ViewCountMessageAttribute.swift in Sources */,
|
D073CE6A1DCBCF17007511FD /* ViewCountMessageAttribute.swift in Sources */,
|
||||||
D0B418AB1D7E0597004562A4 /* MultipartFetch.swift in Sources */,
|
D0B418AB1D7E0597004562A4 /* MultipartFetch.swift in Sources */,
|
||||||
D0B418B71D7E05A6004562A4 /* Phonebook.swift in Sources */,
|
D0B418B71D7E05A6004562A4 /* Phonebook.swift in Sources */,
|
||||||
D03C53741DAD5CA9004C17B3 /* CachedChannelData.swift in Sources */,
|
D03C53741DAD5CA9004C17B3 /* CachedChannelData.swift in Sources */,
|
||||||
D073CEA31DCBF3E1007511FD /* PendingMessageUploadedContent.swift in Sources */,
|
|
||||||
D0B418861D7E056D004562A4 /* Namespaces.swift in Sources */,
|
D0B418861D7E056D004562A4 /* Namespaces.swift in Sources */,
|
||||||
D0F7B1E41E045C7B007EB8A5 /* InstantPage.swift in Sources */,
|
D0F7B1E41E045C7B007EB8A5 /* InstantPage.swift in Sources */,
|
||||||
D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */,
|
D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */,
|
||||||
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
|
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
|
||||||
D0B844101DAB91CD005F29E1 /* MergeLists.swift in Sources */,
|
D0B844101DAB91CD005F29E1 /* MergeLists.swift in Sources */,
|
||||||
|
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */,
|
||||||
D0F7B1E81E045C87007EB8A5 /* PeerParticipants.swift in Sources */,
|
D0F7B1E81E045C87007EB8A5 /* PeerParticipants.swift in Sources */,
|
||||||
D0B844331DAB91E0005F29E1 /* NBPhoneNumber.m in Sources */,
|
D0B844331DAB91E0005F29E1 /* NBPhoneNumber.m in Sources */,
|
||||||
|
D001F3F51E128A1C007A8C60 /* PendingMessageManager.swift in Sources */,
|
||||||
|
D001F3F61E128A1C007A8C60 /* PendingMessageUploadedContent.swift in Sources */,
|
||||||
D0F7B1E71E045C87007EB8A5 /* JoinChannel.swift in Sources */,
|
D0F7B1E71E045C87007EB8A5 /* JoinChannel.swift in Sources */,
|
||||||
D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */,
|
D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */,
|
||||||
D073CEA21DCBF3E1007511FD /* PendingMessageManager.swift in Sources */,
|
D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */,
|
||||||
D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */,
|
D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */,
|
||||||
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
||||||
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */,
|
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */,
|
||||||
|
@ -353,6 +353,13 @@ public enum AccountServiceTaskMasterMode {
|
|||||||
case never
|
case never
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum AccountNetworkState {
|
||||||
|
case waitingForNetwork
|
||||||
|
case connecting
|
||||||
|
case updating
|
||||||
|
case online
|
||||||
|
}
|
||||||
|
|
||||||
public class Account {
|
public class Account {
|
||||||
public let id: AccountId
|
public let id: AccountId
|
||||||
public let basePath: String
|
public let basePath: String
|
||||||
@ -360,7 +367,7 @@ public class Account {
|
|||||||
public let network: Network
|
public let network: Network
|
||||||
public let peerId: PeerId
|
public let peerId: PeerId
|
||||||
|
|
||||||
public private(set) var stateManager: StateManager!
|
public private(set) var stateManager: AccountStateManager!
|
||||||
public private(set) var viewTracker: AccountViewTracker!
|
public private(set) var viewTracker: AccountViewTracker!
|
||||||
public private(set) var pendingMessageManager: PendingMessageManager!
|
public private(set) var pendingMessageManager: PendingMessageManager!
|
||||||
fileprivate let managedContactsDisposable = MetaDisposable()
|
fileprivate let managedContactsDisposable = MetaDisposable()
|
||||||
@ -384,6 +391,11 @@ public class Account {
|
|||||||
public let shouldBeServiceTaskMaster = Promise<AccountServiceTaskMasterMode>()
|
public let shouldBeServiceTaskMaster = Promise<AccountServiceTaskMasterMode>()
|
||||||
public let shouldKeepOnlinePresence = Promise<Bool>()
|
public let shouldKeepOnlinePresence = Promise<Bool>()
|
||||||
|
|
||||||
|
private let networkStateValue = Promise<AccountNetworkState>(.connecting)
|
||||||
|
public var networkState: Signal<AccountNetworkState, NoError> {
|
||||||
|
return self.networkStateValue.get()
|
||||||
|
}
|
||||||
|
|
||||||
public init(id: AccountId, basePath: String, postbox: Postbox, network: Network, peerId: PeerId) {
|
public init(id: AccountId, basePath: String, postbox: Postbox, network: Network, peerId: PeerId) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.basePath = basePath
|
self.basePath = basePath
|
||||||
@ -391,10 +403,29 @@ public class Account {
|
|||||||
self.network = network
|
self.network = network
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
|
|
||||||
self.stateManager = StateManager(account: self)
|
self.stateManager = AccountStateManager(account: self)
|
||||||
self.viewTracker = AccountViewTracker(account: self)
|
self.viewTracker = AccountViewTracker(account: self)
|
||||||
self.pendingMessageManager = PendingMessageManager(network: network, postbox: postbox, stateManager: self.stateManager)
|
self.pendingMessageManager = PendingMessageManager(network: network, postbox: postbox, stateManager: self.stateManager)
|
||||||
|
|
||||||
|
let networkStateSignal = combineLatest(self.stateManager.isUpdating, network.connectionStatus)
|
||||||
|
|> map { isUpdating, connectionStatus -> AccountNetworkState in
|
||||||
|
switch connectionStatus {
|
||||||
|
case .WaitingForNetwork:
|
||||||
|
return .waitingForNetwork
|
||||||
|
case .Connecting:
|
||||||
|
return .connecting
|
||||||
|
case .Updating:
|
||||||
|
return .updating
|
||||||
|
case .Online:
|
||||||
|
if isUpdating {
|
||||||
|
return .updating
|
||||||
|
} else {
|
||||||
|
return .online
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.networkStateValue.set(networkStateSignal |> distinctUntilChanged)
|
||||||
|
|
||||||
let appliedNotificationToken = self.notificationToken.get()
|
let appliedNotificationToken = self.notificationToken.get()
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|> mapToSignal { token -> Signal<Void, NoError> in
|
|> mapToSignal { token -> Signal<Void, NoError> in
|
||||||
|
292
TelegramCore/AccountIntermediateState.swift
Normal file
292
TelegramCore/AccountIntermediateState.swift
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
final class AccountInitialState {
|
||||||
|
let state: AuthorizedAccountState.State
|
||||||
|
let peerIds: Set<PeerId>
|
||||||
|
let messageIds: Set<MessageId>
|
||||||
|
let channelStates: [PeerId: ChannelState]
|
||||||
|
let peerNotificationSettings: [PeerId: PeerNotificationSettings]
|
||||||
|
let peerIdsWithNewMessages: Set<PeerId>
|
||||||
|
let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]
|
||||||
|
|
||||||
|
init(state: AuthorizedAccountState.State, peerIds: Set<PeerId>, messageIds: Set<MessageId>, peerIdsWithNewMessages: Set<PeerId>, channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) {
|
||||||
|
self.state = state
|
||||||
|
self.peerIds = peerIds
|
||||||
|
self.messageIds = messageIds
|
||||||
|
self.channelStates = channelStates
|
||||||
|
self.peerIdsWithNewMessages = peerIdsWithNewMessages
|
||||||
|
self.peerNotificationSettings = peerNotificationSettings
|
||||||
|
self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AccountStateMutationOperation {
|
||||||
|
case AddMessages([StoreMessage], AddMessagesLocation)
|
||||||
|
case DeleteMessagesWithGlobalIds([Int32])
|
||||||
|
case DeleteMessages([MessageId])
|
||||||
|
case EditMessage(MessageId, StoreMessage)
|
||||||
|
case UpdateMedia(MediaId, Media?)
|
||||||
|
case ReadInbox(MessageId)
|
||||||
|
case ReadOutbox(MessageId)
|
||||||
|
case ResetReadState(PeerId, MessageId.Namespace, MessageId.Id, MessageId.Id, MessageId.Id, Int32)
|
||||||
|
case UpdateState(AuthorizedAccountState.State)
|
||||||
|
case UpdateChannelState(PeerId, ChannelState)
|
||||||
|
case UpdatePeerNotificationSettings(PeerId, PeerNotificationSettings)
|
||||||
|
case AddHole(MessageId)
|
||||||
|
case MergeApiChats([Api.Chat])
|
||||||
|
case UpdatePeer(PeerId, (Peer) -> Peer)
|
||||||
|
case MergeApiUsers([Api.User])
|
||||||
|
case MergePeerPresences([PeerId: PeerPresence])
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccountMutableState {
|
||||||
|
let initialState: AccountInitialState
|
||||||
|
let branchOperationIndex: Int
|
||||||
|
|
||||||
|
var operations: [AccountStateMutationOperation] = []
|
||||||
|
|
||||||
|
var state: AuthorizedAccountState.State
|
||||||
|
var peers: [PeerId: Peer]
|
||||||
|
var channelStates: [PeerId: ChannelState]
|
||||||
|
var peerNotificationSettings: [PeerId: PeerNotificationSettings]
|
||||||
|
var storedMessages: Set<MessageId>
|
||||||
|
var readInboxMaxIds: [PeerId: MessageId]
|
||||||
|
|
||||||
|
var storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]
|
||||||
|
|
||||||
|
var insertedPeers: [PeerId: Peer] = [:]
|
||||||
|
|
||||||
|
var preCachedResources: [(MediaResource, Data)] = []
|
||||||
|
|
||||||
|
init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialStoredMessages: Set<MessageId>, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
|
||||||
|
self.initialState = initialState
|
||||||
|
self.state = initialState.state
|
||||||
|
self.peers = initialPeers
|
||||||
|
self.storedMessages = initialStoredMessages
|
||||||
|
self.readInboxMaxIds = initialReadInboxMaxIds
|
||||||
|
self.channelStates = initialState.channelStates
|
||||||
|
self.peerNotificationSettings = initialState.peerNotificationSettings
|
||||||
|
self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp
|
||||||
|
self.branchOperationIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], branchOperationIndex: Int) {
|
||||||
|
self.initialState = initialState
|
||||||
|
self.operations = operations
|
||||||
|
self.state = state
|
||||||
|
self.peers = peers
|
||||||
|
self.channelStates = channelStates
|
||||||
|
self.storedMessages = storedMessages
|
||||||
|
self.peerNotificationSettings = peerNotificationSettings
|
||||||
|
self.readInboxMaxIds = readInboxMaxIds
|
||||||
|
self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp
|
||||||
|
self.branchOperationIndex = branchOperationIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
func branch() -> AccountMutableState {
|
||||||
|
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, branchOperationIndex: self.operations.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func merge(_ other: AccountMutableState) {
|
||||||
|
for i in other.branchOperationIndex ..< other.operations.count {
|
||||||
|
self.addOperation(other.operations[i])
|
||||||
|
}
|
||||||
|
for (_, peer) in other.insertedPeers {
|
||||||
|
self.peers[peer.id] = peer
|
||||||
|
}
|
||||||
|
self.preCachedResources.append(contentsOf: other.preCachedResources)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func addPreCachedResource(_ resource: MediaResource, data: Data) {
|
||||||
|
self.preCachedResources.append((resource, data))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func addMessages(_ messages: [StoreMessage], location: AddMessagesLocation) {
|
||||||
|
self.addOperation(.AddMessages(messages, location))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func deleteMessagesWithGlobalIds(_ globalIds: [Int32]) {
|
||||||
|
self.addOperation(.DeleteMessagesWithGlobalIds(globalIds))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func deleteMessages(_ messageIds: [MessageId]) {
|
||||||
|
self.addOperation(.DeleteMessages(messageIds))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func editMessage(_ id: MessageId, message: StoreMessage) {
|
||||||
|
self.addOperation(.EditMessage(id, message))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func updateMedia(_ id: MediaId, media: Media?) {
|
||||||
|
self.addOperation(.UpdateMedia(id, media))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func readInbox(_ messageId: MessageId) {
|
||||||
|
self.addOperation(.ReadInbox(messageId))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func readOutbox(_ messageId: MessageId) {
|
||||||
|
self.addOperation(.ReadOutbox(messageId))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func resetReadState(_ peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, maxOutgoingReadId: MessageId.Id, maxKnownId: MessageId.Id, count: Int32) {
|
||||||
|
self.addOperation(.ResetReadState(peerId, namespace, maxIncomingReadId, maxOutgoingReadId, maxKnownId, count))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func updateState(_ state: AuthorizedAccountState.State) {
|
||||||
|
self.addOperation(.UpdateState(state))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func updateChannelState(_ peerId: PeerId, state: ChannelState) {
|
||||||
|
self.addOperation(.UpdateChannelState(peerId, state))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func updatePeerNotificationSettings(_ peerId: PeerId, notificationSettings: PeerNotificationSettings) {
|
||||||
|
self.addOperation(.UpdatePeerNotificationSettings(peerId, notificationSettings))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func addHole(_ messageId: MessageId) {
|
||||||
|
self.addOperation(.AddHole(messageId))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func mergeChats(_ chats: [Api.Chat]) {
|
||||||
|
self.addOperation(.MergeApiChats(chats))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func updatePeer(_ id: PeerId, _ f: @escaping (Peer) -> Peer) {
|
||||||
|
self.addOperation(.UpdatePeer(id, f))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func mergeUsers(_ users: [Api.User]) {
|
||||||
|
self.addOperation(.MergeApiUsers(users))
|
||||||
|
|
||||||
|
var presences: [PeerId: PeerPresence] = [:]
|
||||||
|
for user in users {
|
||||||
|
switch user {
|
||||||
|
case let .user(_, id, _, _, _, _, _, _, status, _, _, _):
|
||||||
|
if let status = status {
|
||||||
|
presences[PeerId(namespace: Namespaces.Peer.CloudUser, id: id)] = TelegramUserPresence(apiStatus: status)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case .userEmpty:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !presences.isEmpty {
|
||||||
|
self.addOperation(.MergePeerPresences(presences))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func mergePeerPresences(_ presences: [PeerId: PeerPresence]) {
|
||||||
|
self.addOperation(.MergePeerPresences(presences))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
|
switch operation {
|
||||||
|
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences:
|
||||||
|
break
|
||||||
|
case let .AddMessages(messages, _):
|
||||||
|
for message in messages {
|
||||||
|
if case let .Id(id) = message.id {
|
||||||
|
self.storedMessages.insert(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case let .UpdateState(state):
|
||||||
|
self.state = state
|
||||||
|
case let .UpdateChannelState(peerId, channelState):
|
||||||
|
self.channelStates[peerId] = channelState
|
||||||
|
case let .UpdatePeerNotificationSettings(peerId, notificationSettings):
|
||||||
|
self.peerNotificationSettings[peerId] = notificationSettings
|
||||||
|
case let .MergeApiChats(chats):
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = mergeGroupOrChannel(lhs: peers[chat.peerId], rhs: chat) {
|
||||||
|
peers[groupOrChannel.id] = groupOrChannel
|
||||||
|
insertedPeers[groupOrChannel.id] = groupOrChannel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case let .MergeApiUsers(users):
|
||||||
|
for apiUser in users {
|
||||||
|
if let user = TelegramUser.merge(peers[apiUser.peerId] as? TelegramUser, rhs: apiUser) {
|
||||||
|
peers[user.id] = user
|
||||||
|
insertedPeers[user.id] = user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case let .UpdatePeer(id, f):
|
||||||
|
if let peer = self.peers[id] {
|
||||||
|
let updatedPeer = f(peer)
|
||||||
|
peers[id] = updatedPeer
|
||||||
|
insertedPeers[id] = updatedPeer
|
||||||
|
}
|
||||||
|
case let .ReadInbox(messageId):
|
||||||
|
let current = self.readInboxMaxIds[messageId.peerId]
|
||||||
|
if current == nil || current! < messageId {
|
||||||
|
self.readInboxMaxIds[messageId.peerId] = messageId
|
||||||
|
}
|
||||||
|
//namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, maxOutgoingReadId: MessageId.Id, maxKnownId: MessageId.Id, count: Int32
|
||||||
|
case let .ResetReadState(peerId, namespace, maxIncomingReadId, _, _, _):
|
||||||
|
let current = self.readInboxMaxIds[peerId]
|
||||||
|
if namespace == Namespaces.Message.Cloud {
|
||||||
|
if current == nil || current!.id < maxIncomingReadId {
|
||||||
|
self.readInboxMaxIds[peerId] = MessageId(peerId: peerId, namespace: namespace, id: maxIncomingReadId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.operations.append(operation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccountFinalState {
|
||||||
|
let state: AccountMutableState
|
||||||
|
let shouldPoll: Bool
|
||||||
|
let incomplete: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccountFinalStateEvents {
|
||||||
|
let addedIncomingMessageIds: [MessageId]
|
||||||
|
|
||||||
|
var isEmpty: Bool {
|
||||||
|
return self.addedIncomingMessageIds.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.addedIncomingMessageIds = []
|
||||||
|
}
|
||||||
|
|
||||||
|
init(addedIncomingMessageIds: [MessageId]) {
|
||||||
|
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
|
}
|
||||||
|
|
||||||
|
init(state: AccountMutableState) {
|
||||||
|
var addedIncomingMessageIds: [MessageId] = []
|
||||||
|
for operation in state.operations {
|
||||||
|
switch operation {
|
||||||
|
case let .AddMessages(messages, location):
|
||||||
|
if case .UpperHistoryBlock = location {
|
||||||
|
for message in messages {
|
||||||
|
if case let .Id(id) = message.id, message.flags.contains(.Incoming) {
|
||||||
|
addedIncomingMessageIds.append(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func union(with other: AccountFinalStateEvents) -> AccountFinalStateEvents {
|
||||||
|
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds)
|
||||||
|
}
|
||||||
|
}
|
@ -15,232 +15,6 @@ private enum Event<T, E> {
|
|||||||
case Completion
|
case Completion
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class InitialState {
|
|
||||||
let state: AuthorizedAccountState.State
|
|
||||||
let peerIds: Set<PeerId>
|
|
||||||
let messageIds: Set<MessageId>
|
|
||||||
let channelStates: [PeerId: ChannelState]
|
|
||||||
let peerNotificationSettings: [PeerId: PeerNotificationSettings]
|
|
||||||
let peerIdsWithNewMessages: Set<PeerId>
|
|
||||||
let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]
|
|
||||||
|
|
||||||
init(state: AuthorizedAccountState.State, peerIds: Set<PeerId>, messageIds: Set<MessageId>, peerIdsWithNewMessages: Set<PeerId>, channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) {
|
|
||||||
self.state = state
|
|
||||||
self.peerIds = peerIds
|
|
||||||
self.messageIds = messageIds
|
|
||||||
self.channelStates = channelStates
|
|
||||||
self.peerIdsWithNewMessages = peerIdsWithNewMessages
|
|
||||||
self.peerNotificationSettings = peerNotificationSettings
|
|
||||||
self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum MutationOperation {
|
|
||||||
case AddMessages([StoreMessage], AddMessagesLocation)
|
|
||||||
case DeleteMessagesWithGlobalIds([Int32])
|
|
||||||
case DeleteMessages([MessageId])
|
|
||||||
case EditMessage(MessageId, StoreMessage)
|
|
||||||
case UpdateMedia(MediaId, Media?)
|
|
||||||
case ReadInbox(MessageId)
|
|
||||||
case ReadOutbox(MessageId)
|
|
||||||
case ResetReadState(PeerId, MessageId.Namespace, MessageId.Id, MessageId.Id, MessageId.Id, Int32)
|
|
||||||
case UpdateState(AuthorizedAccountState.State)
|
|
||||||
case UpdateChannelState(PeerId, ChannelState)
|
|
||||||
case UpdatePeerNotificationSettings(PeerId, PeerNotificationSettings)
|
|
||||||
case AddHole(MessageId)
|
|
||||||
case MergeApiChats([Api.Chat])
|
|
||||||
case UpdatePeer(PeerId, (Peer) -> Peer)
|
|
||||||
case MergeApiUsers([Api.User])
|
|
||||||
case MergePeerPresences([PeerId: PeerPresence])
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct MutableState {
|
|
||||||
let initialState: InitialState
|
|
||||||
let branchOperationIndex: Int
|
|
||||||
|
|
||||||
fileprivate var operations: [MutationOperation] = []
|
|
||||||
|
|
||||||
fileprivate var state: AuthorizedAccountState.State
|
|
||||||
fileprivate var peers: [PeerId: Peer]
|
|
||||||
fileprivate var channelStates: [PeerId: ChannelState]
|
|
||||||
fileprivate var peerNotificationSettings: [PeerId: PeerNotificationSettings]
|
|
||||||
fileprivate var storedMessages: Set<MessageId>
|
|
||||||
|
|
||||||
fileprivate var storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]
|
|
||||||
|
|
||||||
fileprivate var insertedPeers: [PeerId: Peer] = [:]
|
|
||||||
|
|
||||||
fileprivate var preCachedResources: [(MediaResource, Data)] = []
|
|
||||||
|
|
||||||
init(initialState: InitialState, initialPeers: [PeerId: Peer], initialStoredMessages: Set<MessageId>, storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
|
|
||||||
self.initialState = initialState
|
|
||||||
self.state = initialState.state
|
|
||||||
self.peers = initialPeers
|
|
||||||
self.storedMessages = initialStoredMessages
|
|
||||||
self.channelStates = initialState.channelStates
|
|
||||||
self.peerNotificationSettings = initialState.peerNotificationSettings
|
|
||||||
self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp
|
|
||||||
self.branchOperationIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
init(initialState: InitialState, operations: [MutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set<MessageId>, storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], branchOperationIndex: Int) {
|
|
||||||
self.initialState = initialState
|
|
||||||
self.operations = operations
|
|
||||||
self.state = state
|
|
||||||
self.peers = peers
|
|
||||||
self.channelStates = channelStates
|
|
||||||
self.storedMessages = storedMessages
|
|
||||||
self.peerNotificationSettings = peerNotificationSettings
|
|
||||||
self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp
|
|
||||||
self.branchOperationIndex = branchOperationIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func branch() -> MutableState {
|
|
||||||
return MutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, branchOperationIndex: self.operations.count)
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func merge(_ other: MutableState) {
|
|
||||||
for i in other.branchOperationIndex ..< other.operations.count {
|
|
||||||
self.addOperation(other.operations[i])
|
|
||||||
}
|
|
||||||
for (_, peer) in other.insertedPeers {
|
|
||||||
self.peers[peer.id] = peer
|
|
||||||
}
|
|
||||||
self.preCachedResources.append(contentsOf: other.preCachedResources)
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func addPreCachedResource(_ resource: MediaResource, data: Data) {
|
|
||||||
self.preCachedResources.append((resource, data))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func addMessages(_ messages: [StoreMessage], location: AddMessagesLocation) {
|
|
||||||
self.addOperation(.AddMessages(messages, location))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func deleteMessagesWithGlobalIds(_ globalIds: [Int32]) {
|
|
||||||
self.addOperation(.DeleteMessagesWithGlobalIds(globalIds))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func deleteMessages(_ messageIds: [MessageId]) {
|
|
||||||
self.addOperation(.DeleteMessages(messageIds))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func editMessage(_ id: MessageId, message: StoreMessage) {
|
|
||||||
self.addOperation(.EditMessage(id, message))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func updateMedia(_ id: MediaId, media: Media?) {
|
|
||||||
self.addOperation(.UpdateMedia(id, media))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func readInbox(_ messageId: MessageId) {
|
|
||||||
self.addOperation(.ReadInbox(messageId))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func readOutbox(_ messageId: MessageId) {
|
|
||||||
self.addOperation(.ReadOutbox(messageId))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func resetReadState(_ peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, maxOutgoingReadId: MessageId.Id, maxKnownId: MessageId.Id, count: Int32) {
|
|
||||||
self.addOperation(.ResetReadState(peerId, namespace, maxIncomingReadId, maxOutgoingReadId, maxKnownId, count))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func updateState(_ state: AuthorizedAccountState.State) {
|
|
||||||
self.addOperation(.UpdateState(state))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func updateChannelState(_ peerId: PeerId, state: ChannelState) {
|
|
||||||
self.addOperation(.UpdateChannelState(peerId, state))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func updatePeerNotificationSettings(_ peerId: PeerId, notificationSettings: PeerNotificationSettings) {
|
|
||||||
self.addOperation(.UpdatePeerNotificationSettings(peerId, notificationSettings))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func addHole(_ messageId: MessageId) {
|
|
||||||
self.addOperation(.AddHole(messageId))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func mergeChats(_ chats: [Api.Chat]) {
|
|
||||||
self.addOperation(.MergeApiChats(chats))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func updatePeer(_ id: PeerId, _ f: @escaping (Peer) -> Peer) {
|
|
||||||
self.addOperation(.UpdatePeer(id, f))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func mergeUsers(_ users: [Api.User]) {
|
|
||||||
self.addOperation(.MergeApiUsers(users))
|
|
||||||
|
|
||||||
var presences: [PeerId: PeerPresence] = [:]
|
|
||||||
for user in users {
|
|
||||||
switch user {
|
|
||||||
case let .user(_, id, _, _, _, _, _, _, status, _, _, _):
|
|
||||||
if let status = status {
|
|
||||||
presences[PeerId(namespace: Namespaces.Peer.CloudUser, id: id)] = TelegramUserPresence(apiStatus: status)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case .userEmpty:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !presences.isEmpty {
|
|
||||||
self.addOperation(.MergePeerPresences(presences))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func mergePeerPresences(_ presences: [PeerId: PeerPresence]) {
|
|
||||||
self.addOperation(.MergePeerPresences(presences))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func addOperation(_ operation: MutationOperation) {
|
|
||||||
switch operation {
|
|
||||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadInbox, .ReadOutbox, .ResetReadState, .MergePeerPresences:
|
|
||||||
break
|
|
||||||
case let .AddMessages(messages, _):
|
|
||||||
for message in messages {
|
|
||||||
if case let .Id(id) = message.id {
|
|
||||||
self.storedMessages.insert(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .UpdateState(state):
|
|
||||||
self.state = state
|
|
||||||
case let .UpdateChannelState(peerId, channelState):
|
|
||||||
self.channelStates[peerId] = channelState
|
|
||||||
case let .UpdatePeerNotificationSettings(peerId, notificationSettings):
|
|
||||||
self.peerNotificationSettings[peerId] = notificationSettings
|
|
||||||
case let .MergeApiChats(chats):
|
|
||||||
for chat in chats {
|
|
||||||
if let groupOrChannel = mergeGroupOrChannel(lhs: peers[chat.peerId], rhs: chat) {
|
|
||||||
peers[groupOrChannel.id] = groupOrChannel
|
|
||||||
insertedPeers[groupOrChannel.id] = groupOrChannel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .MergeApiUsers(users):
|
|
||||||
for apiUser in users {
|
|
||||||
if let user = TelegramUser.merge(peers[apiUser.peerId] as? TelegramUser, rhs: apiUser) {
|
|
||||||
peers[user.id] = user
|
|
||||||
insertedPeers[user.id] = user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case let .UpdatePeer(id, f):
|
|
||||||
if let peer = self.peers[id] {
|
|
||||||
let updatedPeer = f(peer)
|
|
||||||
peers[id] = updatedPeer
|
|
||||||
insertedPeers[id] = updatedPeer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.operations.append(operation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct FinalState {
|
|
||||||
let state: MutableState
|
|
||||||
let shouldPoll: Bool
|
|
||||||
let incomplete: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
private func peerIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<PeerId> {
|
private func peerIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<PeerId> {
|
||||||
var peerIds = Set<PeerId>()
|
var peerIds = Set<PeerId>()
|
||||||
|
|
||||||
@ -279,6 +53,13 @@ private func peersWithNewMessagesFromUpdateGroups(_ groups: [UpdateGroup]) -> Se
|
|||||||
if let messageId = update.messageId {
|
if let messageId = update.messageId {
|
||||||
peerIds.insert(messageId.peerId)
|
peerIds.insert(messageId.peerId)
|
||||||
}
|
}
|
||||||
|
switch update {
|
||||||
|
case let .updateChannelTooLong(_, channelId, _):
|
||||||
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
peerIds.insert(peerId)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +184,13 @@ private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Differ
|
|||||||
if let messageId = update.messageId {
|
if let messageId = update.messageId {
|
||||||
peerIds.insert(messageId.peerId)
|
peerIds.insert(messageId.peerId)
|
||||||
}
|
}
|
||||||
|
switch update {
|
||||||
|
case let .updateChannelTooLong(_, channelId, _):
|
||||||
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
peerIds.insert(peerId)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .differenceEmpty:
|
case .differenceEmpty:
|
||||||
break
|
break
|
||||||
@ -417,6 +205,13 @@ private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Differ
|
|||||||
if let messageId = update.messageId {
|
if let messageId = update.messageId {
|
||||||
peerIds.insert(messageId.peerId)
|
peerIds.insert(messageId.peerId)
|
||||||
}
|
}
|
||||||
|
switch update {
|
||||||
|
case let .updateChannelTooLong(_, channelId, _):
|
||||||
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
peerIds.insert(peerId)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .differenceTooLong:
|
case .differenceTooLong:
|
||||||
break
|
break
|
||||||
@ -461,7 +256,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
|
|||||||
return messageTimestamps
|
return messageTimestamps
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set<PeerId>, associatedMessageIds: Set<MessageId>, peerIdsWithNewMessages: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> MutableState {
|
private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set<PeerId>, associatedMessageIds: Set<MessageId>, peerIdsWithNewMessages: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
var channelStates: [PeerId: ChannelState] = [:]
|
var channelStates: [PeerId: ChannelState] = [:]
|
||||||
|
|
||||||
@ -494,17 +289,27 @@ private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set<PeerId>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var peerNotificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
var peerNotificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||||
|
var readInboxMaxIds: [PeerId: MessageId] = [:]
|
||||||
|
|
||||||
for peerId in peerIdsWithNewMessages {
|
for peerId in peerIdsWithNewMessages {
|
||||||
if let notificationSettings = modifier.getPeerNotificationSettings(peerId) {
|
if let notificationSettings = modifier.getPeerNotificationSettings(peerId) {
|
||||||
peerNotificationSettings[peerId] = notificationSettings
|
peerNotificationSettings[peerId] = notificationSettings
|
||||||
}
|
}
|
||||||
|
if let readStates = modifier.getPeerReadStates(peerId) {
|
||||||
|
for (namespace, state) in readStates {
|
||||||
|
if namespace == Namespaces.Message.Cloud {
|
||||||
|
readInboxMaxIds[peerId] = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: state.maxIncomingReadId)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MutableState(initialState: InitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, channelStates: channelStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps), initialPeers: peers, initialStoredMessages: storedMessages, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
return AccountMutableState(initialState: AccountInitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, channelStates: channelStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps), initialPeers: peers, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGroup]) -> Signal<MutableState, NoError> {
|
func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGroup]) -> Signal<AccountMutableState, NoError> {
|
||||||
return account.postbox.modify { modifier -> MutableState in
|
return account.postbox.modify { modifier -> AccountMutableState in
|
||||||
let peerIds = peerIdsFromUpdateGroups(groups)
|
let peerIds = peerIdsFromUpdateGroups(groups)
|
||||||
let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups)
|
let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups)
|
||||||
let peerIdsWithNewMessages = peersWithNewMessagesFromUpdateGroups(groups)
|
let peerIdsWithNewMessages = peersWithNewMessagesFromUpdateGroups(groups)
|
||||||
@ -513,8 +318,8 @@ private func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initialStateWithDifference(_ account: Account, difference: Api.updates.Difference) -> Signal<MutableState, NoError> {
|
func initialStateWithDifference(_ account: Account, difference: Api.updates.Difference) -> Signal<AccountMutableState, NoError> {
|
||||||
return account.postbox.modify { modifier -> MutableState in
|
return account.postbox.modify { modifier -> AccountMutableState in
|
||||||
let peerIds = peerIdsFromDifference(difference)
|
let peerIds = peerIdsFromDifference(difference)
|
||||||
let associatedMessageIds = associatedMessageIdsFromDifference(difference)
|
let associatedMessageIds = associatedMessageIdsFromDifference(difference)
|
||||||
let peerIdsWithNewMessages = peersWithNewMessagesFromDifference(difference)
|
let peerIdsWithNewMessages = peersWithNewMessagesFromDifference(difference)
|
||||||
@ -522,7 +327,7 @@ private func initialStateWithDifference(_ account: Account, difference: Api.upda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func finalStateWithUpdateGroups(_ account: Account, state: MutableState, groups: [UpdateGroup]) -> Signal<FinalState, NoError> {
|
func finalStateWithUpdateGroups(_ account: Account, state: AccountMutableState, groups: [UpdateGroup]) -> Signal<AccountFinalState, NoError> {
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
|
|
||||||
var hadReset = false
|
var hadReset = false
|
||||||
@ -640,7 +445,7 @@ private func finalStateWithUpdateGroups(_ account: Account, state: MutableState,
|
|||||||
return finalStateWithUpdates(account: account, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty)
|
return finalStateWithUpdates(account: account, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func finalStateWithDifference(account: Account, state: MutableState, difference: Api.updates.Difference) -> Signal<FinalState, NoError> {
|
func finalStateWithDifference(account: Account, state: AccountMutableState, difference: Api.updates.Difference) -> Signal<AccountFinalState, NoError> {
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
|
|
||||||
var messages: [Api.Message] = []
|
var messages: [Api.Message] = []
|
||||||
@ -764,7 +569,7 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private func finalStateWithUpdates(account: Account, state: MutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool) -> Signal<FinalState, NoError> {
|
private func finalStateWithUpdates(account: Account, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool) -> Signal<AccountFinalState, NoError> {
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
|
|
||||||
var channelsToPoll = Set<PeerId>()
|
var channelsToPoll = Set<PeerId>()
|
||||||
@ -979,7 +784,7 @@ private func finalStateWithUpdates(account: Account, state: MutableState, update
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pollChannelSignals: [Signal<MutableState, NoError>] = []
|
var pollChannelSignals: [Signal<AccountMutableState, NoError>] = []
|
||||||
for peerId in channelsToPoll {
|
for peerId in channelsToPoll {
|
||||||
if let peer = updatedState.peers[peerId] {
|
if let peer = updatedState.peers[peerId] {
|
||||||
pollChannelSignals.append(pollChannel(account, peer: peer, state: updatedState.branch()))
|
pollChannelSignals.append(pollChannel(account, peer: peer, state: updatedState.branch()))
|
||||||
@ -988,16 +793,16 @@ private func finalStateWithUpdates(account: Account, state: MutableState, update
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return combineLatest(pollChannelSignals) |> mapToSignal { states -> Signal<FinalState, NoError> in
|
return combineLatest(pollChannelSignals) |> mapToSignal { states -> Signal<AccountFinalState, NoError> in
|
||||||
var finalState = updatedState
|
var finalState = updatedState
|
||||||
for state in states {
|
for state in states {
|
||||||
finalState.merge(state)
|
finalState.merge(state)
|
||||||
}
|
}
|
||||||
return resolveAssociatedMessages(account: account, state: finalState)
|
return resolveAssociatedMessages(account: account, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<FinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
return resolveMissingPeerNotificationSettings(account: account, state: resultingState)
|
return resolveMissingPeerNotificationSettings(account: account, state: resultingState)
|
||||||
|> map { resultingState -> FinalState in
|
|> map { resultingState -> AccountFinalState in
|
||||||
return FinalState(state: resultingState, shouldPoll: shouldPoll || missingUpdates, incomplete: missingUpdates)
|
return AccountFinalState(state: resultingState, shouldPoll: shouldPoll, incomplete: missingUpdates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1018,7 +823,7 @@ private func messagesIdsGroupedByPeerId(_ ids: Set<MessageId>) -> [PeerId: [Mess
|
|||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|
||||||
private func resolveAssociatedMessages(account: Account, state: MutableState) -> Signal<MutableState, NoError> {
|
private func resolveAssociatedMessages(account: Account, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
let missingMessageIds = state.initialState.messageIds.subtracting(state.storedMessages)
|
let missingMessageIds = state.initialState.messageIds.subtracting(state.storedMessages)
|
||||||
if missingMessageIds.isEmpty {
|
if missingMessageIds.isEmpty {
|
||||||
return .single(state)
|
return .single(state)
|
||||||
@ -1084,7 +889,7 @@ private func resolveAssociatedMessages(account: Account, state: MutableState) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func resolveMissingPeerNotificationSettings(account: Account, state: MutableState) -> Signal<MutableState, NoError> {
|
private func resolveMissingPeerNotificationSettings(account: Account, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
var missingPeers: [PeerId: Api.InputPeer] = [:]
|
var missingPeers: [PeerId: Api.InputPeer] = [:]
|
||||||
|
|
||||||
for peerId in state.initialState.peerIdsWithNewMessages {
|
for peerId in state.initialState.peerIdsWithNewMessages {
|
||||||
@ -1113,7 +918,7 @@ private func resolveMissingPeerNotificationSettings(account: Account, state: Mut
|
|||||||
signals.append(fetchSettings)
|
signals.append(fetchSettings)
|
||||||
}
|
}
|
||||||
return combineLatest(signals)
|
return combineLatest(signals)
|
||||||
|> map { peersAndSettings -> MutableState in
|
|> map { peersAndSettings -> AccountMutableState in
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
for pair in peersAndSettings {
|
for pair in peersAndSettings {
|
||||||
if let (peerId, settings) = pair {
|
if let (peerId, settings) = pair {
|
||||||
@ -1127,11 +932,11 @@ private func resolveMissingPeerNotificationSettings(account: Account, state: Mut
|
|||||||
return .single(state)
|
return .single(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pollChannel(_ account: Account, peer: Peer, state: MutableState) -> Signal<MutableState, NoError> {
|
private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
if let inputChannel = apiInputChannel(peer) {
|
if let inputChannel = apiInputChannel(peer) {
|
||||||
return account.network.request(Api.functions.updates.getChannelDifference(flags: 0, channel: inputChannel, filter: .channelMessagesFilterEmpty, pts: state.channelStates[peer.id]?.pts ?? 1, limit: 20))
|
return account.network.request(Api.functions.updates.getChannelDifference(flags: 0, channel: inputChannel, filter: .channelMessagesFilterEmpty, pts: state.channelStates[peer.id]?.pts ?? 1, limit: 20))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> map { difference -> MutableState in
|
|> map { difference -> AccountMutableState in
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
switch difference {
|
switch difference {
|
||||||
case let .channelDifference(_, pts, _, newMessages, otherUpdates, chats, users):
|
case let .channelDifference(_, pts, _, newMessages, otherUpdates, chats, users):
|
||||||
@ -1215,7 +1020,7 @@ private func pollChannel(_ account: Account, peer: Peer, state: MutableState) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func verifyTransaction(_ modifier: Modifier, finalState: MutableState) -> Bool {
|
private func verifyTransaction(_ modifier: Modifier, finalState: AccountMutableState) -> Bool {
|
||||||
var hadUpdateState = false
|
var hadUpdateState = false
|
||||||
var channelsWithUpdatedStates = Set<PeerId>()
|
var channelsWithUpdatedStates = Set<PeerId>()
|
||||||
|
|
||||||
@ -1300,8 +1105,8 @@ private final class OptimizeAddMessagesState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func optimizedOperations(_ operations: [MutationOperation]) -> [MutationOperation] {
|
private func optimizedOperations(_ operations: [AccountStateMutationOperation]) -> [AccountStateMutationOperation] {
|
||||||
var result: [MutationOperation] = []
|
var result: [AccountStateMutationOperation] = []
|
||||||
|
|
||||||
var updatedState: AuthorizedAccountState.State?
|
var updatedState: AuthorizedAccountState.State?
|
||||||
var updatedChannelStates: [PeerId: ChannelState] = [:]
|
var updatedChannelStates: [PeerId: ChannelState] = [:]
|
||||||
@ -1345,7 +1150,7 @@ private func optimizedOperations(_ operations: [MutationOperation]) -> [Mutation
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private func replayFinalState(_ modifier: Modifier, finalState: MutableState) -> Bool {
|
func replayFinalState(_ modifier: Modifier, finalState: AccountMutableState) -> Bool {
|
||||||
let verified = verifyTransaction(modifier, finalState: finalState)
|
let verified = verifyTransaction(modifier, finalState: finalState)
|
||||||
if !verified {
|
if !verified {
|
||||||
return false
|
return false
|
||||||
@ -1476,28 +1281,14 @@ private func pollDifference(_ account: Account) -> Signal<Void, NoError> {
|
|||||||
return signal
|
return signal
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
|
||||||
|
|
||||||
|
/*#if os(macOS)
|
||||||
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
||||||
#else
|
#else
|
||||||
private typealias SignalKitTimer = SwiftSignalKit.Timer
|
private typealias SignalKitTimer = SwiftSignalKit.Timer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private enum StateManagerState {
|
|
||||||
case none
|
|
||||||
case pollingDifference
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class StateManagerInternal {
|
|
||||||
private let queue = Queue()
|
|
||||||
private let account: Account
|
|
||||||
|
|
||||||
init(account: Account) {
|
|
||||||
self.account = account
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class StateManager {
|
public final class StateManager {
|
||||||
private let stateQueue = Queue()
|
private let stateQueue = Queue()
|
||||||
|
|
||||||
@ -1674,4 +1465,4 @@ public final class StateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
393
TelegramCore/AccountStateManager.swift
Normal file
393
TelegramCore/AccountStateManager.swift
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private enum AccountStateManagerOperation {
|
||||||
|
case pollDifference(AccountFinalStateEvents)
|
||||||
|
case collectUpdateGroups([UpdateGroup], Double)
|
||||||
|
case processUpdateGroups([UpdateGroup])
|
||||||
|
case custom(Signal<Void, NoError>)
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
||||||
|
#else
|
||||||
|
private typealias SignalKitTimer = SwiftSignalKit.Timer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private enum CustomOperationEvent<T, E> {
|
||||||
|
case Next(T)
|
||||||
|
case Error(E)
|
||||||
|
case Completion
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AccountStateManager {
|
||||||
|
private let queue = Queue()
|
||||||
|
private let account: Account
|
||||||
|
|
||||||
|
private var updateService: UpdateMessageService?
|
||||||
|
private let updateServiceDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
private var operations: [AccountStateManagerOperation] = []
|
||||||
|
private let operationDisposable = MetaDisposable()
|
||||||
|
private var operationTimer: SignalKitTimer?
|
||||||
|
|
||||||
|
private let isUpdatingValue = ValuePromise<Bool>(false)
|
||||||
|
private var currentIsUpdatingValue = false {
|
||||||
|
didSet {
|
||||||
|
if self.currentIsUpdatingValue != oldValue {
|
||||||
|
self.isUpdatingValue.set(self.currentIsUpdatingValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var isUpdating: Signal<Bool, NoError> {
|
||||||
|
return self.isUpdatingValue.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
private let notificationMessagesPipe = ValuePipe<[Message]>()
|
||||||
|
public var notificationMessages: Signal<[Message], NoError> {
|
||||||
|
return self.notificationMessagesPipe.signal()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(account: Account) {
|
||||||
|
self.account = account
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.updateServiceDisposable.dispose()
|
||||||
|
self.operationDisposable.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func reset() {
|
||||||
|
self.queue.async {
|
||||||
|
if self.updateService == nil {
|
||||||
|
self.updateService = UpdateMessageService(peerId: self.account.peerId)
|
||||||
|
self.updateServiceDisposable.set(self.updateService!.pipe.signal().start(next: { [weak self] groups in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.addUpdateGroups(groups)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
self.account.network.mtProto.add(self.updateService)
|
||||||
|
}
|
||||||
|
self.operationDisposable.set(nil)
|
||||||
|
self.operations.removeAll()
|
||||||
|
self.addOperation(.pollDifference(AccountFinalStateEvents()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addUpdates(_ updates: Api.Updates) {
|
||||||
|
self.queue.async {
|
||||||
|
self.updateService?.addUpdates(updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addUpdateGroups(_ groups: [UpdateGroup]) {
|
||||||
|
self.queue.async {
|
||||||
|
if let last = self.operations.last {
|
||||||
|
switch last {
|
||||||
|
case .pollDifference, .processUpdateGroups, .custom:
|
||||||
|
self.operations.append(.collectUpdateGroups(groups, 0.0))
|
||||||
|
case let .collectUpdateGroups(currentGroups, timestamp):
|
||||||
|
if timestamp.isEqual(to: 0.0) {
|
||||||
|
self.operations[self.operations.count - 1] = .collectUpdateGroups(currentGroups + groups, timestamp)
|
||||||
|
} else {
|
||||||
|
self.operations[self.operations.count - 1] = .processUpdateGroups(currentGroups + groups)
|
||||||
|
self.startFirstOperation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.operations.append(.collectUpdateGroups(groups, 0.0))
|
||||||
|
self.startFirstOperation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addCustomOperation<T, E>(_ f: Signal<T, E>) -> Signal<T, E> {
|
||||||
|
let pipe = ValuePipe<CustomOperationEvent<T, E>>()
|
||||||
|
return Signal<T, E> { subscriber in
|
||||||
|
let disposable = pipe.signal().start(next: { event in
|
||||||
|
switch event {
|
||||||
|
case let .Next(next):
|
||||||
|
subscriber.putNext(next)
|
||||||
|
case let .Error(error):
|
||||||
|
subscriber.putError(error)
|
||||||
|
case .Completion:
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let signal = Signal<Void, NoError> { subscriber in
|
||||||
|
return f.start(next: { next in
|
||||||
|
pipe.putNext(.Next(next))
|
||||||
|
}, error: { error in
|
||||||
|
pipe.putNext(.Error(error))
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}, completed: {
|
||||||
|
pipe.putNext(.Completion)
|
||||||
|
subscriber.putCompletion()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addOperation(.custom(signal))
|
||||||
|
|
||||||
|
return disposable
|
||||||
|
} |> runOn(self.queue)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addOperation(_ operation: AccountStateManagerOperation) {
|
||||||
|
self.queue.async {
|
||||||
|
let begin = self.operations.isEmpty
|
||||||
|
self.operations.append(operation)
|
||||||
|
if begin {
|
||||||
|
self.startFirstOperation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startFirstOperation() {
|
||||||
|
guard let operation = self.operations.first else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch operation {
|
||||||
|
case let .pollDifference(currentEvents):
|
||||||
|
self.currentIsUpdatingValue = true
|
||||||
|
let account = self.account
|
||||||
|
let queue = self.queue
|
||||||
|
let signal = account.postbox.state()
|
||||||
|
|> filter { state in
|
||||||
|
if let _ = state as? AuthorizedAccountState {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> take(1)
|
||||||
|
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountFinalState?), NoError> in
|
||||||
|
if let authorizedState = (state as! AuthorizedAccountState).state {
|
||||||
|
let request = account.network.request(Api.functions.updates.getDifference(flags: 0, pts: authorizedState.pts, ptsTotalLimit: nil, date: authorizedState.date, qts: authorizedState.qts))
|
||||||
|
|> retryRequest
|
||||||
|
return request |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountFinalState?), NoError> in
|
||||||
|
return initialStateWithDifference(account, difference: difference)
|
||||||
|
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountFinalState?), NoError> in
|
||||||
|
if state.initialState.state != authorizedState {
|
||||||
|
trace("State", what: "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)")
|
||||||
|
return .single((nil, nil))
|
||||||
|
} else {
|
||||||
|
return finalStateWithDifference(account: account, state: state, difference: difference)
|
||||||
|
|> mapToSignal { finalState -> Signal<(Api.updates.Difference?, AccountFinalState?), NoError> in
|
||||||
|
if !finalState.state.preCachedResources.isEmpty {
|
||||||
|
for (resource, data) in finalState.state.preCachedResources {
|
||||||
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return account.postbox.modify { modifier -> (Api.updates.Difference?, AccountFinalState?) in
|
||||||
|
if replayFinalState(modifier, finalState: finalState.state) {
|
||||||
|
return (difference, finalState)
|
||||||
|
} else {
|
||||||
|
return (nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let appliedState = account.network.request(Api.functions.updates.getState())
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { state in
|
||||||
|
return account.postbox.modify { modifier -> (Api.updates.Difference?, AccountFinalState?) in
|
||||||
|
if let currentState = modifier.getState() as? AuthorizedAccountState {
|
||||||
|
switch state {
|
||||||
|
case let .state(pts, qts, date, seq, _):
|
||||||
|
modifier.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: qts, date: date, seq: seq)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appliedState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signal.start(next: { [weak self] difference, finalState in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if case let .pollDifference = strongSelf.operations.removeFirst() {
|
||||||
|
let events: AccountFinalStateEvents
|
||||||
|
if let finalState = finalState {
|
||||||
|
events = currentEvents.union(with: AccountFinalStateEvents(state: finalState.state))
|
||||||
|
} else {
|
||||||
|
events = currentEvents
|
||||||
|
}
|
||||||
|
if let difference = difference {
|
||||||
|
switch difference {
|
||||||
|
case .differenceSlice:
|
||||||
|
strongSelf.operations.insert(.pollDifference(events), at: 0)
|
||||||
|
default:
|
||||||
|
if !events.isEmpty {
|
||||||
|
strongSelf.addEvents(events)
|
||||||
|
}
|
||||||
|
strongSelf.currentIsUpdatingValue = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !events.isEmpty {
|
||||||
|
strongSelf.addEvents(events)
|
||||||
|
}
|
||||||
|
strongSelf.operations.removeAll()
|
||||||
|
strongSelf.operations.append(.pollDifference(AccountFinalStateEvents()))
|
||||||
|
}
|
||||||
|
strongSelf.startFirstOperation()
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, error: { _ in
|
||||||
|
assertionFailure()
|
||||||
|
trace("AccountStateManager", what: "processUpdateGroups signal completed with error")
|
||||||
|
})
|
||||||
|
case let .collectUpdateGroups(groups, timeout):
|
||||||
|
self.operationTimer?.invalidate()
|
||||||
|
let operationTimer = SignalKitTimer(timeout: timeout, repeat: false, completion: { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if case let .collectUpdateGroups(groups, _) = strongSelf.operations[0] {
|
||||||
|
if timeout.isEqual(to: 0.0) {
|
||||||
|
strongSelf.operations[0] = .processUpdateGroups(groups)
|
||||||
|
} else {
|
||||||
|
trace("AccountStateManager", what: "timeout while waiting for updates")
|
||||||
|
strongSelf.operations.removeAll()
|
||||||
|
strongSelf.operations.append(.pollDifference(AccountFinalStateEvents()))
|
||||||
|
}
|
||||||
|
strongSelf.startFirstOperation()
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, queue: self.queue)
|
||||||
|
self.operationTimer = operationTimer
|
||||||
|
operationTimer.start()
|
||||||
|
case let .processUpdateGroups(groups):
|
||||||
|
let account = self.account
|
||||||
|
let queue = self.queue
|
||||||
|
let signal = initialStateWithUpdateGroups(account, groups: groups)
|
||||||
|
|> mapToSignal { [weak self] state -> Signal<(Bool, AccountFinalState), NoError> in
|
||||||
|
return finalStateWithUpdateGroups(account, state: state, groups: groups)
|
||||||
|
|> mapToSignal { finalState in
|
||||||
|
if !finalState.state.preCachedResources.isEmpty {
|
||||||
|
for (resource, data) in finalState.state.preCachedResources {
|
||||||
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.postbox.modify { modifier -> Bool in
|
||||||
|
return replayFinalState(modifier, finalState: finalState.state)
|
||||||
|
}
|
||||||
|
|> map({ ($0, finalState) })
|
||||||
|
|> deliverOn(queue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signal.start(next: { [weak self] result, finalState in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if case let .processUpdateGroups(groups) = strongSelf.operations.removeFirst() {
|
||||||
|
if result && !finalState.shouldPoll {
|
||||||
|
let events = AccountFinalStateEvents(state: finalState.state)
|
||||||
|
if !events.isEmpty {
|
||||||
|
strongSelf.addEvents(events)
|
||||||
|
}
|
||||||
|
if finalState.incomplete {
|
||||||
|
strongSelf.operations.insert(.collectUpdateGroups(groups, 2.0), at: 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.operations.removeAll()
|
||||||
|
strongSelf.operations.append(.pollDifference(AccountFinalStateEvents()))
|
||||||
|
}
|
||||||
|
strongSelf.startFirstOperation()
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, error: { _ in
|
||||||
|
assertionFailure()
|
||||||
|
trace("AccountStateManager", what: "processUpdateGroups signal completed with error")
|
||||||
|
})
|
||||||
|
case let .custom(signal):
|
||||||
|
let completed: () -> Void = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if case .custom = strongSelf.operations.removeFirst() {
|
||||||
|
strongSelf.startFirstOperation()
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signal.start(error: { _ in
|
||||||
|
completed()
|
||||||
|
}, completed: {
|
||||||
|
completed()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addEvents(_ events: AccountFinalStateEvents) {
|
||||||
|
if !events.addedIncomingMessageIds.isEmpty {
|
||||||
|
(self.account.postbox.modify { modifier -> [Message] in
|
||||||
|
let timestamp = Int32(self.account.network.context.globalTime())
|
||||||
|
var messages: [Message] = []
|
||||||
|
for id in events.addedIncomingMessageIds {
|
||||||
|
var notify = true
|
||||||
|
|
||||||
|
if let notificationSettings = modifier.getPeerNotificationSettings(id.peerId) as? TelegramPeerNotificationSettings {
|
||||||
|
switch notificationSettings.muteState {
|
||||||
|
case let .muted(until):
|
||||||
|
if until >= timestamp {
|
||||||
|
notify = false
|
||||||
|
}
|
||||||
|
case .unmuted:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace("AccountStateManager", what: "notification settings for \(id.peerId) are undefined")
|
||||||
|
}
|
||||||
|
|
||||||
|
var foundReadState = false
|
||||||
|
if let readStates = modifier.getPeerReadStates(id.peerId) {
|
||||||
|
for (namespace, readState) in readStates {
|
||||||
|
if namespace == id.namespace {
|
||||||
|
if id.id <= readState.maxIncomingReadId {
|
||||||
|
notify = false
|
||||||
|
}
|
||||||
|
foundReadState = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundReadState {
|
||||||
|
trace("AccountStateManager", what: "read state for \(id.peerId) is undefined")
|
||||||
|
}
|
||||||
|
|
||||||
|
if notify {
|
||||||
|
if let message = modifier.getMessage(id) {
|
||||||
|
messages.append(message)
|
||||||
|
} else {
|
||||||
|
trace("AccountStateManager", what: "notification message doesn't exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return messages
|
||||||
|
}).start(next: { [weak self] messages in
|
||||||
|
if let strongSelf = self {
|
||||||
|
for message in messages {
|
||||||
|
print("notify: \(message.peers[message.id.peerId]?.displayTitle): \(message.text)")
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.notificationMessagesPipe.putNext(messages)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -261,27 +261,27 @@ public final class AccountViewTracker {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func aroundUnreadMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, tagMask: MessageTags? = nil) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
public func aroundUnreadMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, tagMask: MessageTags? = nil, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||||
if let account = self.account {
|
if let account = self.account {
|
||||||
let signal = account.postbox.aroundUnreadMessageHistoryViewForPeerId(peerId, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask)
|
let signal = account.postbox.aroundUnreadMessageHistoryViewForPeerId(peerId, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, additionalData: additionalData)
|
||||||
return wrappedMessageHistorySignal(signal)
|
return wrappedMessageHistorySignal(signal)
|
||||||
} else {
|
} else {
|
||||||
return .never()
|
return .never()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func aroundIdMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, messageId: MessageId, tagMask: MessageTags? = nil) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
public func aroundIdMessageHistoryViewForPeerId(_ peerId: PeerId, count: Int, messageId: MessageId, tagMask: MessageTags? = nil, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||||
if let account = self.account {
|
if let account = self.account {
|
||||||
let signal = account.postbox.aroundIdMessageHistoryViewForPeerId(peerId, count: count, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask)
|
let signal = account.postbox.aroundIdMessageHistoryViewForPeerId(peerId, count: count, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, additionalData: additionalData)
|
||||||
return wrappedMessageHistorySignal(signal)
|
return wrappedMessageHistorySignal(signal)
|
||||||
} else {
|
} else {
|
||||||
return .never()
|
return .never()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func aroundMessageHistoryViewForPeerId(_ peerId: PeerId, index: MessageIndex, count: Int, anchorIndex: MessageIndex, fixedCombinedReadState: CombinedPeerReadState?, tagMask: MessageTags? = nil) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
public func aroundMessageHistoryViewForPeerId(_ peerId: PeerId, index: MessageIndex, count: Int, anchorIndex: MessageIndex, fixedCombinedReadState: CombinedPeerReadState?, tagMask: MessageTags? = nil, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||||
if let account = self.account {
|
if let account = self.account {
|
||||||
let signal = account.postbox.aroundMessageHistoryViewForPeerId(peerId, index: index, count: count, anchorIndex: anchorIndex, fixedCombinedReadState: fixedCombinedReadState, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask)
|
let signal = account.postbox.aroundMessageHistoryViewForPeerId(peerId, index: index, count: count, anchorIndex: anchorIndex, fixedCombinedReadState: fixedCombinedReadState, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, additionalData: additionalData)
|
||||||
return wrappedMessageHistorySignal(signal)
|
return wrappedMessageHistorySignal(signal)
|
||||||
} else {
|
} else {
|
||||||
return .never()
|
return .never()
|
||||||
|
@ -23,7 +23,7 @@ private func applyMediaResourceChanges(from: Media, to: Media, postbox: Postbox)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyUpdateMessage(postbox: Postbox, stateManager: StateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> {
|
func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> {
|
||||||
let messageId = result.rawMessageIds.first
|
let messageId = result.rawMessageIds.first
|
||||||
let apiMessage = result.messages.first
|
let apiMessage = result.messages.first
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import Foundation
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
func managedServiceViews(network: Network, postbox: Postbox, stateManager: StateManager, pendingMessageManager: PendingMessageManager) -> Signal<Void, NoError> {
|
func managedServiceViews(network: Network, postbox: Postbox, stateManager: AccountStateManager, pendingMessageManager: PendingMessageManager) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let disposable = DisposableSet()
|
let disposable = DisposableSet()
|
||||||
disposable.add(managedMessageHistoryHoles(network: network, postbox: postbox).start())
|
disposable.add(managedMessageHistoryHoles(network: network, postbox: postbox).start())
|
||||||
|
@ -39,7 +39,7 @@ private final class ManagedSynchronizePeerReadStatesState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func managedSynchronizePeerReadStates(network: Network, postbox: Postbox, stateManager: StateManager) -> Signal<Void, NoError> {
|
func managedSynchronizePeerReadStates(network: Network, postbox: Postbox, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let state = Atomic(value: ManagedSynchronizePeerReadStatesState())
|
let state = Atomic(value: ManagedSynchronizePeerReadStatesState())
|
||||||
|
|
||||||
|
@ -133,6 +133,13 @@ func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoP
|
|||||||
let requestService = MTRequestMessageService(context: context)!
|
let requestService = MTRequestMessageService(context: context)!
|
||||||
let connectionStatusDelegate = MTProtoConnectionStatusDelegate()
|
let connectionStatusDelegate = MTProtoConnectionStatusDelegate()
|
||||||
connectionStatusDelegate.action = { [weak connectionStatus] flags in
|
connectionStatusDelegate.action = { [weak connectionStatus] flags in
|
||||||
|
if flags.contains(.Connected) {
|
||||||
|
if !flags.intersection([.UpdatingConnectionContext, .PerformingServiceTasks]).isEmpty {
|
||||||
|
connectionStatus?.set(single(ConnectionStatus.Updating, NoError.self))
|
||||||
|
} else {
|
||||||
|
connectionStatus?.set(single(ConnectionStatus.Online, NoError.self))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !flags.contains(.NetworkAvailable) {
|
if !flags.contains(.NetworkAvailable) {
|
||||||
connectionStatus?.set(single(ConnectionStatus.WaitingForNetwork, NoError.self))
|
connectionStatus?.set(single(ConnectionStatus.WaitingForNetwork, NoError.self))
|
||||||
} else if !flags.contains(.Connected) {
|
} else if !flags.contains(.Connected) {
|
||||||
@ -143,6 +150,7 @@ func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoP
|
|||||||
connectionStatus?.set(single(ConnectionStatus.Online, NoError.self))
|
connectionStatus?.set(single(ConnectionStatus.Online, NoError.self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mtProto.delegate = connectionStatusDelegate
|
mtProto.delegate = connectionStatusDelegate
|
||||||
mtProto.add(requestService)
|
mtProto.add(requestService)
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ private final class PendingMessageRequestDependencyTag: NetworkRequestDependency
|
|||||||
public final class PendingMessageManager {
|
public final class PendingMessageManager {
|
||||||
private let network: Network
|
private let network: Network
|
||||||
private let postbox: Postbox
|
private let postbox: Postbox
|
||||||
private let stateManager: StateManager
|
private let stateManager: AccountStateManager
|
||||||
|
|
||||||
private let queue = Queue()
|
private let queue = Queue()
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public final class PendingMessageManager {
|
|||||||
|
|
||||||
private var peerSummaryContexts: [PeerId: PeerPendingMessagesSummaryContext] = [:]
|
private var peerSummaryContexts: [PeerId: PeerPendingMessagesSummaryContext] = [:]
|
||||||
|
|
||||||
init(network: Network, postbox: Postbox, stateManager: StateManager) {
|
init(network: Network, postbox: Postbox, stateManager: AccountStateManager) {
|
||||||
self.network = network
|
self.network = network
|
||||||
self.postbox = postbox
|
self.postbox = postbox
|
||||||
self.stateManager = stateManager
|
self.stateManager = stateManager
|
||||||
@ -219,7 +219,7 @@ public final class PendingMessageManager {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendMessageContent(network: Network, postbox: Postbox, stateManager: StateManager, message: Message, content: PendingMessageUploadedContent) -> Signal<Void, NoError> {
|
private func sendMessageContent(network: Network, postbox: Postbox, stateManager: AccountStateManager, message: Message, content: PendingMessageUploadedContent) -> Signal<Void, NoError> {
|
||||||
return postbox.modify { [weak self] modifier -> Signal<Void, NoError> in
|
return postbox.modify { [weak self] modifier -> Signal<Void, NoError> in
|
||||||
if let peer = modifier.getPeer(message.id.peerId), let inputPeer = apiInputPeer(peer) {
|
if let peer = modifier.getPeer(message.id.peerId), let inputPeer = apiInputPeer(peer) {
|
||||||
var uniqueId: Int64 = 0
|
var uniqueId: Int64 = 0
|
||||||
@ -301,7 +301,7 @@ public final class PendingMessageManager {
|
|||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applySentMessage(postbox: Postbox, stateManager: StateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> {
|
private func applySentMessage(postbox: Postbox, stateManager: AccountStateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> {
|
||||||
let messageId = result.rawMessageIds.first
|
let messageId = result.rawMessageIds.first
|
||||||
let apiMessage = result.messages.first
|
let apiMessage = result.messages.first
|
||||||
|
|
||||||
|
36
TelegramCore/RequestStartBot.swift
Normal file
36
TelegramCore/RequestStartBot.swift
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public func requestStartBot(account: Account, botPeerId: PeerId, payload: String?) -> Signal<Void, NoError> {
|
||||||
|
if let payload = payload, !payload.isEmpty {
|
||||||
|
return account.postbox.loadedPeerWithId(botPeerId)
|
||||||
|
|> mapToSignal { botPeer -> Signal<Void, NoError> in
|
||||||
|
if let inputUser = apiInputUser(botPeer) {
|
||||||
|
var randomId: Int64 = 0
|
||||||
|
arc4random_buf(&randomId, 8)
|
||||||
|
let r = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: .inputPeerEmpty, randomId: randomId, startParam: payload ?? ""))
|
||||||
|
|> mapToSignal { result -> Signal<Void, MTRpcError> in
|
||||||
|
account.stateManager.addUpdates(result)
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<Void, MTRpcError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
|> retryRequest
|
||||||
|
} else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], media: nil, replyToMessageId: nil)])
|
||||||
|
}
|
||||||
|
}
|
@ -46,12 +46,18 @@ final class CachedResolvedByNamePeer: Coding {
|
|||||||
|
|
||||||
private let resolvedByNamePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200)
|
private let resolvedByNamePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200)
|
||||||
|
|
||||||
public enum ResolvePeerByNameCachedPolicy {
|
public enum ResolvePeerByNameOptionCached {
|
||||||
case remoteIfEarlierThan(timestamp: Int32)
|
case none
|
||||||
case remote
|
case cached
|
||||||
|
case cachedIfLaterThan(timestamp: Int32)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func resolvePeerByName(account: Account, name: String, ageLimit: Int32 = 60 * 60) -> Signal<PeerId?, NoError> {
|
public enum ResolvePeerByNameOptionRemote {
|
||||||
|
case updateIfEarlierThan(timestamp: Int32)
|
||||||
|
case update
|
||||||
|
}
|
||||||
|
|
||||||
|
public func resolvePeerByName(account: Account, name: String, ageLimit: Int32 = 2 * 60 * 60 * 24) -> Signal<PeerId?, NoError> {
|
||||||
var normalizedName = name
|
var normalizedName = name
|
||||||
if normalizedName.hasPrefix("@") {
|
if normalizedName.hasPrefix("@") {
|
||||||
normalizedName = normalizedName.substring(from: name.index(after: name.startIndex))
|
normalizedName = normalizedName.substring(from: name.index(after: name.startIndex))
|
||||||
|
@ -31,9 +31,22 @@ private func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]
|
|||||||
return Message(stableId: 0, stableVersion: 0, id: id, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, forwardInfo: nil, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
return Message(stableId: 0, stableVersion: 0, id: id, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, forwardInfo: nil, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func searchMessages(account: Account, query: String) -> Signal<[Message], NoError> {
|
public func searchMessages(account: Account, peerId: PeerId?, query: String) -> Signal<[Message], NoError> {
|
||||||
let searchResult = account.network.request(Api.functions.messages.searchGlobal(q: query, offsetDate: 0, offsetPeer: Api.InputPeer.inputPeerEmpty, offsetId: 0, limit: 64))
|
let searchResult: Signal<Api.messages.Messages, NoError>
|
||||||
|
if let peerId = peerId {
|
||||||
|
searchResult = account.postbox.loadedPeerWithId(peerId)
|
||||||
|
|> mapToSignal { peer -> Signal<Api.messages.Messages, NoError> in
|
||||||
|
if let inputPeer = apiInputPeer(peer) {
|
||||||
|
return account.network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: query, filter: .inputMessagesFilterEmpty, minDate: 0, maxDate: Int32.max - 1, offset: 0, maxId: Int32.max - 1, limit: 64))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|
} else {
|
||||||
|
return .never()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
searchResult = account.network.request(Api.functions.messages.searchGlobal(q: query, offsetDate: 0, offsetPeer: Api.InputPeer.inputPeerEmpty, offsetId: 0, limit: 64))
|
||||||
|
|> retryRequest
|
||||||
|
}
|
||||||
|
|
||||||
let processedSearchResult = searchResult
|
let processedSearchResult = searchResult
|
||||||
|> mapToSignal { result -> Signal<[Message], NoError> in
|
|> mapToSignal { result -> Signal<[Message], NoError> in
|
||||||
|
@ -39,7 +39,7 @@ private func applyMediaResourceChanges(from: Media, to: Media, postbox: Postbox)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendUnsentMessage(network: Network, postbox: Postbox, stateManager: StateManager, message: Message) -> Signal<Void, NoError> {
|
func sendUnsentMessage(network: Network, postbox: Postbox, stateManager: AccountStateManager, message: Message) -> Signal<Void, NoError> {
|
||||||
return postbox.loadedPeerWithId(message.id.peerId)
|
return postbox.loadedPeerWithId(message.id.peerId)
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { peer -> Signal<Void, NoError> in
|
|> mapToSignal { peer -> Signal<Void, NoError> in
|
||||||
|
@ -149,7 +149,7 @@ private func localReadStateMarker(network: Network, postbox: Postbox, peerId: Pe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validatePeerReadState(network: Network, postbox: Postbox, stateManager: StateManager, peerId: PeerId) -> Signal<Void, NoError> {
|
private func validatePeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Signal<Void, NoError> {
|
||||||
let readStateWithInitialState = localReadStateMarker(network: network, postbox: postbox, peerId: peerId)
|
let readStateWithInitialState = localReadStateMarker(network: network, postbox: postbox, peerId: peerId)
|
||||||
|> mapToSignal { marker -> Signal<(PeerReadState, PeerReadStateMarker, PeerReadStateMarker), VerifyReadStateError> in
|
|> mapToSignal { marker -> Signal<(PeerReadState, PeerReadStateMarker, PeerReadStateMarker), VerifyReadStateError> in
|
||||||
return dialogReadState(network: network, postbox: postbox, peerId: peerId)
|
return dialogReadState(network: network, postbox: postbox, peerId: peerId)
|
||||||
@ -157,7 +157,7 @@ private func validatePeerReadState(network: Network, postbox: Postbox, stateMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maybeAppliedReadState = readStateWithInitialState |> mapToSignal { (readState, initialMarker, finalMarker) -> Signal<Void, VerifyReadStateError> in
|
let maybeAppliedReadState = readStateWithInitialState |> mapToSignal { (readState, initialMarker, finalMarker) -> Signal<Void, VerifyReadStateError> in
|
||||||
return stateManager.injectedStateModification(postbox.modify { modifier -> VerifyReadStateError? in
|
return stateManager.addCustomOperation(postbox.modify { modifier -> VerifyReadStateError? in
|
||||||
if initialMarker == finalMarker {
|
if initialMarker == finalMarker {
|
||||||
modifier.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud: readState]])
|
modifier.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud: readState]])
|
||||||
return nil
|
return nil
|
||||||
@ -186,7 +186,7 @@ private func validatePeerReadState(network: Network, postbox: Postbox, stateMana
|
|||||||
|> retry(0.1, maxDelay: 5.0, onQueue: Queue.concurrentDefaultQueue())
|
|> retry(0.1, maxDelay: 5.0, onQueue: Queue.concurrentDefaultQueue())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pushPeerReadState(network: Network, postbox: Postbox, peerId: PeerId, readState: PeerReadState) -> Signal<PeerReadState, VerifyReadStateError> {
|
private func pushPeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId, readState: PeerReadState) -> Signal<PeerReadState, VerifyReadStateError> {
|
||||||
return inputPeer(postbox: postbox, peerId: peerId)
|
return inputPeer(postbox: postbox, peerId: peerId)
|
||||||
|> mapToSignal { inputPeer -> Signal<PeerReadState, VerifyReadStateError> in
|
|> mapToSignal { inputPeer -> Signal<PeerReadState, VerifyReadStateError> in
|
||||||
switch inputPeer {
|
switch inputPeer {
|
||||||
@ -199,14 +199,19 @@ private func pushPeerReadState(network: Network, postbox: Postbox, peerId: PeerI
|
|||||||
default:
|
default:
|
||||||
return network.request(Api.functions.messages.readHistory(peer: inputPeer, maxId: readState.maxIncomingReadId))
|
return network.request(Api.functions.messages.readHistory(peer: inputPeer, maxId: readState.maxIncomingReadId))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> mapToSignalPromotingError { _ -> Signal<PeerReadState, VerifyReadStateError> in
|
|> mapToSignalPromotingError { result -> Signal<PeerReadState, VerifyReadStateError>
|
||||||
|
in
|
||||||
|
switch result {
|
||||||
|
case let .affectedMessages(pts, ptsCount):
|
||||||
|
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
|
||||||
|
}
|
||||||
return .single(readState)
|
return .single(readState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pushPeerReadState(network: Network, postbox: Postbox, stateManager: StateManager, peerId: PeerId) -> Signal<Void, NoError> {
|
private func pushPeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Signal<Void, NoError> {
|
||||||
let currentReadState = postbox.modify { modifier -> PeerReadState? in
|
let currentReadState = postbox.modify { modifier -> PeerReadState? in
|
||||||
if let readStates = modifier.getPeerReadStates(peerId) {
|
if let readStates = modifier.getPeerReadStates(peerId) {
|
||||||
for (namespace, readState) in readStates {
|
for (namespace, readState) in readStates {
|
||||||
@ -221,7 +226,7 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
|
|||||||
let pushedState = currentReadState
|
let pushedState = currentReadState
|
||||||
|> mapToSignalPromotingError { readState -> Signal<PeerReadState, VerifyReadStateError> in
|
|> mapToSignalPromotingError { readState -> Signal<PeerReadState, VerifyReadStateError> in
|
||||||
if let readState = readState {
|
if let readState = readState {
|
||||||
return pushPeerReadState(network: network, postbox: postbox, peerId: peerId, readState: readState)
|
return pushPeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId, readState: readState)
|
||||||
} else {
|
} else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
@ -229,7 +234,7 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
|
|||||||
|
|
||||||
let verifiedState = pushedState
|
let verifiedState = pushedState
|
||||||
|> mapToSignal { readState -> Signal<Void, VerifyReadStateError> in
|
|> mapToSignal { readState -> Signal<Void, VerifyReadStateError> in
|
||||||
return stateManager.injectedStateModification(postbox.modify { modifier -> VerifyReadStateError? in
|
return stateManager.addCustomOperation(postbox.modify { modifier -> VerifyReadStateError? in
|
||||||
if let readStates = modifier.getPeerReadStates(peerId) {
|
if let readStates = modifier.getPeerReadStates(peerId) {
|
||||||
for (namespace, currentReadState) in readStates where namespace == Namespaces.Message.Cloud {
|
for (namespace, currentReadState) in readStates where namespace == Namespaces.Message.Cloud {
|
||||||
if currentReadState == readState {
|
if currentReadState == readState {
|
||||||
@ -264,7 +269,7 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
|
|||||||
|> retry(0.1, maxDelay: 5.0, onQueue: Queue.concurrentDefaultQueue())
|
|> retry(0.1, maxDelay: 5.0, onQueue: Queue.concurrentDefaultQueue())
|
||||||
}
|
}
|
||||||
|
|
||||||
func synchronizePeerReadState(network: Network, postbox: Postbox, stateManager: StateManager, peerId: PeerId, push: Bool, validate: Bool) -> Signal<Void, NoError> {
|
func synchronizePeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId, push: Bool, validate: Bool) -> Signal<Void, NoError> {
|
||||||
var signal: Signal<Void, NoError> = .complete()
|
var signal: Signal<Void, NoError> = .complete()
|
||||||
if push {
|
if push {
|
||||||
signal = signal |> then(pushPeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId))
|
signal = signal |> then(pushPeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId))
|
||||||
|
@ -101,7 +101,7 @@ public struct MessageTextEntity: Coding, Equatable {
|
|||||||
public let range: Range<Int>
|
public let range: Range<Int>
|
||||||
public let type: MessageTextEntityType
|
public let type: MessageTextEntityType
|
||||||
|
|
||||||
init(range: Range<Int>, type: MessageTextEntityType) {
|
public init(range: Range<Int>, type: MessageTextEntityType) {
|
||||||
self.range = range
|
self.range = range
|
||||||
self.type = type
|
self.type = type
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ public class TextEntitiesMessageAttribute: MessageAttribute, Equatable {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
init(entities: [MessageTextEntity]) {
|
public init(entities: [MessageTextEntity]) {
|
||||||
self.entities = entities
|
self.entities = entities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user