mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-30 19:58:39 +00:00
Merge branch 'master' of github.com:peter-iakovlev/TelegramCoreDev
This commit is contained in:
commit
ccd60ac08b
@ -366,6 +366,8 @@
|
||||
D05A32E51E6F0B2E002760B4 /* RecentAccountSessions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */; };
|
||||
D05A32E71E6F0B5C002760B4 /* RecentAccountSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */; };
|
||||
D05A32E81E6F0B5C002760B4 /* RecentAccountSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */; };
|
||||
D05D8B372192F8AF0064586F /* LocalizationListState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05D8B362192F8AF0064586F /* LocalizationListState.swift */; };
|
||||
D05D8B382192F8AF0064586F /* LocalizationListState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05D8B362192F8AF0064586F /* LocalizationListState.swift */; };
|
||||
D0613FCA1E60440600202CDB /* InvitationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FC91E60440600202CDB /* InvitationLinks.swift */; };
|
||||
D0613FCB1E60440600202CDB /* InvitationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FC91E60440600202CDB /* InvitationLinks.swift */; };
|
||||
D0613FCF1E60520700202CDB /* ChannelMembers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FCE1E60520700202CDB /* ChannelMembers.swift */; };
|
||||
@ -957,6 +959,7 @@
|
||||
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
|
||||
D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSessions.swift; sourceTree = "<group>"; };
|
||||
D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSession.swift; sourceTree = "<group>"; };
|
||||
D05D8B362192F8AF0064586F /* LocalizationListState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationListState.swift; sourceTree = "<group>"; };
|
||||
D0613FC91E60440600202CDB /* InvitationLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InvitationLinks.swift; sourceTree = "<group>"; };
|
||||
D0613FCE1E60520700202CDB /* ChannelMembers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelMembers.swift; sourceTree = "<group>"; };
|
||||
D0613FD61E606B3B00202CDB /* ConvertGroupToSupergroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvertGroupToSupergroup.swift; sourceTree = "<group>"; };
|
||||
@ -1680,6 +1683,7 @@
|
||||
D08CAA7F1ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift */,
|
||||
D08CAA831ED8164B0000FDA8 /* Localization.swift */,
|
||||
D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */,
|
||||
D05D8B362192F8AF0064586F /* LocalizationListState.swift */,
|
||||
);
|
||||
name = Localization;
|
||||
sourceTree = "<group>";
|
||||
@ -2179,6 +2183,7 @@
|
||||
D01AC91D1DD5DA5E00E8160F /* RequestMessageActionCallback.swift in Sources */,
|
||||
D00C7CEB1E37A8540080C3D5 /* SetSecretChatMessageAutoremoveTimeoutInteractively.swift in Sources */,
|
||||
D09BB6B61DB0428000A905C0 /* PendingMessageUploadedContent.swift in Sources */,
|
||||
D05D8B372192F8AF0064586F /* LocalizationListState.swift in Sources */,
|
||||
D0F3CC7D1DDE289E008148FA /* ResolvePeerByName.swift in Sources */,
|
||||
D0B843B71DA7FF30005F29E1 /* NBMetadataCoreMapper.m in Sources */,
|
||||
D0AB0B921D65E9FA002C78E7 /* ManagedServiceViews.swift in Sources */,
|
||||
@ -2716,6 +2721,7 @@
|
||||
D07047BB1F3DF75500F6A8D4 /* ConsumePersonalMessageAction.swift in Sources */,
|
||||
D0380DBB204EF306000414AB /* MessageMediaPreuploadManager.swift in Sources */,
|
||||
D050F2621E4A5AE700988324 /* GlobalNotificationSettings.swift in Sources */,
|
||||
D05D8B382192F8AF0064586F /* LocalizationListState.swift in Sources */,
|
||||
D0DFD5E01FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */,
|
||||
D0B418991D7E0580004562A4 /* TelegramMediaMap.swift in Sources */,
|
||||
D0E8174A2010E7E300B82BBB /* ChannelAdminEventLogContext.swift in Sources */,
|
||||
|
||||
@ -185,10 +185,14 @@ let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
||||
}
|
||||
|
||||
return SeedConfiguration(initializeChatListWithHole: (topLevel: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: Int32.max - 1)), groups: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))), initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: MessageTags.all, messageTagsWithSummary: MessageTags.unseenPersonalMessage, existingGlobalMessageTags: GlobalMessageTags.all, peerNamespacesRequiringMessageTextIndex: [Namespaces.Peer.SecretChat], peerSummaryCounterTags: { peer in
|
||||
if let peer = peer as? TelegramChannel, let addressName = peer.addressName, !addressName.isEmpty {
|
||||
if let peer = peer as? TelegramChannel {
|
||||
switch peer.info {
|
||||
case .group:
|
||||
return [.publicGroups]
|
||||
if let addressName = peer.addressName, !addressName.isEmpty {
|
||||
return [.publicGroups]
|
||||
} else {
|
||||
return [.regularChatsAndPrivateGroups]
|
||||
}
|
||||
case .broadcast:
|
||||
return [.channels]
|
||||
}
|
||||
|
||||
@ -89,6 +89,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(SynchronizeSavedStickersOperation.self, f: { SynchronizeSavedStickersOperation(decoder: $0) })
|
||||
declareEncodable(CacheStorageSettings.self, f: { CacheStorageSettings(decoder: $0) })
|
||||
declareEncodable(LocalizationSettings.self, f: { LocalizationSettings(decoder: $0) })
|
||||
declareEncodable(LocalizationListState.self, f: { LocalizationListState(decoder: $0) })
|
||||
declareEncodable(ProxySettings.self, f: { ProxySettings(decoder: $0) })
|
||||
declareEncodable(NetworkSettings.self, f: { NetworkSettings(decoder: $0) })
|
||||
declareEncodable(RemoteStorageConfiguration.self, f: { RemoteStorageConfiguration(decoder: $0) })
|
||||
@ -207,20 +208,20 @@ public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkI
|
||||
initialKind = .authorized
|
||||
}
|
||||
let updatedKind = postbox.stateView()
|
||||
|> map { view -> Bool in
|
||||
let kind: AccountKind
|
||||
if view.state is AuthorizedAccountState {
|
||||
kind = .authorized
|
||||
} else {
|
||||
kind = .unauthorized
|
||||
}
|
||||
if kind != initialKind {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|> map { view -> Bool in
|
||||
let kind: AccountKind
|
||||
if view.state is AuthorizedAccountState {
|
||||
kind = .authorized
|
||||
} else {
|
||||
kind = .unauthorized
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
if kind != initialKind {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
return Signal { subscriber in
|
||||
subscriber.putNext(accountResult)
|
||||
@ -242,28 +243,27 @@ public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkI
|
||||
public func logoutFromAccount(id: AccountRecordId, accountManager: AccountManager) -> Signal<Void, NoError> {
|
||||
Logger.shared.log("AccountManager", "logoutFromAccount \(id)")
|
||||
return accountManager.transaction { transaction -> Void in
|
||||
let currentId = transaction.getCurrentId()
|
||||
if let currentId = currentId {
|
||||
transaction.updateRecord(currentId, { current in
|
||||
if let current = current {
|
||||
var found = false
|
||||
for attribute in current.attributes {
|
||||
if attribute is LoggedOutAccountAttribute {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
transaction.updateRecord(id, { current in
|
||||
if let current = current {
|
||||
var found = false
|
||||
for attribute in current.attributes {
|
||||
if attribute is LoggedOutAccountAttribute {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if found {
|
||||
return current
|
||||
} else {
|
||||
return AccountRecord(id: current.id, attributes: current.attributes + [LoggedOutAccountAttribute()], temporarySessionId: nil)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
let id = transaction.createRecord([])
|
||||
transaction.setCurrentId(id)
|
||||
if found {
|
||||
return current
|
||||
} else {
|
||||
return AccountRecord(id: current.id, attributes: current.attributes + [LoggedOutAccountAttribute()], temporarySessionId: nil)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
if transaction.getCurrentId() == id {
|
||||
let updatedId = transaction.createRecord([])
|
||||
transaction.setCurrentId(updatedId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -285,14 +285,15 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume
|
||||
var disposeList: [(AccountRecordId, MetaDisposable)] = []
|
||||
var beginList: [(AccountRecordId, MetaDisposable)] = []
|
||||
let _ = loggedOutAccounts.modify { disposables in
|
||||
let validIds = Set(view.records.filter {
|
||||
for attribute in $0.attributes {
|
||||
var validIds = Set<AccountRecordId>()
|
||||
outer: for record in view.records {
|
||||
for attribute in record.attributes {
|
||||
if attribute is LoggedOutAccountAttribute {
|
||||
return true
|
||||
validIds.insert(record.id)
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
return false
|
||||
}.map { $0.id })
|
||||
}
|
||||
|
||||
var disposables = disposables
|
||||
|
||||
@ -320,7 +321,7 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume
|
||||
disposable.dispose()
|
||||
}
|
||||
for (id, disposable) in beginList {
|
||||
Logger.shared.log("managedCleanupAccounts", "cleanup \(id)")
|
||||
Logger.shared.log("managedCleanupAccounts", "cleanup \(id), current is \(String(describing: view.currentRecord?.id))")
|
||||
disposable.set(cleanupAccount(networkArguments: networkArguments, accountManager: accountManager, id: id, rootPath: rootPath, auxiliaryMethods: auxiliaryMethods).start())
|
||||
}
|
||||
|
||||
|
||||
@ -101,13 +101,6 @@ private func locallyGeneratedMessageTimestampsFromUpdateGroups(_ groups: [Update
|
||||
messageTimestamps[peerId]!.append((Namespaces.Message.Local, date))
|
||||
}
|
||||
}
|
||||
case let .updateContactRegistered(userId, date):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
if messageTimestamps[peerId] == nil {
|
||||
messageTimestamps[peerId] = [(Namespaces.Message.Local, date)]
|
||||
} else {
|
||||
messageTimestamps[peerId]!.append((Namespaces.Message.Local, date))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -306,13 +299,6 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
|
||||
messageTimestamps[peerId]!.append((Namespaces.Message.Local, date))
|
||||
}
|
||||
}
|
||||
case let .updateContactRegistered(userId, date):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
if messageTimestamps[peerId] == nil {
|
||||
messageTimestamps[peerId] = [(Namespaces.Message.Local, date)]
|
||||
} else {
|
||||
messageTimestamps[peerId]!.append((Namespaces.Message.Local, date))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -920,25 +906,6 @@ private func finalStateWithUpdatesAndServerTime(account: Account, state: Account
|
||||
} else {
|
||||
updatedState.addDisplayAlert(text)
|
||||
}
|
||||
case let .updateContactRegistered(userId, date):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
|
||||
var alreadyStored = false
|
||||
if let storedMessages = updatedState.storedMessagesByPeerIdAndTimestamp[peerId] {
|
||||
for index in storedMessages {
|
||||
if index.timestamp == date {
|
||||
alreadyStored = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if alreadyStored {
|
||||
Logger.shared.log("State", "skipping joined message at \(date) for \(peerId): already stored")
|
||||
} else {
|
||||
let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "", attributes: [], media: [TelegramMediaAction(action: .peerJoined)])
|
||||
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
||||
}
|
||||
case let .updateReadChannelInbox(channelId, maxId):
|
||||
updatedState.readInbox(MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: maxId))
|
||||
case let .updateReadChannelOutbox(channelId, maxId):
|
||||
|
||||
@ -110,6 +110,11 @@ public final class AccountStateManager {
|
||||
return self.appliedIncomingReadMessagesPipe.signal()
|
||||
}
|
||||
|
||||
private let significantStateUpdateCompletedPipe = ValuePipe<Void>()
|
||||
var significantStateUpdateCompleted: Signal<Void, NoError> {
|
||||
return self.significantStateUpdateCompletedPipe.signal()
|
||||
}
|
||||
|
||||
private var updatedWebpageContexts: [MediaId: UpdatedWebpageSubscriberContext] = [:]
|
||||
|
||||
private let delayNotificatonsUntil = Atomic<Int32?>(value: nil)
|
||||
@ -424,6 +429,7 @@ public final class AccountStateManager {
|
||||
strongSelf.insertProcessEvents(events)
|
||||
}
|
||||
strongSelf.currentIsUpdatingValue = false
|
||||
strongSelf.significantStateUpdateCompletedPipe.putNext(Void())
|
||||
}
|
||||
} else {
|
||||
if !events.isEmpty {
|
||||
|
||||
@ -89,7 +89,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1343524562] = { return Api.InputChannel.parse_inputChannel($0) }
|
||||
dict[414687501] = { return Api.DcOption.parse_dcOption($0) }
|
||||
dict[-1705233435] = { return Api.account.PasswordSettings.parse_passwordSettings($0) }
|
||||
dict[106019213] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
||||
dict[-288727837] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
||||
dict[-1987579119] = { return Api.help.AppUpdate.parse_appUpdate($0) }
|
||||
dict[-1000708810] = { return Api.help.AppUpdate.parse_noAppUpdate($0) }
|
||||
dict[-209337866] = { return Api.LangPackDifference.parse_langPackDifference($0) }
|
||||
@ -154,7 +154,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[469489699] = { return Api.Update.parse_updateUserStatus($0) }
|
||||
dict[-1489818765] = { return Api.Update.parse_updateUserName($0) }
|
||||
dict[-1791935732] = { return Api.Update.parse_updateUserPhoto($0) }
|
||||
dict[628472761] = { return Api.Update.parse_updateContactRegistered($0) }
|
||||
dict[-1657903163] = { return Api.Update.parse_updateContactLink($0) }
|
||||
dict[314359194] = { return Api.Update.parse_updateNewEncryptedMessage($0) }
|
||||
dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($0) }
|
||||
@ -631,6 +630,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1410748418] = { return Api.MessageAction.parse_messageActionBotAllowed($0) }
|
||||
dict[455635795] = { return Api.MessageAction.parse_messageActionSecureValuesSentMe($0) }
|
||||
dict[-648257196] = { return Api.MessageAction.parse_messageActionSecureValuesSent($0) }
|
||||
dict[1894744724] = { return Api.MessageAction.parse_messageActionContactSignUp($0) }
|
||||
dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) }
|
||||
dict[462375633] = { return Api.PhoneCall.parse_phoneCallWaiting($0) }
|
||||
dict[-2089411356] = { return Api.PhoneCall.parse_phoneCallRequested($0) }
|
||||
@ -651,7 +651,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1889961234] = { return Api.PeerNotifySettings.parse_peerNotifySettingsEmpty($0) }
|
||||
dict[-1353671392] = { return Api.PeerNotifySettings.parse_peerNotifySettings($0) }
|
||||
dict[-1995686519] = { return Api.InputBotInlineMessageID.parse_inputBotInlineMessageID($0) }
|
||||
dict[-242812612] = { return Api.PageRelatedArticle.parse_pageRelatedArticle($0) }
|
||||
dict[-1282352120] = { return Api.PageRelatedArticle.parse_pageRelatedArticle($0) }
|
||||
dict[313694676] = { return Api.StickerPack.parse_stickerPack($0) }
|
||||
dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) }
|
||||
dict[-715532088] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
||||
|
||||
@ -2362,13 +2362,13 @@ extension Api {
|
||||
|
||||
}
|
||||
enum LangPackLanguage: TypeConstructorDescription {
|
||||
case langPackLanguage(flags: Int32, name: String, nativeName: String, langCode: String, baseLangCode: String?, pluralCode: String, stringsCount: Int32, translatedCount: Int32)
|
||||
case langPackLanguage(flags: Int32, name: String, nativeName: String, langCode: String, baseLangCode: String?, pluralCode: String, stringsCount: Int32, translatedCount: Int32, translationsUrl: String)
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount):
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount, let translationsUrl):
|
||||
if boxed {
|
||||
buffer.appendInt32(106019213)
|
||||
buffer.appendInt32(-288727837)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(name, buffer: buffer, boxed: false)
|
||||
@ -2378,14 +2378,15 @@ extension Api {
|
||||
serializeString(pluralCode, buffer: buffer, boxed: false)
|
||||
serializeInt32(stringsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(translatedCount, buffer: buffer, boxed: false)
|
||||
serializeString(translationsUrl, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount):
|
||||
return ("langPackLanguage", [("flags", flags), ("name", name), ("nativeName", nativeName), ("langCode", langCode), ("baseLangCode", baseLangCode), ("pluralCode", pluralCode), ("stringsCount", stringsCount), ("translatedCount", translatedCount)])
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount, let translationsUrl):
|
||||
return ("langPackLanguage", [("flags", flags), ("name", name), ("nativeName", nativeName), ("langCode", langCode), ("baseLangCode", baseLangCode), ("pluralCode", pluralCode), ("stringsCount", stringsCount), ("translatedCount", translatedCount), ("translationsUrl", translationsUrl)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -2406,6 +2407,8 @@ extension Api {
|
||||
_7 = reader.readInt32()
|
||||
var _8: Int32?
|
||||
_8 = reader.readInt32()
|
||||
var _9: String?
|
||||
_9 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -2414,8 +2417,9 @@ extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.LangPackLanguage.langPackLanguage(flags: _1!, name: _2!, nativeName: _3!, langCode: _4!, baseLangCode: _5, pluralCode: _6!, stringsCount: _7!, translatedCount: _8!)
|
||||
let _c9 = _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.LangPackLanguage.langPackLanguage(flags: _1!, name: _2!, nativeName: _3!, langCode: _4!, baseLangCode: _5, pluralCode: _6!, stringsCount: _7!, translatedCount: _8!, translationsUrl: _9!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -3337,7 +3341,6 @@ extension Api {
|
||||
case updateUserStatus(userId: Int32, status: Api.UserStatus)
|
||||
case updateUserName(userId: Int32, firstName: String, lastName: String, username: String)
|
||||
case updateUserPhoto(userId: Int32, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool)
|
||||
case updateContactRegistered(userId: Int32, date: Int32)
|
||||
case updateContactLink(userId: Int32, myLink: Api.ContactLink, foreignLink: Api.ContactLink)
|
||||
case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32)
|
||||
case updateEncryptedChatTyping(chatId: Int32)
|
||||
@ -3473,13 +3476,6 @@ extension Api {
|
||||
photo.serialize(buffer, true)
|
||||
previous.serialize(buffer, true)
|
||||
break
|
||||
case .updateContactRegistered(let userId, let date):
|
||||
if boxed {
|
||||
buffer.appendInt32(628472761)
|
||||
}
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateContactLink(let userId, let myLink, let foreignLink):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1657903163)
|
||||
@ -3988,8 +3984,6 @@ extension Api {
|
||||
return ("updateUserName", [("userId", userId), ("firstName", firstName), ("lastName", lastName), ("username", username)])
|
||||
case .updateUserPhoto(let userId, let date, let photo, let previous):
|
||||
return ("updateUserPhoto", [("userId", userId), ("date", date), ("photo", photo), ("previous", previous)])
|
||||
case .updateContactRegistered(let userId, let date):
|
||||
return ("updateContactRegistered", [("userId", userId), ("date", date)])
|
||||
case .updateContactLink(let userId, let myLink, let foreignLink):
|
||||
return ("updateContactLink", [("userId", userId), ("myLink", myLink), ("foreignLink", foreignLink)])
|
||||
case .updateNewEncryptedMessage(let message, let qts):
|
||||
@ -4271,20 +4265,6 @@ extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_updateContactRegistered(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.Update.updateContactRegistered(userId: _1!, date: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_updateContactLink(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
@ -15158,6 +15138,7 @@ extension Api {
|
||||
case messageActionBotAllowed(domain: String)
|
||||
case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted)
|
||||
case messageActionSecureValuesSent(types: [Api.SecureValueType])
|
||||
case messageActionContactSignUp(flags: Int32)
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -15323,6 +15304,12 @@ extension Api {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .messageActionContactSignUp(let flags):
|
||||
if boxed {
|
||||
buffer.appendInt32(1894744724)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -15372,6 +15359,8 @@ extension Api {
|
||||
return ("messageActionSecureValuesSentMe", [("values", values), ("credentials", credentials)])
|
||||
case .messageActionSecureValuesSent(let types):
|
||||
return ("messageActionSecureValuesSent", [("types", types)])
|
||||
case .messageActionContactSignUp(let flags):
|
||||
return ("messageActionContactSignUp", [("flags", flags)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -15637,6 +15626,17 @@ extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_messageActionContactSignUp(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.MessageAction.messageActionContactSignUp(flags: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
enum PhoneCall: TypeConstructorDescription {
|
||||
@ -16258,13 +16258,13 @@ extension Api {
|
||||
|
||||
}
|
||||
enum PageRelatedArticle: TypeConstructorDescription {
|
||||
case pageRelatedArticle(flags: Int32, url: String, webpageId: Int64, title: String?, description: String?, photoId: Int64?)
|
||||
case pageRelatedArticle(flags: Int32, url: String, webpageId: Int64, title: String?, description: String?, photoId: Int64?, author: String?, publishedDate: Int32?)
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId):
|
||||
case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate):
|
||||
if boxed {
|
||||
buffer.appendInt32(-242812612)
|
||||
buffer.appendInt32(-1282352120)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
@ -16272,14 +16272,16 @@ extension Api {
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt64(photoId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(author!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(publishedDate!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId):
|
||||
return ("pageRelatedArticle", [("flags", flags), ("url", url), ("webpageId", webpageId), ("title", title), ("description", description), ("photoId", photoId)])
|
||||
case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate):
|
||||
return ("pageRelatedArticle", [("flags", flags), ("url", url), ("webpageId", webpageId), ("title", title), ("description", description), ("photoId", photoId), ("author", author), ("publishedDate", publishedDate)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -16296,14 +16298,20 @@ extension Api {
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
||||
var _6: Int64?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt64() }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) }
|
||||
var _8: Int32?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.PageRelatedArticle.pageRelatedArticle(flags: _1!, url: _2!, webpageId: _3!, title: _4, description: _5, photoId: _6)
|
||||
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.PageRelatedArticle.pageRelatedArticle(flags: _1!, url: _2!, webpageId: _3!, title: _4, description: _5, photoId: _6, author: _7, publishedDate: _8)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
||||
@ -4939,12 +4939,53 @@ extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
static func confirmPasswordEmail(email: String, code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
static func confirmPasswordEmail(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-558870880)
|
||||
serializeString(email, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(-1881204448)
|
||||
serializeString(code, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "account.confirmPasswordEmail", parameters: [("email", email), ("code", code)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
return (FunctionDescription(name: "account.confirmPasswordEmail", parameters: [("code", code)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func resendPasswordEmail() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(2055154197)
|
||||
|
||||
return (FunctionDescription(name: "account.resendPasswordEmail", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func getContactSignUpNotification() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1626880216)
|
||||
|
||||
return (FunctionDescription(name: "account.getContactSignUpNotification", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func setContactSignUpNotification(silent: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-806076575)
|
||||
silent.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "account.setContactSignUpNotification", parameters: [("silent", silent)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
|
||||
@ -15,8 +15,8 @@ public enum ConfirmTwoStepRecoveryEmailError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func confirmTwoStepRecoveryEmail(network: Network, email: String, code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
|
||||
return network.request(Api.functions.account.confirmPasswordEmail(email: email, code: code), automaticFloodWait: false)
|
||||
public func confirmTwoStepRecoveryEmail(network: Network, code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
|
||||
return network.request(Api.functions.account.confirmPasswordEmail(code: code), automaticFloodWait: false)
|
||||
|> mapError { error -> ConfirmTwoStepRecoveryEmailError in
|
||||
if error.errorDescription == "EMAIL_INVALID" {
|
||||
return .invalidEmail
|
||||
@ -31,3 +31,19 @@ public func confirmTwoStepRecoveryEmail(network: Network, email: String, code: S
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public enum ResendTwoStepRecoveryEmailError {
|
||||
case flood
|
||||
case generic
|
||||
}
|
||||
|
||||
public func resendTwoStepRecoveryEmail(network: Network) -> Signal<Never, ResendTwoStepRecoveryEmailError> {
|
||||
return network.request(Api.functions.account.resendPasswordEmail(), automaticFloodWait: false)
|
||||
|> mapError { error -> ResendTwoStepRecoveryEmailError in
|
||||
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
|
||||
return .flood
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
@ -35,9 +35,11 @@ private final class ContactSyncManagerImpl {
|
||||
private var nextId: Int32 = 0
|
||||
private var operations: [ContactSyncOperation] = []
|
||||
|
||||
private var lastContactPresencesRequestTimestamp: Double?
|
||||
private var reimportAttempts: [TelegramDeviceContactImportIdentifier: Double] = [:]
|
||||
|
||||
private let importableContactsDisposable = MetaDisposable()
|
||||
private let significantStateUpdateCompletedDisposable = MetaDisposable()
|
||||
|
||||
init(queue: Queue, postbox: Postbox, network: Network, accountPeerId: PeerId, stateManager: AccountStateManager) {
|
||||
self.queue = queue
|
||||
@ -61,6 +63,36 @@ private final class ContactSyncManagerImpl {
|
||||
strongSelf.addOperation(.updatePresences)
|
||||
strongSelf.addOperation(.sync(importableContacts: importableContacts))
|
||||
}))
|
||||
self.significantStateUpdateCompletedDisposable.set((self.stateManager.significantStateUpdateCompleted
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let timestamp = CFAbsoluteTimeGetCurrent()
|
||||
let shouldUpdate: Bool
|
||||
if let lastContactPresencesRequestTimestamp = strongSelf.lastContactPresencesRequestTimestamp {
|
||||
if timestamp > lastContactPresencesRequestTimestamp + 30.0 * 60.0 {
|
||||
shouldUpdate = true
|
||||
} else {
|
||||
shouldUpdate = false
|
||||
}
|
||||
} else {
|
||||
shouldUpdate = true
|
||||
}
|
||||
if shouldUpdate {
|
||||
strongSelf.lastContactPresencesRequestTimestamp = timestamp
|
||||
var found = false
|
||||
for operation in strongSelf.operations {
|
||||
if case .updatePresences = operation.content {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
strongSelf.addOperation(.updatePresences)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func addIsContactUpdates(_ updates: [(PeerId, Bool)]) {
|
||||
|
||||
@ -950,7 +950,7 @@ extension InstantPageTableRow {
|
||||
extension InstantPageRelatedArticle {
|
||||
convenience init(apiRelatedArticle: Api.PageRelatedArticle) {
|
||||
switch apiRelatedArticle {
|
||||
case let .pageRelatedArticle(flags, url, webpageId, title, description, photoId):
|
||||
case let .pageRelatedArticle(flags, url, webpageId, title, description, photoId, author, publishedDate):
|
||||
var posterPhotoId: MediaId?
|
||||
if let photoId = photoId {
|
||||
posterPhotoId = MediaId(namespace: Namespaces.Media.CloudImage, id: photoId)
|
||||
|
||||
@ -5,20 +5,21 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public final class LimitsConfiguration: PreferencesEntry {
|
||||
public let maxGroupMemberCount: Int32
|
||||
public let maxSupergroupMemberCount: Int32
|
||||
public let maxMessageForwardBatchSize: Int32
|
||||
public let maxSavedGifCount: Int32
|
||||
public let maxRecentStickerCount: Int32
|
||||
public let maxMessageEditingInterval: Int32
|
||||
public let maxMediaCaptionLength: Int32
|
||||
public struct LimitsConfiguration: Equatable, PreferencesEntry {
|
||||
public var maxGroupMemberCount: Int32
|
||||
public var maxSupergroupMemberCount: Int32
|
||||
public var maxMessageForwardBatchSize: Int32
|
||||
public var maxSavedGifCount: Int32
|
||||
public var maxRecentStickerCount: Int32
|
||||
public var maxMessageEditingInterval: Int32
|
||||
public var maxMediaCaptionLength: Int32
|
||||
public var canRemoveIncomingMessagesInPrivateChats: Bool
|
||||
|
||||
public static var defaultValue: LimitsConfiguration {
|
||||
return LimitsConfiguration(maxGroupMemberCount: 200, maxSupergroupMemberCount: 5000, maxMessageForwardBatchSize: 50, maxSavedGifCount: 200, maxRecentStickerCount: 20, maxMessageEditingInterval: 2 * 24 * 60 * 60, maxMediaCaptionLength: 1000)
|
||||
return LimitsConfiguration(maxGroupMemberCount: 200, maxSupergroupMemberCount: 5000, maxMessageForwardBatchSize: 50, maxSavedGifCount: 200, maxRecentStickerCount: 20, maxMessageEditingInterval: 2 * 24 * 60 * 60, maxMediaCaptionLength: 1000, canRemoveIncomingMessagesInPrivateChats: false)
|
||||
}
|
||||
|
||||
init(maxGroupMemberCount: Int32, maxSupergroupMemberCount: Int32, maxMessageForwardBatchSize: Int32, maxSavedGifCount: Int32, maxRecentStickerCount: Int32, maxMessageEditingInterval: Int32, maxMediaCaptionLength: Int32) {
|
||||
init(maxGroupMemberCount: Int32, maxSupergroupMemberCount: Int32, maxMessageForwardBatchSize: Int32, maxSavedGifCount: Int32, maxRecentStickerCount: Int32, maxMessageEditingInterval: Int32, maxMediaCaptionLength: Int32, canRemoveIncomingMessagesInPrivateChats: Bool) {
|
||||
self.maxGroupMemberCount = maxGroupMemberCount
|
||||
self.maxSupergroupMemberCount = maxSupergroupMemberCount
|
||||
self.maxMessageForwardBatchSize = maxMessageForwardBatchSize
|
||||
@ -26,6 +27,7 @@ public final class LimitsConfiguration: PreferencesEntry {
|
||||
self.maxRecentStickerCount = maxRecentStickerCount
|
||||
self.maxMessageEditingInterval = maxMessageEditingInterval
|
||||
self.maxMediaCaptionLength = maxMediaCaptionLength
|
||||
self.canRemoveIncomingMessagesInPrivateChats = canRemoveIncomingMessagesInPrivateChats
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
@ -36,6 +38,7 @@ public final class LimitsConfiguration: PreferencesEntry {
|
||||
self.maxRecentStickerCount = decoder.decodeInt32ForKey("maxRecentStickerCount", orElse: 20)
|
||||
self.maxMessageEditingInterval = decoder.decodeInt32ForKey("maxMessageEditingInterval", orElse: 2 * 24 * 60 * 60)
|
||||
self.maxMediaCaptionLength = decoder.decodeInt32ForKey("maxMediaCaptionLength", orElse: 1000)
|
||||
self.canRemoveIncomingMessagesInPrivateChats = decoder.decodeInt32ForKey("canRemoveIncomingMessagesInPrivateChats", orElse: 0) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -46,34 +49,14 @@ public final class LimitsConfiguration: PreferencesEntry {
|
||||
encoder.encodeInt32(self.maxRecentStickerCount, forKey: "maxRecentStickerCount")
|
||||
encoder.encodeInt32(self.maxMessageEditingInterval, forKey: "maxMessageEditingInterval")
|
||||
encoder.encodeInt32(self.maxMediaCaptionLength, forKey: "maxMediaCaptionLength")
|
||||
encoder.encodeInt32(self.canRemoveIncomingMessagesInPrivateChats ? 1 : 0, forKey: "canRemoveIncomingMessagesInPrivateChats")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
guard let to = to as? LimitsConfiguration else {
|
||||
return false
|
||||
}
|
||||
if self.maxGroupMemberCount != to.maxGroupMemberCount {
|
||||
return false
|
||||
}
|
||||
if self.maxSupergroupMemberCount != to.maxSupergroupMemberCount {
|
||||
return false
|
||||
}
|
||||
if self.maxMessageForwardBatchSize != to.maxMessageForwardBatchSize {
|
||||
return false
|
||||
}
|
||||
if self.maxSavedGifCount != to.maxSavedGifCount {
|
||||
return false
|
||||
}
|
||||
if self.maxRecentStickerCount != to.maxRecentStickerCount {
|
||||
return false
|
||||
}
|
||||
if self.maxMessageEditingInterval != to.maxMessageEditingInterval {
|
||||
return false
|
||||
}
|
||||
if self.maxMediaCaptionLength != to.maxMediaCaptionLength {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return self == to
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public final class LocalizationInfo: PostboxCoding {
|
||||
public struct LocalizationInfo: PostboxCoding, Equatable {
|
||||
public let languageCode: String
|
||||
public let baseLanguageCode: String?
|
||||
public let customPluralizationCode: String?
|
||||
@ -14,8 +14,9 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
public let isOfficial: Bool
|
||||
public let totalStringCount: Int32
|
||||
public let translatedStringCount: Int32
|
||||
public let platformUrl: String
|
||||
|
||||
public init(languageCode: String, baseLanguageCode: String?, customPluralizationCode: String?, title: String, localizedTitle: String, isOfficial: Bool, totalStringCount: Int32, translatedStringCount: Int32) {
|
||||
public init(languageCode: String, baseLanguageCode: String?, customPluralizationCode: String?, title: String, localizedTitle: String, isOfficial: Bool, totalStringCount: Int32, translatedStringCount: Int32, platformUrl: String) {
|
||||
self.languageCode = languageCode
|
||||
self.baseLanguageCode = baseLanguageCode
|
||||
self.customPluralizationCode = customPluralizationCode
|
||||
@ -24,6 +25,7 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
self.isOfficial = isOfficial
|
||||
self.totalStringCount = totalStringCount
|
||||
self.translatedStringCount = translatedStringCount
|
||||
self.platformUrl = platformUrl
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
@ -35,6 +37,7 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
self.isOfficial = decoder.decodeInt32ForKey("of", orElse: 0) != 0
|
||||
self.totalStringCount = decoder.decodeInt32ForKey("tsc", orElse: 0)
|
||||
self.translatedStringCount = decoder.decodeInt32ForKey("lsc", orElse: 0)
|
||||
self.platformUrl = decoder.decodeStringForKey("platformUrl", orElse: "")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -54,14 +57,15 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
encoder.encodeInt32(self.isOfficial ? 1 : 0, forKey: "of")
|
||||
encoder.encodeInt32(self.totalStringCount, forKey: "tsc")
|
||||
encoder.encodeInt32(self.translatedStringCount, forKey: "lsc")
|
||||
encoder.encodeString(self.platformUrl, forKey: "platformUrl")
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalizationInfo {
|
||||
convenience init(apiLanguage: Api.LangPackLanguage) {
|
||||
init(apiLanguage: Api.LangPackLanguage) {
|
||||
switch apiLanguage {
|
||||
case let .langPackLanguage(language):
|
||||
self.init(languageCode: language.langCode, baseLanguageCode: language.baseLangCode, customPluralizationCode: language.pluralCode, title: language.name, localizedTitle: language.nativeName, isOfficial: (language.flags & (1 << 0)) != 0, totalStringCount: language.stringsCount, translatedStringCount: language.translatedCount)
|
||||
self.init(languageCode: language.langCode, baseLanguageCode: language.baseLangCode, customPluralizationCode: language.pluralCode, title: language.name, localizedTitle: language.nativeName, isOfficial: (language.flags & (1 << 0)) != 0, totalStringCount: language.stringsCount, translatedStringCount: language.translatedCount, platformUrl: language.translationsUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
102
TelegramCore/LocalizationListState.swift
Normal file
102
TelegramCore/LocalizationListState.swift
Normal file
@ -0,0 +1,102 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public struct LocalizationListState: PreferencesEntry, Equatable {
|
||||
public var availableOfficialLocalizations: [LocalizationInfo]
|
||||
public var availableSavedLocalizations: [LocalizationInfo]
|
||||
|
||||
public static var defaultSettings: LocalizationListState {
|
||||
return LocalizationListState(availableOfficialLocalizations: [], availableSavedLocalizations: [])
|
||||
}
|
||||
|
||||
public init(availableOfficialLocalizations: [LocalizationInfo], availableSavedLocalizations: [LocalizationInfo]) {
|
||||
self.availableOfficialLocalizations = availableOfficialLocalizations
|
||||
self.availableSavedLocalizations = availableSavedLocalizations
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.availableOfficialLocalizations = decoder.decodeObjectArrayWithDecoderForKey("availableOfficialLocalizations")
|
||||
self.availableSavedLocalizations = decoder.decodeObjectArrayWithDecoderForKey("availableSavedLocalizations")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeObjectArray(self.availableOfficialLocalizations, forKey: "availableOfficialLocalizations")
|
||||
encoder.encodeObjectArray(self.availableSavedLocalizations, forKey: "availableSavedLocalizations")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
guard let to = to as? LocalizationListState else {
|
||||
return false
|
||||
}
|
||||
|
||||
return self == to
|
||||
}
|
||||
}
|
||||
|
||||
public func removeSavedLocalization(transaction: Transaction, languageCode: String) {
|
||||
updateLocalizationListStateInteractively(transaction: transaction, { state in
|
||||
var state = state
|
||||
state.availableSavedLocalizations = state.availableSavedLocalizations.filter({ $0.languageCode != languageCode })
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
func updateLocalizationListStateInteractively(postbox: Postbox, _ f: @escaping (LocalizationListState) -> LocalizationListState) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
updateLocalizationListStateInteractively(transaction: transaction, f)
|
||||
}
|
||||
}
|
||||
|
||||
func updateLocalizationListStateInteractively(transaction: Transaction, _ f: @escaping (LocalizationListState) -> LocalizationListState) {
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.localizationListState, { current in
|
||||
let previous = (current as? LocalizationListState) ?? LocalizationListState.defaultSettings
|
||||
var updated = f(previous)
|
||||
var removeOfficialIndices: [Int] = []
|
||||
var officialSet = Set<String>()
|
||||
for i in 0 ..< updated.availableOfficialLocalizations.count {
|
||||
if officialSet.contains(updated.availableOfficialLocalizations[i].languageCode) {
|
||||
removeOfficialIndices.append(i)
|
||||
} else {
|
||||
officialSet.insert(updated.availableOfficialLocalizations[i].languageCode)
|
||||
}
|
||||
}
|
||||
for i in removeOfficialIndices.reversed() {
|
||||
updated.availableOfficialLocalizations.remove(at: i)
|
||||
}
|
||||
var removeSavedIndices: [Int] = []
|
||||
var savedSet = Set<String>()
|
||||
for i in 0 ..< updated.availableSavedLocalizations.count {
|
||||
if savedSet.contains(updated.availableSavedLocalizations[i].languageCode) {
|
||||
removeSavedIndices.append(i)
|
||||
} else {
|
||||
savedSet.insert(updated.availableSavedLocalizations[i].languageCode)
|
||||
}
|
||||
}
|
||||
for i in removeSavedIndices.reversed() {
|
||||
updated.availableSavedLocalizations.remove(at: i)
|
||||
}
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
||||
public func synchronizedLocalizationListState(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
|
||||
return network.request(Api.functions.langpack.getLanguages(langPack: ""))
|
||||
|> retryRequest
|
||||
|> mapToSignal { languages -> Signal<Never, NoError> in
|
||||
let infos: [LocalizationInfo] = languages.map(LocalizationInfo.init(apiLanguage:))
|
||||
return postbox.transaction { transaction -> Void in
|
||||
updateLocalizationListStateInteractively(transaction: transaction, { current in
|
||||
var current = current
|
||||
current.availableOfficialLocalizations = infos
|
||||
return current
|
||||
})
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
@ -7,23 +7,27 @@ import Foundation
|
||||
|
||||
public final class LocalizationComponent: Equatable, PostboxCoding {
|
||||
public let languageCode: String
|
||||
public let localizedName: String
|
||||
public let localization: Localization
|
||||
public let customPluralizationCode: String?
|
||||
|
||||
public init(languageCode: String, localization: Localization, customPluralizationCode: String?) {
|
||||
public init(languageCode: String, localizedName: String, localization: Localization, customPluralizationCode: String?) {
|
||||
self.languageCode = languageCode
|
||||
self.localizedName = localizedName
|
||||
self.localization = localization
|
||||
self.customPluralizationCode = customPluralizationCode
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "")
|
||||
self.localizedName = decoder.decodeStringForKey("localizedName", orElse: "")
|
||||
self.localization = decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization
|
||||
self.customPluralizationCode = decoder.decodeOptionalStringForKey("cpl")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeString(self.languageCode, forKey: "lc")
|
||||
encoder.encodeString(self.localizedName, forKey: "localizedName")
|
||||
encoder.encodeObject(self.localization, forKey: "loc")
|
||||
if let customPluralizationCode = self.customPluralizationCode {
|
||||
encoder.encodeString(customPluralizationCode, forKey: "cpl")
|
||||
@ -36,6 +40,9 @@ public final class LocalizationComponent: Equatable, PostboxCoding {
|
||||
if lhs.languageCode != rhs.languageCode {
|
||||
return false
|
||||
}
|
||||
if lhs.localizedName != rhs.localizedName {
|
||||
return false
|
||||
}
|
||||
if lhs.localization != rhs.localization {
|
||||
return false
|
||||
}
|
||||
@ -57,7 +64,7 @@ public final class LocalizationSettings: PreferencesEntry, Equatable {
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
if let languageCode = decoder.decodeOptionalStringForKey("lc") {
|
||||
self.primaryComponent = LocalizationComponent(languageCode: languageCode, localization: decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization, customPluralizationCode: nil)
|
||||
self.primaryComponent = LocalizationComponent(languageCode: languageCode, localizedName: "", localization: decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization, customPluralizationCode: nil)
|
||||
self.secondaryComponent = nil
|
||||
} else {
|
||||
self.primaryComponent = decoder.decodeObjectForKey("primaryComponent", decoder: { LocalizationComponent(decoder: $0) }) as! LocalizationComponent
|
||||
|
||||
@ -139,11 +139,23 @@ public func downloadAndApplyLocalization(postbox: Postbox, network: Network, lan
|
||||
}
|
||||
var secondaryComponent: LocalizationComponent?
|
||||
if let secondaryCode = preview.baseLanguageCode, components.count > 1 {
|
||||
secondaryComponent = LocalizationComponent(languageCode: secondaryCode, localization: components[1], customPluralizationCode: nil)
|
||||
secondaryComponent = LocalizationComponent(languageCode: secondaryCode, localizedName: "", localization: components[1], customPluralizationCode: nil)
|
||||
}
|
||||
return postbox.transaction { transaction -> Signal<Void, DownloadAndApplyLocalizationError> in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.localizationSettings, { _ in
|
||||
return LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: preview.languageCode, localization: primaryLocalization, customPluralizationCode: preview.customPluralizationCode), secondaryComponent: secondaryComponent)
|
||||
return LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: preview.languageCode, localizedName: preview.localizedTitle, localization: primaryLocalization, customPluralizationCode: preview.customPluralizationCode), secondaryComponent: secondaryComponent)
|
||||
})
|
||||
|
||||
updateLocalizationListStateInteractively(transaction: transaction, { state in
|
||||
var state = state
|
||||
for i in 0 ..< state.availableSavedLocalizations.count {
|
||||
if state.availableSavedLocalizations[i].languageCode == preview.languageCode {
|
||||
state.availableSavedLocalizations.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
state.availableSavedLocalizations.insert(preview, at: 0)
|
||||
return state
|
||||
})
|
||||
|
||||
network.context.updateApiEnvironment { current in
|
||||
|
||||
@ -60,7 +60,7 @@ func managedConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<V
|
||||
return entry
|
||||
})
|
||||
|
||||
updateLimitsConfiguration(transaction: transaction, configuration: LimitsConfiguration(maxGroupMemberCount: config.chatSizeMax, maxSupergroupMemberCount: config.megagroupSizeMax, maxMessageForwardBatchSize: config.forwardedCountMax, maxSavedGifCount: config.savedGifsLimit, maxRecentStickerCount: config.stickersRecentLimit, maxMessageEditingInterval: config.editTimeLimit, maxMediaCaptionLength: config.captionLengthMax))
|
||||
updateLimitsConfiguration(transaction: transaction, configuration: LimitsConfiguration(maxGroupMemberCount: config.chatSizeMax, maxSupergroupMemberCount: config.megagroupSizeMax, maxMessageForwardBatchSize: config.forwardedCountMax, maxSavedGifCount: config.savedGifsLimit, maxRecentStickerCount: config.stickersRecentLimit, maxMessageEditingInterval: config.editTimeLimit, maxMediaCaptionLength: config.captionLengthMax, canRemoveIncomingMessagesInPrivateChats: (config.flags & (1 << 6)) != 0))
|
||||
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
var invalidateLocalization = false
|
||||
|
||||
@ -174,7 +174,7 @@ private func synchronizeLocalizationUpdates(transaction: Transaction, postbox: P
|
||||
return postbox.transaction { transaction -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
|
||||
var currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
var currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localizedName: "English", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
|
||||
for difference in parsedDifferences {
|
||||
let current: (isPrimary: Bool, entries: [LocalizationEntry])
|
||||
@ -205,9 +205,9 @@ private func synchronizeLocalizationUpdates(transaction: Transaction, postbox: P
|
||||
}
|
||||
mergedEntries.append(contentsOf: difference.entries)
|
||||
if current.isPrimary {
|
||||
currentSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
currentSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localizedName: currentSettings.primaryComponent.localizedName, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
} else if let currentSecondary = currentSettings.secondaryComponent {
|
||||
currentSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
currentSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localizedName: currentSecondary.localizedName, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,13 +284,13 @@ func tryApplyingLanguageDifference(transaction: Transaction, langCode: String, d
|
||||
}
|
||||
mergedEntries.append(contentsOf: updatedEntries)
|
||||
|
||||
let currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
let currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localizedName: "English", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
|
||||
var updatedSettings: LocalizationSettings
|
||||
if isPrimary {
|
||||
updatedSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
updatedSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localizedName: currentSettings.primaryComponent.localizedName, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
} else if let currentSecondary = currentSettings.secondaryComponent {
|
||||
updatedSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
updatedSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localizedName: currentSecondary.localizedName, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
} else {
|
||||
assertionFailure()
|
||||
return false
|
||||
|
||||
@ -146,6 +146,7 @@ private enum PreferencesKeyValues: Int32 {
|
||||
case remoteStorageConfiguration = 10
|
||||
case voipConfiguration = 11
|
||||
case appChangelogState = 12
|
||||
case localizationListState = 13
|
||||
}
|
||||
|
||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||
@ -226,6 +227,12 @@ public struct PreferencesKeys {
|
||||
key.setInt32(0, value: PreferencesKeyValues.appChangelogState.rawValue)
|
||||
return key
|
||||
}()
|
||||
|
||||
public static let localizationListState: ValueBoxKey = {
|
||||
let key = ValueBoxKey(length: 4)
|
||||
key.setInt32(0, value: PreferencesKeyValues.localizationListState.rawValue)
|
||||
return key
|
||||
}()
|
||||
}
|
||||
|
||||
private enum SharedDataKeyValues: Int32 {
|
||||
|
||||
@ -202,7 +202,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 88
|
||||
return 90
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
||||
@ -209,7 +209,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
}
|
||||
|
||||
switch action {
|
||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe:
|
||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp:
|
||||
break
|
||||
case let .messageActionChannelMigrateFrom(_, chatId):
|
||||
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId))
|
||||
|
||||
@ -282,6 +282,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
||||
return nil
|
||||
case let .messageActionSecureValuesSent(types):
|
||||
return TelegramMediaAction(action: .botSentSecureValues(types: types.map(SentSecureValueType.init)))
|
||||
case .messageActionContactSignUp:
|
||||
return TelegramMediaAction(action: .peerJoined)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -281,8 +281,6 @@ extension Api.Update {
|
||||
case let .chatParticipantsForbidden(_, chatId, _):
|
||||
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)]
|
||||
}
|
||||
case let .updateContactRegistered(userId, _):
|
||||
return [PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
|
||||
case let .updateDeleteChannelMessages(channelId, _, _, _):
|
||||
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
|
||||
case let .updateNewChannelMessage(message, _, _):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user