diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index d6914cd865..f345e62167 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -396,6 +396,7 @@ D0B1671E1F9EA2C300976B40 /* ChatHistoryPreloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B1671C1F9EA2C300976B40 /* ChatHistoryPreloadManager.swift */; }; D0B167231F9F972E00976B40 /* LoggingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B167221F9F972E00976B40 /* LoggingSettings.swift */; }; D0B167241F9F972E00976B40 /* LoggingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B167221F9F972E00976B40 /* LoggingSettings.swift */; }; + D0B2F7742052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B2F7732052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift */; }; D0B417C11D7DCEEF004562A4 /* ApiGroupOrChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B417C01D7DCEEF004562A4 /* ApiGroupOrChannel.swift */; }; D0B4186B1D7E03D5004562A4 /* TelegramCoreMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B418691D7E03D5004562A4 /* TelegramCoreMac.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0B418721D7E0409004562A4 /* PostboxMac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0B418701D7E0409004562A4 /* PostboxMac.framework */; }; @@ -864,6 +865,7 @@ D0AF32371FAE8C910097362B /* MultipeerConnectivity.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MultipeerConnectivity.framework; path = System/Library/Frameworks/MultipeerConnectivity.framework; sourceTree = SDKROOT; }; D0B1671C1F9EA2C300976B40 /* ChatHistoryPreloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHistoryPreloadManager.swift; sourceTree = ""; }; D0B167221F9F972E00976B40 /* LoggingSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingSettings.swift; sourceTree = ""; }; + D0B2F7732052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelegramDeviceContactImportInfo.swift; sourceTree = ""; }; D0B417C01D7DCEEF004562A4 /* ApiGroupOrChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApiGroupOrChannel.swift; sourceTree = ""; }; D0B418671D7E03D5004562A4 /* TelegramCoreMac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TelegramCoreMac.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0B418691D7E03D5004562A4 /* TelegramCoreMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TelegramCoreMac.h; sourceTree = ""; }; @@ -1357,6 +1359,7 @@ children = ( D03B0D6C1D631AA300955575 /* ContactManagement.swift */, D01C7F091EFC3607008305F1 /* ManagedDeviceContacts.swift */, + D0B2F7732052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift */, ); name = Contacts; sourceTree = ""; @@ -1946,6 +1949,7 @@ D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */, D03DC9131F82F89D001D584C /* RegularChatState.swift in Sources */, D0613FCF1E60520700202CDB /* ChannelMembers.swift in Sources */, + D0B2F7742052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift in Sources */, C2366C891E4F40480097CCFF /* SupportPeerId.swift in Sources */, D0AF32351FAE8C6B0097362B /* MultipeerManager.swift in Sources */, D05A32E11E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index 1ed178070e..9a32b874b5 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -254,6 +254,7 @@ private var declaredEncodables: Void = { declareEncodable(CachedLocalizationInfos.self, f: { CachedLocalizationInfos(decoder: $0) }) declareEncodable(SynchronizeGroupedPeersOperation.self, f: { SynchronizeGroupedPeersOperation(decoder: $0) }) declareEncodable(ContentPrivacySettings.self, f: { ContentPrivacySettings(decoder: $0) }) + declareEncodable(TelegramDeviceContactImportInfo.self, f: { TelegramDeviceContactImportInfo(decoder: $0) }) return }() diff --git a/TelegramCore/ManagedDeviceContacts.swift b/TelegramCore/ManagedDeviceContacts.swift index 136e1bbbb7..38c14ca483 100644 --- a/TelegramCore/ManagedDeviceContacts.swift +++ b/TelegramCore/ManagedDeviceContacts.swift @@ -168,13 +168,17 @@ func managedDeviceContacts(postbox: Postbox, network: Network, deviceContacts: S } return (applyRemovedContacts(postbox: postbox, network: network, peerIds: removedPeerIds) - |> map { _ -> ([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents]) in + |> map { _ -> ([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents], [String: Int32]) in assertionFailure() - return ([], [:], [:]) + return ([], [:], [:], [:]) } |> then(applyAddedOrUpdatedContacts(network: network, contacts: addedOrUpdatedContacts))) - |> mapToSignal { peers, peerPresences, importedContents -> Signal in + |> mapToSignal { peers, peerPresences, importedContents, importedByCounts -> Signal in return postbox.modify { modifier -> Signal in + for (phone, count) in importedByCounts { + modifier.setDeviceContactImportInfo(TelegramDeviceContactImportIdentifier.phoneNumber(phone), value: TelegramDeviceContactImportInfo(importedByCount: count)) + } + let updatedInfo: UnorderedItemListTagMetaInfo if let previousInfo = metaInfo as? ManagedDeviceContactsMetaInfo { updatedInfo = ManagedDeviceContactsMetaInfo(version: previousInfo.version + 1) @@ -245,19 +249,20 @@ private func applyRemovedContacts(postbox: Postbox, network: Network, peerIds: [ inputUsers.append(inputUser) } } - return network.request(Api.functions.contacts.deleteContacts(id: inputUsers)) + return .complete() + /*return network.request(Api.functions.contacts.deleteContacts(id: inputUsers)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { _ -> Signal in return .complete() - } + }*/ } |> mapError { _ -> ManagedDeviceContactsError in return .generic } |> switchToLatest } -private func applyAddedOrUpdatedContacts(network: Network, contacts: [ManagedDeviceContactEntryContents]) -> Signal<([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents]), ManagedDeviceContactsError> { +private func applyAddedOrUpdatedContacts(network: Network, contacts: [ManagedDeviceContactEntryContents]) -> Signal<([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents], [String: Int32]), ManagedDeviceContactsError> { if contacts.isEmpty { - return .single(([], [:], [:])) + return .single(([], [:], [:], [:])) } var clientIdToContact: [Int64: ManagedDeviceContactEntryContents] = [:] @@ -272,9 +277,9 @@ private func applyAddedOrUpdatedContacts(network: Network, contacts: [ManagedDev |> `catch` { _ -> Signal in return .fail(.generic) } - |> mapToSignal { result -> Signal<([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents]), ManagedDeviceContactsError> in + |> mapToSignal { result -> Signal<([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents], [String: Int32]), ManagedDeviceContactsError> in switch result { - case let .importedContacts(imported, _, retryContacts, users): + case let .importedContacts(imported, popularInvites, retryContacts, users): var peers: [Peer] = [] var peerPresences: [PeerId: PeerPresence] = [:] var importedContents: [ValueBoxKey: ManagedDeviceContactEntryContents] = [:] @@ -308,8 +313,18 @@ private func applyAddedOrUpdatedContacts(network: Network, contacts: [ManagedDev importedContents[ValueBoxKey(contents.phoneNumber)] = updatedContents } } + + var importedByCounts: [String: Int32] = [:] + for item in popularInvites { + switch item { + case let .popularContact(clientId, importers): + if let contact = clientIdToContact[clientId] { + importedByCounts[contact.phoneNumber] = importers + } + } + } - return .single((peers, peerPresences, importedContents)) + return .single((peers, peerPresences, importedContents, importedByCounts)) } } } diff --git a/TelegramCore/TelegramDeviceContactImportInfo.swift b/TelegramCore/TelegramDeviceContactImportInfo.swift new file mode 100644 index 0000000000..1f97b825a7 --- /dev/null +++ b/TelegramCore/TelegramDeviceContactImportInfo.swift @@ -0,0 +1,72 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + +enum TelegramDeviceContactImportIdentifier: DeviceContactImportIdentifier { + case phoneNumber(String) + + init(decoder: PostboxDecoder) { + switch decoder.decodeInt32ForKey("_t", orElse: 0) { + case 0: + self = .phoneNumber(decoder.decodeStringForKey("p", orElse: "")) + default: + assertionFailure() + self = .phoneNumber("") + } + } + + func encode(_ encoder: PostboxEncoder) { + switch self { + case let .phoneNumber(number): + encoder.encodeInt32(0, forKey: "_t") + encoder.encodeString(number, forKey: "p") + } + } + + var key: ValueBoxKey { + switch self { + case let .phoneNumber(number): + let numberKey = ValueBoxKey(number) + return numberKey + } + } +} + +final class TelegramDeviceContactImportInfo: PostboxCoding { + let importedByCount: Int32 + + init(importedByCount: Int32) { + self.importedByCount = importedByCount + } + + init(decoder: PostboxDecoder) { + self.importedByCount = decoder.decodeInt32ForKey("ic", orElse: 0) + } + + func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.importedByCount, forKey: "ic") + } +} + +public func deviceContactsImportedByCount(postbox: Postbox, contacts: [DeviceContact]) -> Signal<[String: Int32], NoError> { + return postbox.modify { modifier -> [String: Int32] in + var result: [String: Int32] = [:] + for contact in contacts { + var maxCount: Int32 = 0 + for number in contact.phoneNumbers { + if let value = modifier.getDeviceContactImportInfo(TelegramDeviceContactImportIdentifier.phoneNumber(number.number.normalized.rawValue)) as? TelegramDeviceContactImportInfo { + maxCount = max(maxCount, value.importedByCount) + } + } + if maxCount != 0 { + result[contact.id] = maxCount + } + } + return result + } +}