API updates

[skip ci]
This commit is contained in:
Peter 2019-06-14 01:21:42 +01:00
parent 819583121e
commit 7ffb9e3034
32 changed files with 2955 additions and 2787 deletions

View File

@ -4363,6 +4363,8 @@ Any member of this group will be able to see messages in the channel.";
"AddContact.ContactWillBeSharedNow" = "When you tap **Done**, your phone number will become visible to %@.";
"AddContact.ContactWillBeSharedAfterMutual" = "Phone number will be visible once %1$@ adds you as a contact. Your phone number will become visible to %1$@.";
"AddContact.SharedContactException" = "Share My Phone Number";
"AddContact.SharedContactExceptionInfo" = "You can make your phone visible to %@.";
"AddContact.StatusSuccess" = "%@ is now in your contacts list.";
"Conversation.ShareMyPhoneNumber.StatusSuccess" = "%@ can now see your phone number.";

View File

@ -1291,10 +1291,10 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
updatedState.updatePeerChatInclusion(peerId: peer.peerId, groupId: PeerGroupId(rawValue: folderId), changedGroup: true)
}
}
case let .updateContactLocated(contacts):
case let .updatePeerLocated(contacts):
var peersNearby: [PeerNearby] = []
for case let .contactLocated(userId, expires, distance) in contacts {
peersNearby.append(PeerNearby(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), expires: expires, distance: distance))
for case let .peerLocated(peer, expires, distance) in contacts {
peersNearby.append(PeerNearby(id: peer.peerId, expires: expires, distance: distance))
}
updatedState.updatePeersNearby(peersNearby)
default:

View File

@ -202,7 +202,7 @@ private func wrappedHistoryViewAdditionalData(chatLocation: ChatLocation, additi
private final class PeerCachedDataContext {
var viewIds = Set<Int32>()
var timestamp: Double?
var referenceData: CachedPeerData?
var hasCachedData: Bool = false
let disposable = MetaDisposable()
deinit {
@ -780,22 +780,22 @@ public final class AccountViewTracker {
}
}
private func updateCachedPeerData(peerId: PeerId, viewId: Int32, referenceData: CachedPeerData?) {
private func updateCachedPeerData(peerId: PeerId, viewId: Int32, hasCachedData: Bool) {
self.queue.async {
let context: PeerCachedDataContext
var dataUpdated = false
if let existingContext = self.cachedDataContexts[peerId] {
context = existingContext
context.referenceData = referenceData
context.hasCachedData = hasCachedData
if context.timestamp == nil || abs(CFAbsoluteTimeGetCurrent() - context.timestamp!) > 60.0 * 5 {
context.timestamp = CFAbsoluteTimeGetCurrent()
dataUpdated = true
}
} else {
context = PeerCachedDataContext()
context.referenceData = referenceData
context.hasCachedData = hasCachedData
self.cachedDataContexts[peerId] = context
if context.referenceData == nil || context.timestamp == nil || abs(CFAbsoluteTimeGetCurrent() - context.timestamp!) > 60.0 * 5 {
if !context.hasCachedData || context.timestamp == nil || abs(CFAbsoluteTimeGetCurrent() - context.timestamp!) > 60.0 * 5 {
context.timestamp = CFAbsoluteTimeGetCurrent()
dataUpdated = true
}
@ -816,7 +816,7 @@ public final class AccountViewTracker {
context.viewIds.remove(id)
if context.viewIds.isEmpty {
context.disposable.set(nil)
context.referenceData = nil
context.hasCachedData = false
}
}
}
@ -968,7 +968,7 @@ public final class AccountViewTracker {
}
}, next: { [weak self] next, viewId in
if let strongSelf = self {
strongSelf.updateCachedPeerData(peerId: peerId, viewId: viewId, referenceData: next.cachedData)
strongSelf.updateCachedPeerData(peerId: peerId, viewId: viewId, hasCachedData: next.cachedData != nil)
}
}, disposed: { [weak self] viewId in
if let strongSelf = self {

View File

@ -10,7 +10,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-206066487] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[461151667] = { return Api.ChatFull.parse_chatFull($0) }
dict[-1736252138] = { return Api.ChatFull.parse_channelFull($0) }
dict[277964371] = { return Api.ChatFull.parse_channelFull($0) }
dict[1465219162] = { return Api.PollResults.parse_pollResults($0) }
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
@ -172,7 +172,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[-1657903163] = { return Api.Update.parse_updateContactLink($0) }
dict[314359194] = { return Api.Update.parse_updateNewEncryptedMessage($0) }
dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($0) }
dict[-1264392051] = { return Api.Update.parse_updateEncryption($0) }
@ -234,7 +233,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[856380452] = { return Api.Update.parse_updateReadChannelInbox($0) }
dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) }
dict[1786671974] = { return Api.Update.parse_updatePeerSettings($0) }
dict[1602468195] = { return Api.Update.parse_updateContactLocated($0) }
dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) }
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
@ -247,7 +246,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-55902537] = { return Api.InputDialogPeer.parse_inputDialogPeer($0) }
dict[1684014375] = { return Api.InputDialogPeer.parse_inputDialogPeerFolder($0) }
dict[-994444869] = { return Api.Error.parse_error($0) }
dict[-1150339286] = { return Api.ContactLocated.parse_contactLocated($0) }
dict[-1560655744] = { return Api.KeyboardButton.parse_keyboardButton($0) }
dict[629866245] = { return Api.KeyboardButton.parse_keyboardButtonUrl($0) }
dict[1748655686] = { return Api.KeyboardButton.parse_keyboardButtonCallback($0) }
@ -384,6 +382,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1895328189] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionStopPoll($0) }
dict[1129042607] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangePhoto($0) }
dict[-1569748965] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLinkedChat($0) }
dict[241923758] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLocation($0) }
dict[-526508104] = { return Api.help.ProxyData.parse_proxyDataEmpty($0) }
dict[737668643] = { return Api.help.ProxyData.parse_proxyDataPromo($0) }
dict[-543777747] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) }
@ -456,6 +455,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
dict[157948117] = { return Api.upload.File.parse_file($0) }
dict[-242427324] = { return Api.upload.File.parse_fileCdnRedirect($0) }
dict[-1078612597] = { return Api.ChannelLocation.parse_channelLocationEmpty($0) }
dict[547062491] = { return Api.ChannelLocation.parse_channelLocation($0) }
dict[182649427] = { return Api.MessageRange.parse_messageRange($0) }
dict[946083368] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultSuccess($0) }
dict[904138920] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultArchive($0) }
@ -702,9 +703,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($0) }
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
dict[1599050311] = { return Api.ContactLink.parse_contactLinkUnknown($0) }
dict[-17968211] = { return Api.ContactLink.parse_contactLinkNone($0) }
dict[-721239344] = { return Api.ContactLink.parse_contactLinkContact($0) }
dict[-104284986] = { return Api.WebDocument.parse_webDocumentNoProxy($0) }
dict[475467473] = { return Api.WebDocument.parse_webDocument($0) }
dict[-1290580579] = { return Api.contacts.Found.parse_found($0) }
@ -757,6 +755,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-931638658] = { return Api.EncryptedChat.parse_encryptedChatRequested($0) }
dict[-94974410] = { return Api.EncryptedChat.parse_encryptedChat($0) }
dict[332848423] = { return Api.EncryptedChat.parse_encryptedChatDiscarded($0) }
dict[-901375139] = { return Api.PeerLocated.parse_peerLocated($0) }
dict[922273905] = { return Api.Document.parse_documentEmpty($0) }
dict[-1683841855] = { return Api.Document.parse_document($0) }
dict[-1707344487] = { return Api.messages.HighScores.parse_highScores($0) }
@ -929,8 +928,6 @@ struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.Error:
_1.serialize(buffer, boxed)
case let _1 as Api.ContactLocated:
_1.serialize(buffer, boxed)
case let _1 as Api.KeyboardButton:
_1.serialize(buffer, boxed)
case let _1 as Api.ContactStatus:
@ -1095,6 +1092,8 @@ struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.upload.File:
_1.serialize(buffer, boxed)
case let _1 as Api.ChannelLocation:
_1.serialize(buffer, boxed)
case let _1 as Api.MessageRange:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.StickerSetInstallResult:
@ -1285,8 +1284,6 @@ struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.DialogPeer:
_1.serialize(buffer, boxed)
case let _1 as Api.ContactLink:
_1.serialize(buffer, boxed)
case let _1 as Api.WebDocument:
_1.serialize(buffer, boxed)
case let _1 as Api.contacts.Found:
@ -1325,6 +1322,8 @@ struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.EncryptedChat:
_1.serialize(buffer, boxed)
case let _1 as Api.PeerLocated:
_1.serialize(buffer, boxed)
case let _1 as Api.Document:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.HighScores:

View File

