From 9b342df78dd368273731a545435805950738854c Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 21 Aug 2020 13:56:34 +0300 Subject: [PATCH] Update API [skip ci] --- .../Sources/ChatListSearchContainerNode.swift | 2 +- ...onSequenceCountrySelectionController.swift | 7 +- .../Sources/HashtagSearchController.swift | 2 +- submodules/SyncCore/Sources/Namespaces.swift | 7 + submodules/TelegramApi/Sources/Api0.swift | 2 +- submodules/TelegramApi/Sources/Api2.swift | 30 ++-- submodules/TelegramApi/Sources/Api3.swift | 41 +++--- .../TelegramCore/Sources/AccountManager.swift | 2 + .../TelegramCore/Sources/Countries.swift | 128 +++++++++++++++--- .../TelegramCore/Sources/SearchMessages.swift | 13 +- ...rizationSequencePhoneEntryController.swift | 2 +- 11 files changed, 171 insertions(+), 65 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 96189597db..d75ff72adc 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -762,7 +762,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo ) ) let location: SearchMessagesLocation - location = .general + location = .general(tags: nil) updateSearchContext { _ in return (nil, true) diff --git a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift index eadca6c645..79b65b718f 100644 --- a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift +++ b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift @@ -3,6 +3,7 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit +import Postbox import TelegramPresentationData import TelegramStringFormatting import SearchBarNode @@ -46,7 +47,7 @@ private func loadCountryCodes() -> [Country] { let countryName = locale.localizedString(forIdentifier: countryId) ?? "" if let countryCodeInt = Int(countryCode) { - result.append(Country(code: countryId, defaultName: countryName, name: countryName, countryCodes: [Country.CountryCode(code: countryCode, prefixes: [], patterns: [])])) + result.append(Country(code: countryId, name: countryName, localizedName: nil, countryCodes: [Country.CountryCode(code: countryCode, prefixes: [], patterns: [])], hidden: false)) } if let maybeNameRange = maybeNameRange { @@ -61,8 +62,8 @@ private func loadCountryCodes() -> [Country] { private var countryCodes: [Country] = loadCountryCodes() -public func loadServerCountryCodes(network: Network) { - let _ = (getCountriesList(network: network, langCode: "") +public func loadServerCountryCodes(accountManager: AccountManager, network: Network) { + let _ = (getCountriesList(accountManager: accountManager, network: network, langCode: nil) |> deliverOnMainQueue).start(next: { countries in countryCodes = countries }) diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index 78442b6a65..538fa413c0 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -41,7 +41,7 @@ public final class HashtagSearchController: TelegramBaseController { let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations) - let location: SearchMessagesLocation = .general + let location: SearchMessagesLocation = .general(tags: nil) let search = searchMessages(account: context.account, location: location, query: query, state: nil) let foundMessages: Signal<[ChatListSearchEntry], NoError> = search |> map { result, _ in diff --git a/submodules/SyncCore/Sources/Namespaces.swift b/submodules/SyncCore/Sources/Namespaces.swift index c678f7d3ab..1cc493ca0f 100644 --- a/submodules/SyncCore/Sources/Namespaces.swift +++ b/submodules/SyncCore/Sources/Namespaces.swift @@ -348,6 +348,7 @@ private enum SharedDataKeyValues: Int32 { case proxySettings = 4 case autodownloadSettings = 5 case themeSettings = 6 + case countriesList = 7 } public struct SharedDataKeys { @@ -386,6 +387,12 @@ public struct SharedDataKeys { key.setInt32(0, value: SharedDataKeyValues.themeSettings.rawValue) return key }() + + public static let countriesList: ValueBoxKey = { + let key = ValueBoxKey(length: 4) + key.setInt32(0, value: SharedDataKeyValues.countriesList.rawValue) + return key + }() } public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 7eb6f16d2b..9d6c66583c 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -449,7 +449,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-524237339] = { return Api.PageTableRow.parse_pageTableRow($0) } dict[-40996577] = { return Api.DraftMessage.parse_draftMessage($0) } dict[453805082] = { return Api.DraftMessage.parse_draftMessageEmpty($0) } - dict[-77073091] = { return Api.help.Country.parse_country($0) } + dict[-1014526429] = { return Api.help.Country.parse_country($0) } dict[418631927] = { return Api.StatsGroupTopPoster.parse_statsGroupTopPoster($0) } dict[-2128640689] = { return Api.account.SentEmailCode.parse_sentEmailCode($0) } dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) } diff --git a/submodules/TelegramApi/Sources/Api2.swift b/submodules/TelegramApi/Sources/Api2.swift index 16c442f2ff..a47b7c7b83 100644 --- a/submodules/TelegramApi/Sources/Api2.swift +++ b/submodules/TelegramApi/Sources/Api2.swift @@ -2003,17 +2003,18 @@ public struct help { } public enum Country: TypeConstructorDescription { - case country(iso2: String, defaultName: String, name: String, countryCodes: [Api.help.CountryCode]) + case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .country(let iso2, let defaultName, let name, let countryCodes): + case .country(let flags, let iso2, let defaultName, let name, let countryCodes): if boxed { - buffer.appendInt32(-77073091) + buffer.appendInt32(-1014526429) } + serializeInt32(flags, buffer: buffer, boxed: false) serializeString(iso2, buffer: buffer, boxed: false) serializeString(defaultName, buffer: buffer, boxed: false) - serializeString(name, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)} buffer.appendInt32(481674261) buffer.appendInt32(Int32(countryCodes.count)) for item in countryCodes { @@ -2025,28 +2026,31 @@ public struct help { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .country(let iso2, let defaultName, let name, let countryCodes): - return ("country", [("iso2", iso2), ("defaultName", defaultName), ("name", name), ("countryCodes", countryCodes)]) + case .country(let flags, let iso2, let defaultName, let name, let countryCodes): + return ("country", [("flags", flags), ("iso2", iso2), ("defaultName", defaultName), ("name", name), ("countryCodes", countryCodes)]) } } public static func parse_country(_ reader: BufferReader) -> Country? { - var _1: String? - _1 = parseString(reader) + var _1: Int32? + _1 = reader.readInt32() var _2: String? _2 = parseString(reader) var _3: String? _3 = parseString(reader) - var _4: [Api.help.CountryCode]? + var _4: String? + if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } + var _5: [Api.help.CountryCode]? if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.help.Country.country(iso2: _1!, defaultName: _2!, name: _3!, countryCodes: _4!) + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index f2e20a21b1..ca53c4c50a 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -3348,26 +3348,6 @@ public extension Api { }) } - public static func searchGlobal(flags: Int32, folderId: Int32?, q: String, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1083038300) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - serializeString(q, buffer: buffer, boxed: false) - serializeInt32(offsetRate, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.searchGlobal", parameters: [("flags", flags), ("folderId", folderId), ("q", q), ("offsetRate", offsetRate), ("offsetPeer", offsetPeer), ("offsetId", offsetId), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } - public static func sendMessage(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, message: String, randomId: Int64, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() buffer.appendInt32(1376532592) @@ -3719,6 +3699,27 @@ public extension Api { return result }) } + + public static func searchGlobal(flags: Int32, folderId: Int32?, q: String, filter: Api.MessagesFilter, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1934479725) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeString(q, buffer: buffer, boxed: false) + filter.serialize(buffer, true) + serializeInt32(offsetRate, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.searchGlobal", parameters: [("flags", flags), ("folderId", folderId), ("q", q), ("filter", filter), ("offsetRate", offsetRate), ("offsetPeer", offsetPeer), ("offsetId", offsetId), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } } public struct channels { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { diff --git a/submodules/TelegramCore/Sources/AccountManager.swift b/submodules/TelegramCore/Sources/AccountManager.swift index fb9b223ac9..9877a921ae 100644 --- a/submodules/TelegramCore/Sources/AccountManager.swift +++ b/submodules/TelegramCore/Sources/AccountManager.swift @@ -163,6 +163,8 @@ private var declaredEncodables: Void = { declareEncodable(CachedChatContextResult.self, f: { CachedChatContextResult(decoder: $0) }) declareEncodable(PeerAccessRestrictionInfo.self, f: { PeerAccessRestrictionInfo(decoder: $0) }) declareEncodable(TelegramMediaImage.VideoRepresentation.self, f: { TelegramMediaImage.VideoRepresentation(decoder: $0) }) + declareEncodable(Country.self, f: { Country(decoder: $0) }) + declareEncodable(Country.CountryCode.self, f: { Country.CountryCode(decoder: $0) }) return }() diff --git a/submodules/TelegramCore/Sources/Countries.swift b/submodules/TelegramCore/Sources/Countries.swift index 9d1349f6fb..15ebe870cb 100644 --- a/submodules/TelegramCore/Sources/Countries.swift +++ b/submodules/TelegramCore/Sources/Countries.swift @@ -5,8 +5,12 @@ import TelegramApi import SyncCore -public struct Country { - public struct CountryCode { +public struct Country: PostboxCoding, Equatable { + public static func == (lhs: Country, rhs: Country) -> Bool { + return lhs.code == rhs.code && lhs.name == rhs.name && lhs.localizedName == rhs.localizedName && lhs.countryCodes == rhs.countryCodes && lhs.hidden == rhs.hidden + } + + public struct CountryCode: PostboxCoding, Equatable { public let code: String public let prefixes: [String] public let patterns: [String] @@ -16,37 +20,125 @@ public struct Country { self.prefixes = prefixes self.patterns = patterns } + + public init(decoder: PostboxDecoder) { + self.code = decoder.decodeStringForKey("c", orElse: "") + self.prefixes = decoder.decodeStringArrayForKey("pfx") + self.patterns = decoder.decodeStringArrayForKey("ptrn") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeString(self.code, forKey: "c") + encoder.encodeStringArray(self.prefixes, forKey: "pfx") + encoder.encodeStringArray(self.patterns, forKey: "ptrn") + } } public let code: String - public let defaultName: String public let name: String + public let localizedName: String? public let countryCodes: [CountryCode] + public let hidden: Bool - public init(code: String, defaultName: String, name: String, countryCodes: [CountryCode]) { + public init(code: String, name: String, localizedName: String?, countryCodes: [CountryCode], hidden: Bool) { self.code = code - self.defaultName = defaultName self.name = name + self.localizedName = localizedName self.countryCodes = countryCodes + self.hidden = hidden + } + + public init(decoder: PostboxDecoder) { + self.code = decoder.decodeStringForKey("c", orElse: "") + self.name = decoder.decodeStringForKey("n", orElse: "") + self.localizedName = decoder.decodeOptionalStringForKey("ln") + self.countryCodes = decoder.decodeObjectArrayForKey("cc").map { $0 as! CountryCode } + self.hidden = decoder.decodeBoolForKey("h", orElse: false) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeString(self.code, forKey: "c") + encoder.encodeString(self.name, forKey: "n") + if let localizedName = self.localizedName { + encoder.encodeString(localizedName, forKey: "ln") + } else { + encoder.encodeNil(forKey: "ln") + } + encoder.encodeObjectArray(self.countryCodes, forKey: "cc") + encoder.encodeBool(self.hidden, forKey: "h") } } -public func getCountriesList(network: Network, langCode: String) -> Signal<[Country], NoError> { - return network.request(Api.functions.help.getCountriesList(langCode: langCode, hash: 0)) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) +public final class CountriesList: PreferencesEntry, Equatable { + public let countries: [Country] + public let hash: Int32 + + public init(countries: [Country], hash: Int32) { + self.countries = countries + self.hash = hash } - |> map { result in - if let result = result { + + public init(decoder: PostboxDecoder) { + self.countries = decoder.decodeObjectArrayForKey("c").map { $0 as! Country } + self.hash = decoder.decodeInt32ForKey("h", orElse: 0) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeObjectArray(self.countries, forKey: "c") + encoder.encodeInt32(self.hash, forKey: "h") + } + + public func isEqual(to: PreferencesEntry) -> Bool { + if let to = to as? CountriesList { + return self == to + } else { + return false + } + } + + public static func ==(lhs: CountriesList, rhs: CountriesList) -> Bool { + return lhs.countries == rhs.countries && lhs.hash == rhs.hash + } +} + + +public func getCountriesList(accountManager: AccountManager, network: Network, langCode: String?, forceUpdate: Bool = false) -> Signal<[Country], NoError> { + let fetch: ([Country]?, Int32?) -> Signal<[Country], NoError> = { current, hash in + return network.request(Api.functions.help.getCountriesList(langCode: langCode ?? "", hash: hash ?? 0)) + |> retryRequest + |> mapToSignal { result -> Signal<[Country], NoError> in switch result { case let .countriesList(apiCountries, hash): - return apiCountries.map { Country(apiCountry: $0) } + let result = apiCountries.compactMap { Country(apiCountry: $0) } + if result == current { + return .complete() + } else { + let _ = accountManager.transaction { transaction in + transaction.updateSharedData(SharedDataKeys.countriesList, { _ in + return CountriesList(countries: result, hash: hash) + }) + }.start() + return .single(result) + } case .countriesListNotModified: - return [] + return .complete() } - } else { - return [] + } + } + + if forceUpdate { + return fetch(nil, nil) + } else { + return accountManager.sharedData(keys: [SharedDataKeys.countriesList]) + |> map { sharedData -> ([Country], Int32) in + if let countriesList = sharedData.entries[SharedDataKeys.countriesList] as? CountriesList { + return (countriesList.countries, countriesList.hash) + } else { + return ([], 0) + } + } |> mapToSignal { current, hash -> Signal<[Country], NoError> in + return .single(current) + |> then(fetch(current, hash)) } } } @@ -65,8 +157,8 @@ extension Country.CountryCode { extension Country { init(apiCountry: Api.help.Country) { switch apiCountry { - case let .country(iso2, defaultName, name, countryCodes): - self.init(code: iso2, defaultName: defaultName, name: name, countryCodes: countryCodes.map { Country.CountryCode(apiCountryCode: $0) }) + case let .country(flags, iso2, defaultName, name, countryCodes): + self.init(code: iso2, name: defaultName, localizedName: name, countryCodes: countryCodes.map { Country.CountryCode(apiCountryCode: $0) }, hidden: (flags & 1 << 0) != 0) } } } diff --git a/submodules/TelegramCore/Sources/SearchMessages.swift b/submodules/TelegramCore/Sources/SearchMessages.swift index c7710ab77e..583f406f0c 100644 --- a/submodules/TelegramCore/Sources/SearchMessages.swift +++ b/submodules/TelegramCore/Sources/SearchMessages.swift @@ -7,7 +7,7 @@ import MtProtoKit import SyncCore public enum SearchMessagesLocation: Equatable { - case general + case general(tags: MessageTags?) case group(PeerGroupId) case peer(peerId: PeerId, fromId: PeerId?, tags: MessageTags?) case publicForwards(messageId: MessageId, datacenterId: Int?) @@ -193,7 +193,6 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q } let filter: Api.MessagesFilter - if let tags = tags { if tags.contains(.file) { filter = .inputMessagesFilterDocument @@ -270,7 +269,8 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q } case .group: remoteSearchResult = .single((nil, nil)) - case .general: + case let .general(tags): + let filter: Api.MessagesFilter = tags.flatMap { messageFilterForTagMask($0) } ?? .inputMessagesFilterEmpty remoteSearchResult = account.postbox.transaction { transaction -> (Int32, MessageIndex?, Api.InputPeer) in var lowerBound: MessageIndex? if let state = state, let message = state.main.messages.last { @@ -283,7 +283,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q } } |> mapToSignal { (nextRate, lowerBound, inputPeer) in - return account.network.request(Api.functions.messages.searchGlobal(flags: 0, folderId: nil, q: query, offsetRate: nextRate, offsetPeer: inputPeer, offsetId: lowerBound?.id.id ?? 0, limit: limit), automaticFloodWait: false) + return account.network.request(Api.functions.messages.searchGlobal(flags: 0, folderId: nil, q: query, filter: filter, offsetRate: nextRate, offsetPeer: inputPeer, offsetId: lowerBound?.id.id ?? 0, limit: limit), automaticFloodWait: false) |> map { result -> (Api.messages.Messages?, Api.messages.Messages?) in return (result, nil) } @@ -292,8 +292,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q } } case let .publicForwards(messageId, datacenterId): - remoteSearchResult = .single((nil, nil)) - /*remoteSearchResult = account.postbox.transaction { transaction -> (Api.InputChannel?, Int32, MessageIndex?, Api.InputPeer) in + remoteSearchResult = account.postbox.transaction { transaction -> (Api.InputChannel?, Int32, MessageIndex?, Api.InputPeer) in let sourcePeer = transaction.getPeer(messageId.peerId) let inputChannel = sourcePeer.flatMap { apiInputChannel($0) } @@ -330,7 +329,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q |> `catch` { _ -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in return .single((nil, nil)) } - }*/ + } } return remoteSearchResult diff --git a/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift b/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift index bf5948de32..1ff91532a6 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift @@ -58,7 +58,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController { self.openUrl = openUrl self.back = back - loadServerCountryCodes(network: account.network) + loadServerCountryCodes(accountManager: sharedContext.accountManager, network: account.network) super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: AuthorizationSequenceController.navigationBarTheme(presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings)))