Fixed unread counter category for private channels

Added support for "contact joined" service messages
Updated password recovery API
Updated Localization APIs
Added limited contact presence polling after getDifference
This commit is contained in:
Peter 2018-11-11 17:46:21 +04:00
parent bf8ec5775f
commit 0b96d69daa
23 changed files with 369 additions and 173 deletions

View File

@ -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 */,

View File

@ -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]
}

View File

@ -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())
}

View File

@ -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):

View File

@ -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 {

View File

@ -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) }

View File

@ -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

View File

@ -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() {

View File

@ -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
}

View File

@ -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)]) {

View File

@ -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)

View File

@ -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
}
}

View File

@ -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)
}
}
}

View 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
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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! {

View File

@ -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))

View File

@ -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)
}
}

View File

@ -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, _, _):