@ -51,7 +51,7 @@ extension Api {
}
enum ChatFull: TypeConstructorDescription {
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?)
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, pts: Int32)
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, pts: Int32)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -74,9 +74,9 @@ extension Api {
if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
break
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let pts):
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let pts):
if boxed {
buffer.appendInt32(-1736252138)
buffer.appendInt32(277964371)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
@ -103,7 +103,8 @@ extension Api {
if Int(flags) & Int(1 << 8) != 0 {stickerset!.serialize(buffer, true)}
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(availableMinId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {serializeInt32(linkedChatId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 14) != 0 {serializeInt32(linkedChatId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 15) != 0 {location!.serialize(buffer, true)}
serializeInt32(pts, buffer: buffer, boxed: false)
break
}
@ -113,8 +114,8 @@ extension Api {
switch self {
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId):
return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("folderId", folderId)])
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let pts):
return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("pts", pts)])
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let pts):
return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("location", location), ("pts", pts)])
}
}
@ -220,9 +221,13 @@ extension Api {
var _21: Int32?
if Int(_1!) & Int(1 << 11) != 0 {_21 = reader.readInt32() }
var _22: Int32?
if Int(_1!) & Int(1 << 13) != 0 {_22 = reader.readInt32() }
var _23: Int32?
_23 = reader.readInt32()
if Int(_1!) & Int(1 << 14) != 0 {_22 = reader.readInt32() }
var _23: Api.ChannelLocation?
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
_23 = Api.parse(reader, signature: signature) as? Api.ChannelLocation
} }
var _24: Int32?
_24 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -244,10 +249,11 @@ extension Api {
let _c19 = (Int(_1!) & Int(1 << 8) == 0) || _19 != nil
let _c20 = (Int(_1!) & Int(1 << 9) == 0) || _20 != nil
let _c21 = (Int(_1!) & Int(1 << 11) == 0) || _21 != nil
let _c22 = (Int(_1!) & Int(1 << 13) == 0) || _22 != nil
let _c23 = _23 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 {
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, pts: _23!)
let _c22 = (Int(_1!) & Int(1 << 14) == 0) || _22 != nil
let _c23 = (Int(_1!) & Int(1 << 15) == 0) || _23 != nil
let _c24 = _24 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 {
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, pts: _24!)
}
else {
return nil
@ -3943,7 +3949,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 updateContactLink(userId: Int32, myLink: Api.ContactLink, foreignLink: Api.ContactLink)
case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32)
case updateEncryptedChatTyping(chatId: Int32)
case updateEncryption(chat: Api.EncryptedChat, date: Int32)
@ -4005,7 +4010,7 @@ extension Api {
case updateReadChannelInbox(flags: Int32, folderId: Int32?, channelId: Int32, maxId: Int32, stillUnreadCount: Int32, pts: Int32)
case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32)
case updatePeerSettings(peer: Api.Peer, settings: Api.PeerSettings)
case updateContactLocated(contacts: [Api.ContactLocated])
case updatePeerLocated(peers: [Api.PeerLocated])
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -4082,14 +4087,6 @@ extension Api {
photo.serialize(buffer, true)
previous.serialize(buffer, true)
break
case .updateContactLink(let userId, let myLink, let foreignLink):
if boxed {
buffer.appendInt32(-1657903163)
}
serializeInt32(userId, buffer: buffer, boxed: false)
myLink.serialize(buffer, true)
foreignLink.serialize(buffer, true)
break
case .updateNewEncryptedMessage(let message, let qts):
if boxed {
buffer.appendInt32(314359194)
@ -4605,13 +4602,13 @@ extension Api {
peer.serialize(buffer, true)
settings.serialize(buffer, true)
break
case .updateContactLocated(let contacts):
case .updatePeerLocated(let peers):
if boxed {
buffer.appendInt32(1602468195)
buffer.appendInt32(-1263546448)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(contacts.count))
for item in contacts {
buffer.appendInt32(Int32(peers.count))
for item in peers {
item.serialize(buffer, true)
}
break
@ -4638,8 +4635,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 .updateContactLink(let userId, let myLink, let foreignLink):
return ("updateContactLink", [("userId", userId), ("myLink", myLink), ("foreignLink", foreignLink)])
case .updateNewEncryptedMessage(let message, let qts):
return ("updateNewEncryptedMessage", [("message", message), ("qts", qts)])
case .updateEncryptedChatTyping(let chatId):
@ -4762,8 +4757,8 @@ extension Api {
return ("updateReadHistoryInbox", [("flags", flags), ("folderId", folderId), ("peer", peer), ("maxId", maxId), ("stillUnreadCount", stillUnreadCount), ("pts", pts), ("ptsCount", ptsCount)])
case .updatePeerSettings(let peer, let settings):
return ("updatePeerSettings", [("peer", peer), ("settings", settings)])
case .updateContactLocated(let contacts):
return ("updateContactLocated", [("contacts", contacts)])
case .updatePeerLocated(let peers):
return ("updatePeerLocated", [("peers", peers)])
}
}
@ -4927,27 +4922,6 @@ extension Api {
return nil
}
}
static func parse_updateContactLink(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.ContactLink?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.ContactLink
}
var _3: Api.ContactLink?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.ContactLink
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.Update.updateContactLink(userId: _1!, myLink: _2!, foreignLink: _3!)
}
else {
return nil
}
}
static func parse_updateNewEncryptedMessage(_ reader: BufferReader) -> Update? {
var _1: Api.EncryptedMessage?
if let signature = reader.readInt32() {
@ -5986,14 +5960,14 @@ extension Api {
return nil
}
}
static func parse_updateContactLocated(_ reader: BufferReader) -> Update? {
var _1: [Api.ContactLocated]?
static func parse_updatePeerLocated(_ reader: BufferReader) -> Update? {
var _1: [Api.PeerLocated]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ContactLocated.self)
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerLocated.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.Update.updateContactLocated(contacts: _1!)
return Api.Update.updatePeerLocated(peers: _1!)
}
else {
return nil
@ -6338,48 +6312,6 @@ extension Api {
}
}
}
enum ContactLocated: TypeConstructorDescription {
case contactLocated(userId: Int32, expires: Int32, distance: Int32)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .contactLocated(let userId, let expires, let distance):
if boxed {
buffer.appendInt32(-1150339286)
}
serializeInt32(userId, buffer: buffer, boxed: false)
serializeInt32(expires, buffer: buffer, boxed: false)
serializeInt32(distance, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .contactLocated(let userId, let expires, let distance):
return ("contactLocated", [("userId", userId), ("expires", expires), ("distance", distance)])
}
}
static func parse_contactLocated(_ reader: BufferReader) -> ContactLocated? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.ContactLocated.contactLocated(userId: _1!, expires: _2!, distance: _3!)
}
else {
return nil
}
}
}
enum KeyboardButton: TypeConstructorDescription {
case keyboardButton(text: String)
@ -9267,6 +9199,7 @@ extension Api {
case channelAdminLogEventActionStopPoll(message: Api.Message)
case channelAdminLogEventActionChangePhoto(prevPhoto: Api.Photo, newPhoto: Api.Photo)
case channelAdminLogEventActionChangeLinkedChat(prevValue: Int32, newValue: Int32)
case channelAdminLogEventActionChangeLocation(prevValue: Api.ChannelLocation, newValue: Api.ChannelLocation)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -9394,6 +9327,13 @@ extension Api {
serializeInt32(prevValue, buffer: buffer, boxed: false)
serializeInt32(newValue, buffer: buffer, boxed: false)
break
case .channelAdminLogEventActionChangeLocation(let prevValue, let newValue):
if boxed {
buffer.appendInt32(241923758)
}
prevValue.serialize(buffer, true)
newValue.serialize(buffer, true)
break
}
}
@ -9437,6 +9377,8 @@ extension Api {
return ("channelAdminLogEventActionChangePhoto", [("prevPhoto", prevPhoto), ("newPhoto", newPhoto)])
case .channelAdminLogEventActionChangeLinkedChat(let prevValue, let newValue):
return ("channelAdminLogEventActionChangeLinkedChat", [("prevValue", prevValue), ("newValue", newValue)])
case .channelAdminLogEventActionChangeLocation(let prevValue, let newValue):
return ("channelAdminLogEventActionChangeLocation", [("prevValue", prevValue), ("newValue", newValue)])
}
}
@ -9701,6 +9643,24 @@ extension Api {
return nil
}
}
static func parse_channelAdminLogEventActionChangeLocation(_ reader: BufferReader) -> ChannelAdminLogEventAction? {
var _1: Api.ChannelLocation?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.ChannelLocation
}
var _2: Api.ChannelLocation?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.ChannelLocation
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.ChannelAdminLogEventAction.channelAdminLogEventActionChangeLocation(prevValue: _1!, newValue: _2!)
}
else {
return nil
}
}
}
enum SecurePlainData: TypeConstructorDescription {
@ -11404,6 +11364,58 @@ extension Api {
}
}
}
enum ChannelLocation: TypeConstructorDescription {
case channelLocationEmpty
case channelLocation(geoPoint: Api.GeoPoint, address: String)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .channelLocationEmpty:
if boxed {
buffer.appendInt32(-1078612597)
}
break
case .channelLocation(let geoPoint, let address):
if boxed {
buffer.appendInt32(547062491)
}
geoPoint.serialize(buffer, true)
serializeString(address, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .channelLocationEmpty:
return ("channelLocationEmpty", [])
case .channelLocation(let geoPoint, let address):
return ("channelLocation", [("geoPoint", geoPoint), ("address", address)])
}
}
static func parse_channelLocationEmpty(_ reader: BufferReader) -> ChannelLocation? {
return Api.ChannelLocation.channelLocationEmpty
}
static func parse_channelLocation(_ reader: BufferReader) -> ChannelLocation? {
var _1: Api.GeoPoint?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.GeoPoint
}
var _2: String?
_2 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.ChannelLocation.channelLocation(geoPoint: _1!, address: _2!)
}
else {
return nil
}
}
}
enum MessageRange: TypeConstructorDescription {
case messageRange(minId: Int32, maxId: Int32)
@ -17788,56 +17800,6 @@ extension Api {
}
}
}
enum ContactLink: TypeConstructorDescription {
case contactLinkUnknown
case contactLinkNone
case contactLinkContact
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .contactLinkUnknown:
if boxed {
buffer.appendInt32(1599050311)
}
break
case .contactLinkNone:
if boxed {
buffer.appendInt32(-17968211)
}
break
case .contactLinkContact:
if boxed {
buffer.appendInt32(-721239344)
}
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .contactLinkUnknown:
return ("contactLinkUnknown", [])
case .contactLinkNone:
return ("contactLinkNone", [])
case .contactLinkContact:
return ("contactLinkContact", [])
}
}
static func parse_contactLinkUnknown(_ reader: BufferReader) -> ContactLink? {
return Api.ContactLink.contactLinkUnknown
}
static func parse_contactLinkNone(_ reader: BufferReader) -> ContactLink? {
return Api.ContactLink.contactLinkNone
}
static func parse_contactLinkContact(_ reader: BufferReader) -> ContactLink? {
return Api.ContactLink.contactLinkContact
}
}
enum WebDocument: TypeConstructorDescription {
case webDocumentNoProxy(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute])
@ -19086,6 +19048,50 @@ extension Api {
}
}
}
enum PeerLocated: TypeConstructorDescription {
case peerLocated(peer: Api.Peer, expires: Int32, distance: Int32)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .peerLocated(let peer, let expires, let distance):
if boxed {
buffer.appendInt32(-901375139)
}
peer.serialize(buffer, true)
serializeInt32(expires, buffer: buffer, boxed: false)
serializeInt32(distance, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .peerLocated(let peer, let expires, let distance):
return ("peerLocated", [("peer", peer), ("expires", expires), ("distance", distance)])
}
}
static func parse_peerLocated(_ reader: BufferReader) -> PeerLocated? {
var _1: Api.Peer?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.PeerLocated.peerLocated(peer: _1!, expires: _2!, distance: _3!)
}
else {
return nil
}
}
}
enum Document: TypeConstructorDescription {
case documentEmpty(id: Int64)

View File

@ -2674,24 +2674,6 @@ extension Api {
})
}
static func searchGlobal(q: String, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
let buffer = Buffer()
buffer.appendInt32(259638801)
serializeString(q, buffer: buffer, boxed: false)
serializeInt32(offsetRate, buffer: buffer, boxed: false)
offsetPeer.serialize(buffer, true)
serializeInt32(offsetId, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.searchGlobal", parameters: [("q", q), ("offsetRate", offsetRate), ("offsetPeer", offsetPeer), ("offsetId", offsetId), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
let reader = BufferReader(buffer)
var result: Api.messages.Messages?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.Messages
}
return result
})
}
static func getSearchCounters(peer: Api.InputPeer, filters: [Api.MessagesFilter]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.messages.SearchCounter]>) {
let buffer = Buffer()
buffer.appendInt32(1932455680)
@ -2744,6 +2726,26 @@ extension Api {
})
}
static func searchGlobal(flags: Int32, folderId: Int32?, q: String, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
let buffer = Buffer()
buffer.appendInt32(-1083038300)
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
serializeString(q, buffer: buffer, boxed: false)
serializeInt32(offsetRate, buffer: buffer, boxed: false)
offsetPeer.serialize(buffer, true)
serializeInt32(offsetId, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.searchGlobal", parameters: [("flags", flags), ("folderId", folderId), ("q", q), ("offsetRate", offsetRate), ("offsetPeer", offsetPeer), ("offsetId", offsetId), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
let reader = BufferReader(buffer)
var result: Api.messages.Messages?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.Messages
}
return result
})
}
static func hidePeerSettingsBar(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1336717624)
@ -3289,6 +3291,22 @@ extension Api {
return result
})
}
static func editLocation(channel: Api.InputChannel, geoPoint: Api.InputGeoPoint, address: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1491484525)
channel.serialize(buffer, true)
geoPoint.serialize(buffer, true)
serializeString(address, buffer: buffer, boxed: false)
return (FunctionDescription(name: "channels.editLocation", parameters: [("channel", channel), ("geoPoint", geoPoint), ("address", address)]), 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
})
}
}
struct payments {
static func getPaymentForm(msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentForm>) {
@ -3956,14 +3974,15 @@ extension Api {
})
}
static func addContact(id: Api.InputUser, firstName: String, lastName: String, phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func addContact(flags: Int32, id: Api.InputUser, firstName: String, lastName: String, phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-2035792455)
buffer.appendInt32(-386636848)
serializeInt32(flags, buffer: buffer, boxed: false)
id.serialize(buffer, true)
serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, buffer: buffer, boxed: false)
serializeString(phone, buffer: buffer, boxed: false)
return (FunctionDescription(name: "contacts.addContact", parameters: [("id", id), ("firstName", firstName), ("lastName", lastName), ("phone", phone)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
return (FunctionDescription(name: "contacts.addContact", parameters: [("flags", flags), ("id", id), ("firstName", firstName), ("lastName", lastName), ("phone", phone)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
@ -4005,12 +4024,11 @@ extension Api {
})
}
static func getLocated(geoPoint: Api.InputGeoPoint, radius: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func getLocated(geoPoint: Api.InputGeoPoint) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-261936023)
buffer.appendInt32(171270230)
geoPoint.serialize(buffer, true)
serializeInt32(radius, buffer: buffer, boxed: false)
return (FunctionDescription(name: "contacts.getLocated", parameters: [("geoPoint", geoPoint), ("radius", radius)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
return (FunctionDescription(name: "contacts.getLocated", parameters: [("geoPoint", geoPoint)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {

View File

@ -57,7 +57,9 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .chatForbidden(id, title):
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .channel(flags, id, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, defaultBannedRights, _/*feed*//*, feedId*/):
case let .channel(flags, id, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, defaultBannedRights, _):
let isMin = (flags & (1 << 20)) != 0
let participationStatus: TelegramChannelParticipationStatus
if (flags & Int32(1 << 1)) != 0 {
participationStatus = .kicked

View File

@ -214,6 +214,8 @@ public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: Pe
}
case let .channelAdminLogEventActionChangeLinkedChat(prevValue, newValue):
action = .linkedPeerUpdated(previous: prevValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: prevValue)], updated: newValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: newValue)])
case let .channelAdminLogEventActionChangeLocation(prevValue, newValue):
break
}
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
if let action = action {

View File

@ -44,7 +44,7 @@ public enum AddContactError {
case generic
}
public func addContactInteractively(account: Account, peerId: PeerId, firstName: String, lastName: String, phoneNumber: String) -> Signal<Never, AddContactError> {
public func addContactInteractively(account: Account, peerId: PeerId, firstName: String, lastName: String, phoneNumber: String, addToPrivacyExceptions: Bool) -> Signal<Never, AddContactError> {
return account.postbox.transaction { transaction -> (Api.InputUser, String)? in
if let user = transaction.getPeer(peerId) as? TelegramUser, let inputUser = apiInputUser(user) {
return (inputUser, user.phone == nil ? phoneNumber : "")
@ -57,7 +57,11 @@ public func addContactInteractively(account: Account, peerId: PeerId, firstName:
guard let (inputUser, phone) = inputUserAndPhone else {
return .fail(.generic)
}
return account.network.request(Api.functions.contacts.addContact(id: inputUser, firstName: firstName, lastName: lastName, phone: phone))
var flags: Int32 = 0
if addToPrivacyExceptions {
flags |= (1 << 0)
}
return account.network.request(Api.functions.contacts.addContact(flags: flags, id: inputUser, firstName: firstName, lastName: lastName, phone: phone))
|> mapError { _ -> AddContactError in
return .generic
}

View File

@ -0,0 +1,6 @@
import Foundation
public enum TelegramPeerAccessHash: Hashable {
case personal(Int64)
case genericPublic(Int64)
}

View File

@ -16,6 +16,7 @@ public struct PeerStatusSettings: OptionSet {
public static let canShareContact = PeerStatusSettings(rawValue: 1 << 2)
public static let canBlock = PeerStatusSettings(rawValue: 1 << 3)
public static let canAddContact = PeerStatusSettings(rawValue: 1 << 4)
public static let addExceptionWhenAddingContact = PeerStatusSettings(rawValue: 1 << 5)
}
extension PeerStatusSettings {
@ -35,6 +36,9 @@ extension PeerStatusSettings {
if (flags & (1 << 3)) != 0 {
result.insert(.canShareContact)
}
if (flags & (1 << 4)) != 0 {
result.insert(.addExceptionWhenAddingContact)
}
self = result
}
}

View File

@ -16,7 +16,7 @@ public struct PeerNearby {
public func peersNearby(network: Network, accountStateManager: AccountStateManager, coordinate: (latitude: Double, longitude: Double), radius: Int32) -> Signal<[PeerNearby], NoError> {
let inputGeoPoint = Api.InputGeoPoint.inputGeoPoint(lat: coordinate.latitude, long: coordinate.longitude)
return network.request(Api.functions.contacts.getLocated(geoPoint: inputGeoPoint, radius: radius))
return network.request(Api.functions.contacts.getLocated(geoPoint: inputGeoPoint))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
@ -27,9 +27,9 @@ public func peersNearby(network: Network, accountStateManager: AccountStateManag
switch updates {
case let .updates(updates, _, _, _, _):
for update in updates {
if case let .updateContactLocated(contacts) = update {
for case let .contactLocated(userId, expires, distance) in contacts {
peersNearby.append(PeerNearby(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), expires: expires, distance: distance))
if case let .updatePeerLocated(peers) = update {
for case let .peerLocated(peer, expires, distance) in peers {
peersNearby.append(PeerNearby(id: peer.peerId, expires: expires, distance: distance))
}
}
}

View File

@ -13,6 +13,20 @@ public func removePeerChat(account: Account, peerId: PeerId, reportChatSpam: Boo
}
}
public func terminateSecretChat(transaction: Transaction, peerId: PeerId) {
if let state = transaction.getPeerChatState(peerId) as? SecretChatState, state.embeddedState != .terminated {
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.terminate(reportSpam: false), state: state).withUpdatedEmbeddedState(.terminated)
if updatedState != state {
transaction.setPeerChatState(peerId, state: updatedState)
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
return updated
})
}
}
}
}
public func removePeerChat(account: Account, transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool) {
if let _ = transaction.getPeerChatInterfaceState(peerId) {
transaction.updatePeerChatInterfaceState(peerId, update: { current in
@ -24,8 +38,7 @@ public func removePeerChat(account: Account, transaction: Transaction, mediaBox:
})
}
if peerId.namespace == Namespaces.Peer.SecretChat {
if let state = transaction.getPeerChatState(peerId) as? SecretChatState {
if let state = transaction.getPeerChatState(peerId) as? SecretChatState, state.embeddedState != .terminated {
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.terminate(reportSpam: reportChatSpam), state: state).withUpdatedEmbeddedState(.terminated)
if updatedState != state {
transaction.setPeerChatState(peerId, state: updatedState)

View File

@ -291,7 +291,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
}
}
|> mapToSignal { (nextRate, lowerBound, inputPeer) in
account.network.request(Api.functions.messages.searchGlobal(q: query, offsetRate: nextRate, offsetPeer: inputPeer, offsetId: lowerBound?.id.id ?? 0, limit: limit), automaticFloodWait: false)
account.network.request(Api.functions.messages.searchGlobal(flags: 0, folderId: nil, q: query, offsetRate: nextRate, offsetPeer: inputPeer, offsetId: lowerBound?.id.id ?? 0, limit: limit), automaticFloodWait: false)
|> map { result -> (Api.messages.Messages?, Api.messages.Messages?) in
return (result, nil)
}

View File

@ -302,8 +302,9 @@ extension TelegramUser {
static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? {
switch rhs {
case let .user(flags, _, accessHash, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _):
if let _ = accessHash {
case let .user(flags, _, _, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _):
let isMin = (flags & (1 << 20)) != 0
if !isMin {
return TelegramUser(user: rhs)
} else {
let telegramPhoto = photo.flatMap(parsedTelegramProfilePhoto) ?? []

View File

@ -7,112 +7,140 @@ import Foundation
import SwiftSignalKit
#endif
func fetchAndUpdateSupplementalCachedPeerData(peerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId) {
let cachedData = transaction.getPeerCachedData(peerId: peerId)
if let cachedData = cachedData as? CachedUserData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedGroupData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedChannelData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedSecretChatData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
guard let rawPeer = transaction.getPeer(rawPeerId) else {
return .complete()
}
let peer: Peer
if let secretChat = rawPeer as? TelegramSecretChat {
guard let user = transaction.getPeer(secretChat.regularPeerId) else {
return .complete()
}
peer = user
} else {
peer = rawPeer
}
if peerId.namespace == Namespaces.Peer.SecretChat {
return postbox.transaction { transaction -> Void in
var peerStatusSettings: PeerStatusSettings
if let peer = transaction.getPeer(peerId), let associatedPeerId = peer.associatedPeerId, !transaction.isPeerContact(peerId: associatedPeerId) {
if let peer = peer as? TelegramSecretChat, case .creator = peer.role {
peerStatusSettings = PeerStatusSettings()
peerStatusSettings = []
} else {
peerStatusSettings = PeerStatusSettings()
peerStatusSettings.insert(.canReport)
}
} else {
let cachedData = transaction.getPeerCachedData(peerId: peer.id)
if let cachedData = cachedData as? CachedUserData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedGroupData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedChannelData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
} else if let cachedData = cachedData as? CachedSecretChatData {
if cachedData.peerStatusSettings != nil {
return .complete()
}
}
if peer.id.namespace == Namespaces.Peer.SecretChat {
return postbox.transaction { transaction -> Void in
var peerStatusSettings: PeerStatusSettings
if let peer = transaction.getPeer(peer.id), let associatedPeerId = peer.associatedPeerId, !transaction.isPeerContact(peerId: associatedPeerId) {
if let peer = peer as? TelegramSecretChat, case .creator = peer.role {
peerStatusSettings = PeerStatusSettings()
peerStatusSettings = []
} else {
peerStatusSettings = PeerStatusSettings()
peerStatusSettings.insert(.canReport)
}
transaction.updatePeerCachedData(peerIds: [peerId], update: { peerId, current in
if let current = current as? CachedSecretChatData {
return current.withUpdatedPeerStatusSettings(peerStatusSettings)
} else {
return CachedSecretChatData(peerStatusSettings: peerStatusSettings)
} else {
peerStatusSettings = PeerStatusSettings()
peerStatusSettings = []
}
transaction.updatePeerCachedData(peerIds: [peer.id], update: { peerId, current in
if let current = current as? CachedSecretChatData {
return current.withUpdatedPeerStatusSettings(peerStatusSettings)
} else {
return CachedSecretChatData(peerStatusSettings: peerStatusSettings)
}
})
}
} else if let inputPeer = apiInputPeer(peer) {
return network.request(Api.functions.messages.getPeerSettings(peer: inputPeer))
|> retryRequest
|> mapToSignal { peerSettings -> Signal<Void, NoError> in
let peerStatusSettings = PeerStatusSettings(apiSettings: peerSettings)
return postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
switch peer.id.namespace {
case Namespaces.Peer.CloudUser:
let previous: CachedUserData
if let current = current as? CachedUserData {
previous = current
} else {
previous = CachedUserData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
case Namespaces.Peer.CloudGroup:
let previous: CachedGroupData
if let current = current as? CachedGroupData {
previous = current
} else {
previous = CachedGroupData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
case Namespaces.Peer.CloudChannel:
let previous: CachedChannelData
if let current = current as? CachedChannelData {
previous = current
} else {
previous = CachedChannelData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
default:
break
}
return current
})
}
} else if let inputPeer = apiInputPeer(peer) {
return network.request(Api.functions.messages.getPeerSettings(peer: inputPeer))
|> retryRequest
|> mapToSignal { peerSettings -> Signal<Void, NoError> in
let peerStatusSettings = PeerStatusSettings(apiSettings: peerSettings)
return postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
switch peerId.namespace {
case Namespaces.Peer.CloudUser:
let previous: CachedUserData
if let current = current as? CachedUserData {
previous = current
} else {
previous = CachedUserData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
case Namespaces.Peer.CloudGroup:
let previous: CachedGroupData
if let current = current as? CachedGroupData {
previous = current
} else {
previous = CachedGroupData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
case Namespaces.Peer.CloudChannel:
let previous: CachedChannelData
if let current = current as? CachedChannelData {
previous = current
} else {
previous = CachedChannelData()
}
return previous.withUpdatedPeerStatusSettings(peerStatusSettings)
default:
break
}
return current
})
}
}
} else {
return .complete()
}
} else {
return .complete()
}
} |> switchToLatest
}
|> switchToLatest
}
func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> (Api.InputUser?, Peer?) in
if peerId == accountPeerId {
return (.inputUserSelf, transaction.getPeer(peerId))
func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerId, network: Network, postbox: Postbox) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> (Api.InputUser?, Peer?, PeerId) in
guard let rawPeer = transaction.getPeer(rawPeerId) else {
if rawPeerId == accountPeerId {
return (.inputUserSelf, transaction.getPeer(rawPeerId), rawPeerId)
} else {
return (nil, nil, rawPeerId)
}
}
let peer: Peer
if let secretChat = rawPeer as? TelegramSecretChat {
guard let user = transaction.getPeer(secretChat.regularPeerId) else {
return (nil, nil, rawPeerId)
}
peer = user
} else {
let peer = transaction.getPeer(peerId)
return (peer.flatMap(apiInputUser), peer)
peer = rawPeer
}
if rawPeerId == accountPeerId {
return (.inputUserSelf, transaction.getPeer(rawPeerId), rawPeerId)
} else {
return (apiInputUser(peer), peer, peer.id)
}
}
|> mapToSignal { inputUser, maybePeer -> Signal<Void, NoError> in
|> mapToSignal { inputUser, maybePeer, peerId -> Signal<Void, NoError> in
if let inputUser = inputUser {
return network.request(Api.functions.users.getFullUser(id: inputUser))
|> retryRequest
@ -250,7 +278,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId: PeerId, network
}
switch fullChat {
case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, pts):
case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, pts):
var channelFlags = CachedChannelFlags()
if (flags & (1 << 3)) != 0 {
channelFlags.insert(.canDisplayParticipants)

View File

@ -451,6 +451,8 @@
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0DE1DB539FC00C6B04F /* StickerPack.swift */; };
D073CEA41DCBF3EA007511FD /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */; };
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0E11DB5401A00C6B04F /* StickerManagement.swift */; };
D0750C9022B2FD8300BE5F6E /* PeerAccessHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0750C8F22B2FD8300BE5F6E /* PeerAccessHash.swift */; };
D0750C9122B2FD8300BE5F6E /* PeerAccessHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0750C8F22B2FD8300BE5F6E /* PeerAccessHash.swift */; };
D0754D2A1EEE10FC00884F6E /* BotPaymentForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0754D291EEE10FC00884F6E /* BotPaymentForm.swift */; };
D0754D2B1EEE10FC00884F6E /* BotPaymentForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0754D291EEE10FC00884F6E /* BotPaymentForm.swift */; };
D076F8892296D8E9004F895A /* ManageChannelDiscussionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D076F8882296D8E9004F895A /* ManageChannelDiscussionGroup.swift */; };
@ -1066,6 +1068,7 @@
D07047B91F3DF75500F6A8D4 /* ConsumePersonalMessageAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsumePersonalMessageAction.swift; sourceTree = "<group>"; };
D073CE5C1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForwardSourceInfoAttribute.swift; sourceTree = "<group>"; };
D073CE5F1DCB9D14007511FD /* OutgoingMessageInfoAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingMessageInfoAttribute.swift; sourceTree = "<group>"; };
D0750C8F22B2FD8300BE5F6E /* PeerAccessHash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerAccessHash.swift; sourceTree = "<group>"; };
D0754D291EEE10FC00884F6E /* BotPaymentForm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BotPaymentForm.swift; sourceTree = "<group>"; };
D076F8882296D8E9004F895A /* ManageChannelDiscussionGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageChannelDiscussionGroup.swift; sourceTree = "<group>"; };
D07827BA1E00451F00071108 /* SearchPeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchPeers.swift; sourceTree = "<group>"; };
@ -1445,6 +1448,7 @@
D03B0CDA1D62245F00955575 /* ApiUtils.swift */,
D03B0CD81D62245B00955575 /* PeerUtils.swift */,
D09A2FEA1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift */,
D0750C8F22B2FD8300BE5F6E /* PeerAccessHash.swift */,
D03B0CD41D62245300955575 /* TelegramUser.swift */,
D03B0CD51D62245300955575 /* TelegramGroup.swift */,
D09A2FE51D7CD4940018FB72 /* TelegramChannel.swift */,
@ -2398,6 +2402,7 @@
D0E412E7206ABC7500BEE4A2 /* EncryptedMediaResource.swift in Sources */,
D0AB262621C2F991008F6685 /* TelegramMediaPoll.swift in Sources */,
D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */,
D0750C9022B2FD8300BE5F6E /* PeerAccessHash.swift in Sources */,
D0FC195B2020D1CA00FEDBB2 /* PeerGroupMessageStateVersionAttribute.swift in Sources */,
D0B1671D1F9EA2C300976B40 /* ChatHistoryPreloadManager.swift in Sources */,
D02B199021FB1D520094A764 /* RegisterNotificationToken.swift in Sources */,
@ -2661,6 +2666,7 @@
D0C26D6A1FE02402004ABF18 /* ManagedSynchronizeGroupedPeersOperations.swift in Sources */,
D01C7F051EFC1C49008305F1 /* DeviceContact.swift in Sources */,
D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */,
D0750C9122B2FD8300BE5F6E /* PeerAccessHash.swift in Sources */,
D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */,
D033FEB11E61EB0200644997 /* PeerContactSettings.swift in Sources */,
D0458C891E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift in Sources */,

View File

@ -5834,90 +5834,96 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
}
private func reportPeer() {
if let peer = self.presentationInterfaceState.renderedPeer?.peer {
self.chatDisplayNode.dismissInput()
if let peer = peer as? TelegramChannel, let username = peer.username, !username.isEmpty {
self.present(peerReportOptionsController(context: self.context, subject: .peer(peer.id), present: { [weak self] c, a in
self?.present(c, in: .window(.root))
}), in: .window(.root))
} else if let _ = peer as? TelegramUser {
let presentationData = self.presentationData
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
var reportSpam = true
var deleteChat = true
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(peer.compactDisplayTitle).0),
ActionSheetCheckboxItem(title: presentationData.strings.Conversation_Moderate_Report, label: "", value: reportSpam, action: { [weak controller] checkValue in
reportSpam = checkValue
controller?.updateItem(groupIndex: 0, itemIndex: 1, { item in
if let item = item as? ActionSheetCheckboxItem {
return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action)
}
return item
})
}),
ActionSheetCheckboxItem(title: presentationData.strings.ReportSpam_DeleteThisChat, label: "", value: deleteChat, action: { [weak controller] checkValue in
deleteChat = checkValue
controller?.updateItem(groupIndex: 0, itemIndex: 2, { item in
if let item = item as? ActionSheetCheckboxItem {
return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action)
}
return item
})
}),
ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(peer.compactDisplayTitle).0, color: .destructive, action: { [weak self] in
dismissAction()
guard let strongSelf = self else {
return
}
let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start()
if deleteChat {
let _ = removePeerChat(account: strongSelf.context.account, peerId: peer.id, reportChatSpam: reportSpam).start()
(strongSelf.navigationController as? NavigationController)?.filterController(strongSelf, animated: true)
} else if reportSpam {
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam).start()
}
})
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
self.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} else {
let title: String
var infoString: String?
if let _ = peer as? TelegramGroup {
title = self.presentationData.strings.Conversation_ReportSpam
} else if let _ = peer as? TelegramChannel {
title = self.presentationData.strings.Conversation_ReportSpam
} else {
title = self.presentationData.strings.Conversation_ReportSpam
infoString = self.presentationData.strings.Conversation_ReportSpamConfirmation
}
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
var items: [ActionSheetItem] = []
if let infoString = infoString {
items.append(ActionSheetTextItem(title: infoString))
}
items.append(ActionSheetButtonItem(title: title, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
strongSelf.deleteChat(reportChatSpam: true)
}
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
self.present(actionSheet, in: .window(.root))
guard let renderedPeer = self.presentationInterfaceState.renderedPeer, let peer = renderedPeer.chatMainPeer, let chatPeer = renderedPeer.peer else {
return
}
self.chatDisplayNode.dismissInput()
if let peer = peer as? TelegramChannel, let username = peer.username, !username.isEmpty {
self.present(peerReportOptionsController(context: self.context, subject: .peer(peer.id), present: { [weak self] c, a in
self?.present(c, in: .window(.root))
}), in: .window(.root))
} else if let _ = peer as? TelegramUser {
let presentationData = self.presentationData
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
var reportSpam = true
var deleteChat = true
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(peer.compactDisplayTitle).0),
ActionSheetCheckboxItem(title: presentationData.strings.Conversation_Moderate_Report, label: "", value: reportSpam, action: { [weak controller] checkValue in
reportSpam = checkValue
controller?.updateItem(groupIndex: 0, itemIndex: 1, { item in
if let item = item as? ActionSheetCheckboxItem {
return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action)
}
return item
})
}),
ActionSheetCheckboxItem(title: presentationData.strings.ReportSpam_DeleteThisChat, label: "", value: deleteChat, action: { [weak controller] checkValue in
deleteChat = checkValue
controller?.updateItem(groupIndex: 0, itemIndex: 2, { item in
if let item = item as? ActionSheetCheckboxItem {
return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action)
}
return item
})
}),
ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(peer.compactDisplayTitle).0, color: .destructive, action: { [weak self] in
dismissAction()
guard let strongSelf = self else {
return
}
let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start()
if let _ = chatPeer as? TelegramSecretChat {
let _ = (strongSelf.context.account.postbox.transaction { transaction in
terminateSecretChat(transaction: transaction, peerId: chatPeer.id)
}).start()
}
if deleteChat {
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
(strongSelf.navigationController as? NavigationController)?.filterController(strongSelf, animated: true)
} else if reportSpam {
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam).start()
}
})
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
self.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} else {
let title: String
var infoString: String?
if let _ = peer as? TelegramGroup {
title = self.presentationData.strings.Conversation_ReportSpam
} else if let _ = peer as? TelegramChannel {
title = self.presentationData.strings.Conversation_ReportSpam
} else {
title = self.presentationData.strings.Conversation_ReportSpam
infoString = self.presentationData.strings.Conversation_ReportSpamConfirmation
}
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
var items: [ActionSheetItem] = []
if let infoString = infoString {
items.append(ActionSheetTextItem(title: infoString))
}
items.append(ActionSheetButtonItem(title: title, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
strongSelf.deleteChat(reportChatSpam: true)
}
}))
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
self.present(actionSheet, in: .window(.root))
}
}
@ -5950,8 +5956,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
}
private func addPeerContact() {
if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser, let contactData = DeviceContactExtendedData(peer: peer) {
self.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: true, completion: { [weak self] peer, stableId, contactData in
if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser, let peerStatusSettings = self.presentationInterfaceState.contactStatus?.peerStatusSettings, let contactData = DeviceContactExtendedData(peer: peer) {
self.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: true, shareViaException: peerStatusSettings.contains(.addExceptionWhenAddingContact), completion: { [weak self] peer, stableId, contactData in
guard let strongSelf = self else {
return
}

View File

@ -29,7 +29,7 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat
}
var displayActionsPanel = false
if let contactStatus = chatPresentationInterfaceState.contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings {
if !chatPresentationInterfaceState.peerIsBlocked, let contactStatus = chatPresentationInterfaceState.contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings {
if !peerStatusSettings.isEmpty {
if contactStatus.canAddContact && peerStatusSettings.contains(.canAddContact) {
displayActionsPanel = true

View File

@ -9,6 +9,7 @@ private enum ChatReportPeerTitleButton: Equatable {
case block
case addContact(String?)
case shareMyPhoneNumber
case reportSpam
func title(strings: PresentationStrings) -> String {
switch self {
@ -22,6 +23,8 @@ private enum ChatReportPeerTitleButton: Equatable {
}
case .shareMyPhoneNumber:
return strings.Conversation_ShareMyPhoneNumber
case .reportSpam:
return strings.Conversation_ReportSpam
}
}
}
@ -46,6 +49,8 @@ private func peerButtons(_ state: ChatPresentationInterfaceState) -> [ChatReport
buttons.append(.shareMyPhoneNumber)
}
}
} else if let _ = state.renderedPeer?.chatMainPeer {
buttons.append(.reportSpam)
}
return buttons
}
@ -141,7 +146,8 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
nextButtonOrigin += buttonWidth
}
} else {
let areaWidth = width - maxInset * 2.0
let additionalRightInset: CGFloat = 18.0
let areaWidth = width - maxInset * 2.0 - additionalRightInset
let maxButtonWidth = floor(areaWidth / CGFloat(self.buttons.count))
let buttonSizes = self.buttons.map { button -> CGFloat in
return button.1.sizeThatFits(CGSize(width: maxButtonWidth, height: 100.0)).width
@ -171,7 +177,7 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
switch button {
case .shareMyPhoneNumber:
self.interfaceInteraction?.shareAccountContact()
case .block:
case .block, .reportSpam:
self.interfaceInteraction?.reportPeer()
case .addContact:
self.interfaceInteraction?.presentPeerContact()

View File

@ -381,8 +381,8 @@ public class ContactsController: ViewController {
switch status {
case .allowed:
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: "")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [])
strongSelf.present(deviceContactInfoController(context: strongSelf.context, subject: .create(peer: nil, contactData: contactData, isSharing: false, completion: { peer, stableId, contactData in
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: "+")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [])
strongSelf.present(deviceContactInfoController(context: strongSelf.context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
guard let strongSelf = self else {
return
}

View File

@ -192,17 +192,19 @@ public final class DeviceContactInstantMessagingProfileData: Equatable, Hashable
}
}
private let phonebookUsernamePrefix = "t.me/id"
public extension DeviceContactInstantMessagingProfileData {
convenience init(appProfile: PeerId) {
self.init(label: "mobile", service: "Telegram", username: "@id\(appProfile.id)")
self.init(label: "mobile", service: "Telegram", username: "\(phonebookUsernamePrefix)\(appProfile.id)")
}
}
func parseAppSpecificContactReference(_ value: String) -> PeerId? {
if !value.hasPrefix("@id") {
if !value.hasPrefix(phonebookUsernamePrefix) {
return nil
}
let idString = String(value[value.index(value.startIndex, offsetBy: 3)...])
let idString = String(value[value.index(value.startIndex, offsetBy: phonebookUsernamePrefix.count)...])
if let id = Int32(idString) {
return PeerId(namespace: Namespaces.Peer.CloudUser, id: id)
}

View File

@ -27,8 +27,9 @@ private final class DeviceContactInfoControllerArguments {
let openUrl: (String) -> Void
let openAddress: (DeviceContactAddressData) -> Void
let displayCopyContextMenu: (DeviceContactInfoEntryTag, String) -> Void
let updateShareViaException: (Bool) -> Void
init(account: Account, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void) {
init(account: Account, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void, updateShareViaException: @escaping (Bool) -> Void) {
self.account = account
self.updateEditingName = updateEditingName
self.updatePhone = updatePhone
@ -42,6 +43,7 @@ private final class DeviceContactInfoControllerArguments {
self.openUrl = openUrl
self.openAddress = openAddress
self.displayCopyContextMenu = displayCopyContextMenu
self.updateShareViaException = updateShareViaException
}
}
@ -49,6 +51,7 @@ private enum DeviceContactInfoSection: ItemListSectionId {
case info
case editing
case data
case share
}
private enum DeviceContactInfoEntryTag: Equatable, ItemListItemTag {
@ -82,6 +85,8 @@ private enum DeviceContactInfoConstantEntryId: Hashable {
case birthday
case addPhoneNumber
case phoneNumberSharingInfo
case phoneNumberShareViaException
case phoneNumberShareViaExceptionInfo
}
private enum DeviceContactInfoEntryId: Hashable {
@ -107,6 +112,8 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
case phoneNumber(Int, Int, PresentationTheme, String, String, String, Bool?, Bool)
case editingPhoneNumber(Int, PresentationTheme, PresentationStrings, Int64, String, String, String, Bool)
case phoneNumberSharingInfo(Int, PresentationTheme, String)
case phoneNumberShareViaException(Int, PresentationTheme, String, Bool)
case phoneNumberShareViaExceptionInfo(Int, PresentationTheme, String)
case addPhoneNumber(Int, PresentationTheme, String)
case email(Int, Int, PresentationTheme, String, String, String, Bool?)
case url(Int, Int, PresentationTheme, String, String, String, Bool?)
@ -123,6 +130,8 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
return DeviceContactInfoSection.editing.rawValue
case .invite, .sendMessage, .createContact, .addToExisting:
return DeviceContactInfoSection.info.rawValue
case .phoneNumberShareViaException, .phoneNumberShareViaExceptionInfo:
return DeviceContactInfoSection.share.rawValue
default:
return DeviceContactInfoSection.data.rawValue
}
@ -146,6 +155,10 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
return .phoneNumber(catIndex)
case .phoneNumberSharingInfo:
return .constant(.phoneNumberSharingInfo)
case .phoneNumberShareViaException:
return .constant(.phoneNumberShareViaException)
case .phoneNumberShareViaExceptionInfo:
return .constant(.phoneNumberShareViaExceptionInfo)
case let .editingPhoneNumber(_, _, _, id, _, _, _, _):
return .editingPhoneNumber(id)
case .addPhoneNumber:
@ -236,6 +249,18 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
} else {
return false
}
case let .phoneNumberShareViaException(lhsIndex, lhsTheme, lhsText, lhsValue):
if case let .phoneNumberShareViaException(rhsIndex, rhsTheme, rhsText, rhsValue) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .phoneNumberShareViaExceptionInfo(lhsIndex, lhsTheme, lhsText):
if case let .phoneNumberShareViaExceptionInfo(rhsIndex, rhsTheme, rhsText) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .editingPhoneNumber(lhsIndex, lhsTheme, lhsStrings, lhsId, lhsTitle, lhsLabel, lhsValue, lhsSelected):
if case let .editingPhoneNumber(rhsIndex, rhsTheme, rhsStrings, rhsId, rhsTitle, rhsLabel, rhsValue, rhsSelected) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsId == rhsId, lhsTitle == rhsTitle, lhsLabel == rhsLabel, lhsValue == rhsValue, lhsSelected == rhsSelected {
return true
@ -305,6 +330,10 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
return index
case let .phoneNumberSharingInfo(index, _, _):
return index
case let .phoneNumberShareViaException(index, _, _, _):
return index
case let .phoneNumberShareViaExceptionInfo(index, _, _):
return index
case let .editingPhoneNumber(index, _, _, _, _, _, _, _):
return index
case let .addPhoneNumber(index, _, _):
@ -361,13 +390,19 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
} else {
arguments.callPhone(value)
}
} : nil, longTapAction: {
} : nil, longTapAction: isInteractionEnabled ? {
if selected == nil {
arguments.displayCopyContextMenu(.info(index), value)
}
}, tag: DeviceContactInfoEntryTag.info(index))
} : nil, tag: DeviceContactInfoEntryTag.info(index))
case let .phoneNumberSharingInfo(_, theme, text):
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
case let .phoneNumberShareViaException(_, theme, text, value):
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .plain, updated: { value in
arguments.updateShareViaException(value)
})
case let .phoneNumberShareViaExceptionInfo(_, theme, text):
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
case let .editingPhoneNumber(_, theme, strings, id, title, label, value, hasActiveRevealControls):
return UserInfoEditingPhoneItem(theme: theme, strings: strings, id: id, label: title, value: value, editing: UserInfoEditingPhoneItemEditing(editable: true, hasActiveRevealControls: hasActiveRevealControls), sectionId: self.section, setPhoneIdWithRevealedOptions: { lhs, rhs in
arguments.setPhoneIdWithRevealedOptions(lhs, rhs)
@ -500,6 +535,7 @@ private struct EditingPhoneNumber: Equatable {
private struct DeviceContactInfoState: Equatable {
var savingData: Bool = false
var addToPrivacyExceptions: Bool = true
var editingState: DeviceContactInfoEditingState? = nil
var excludedComponents = Set<DeviceContactInfoDataId>()
var phoneNumbers: [EditingPhoneNumber] = []
@ -532,7 +568,7 @@ private func filteredContactData(contactData: DeviceContactExtendedData, exclude
return DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: contactData.basicData.firstName, lastName: contactData.basicData.lastName, phoneNumbers: phoneNumbers), middleName: contactData.middleName, prefix: contactData.prefix, suffix: contactData.suffix, organization: includeJob ? contactData.organization : "", jobTitle: includeJob ? contactData.jobTitle : "", department: includeJob ? contactData.department : "", emailAddresses: emailAddresses, urls: urls, addresses: addresses, birthdayDate: includeBirthday ? contactData.birthdayDate : nil, socialProfiles: socialProfiles, instantMessagingProfiles: instantMessagingProfiles)
}
private func deviceContactInfoEntries(account: Account, presentationData: PresentationData, peer: Peer?, isShare: Bool, contactData: DeviceContactExtendedData, isContact: Bool, state: DeviceContactInfoState, selecting: Bool, editingPhoneNumbers: Bool) -> [DeviceContactInfoEntry] {
private func deviceContactInfoEntries(account: Account, presentationData: PresentationData, peer: Peer?, isShare: Bool, shareViaException: Bool, contactData: DeviceContactExtendedData, isContact: Bool, state: DeviceContactInfoState, selecting: Bool, editingPhoneNumbers: Bool) -> [DeviceContactInfoEntry] {
var entries: [DeviceContactInfoEntry] = []
var editingName: ItemListAvatarAndNameInfoItemName?
@ -597,6 +633,10 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen
} else {
entries.append(.phoneNumberSharingInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_ContactWillBeSharedNow(peer.compactDisplayTitle).0))
}
if shareViaException {
entries.append(.phoneNumberShareViaException(entries.count, presentationData.theme, presentationData.strings.AddContact_SharedContactException, state.addToPrivacyExceptions))
entries.append(.phoneNumberShareViaExceptionInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_SharedContactExceptionInfo(peer.compactDisplayTitle).0))
}
}
} else {
if editingPhoneNumbers {
@ -691,7 +731,7 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen
public enum DeviceContactInfoSubject {
case vcard(Peer?, DeviceContactStableId?, DeviceContactExtendedData)
case filter(peer: Peer?, contactId: DeviceContactStableId?, contactData: DeviceContactExtendedData, completion: (Peer?, DeviceContactExtendedData) -> Void)
case create(peer: Peer?, contactData: DeviceContactExtendedData, isSharing: Bool, completion: (Peer?, DeviceContactStableId, DeviceContactExtendedData) -> Void)
case create(peer: Peer?, contactData: DeviceContactExtendedData, isSharing: Bool, shareViaException: Bool, completion: (Peer?, DeviceContactStableId, DeviceContactExtendedData) -> Void)
var peer: Peer? {
switch self {
@ -710,7 +750,7 @@ public enum DeviceContactInfoSubject {
return data
case let .filter(_, _, data, _):
return data
case let .create(_, data, _, _):
case let .create(_, data, _, _, _):
return data
}
}
@ -746,7 +786,7 @@ private final class DeviceContactInfoController: ItemListController<DeviceContac
public func deviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)? = nil, cancelled: (() -> Void)? = nil) -> ViewController {
var initialState = DeviceContactInfoState()
if case let .create(peer, contactData, _, _) = subject {
if case let .create(peer, contactData, _, _, _) = subject {
var peerPhoneNumber: String?
var firstName = contactData.basicData.firstName
var lastName = contactData.basicData.lastName
@ -917,7 +957,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
case .createContact:
presentControllerImpl?(deviceContactInfoController(context: context, subject: .create(peer: subject.peer, contactData: subject.contactData, isSharing: false, completion: { peer, stableId, contactData in
presentControllerImpl?(deviceContactInfoController(context: context, subject: .create(peer: subject.peer, contactData: subject.contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
dismissImpl?(false)
if let peer = peer {
@ -950,18 +990,26 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
openAddressImpl?(address)
}, displayCopyContextMenu: { tag, value in
displayCopyContextMenuImpl?(tag, value)
}, updateShareViaException: { value in
updateState { state in
var state = state
state.addToPrivacyExceptions = value
return state
}
})
let contactData: Signal<(Peer?, DeviceContactStableId?, DeviceContactExtendedData), NoError>
var isShare = false
var shareViaException = false
switch subject {
case let .vcard(peer, id, data):
contactData = .single((peer, id, data))
case let .filter(peer, id, data, _):
contactData = .single((peer, id, data))
case let .create(peer, data, share, _):
case let .create(peer, data, share, shareViaExceptionValue, _):
contactData = .single((peer, nil, data))
isShare = share
shareViaException = shareViaExceptionValue
}
let previousEditingPhoneIds = Atomic<Set<Int64>?>(value: nil)
@ -987,7 +1035,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
completion(peerAndContactData.0, filteredData)
dismissImpl?(true)
})
} else if case let .create(createForPeer, _, _, completion) = subject {
} else if case let .create(createForPeer, _, _, _, completion) = subject {
let filteredData = filteredContactData(contactData: peerAndContactData.2, excludedComponents: state.excludedComponents)
var filteredPhoneNumbers: [DeviceContactPhoneNumberData] = []
for phoneNumber in state.phoneNumbers {
@ -1015,16 +1063,18 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
}
rightNavigationButton = ItemListNavigationButton(content: .text(isShare ? presentationData.strings.Common_Done : presentationData.strings.Compose_Create), style: .bold, enabled: (isShare || !filteredPhoneNumbers.isEmpty) && composedContactData != nil, action: {
if let composedContactData = composedContactData {
var addToPrivacyExceptions = false
updateState { state in
var state = state
state.savingData = true
addToPrivacyExceptions = state.addToPrivacyExceptions
return state
}
if let contactDataManager = context.sharedContext.contactDataManager {
switch subject {
case let .create(peer, _, share, _):
case let .create(peer, _, share, shareViaException, _):
if share, filteredPhoneNumbers.count <= 1, let peer = peer {
addContactDisposable.set((addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "")
addContactDisposable.set((addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
|> deliverOnMainQueue).start(error: { _ in
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}, completed: {
@ -1056,9 +1106,9 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
}
if filteredPhoneNumbers.count <= 1 {
switch subject {
case let .create(peer, _, share, _):
case let .create(peer, _, share, shareViaException, _):
if share, let peer = peer {
return addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "")
return addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
|> mapToSignal { _ -> Signal<(DeviceContactStableId, DeviceContactExtendedData, Peer?)?, AddContactError> in
return .complete()
}
@ -1146,7 +1196,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
focusItemTag = DeviceContactInfoEntryTag.editingPhone(insertedPhoneId)
}
let listState = ItemListNodeState(entries: deviceContactInfoEntries(account: context.account, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones), style: .plain, focusItemTag: focusItemTag)
let listState = ItemListNodeState(entries: deviceContactInfoEntries(account: context.account, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, shareViaException: shareViaException, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones), style: .plain, focusItemTag: focusItemTag)
return (controllerState, (listState, arguments))
}
@ -1269,7 +1319,7 @@ private func addContactToExisting(context: AccountContext, parentController: Vie
let _ = (dataSignal
|> deliverOnMainQueue).start(next: { peer, stableId in
guard let stableId = stableId else {
parentController.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: false, completion: { peer, stableId, contactData in
parentController.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
})), in: .window(.root))
return
@ -1315,7 +1365,7 @@ func addContactOptionsController(context: AccountContext, peer: Peer?, contactDa
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Profile_CreateNewContact, action: { [weak controller] in
controller?.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: peer != nil, completion: { peer, stableId, contactData in
controller?.present(deviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: peer != nil, shareViaException: false, completion: { peer, stableId, contactData in
if let peer = peer {
} else {

View File

@ -752,7 +752,9 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
requestActivateSearch()
}
let presentPeerSettings: (PeerId, @escaping () -> Void) -> Void = { peerId, completion in
let presentPeerSettings: (PeerId, @escaping () -> Void) -> Void = { [weak self] peerId, completion in
(self?.searchDisplayController?.contentNode as? NotificationExceptionsSearchContainerNode)?.listNode.clearHighlightAnimated(true)
let _ = (context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
@ -1115,7 +1117,7 @@ private func preparedNotificationExceptionsSearchContainerTransition(theme: Pres
private final class NotificationExceptionsSearchContainerNode: SearchDisplayControllerContentNode {
private let dimNode: ASDisplayNode
private let listNode: ListView
let listNode: ListView
private var enqueuedTransitions: [NotificationExceptionsSearchContainerTransition] = []
private var hasValidLayout = false

View File

@ -267,11 +267,9 @@ private struct NotificationExceptionPeerState : Equatable {
if let notifications = notifications {
self.selectedSound = notifications.messageSound
switch notifications.muteState {
case .muted:
case let .muted(until) where until >= Int32.max - 1:
self.mode = .alwaysOff
case .unmuted:
self.mode = .alwaysOn
case .default:
default:
self.mode = .alwaysOn
}
self.displayPreviews = notifications.displayPreviews == .hide ? .alwaysOff : .alwaysOn

View File

@ -157,7 +157,7 @@ public class NotificationExceptionsController: ViewController {
}
@objc private func removeAllPressed() {
self.controllerNode
self.controllerNode.removeAll()
}
@objc private func editPressed() {

View File

@ -10,7 +10,7 @@ func openAddContact(context: AccountContext, firstName: String = "", lastName: S
switch value {
case .allowed:
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: label, value: phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [])
present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, completion: { peer, stableId, contactData in
present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
if let peer = peer {
if let infoController = peerInfoController(context: context, peer: peer) {
pushController(infoController)

File diff suppressed because it is too large Load Diff

View File

@ -735,16 +735,18 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat
return entries
}
private func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal<Peer?, NoError> {
return postbox.transaction { transaction -> Peer? in
private func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal<(Peer?, CachedPeerData?), NoError> {
return postbox.transaction { transaction -> (Peer?, CachedPeerData?) in
guard let peer = transaction.getPeer(peerId) else {
return nil
return (nil, nil)
}
var resultPeer: Peer?
if let peer = peer as? TelegramSecretChat {
return transaction.getPeer(peer.regularPeerId)
resultPeer = transaction.getPeer(peer.regularPeerId)
} else {
return peer
resultPeer = peer
}
return (resultPeer, resultPeer.flatMap({ transaction.getPeerCachedData(peerId: $0.id) }))
}
}
@ -856,7 +858,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}
}
}, tapAvatarAction: {
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId) |> deliverOnMainQueue).start(next: { peer in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId) |> deliverOnMainQueue).start(next: { peer, _ in
guard let peer = peer else {
return
}
@ -879,12 +881,17 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
openChatImpl?()
}, addContact: {
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, cachedData in
guard let user = peer as? TelegramUser, let contactData = DeviceContactExtendedData(peer: user) else {
return
}
presentControllerImpl?(deviceContactInfoController(context: context, subject: .create(peer: user, contactData: contactData, isSharing: true, completion: { peer, stableId, contactData in
var shareViaException = false
if let cachedData = cachedData as? CachedUserData, let peerStatusSettings = cachedData.peerStatusSettings {
shareViaException = peerStatusSettings.contains(.addExceptionWhenAddingContact)
}
presentControllerImpl?(deviceContactInfoController(context: context, subject: .create(peer: user, contactData: contactData, isSharing: true, shareViaException: shareViaException, completion: { peer, stableId, contactData in
if let peer = peer as? TelegramUser {
if let phone = peer.phone, !phone.isEmpty {
}
@ -931,7 +938,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}, openGroupsInCommon: {
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> take(1)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
guard let peer = peer else {
return
}
@ -941,7 +948,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}, updatePeerBlocked: { value in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> take(1)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
guard let peer = peer else {
return
}
@ -1021,7 +1028,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
ActionSheetButtonItem(title: presentationData.strings.UserInfo_DeleteContact, color: .destructive, action: {
dismissAction()
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
guard let peer = peer else {
return
}
@ -1031,12 +1038,33 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
} else {
deleteContactFromDevice = .complete()
}
updatePeerBlockedDisposable.set((
deleteContactPeerInteractively(account: context.account, peerId: peer.id)
|> then(
deleteContactFromDevice
)
).start())
var deleteSignal = deleteContactPeerInteractively(account: context.account, peerId: peer.id)
|> then(deleteContactFromDevice)
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .loading(cancelled: nil))
presentControllerImpl?(controller, nil)
return ActionDisposable { [weak controller] in
Queue.mainQueue().async() {
controller?.dismiss()
}
}
}
|> runOn(Queue.mainQueue())
|> delay(0.15, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
deleteSignal = deleteSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
}
updatePeerBlockedDisposable.set((deleteSignal
|> deliverOnMainQueue).start())
})
})
]),
@ -1052,7 +1080,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
requestCallImpl()
}, openCallMenu: { number in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(number) == formatPhoneNumber(peerPhoneNumber) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme)
@ -1212,7 +1240,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> mapToSignal { peer -> Signal<Void, NoError> in
|> mapToSignal { peer, _ -> Signal<Void, NoError> in
guard let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty else {
return .complete()
}
@ -1271,7 +1299,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}
shareContactImpl = { [weak controller] in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
if let peer = peer as? TelegramUser, let phone = peer.phone {
let contact = TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)
let shareController = ShareController(context: context, subject: .media(.standalone(media: contact)))
@ -1281,7 +1309,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}
shareMyContactImpl = { [weak controller] in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: context.account.peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
guard let peer = peer as? TelegramUser, let phone = peer.phone else {
return
}
@ -1377,7 +1405,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
}
shareBotImpl = { [weak controller] in
let _ = (getUserPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(next: { peer in
|> deliverOnMainQueue).start(next: { peer, _ in
if let peer = peer as? TelegramUser, let username = peer.username {
let shareController = ShareController(context: context, subject: .url("https://t.me/\(username)"))
controller?.present(shareController, in: .window(.root))

View File

@ -5,8 +5,8 @@ LottieExamples/LottieExamples.xcodeproj/xcuserdata/
LottieExamples.xcworkspace/xcuserdata/
Lottie/Lottie.xcodeproj/xcuserdata/
UserInterfaceState.xcuserstate
xample/lottie-ios.xcodeproj/xcuserdata
Lottie.xcodeproj/xcuserdata/
Example/lottie-ios.xcodeproj/xcuserdata
*/xcuserdata/*
Example/lottie-ios.xcworkspace/xcuserdata/
Example/lottie-ios.xcodeproj/xcuserdata/
.idea/

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Lottie.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>Lottie_iOS.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>31</integer>
</dict>
</dict>
</dict>
</plist>