Chat import fixes

This commit is contained in:
Ali 2021-01-25 17:18:52 +05:00
parent ea4db44aff
commit b61e28ae44
8 changed files with 115 additions and 74 deletions

View File

@ -24,6 +24,8 @@ fi
OUTPUT_PATH="build/artifacts"
BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL" sh buildbox/build-telegram.sh verify
if [ "$CONFIGURATION" == "appstore" ]; then
if [ -z "$IPA_PATH" ]; then
IPA_PATH="$OUTPUT_PATH/Telegram.ipa"
@ -43,8 +45,6 @@ VERIFY_PATH="TelegramVerifyBuild.ipa"
rm -f "$VERIFY_PATH"
cp "$IPA_PATH" "$VERIFY_PATH"
BAZEL_HTTP_CACHE_URL="$BAZEL_HTTP_CACHE_URL" sh buildbox/build-telegram.sh verify
python3 tools/ipadiff.py "$IPA_PATH" "$VERIFY_PATH"
retVal=$?
if [ $retVal -ne 0 ]; then

View File

@ -301,12 +301,18 @@ public final class ChatImportActivityScreen: ViewController {
self.doneButton.isHidden = true
self.progressText.isHidden = true
} else {
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize)
self.statusButtonText.isHidden = false
self.statusButton.isHidden = false
self.doneButton.isHidden = true
self.progressText.isHidden = true
}/* else {
self.statusText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusTextSize.width) / 2.0), y: self.progressText.frame.minY), size: statusTextSize)
self.statusButtonText.isHidden = true
self.statusButton.isHidden = true
self.doneButton.isHidden = false
self.progressText.isHidden = true
}
}*/
let buttonSideInset: CGFloat = 75.0
let buttonWidth = max(240.0, min(layout.size.width - buttonSideInset * 2.0, horizontalContainerFillingSizeForLayout(layout: layout, sideInset: buttonSideInset)))
@ -395,7 +401,7 @@ public final class ChatImportActivityScreen: ViewController {
private let archive: Archive
private let mainEntry: TempBoxFile
private let mainEntrySize: Int
private let otherEntries: [(Entry, String, ChatHistoryImport.MediaType)]
private let otherEntries: [(Entry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>)]
private let totalBytes: Int
private var pendingEntries: [String: (Int, Float)] = [:]
@ -415,7 +421,25 @@ public final class ChatImportActivityScreen: ViewController {
self.peerId = peerId
self.archive = archive
self.mainEntry = mainEntry
self.otherEntries = otherEntries
self.otherEntries = otherEntries.map { entry -> (Entry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>) in
let signal = Signal<TempBoxFile?, NoError> { subscriber in
let tempFile = TempBox.shared.tempFile(fileName: entry.1)
do {
let _ = try archive.extract(entry.0, to: URL(fileURLWithPath: tempFile.path))
subscriber.putNext(tempFile)
subscriber.putCompletion()
} catch {
subscriber.putNext(nil)
subscriber.putCompletion()
}
return EmptyDisposable
}
let promise = Promise<TempBoxFile?>()
promise.set(signal)
return (entry.0, entry.1, entry.2, promise)
}
if let size = fileSize(self.mainEntry.path) {
self.mainEntrySize = size
@ -523,18 +547,16 @@ public final class ChatImportActivityScreen: ViewController {
|> mapToSignal { session -> Signal<(String, Float), ImportError> in
var importSignal: Signal<(String, Float), ImportError> = .single(("", 0.0))
for (entry, fileName, mediaType) in otherEntries {
let unpackedFile = Signal<TempBoxFile, ImportError> { subscriber in
let tempFile = TempBox.shared.tempFile(fileName: fileName)
do {
let _ = try archive.extract(entry, to: URL(fileURLWithPath: tempFile.path))
subscriber.putNext(tempFile)
subscriber.putCompletion()
} catch {
subscriber.putError(.generic)
for (_, fileName, mediaType, fileData) in otherEntries {
let unpackedFile: Signal<TempBoxFile, ImportError> = fileData.get()
|> take(1)
|> castError(ImportError.self)
|> mapToSignal { file -> Signal<TempBoxFile, ImportError> in
if let file = file {
return .single(file)
} else {
return .fail(.generic)
}
return EmptyDisposable
}
let uploadedMedia = unpackedFile
|> mapToSignal { tempFile -> Signal<(String, Float), ImportError> in

View File

@ -11,8 +11,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[-281384243] = { return Api.ChatFull.parse_channelFull($0) }
dict[231260545] = { return Api.ChatFull.parse_chatFull($0) }
dict[2055070967] = { return Api.ChatFull.parse_channelFull($0) }
dict[-213431562] = { return Api.ChatFull.parse_chatFull($0) }
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
@ -736,8 +736,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
dict[1776236393] = { return Api.ExportedChatInvite.parse_chatInviteEmpty($0) }
dict[-64092740] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[1847917725] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
dict[-1392388579] = { return Api.Authorization.parse_authorization($0) }
dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) }

View File

@ -2124,14 +2124,14 @@ public extension Api {
}
public enum ChatFull: TypeConstructorDescription {
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?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?)
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?, call: Api.InputGroupCall?)
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?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?)
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?, call: Api.InputGroupCall?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
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 slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call):
if boxed {
buffer.appendInt32(-281384243)
buffer.appendInt32(2055070967)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
@ -2146,7 +2146,7 @@ public extension Api {
serializeInt32(unreadCount, buffer: buffer, boxed: false)
chatPhoto.serialize(buffer, true)
notifySettings.serialize(buffer, true)
exportedInvite.serialize(buffer, true)
if Int(flags) & Int(1 << 23) != 0 {exportedInvite!.serialize(buffer, true)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(botInfo.count))
for item in botInfo {
@ -2168,7 +2168,7 @@ public extension Api {
break
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call):
if boxed {
buffer.appendInt32(231260545)
buffer.appendInt32(-213431562)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
@ -2176,7 +2176,7 @@ public extension Api {
participants.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {chatPhoto!.serialize(buffer, true)}
notifySettings.serialize(buffer, true)
exportedInvite.serialize(buffer, true)
if Int(flags) & Int(1 << 13) != 0 {exportedInvite!.serialize(buffer, true)}
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(botInfo!.count))
for item in botInfo! {
@ -2230,9 +2230,9 @@ public extension Api {
_13 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
}
var _14: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
}
} }
var _15: [Api.BotInfo]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self)
@ -2282,7 +2282,7 @@ public extension Api {
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c14 = (Int(_1!) & Int(1 << 23) == 0) || _14 != nil
let _c15 = _15 != nil
let _c16 = (Int(_1!) & Int(1 << 4) == 0) || _16 != nil
let _c17 = (Int(_1!) & Int(1 << 4) == 0) || _17 != nil
@ -2298,7 +2298,7 @@ public extension Api {
let _c27 = _27 != nil
let _c28 = (Int(_1!) & Int(1 << 21) == 0) || _28 != 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 && _c25 && _c26 && _c27 && _c28 {
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, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28)
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, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28)
}
else {
return nil
@ -2324,9 +2324,9 @@ public extension Api {
_6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
}
var _7: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
}
} }
var _8: [Api.BotInfo]?
if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self)
@ -2345,13 +2345,13 @@ public extension Api {
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c7 = (Int(_1!) & Int(1 << 13) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 12) == 0) || _11 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7!, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
}
else {
return nil
@ -20882,44 +20882,60 @@ public extension Api {
}
public enum ExportedChatInvite: TypeConstructorDescription {
case chatInviteEmpty
case chatInviteExported(link: String)
case chatInviteExported(flags: Int32, link: String, adminId: Int32, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInviteEmpty:
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage):
if boxed {
buffer.appendInt32(1776236393)
}
break
case .chatInviteExported(let link):
if boxed {
buffer.appendInt32(-64092740)
buffer.appendInt32(1847917725)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false)
serializeInt32(adminId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(startDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInviteEmpty:
return ("chatInviteEmpty", [])
case .chatInviteExported(let link):
return ("chatInviteExported", [("link", link)])
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage):
return ("chatInviteExported", [("flags", flags), ("link", link), ("adminId", adminId), ("date", date), ("startDate", startDate), ("expireDate", expireDate), ("usageLimit", usageLimit), ("usage", usage)])
}
}
public static func parse_chatInviteEmpty(_ reader: BufferReader) -> ExportedChatInvite? {
return Api.ExportedChatInvite.chatInviteEmpty
}
public static func parse_chatInviteExported(_ reader: BufferReader) -> ExportedChatInvite? {
var _1: String?
_1 = parseString(reader)
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
if Int(_1!) & Int(1 << 4) != 0 {_5 = reader.readInt32() }
var _6: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_6 = reader.readInt32() }
var _7: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_7 = reader.readInt32() }
var _8: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_8 = reader.readInt32() }
let _c1 = _1 != nil
if _c1 {
return Api.ExportedChatInvite.chatInviteExported(link: _1!)
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8)
}
else {
return nil

View File

@ -7,12 +7,8 @@ import SyncCore
extension ExportedInvitation {
init?(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite {
case .chatInviteEmpty:
return nil
case let .chatInviteExported(link):
self = ExportedInvitation(link: link, isPermanent: true, isRevoked: false, adminId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil)
/*case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage):
self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage)*/
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage):
self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage)
}
}
}

View File

@ -254,7 +254,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
let photo: TelegramMediaImage? = chatFull.chatPhoto.flatMap(telegramMediaImageFromApiPhoto)
let exportedInvitation = Optional(chatFull.exportedInvite).flatMap { ExportedInvitation(apiExportedInvite: $0) }
let exportedInvitation = chatFull.exportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) }
let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
var peers: [Peer] = []
@ -510,7 +510,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
return previous.withUpdatedFlags(channelFlags)
.withUpdatedAbout(about)
.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: bannedCount, kickedCount: kickedCount))
.withUpdatedExportedInvitation(Optional(apiExportedInvite).flatMap { ExportedInvitation(apiExportedInvite: $0) })
.withUpdatedExportedInvitation(apiExportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) })
.withUpdatedBotInfos(botInfos)
.withUpdatedPinnedMessageId(pinnedMessageId)
.withUpdatedStickerPack(stickerPack)

View File

@ -63,15 +63,19 @@ final class ChatMessageAvatarAccessoryItem: ListViewAccessoryItem {
return false
}
if let forwardInfo = self.forwardInfo, let otherForwardInfo = other.forwardInfo, forwardInfo.flags.contains(.isImported), otherForwardInfo.flags.contains(.isImported) {
if (forwardInfo.authorSignature != nil) == (otherForwardInfo.authorSignature != nil) && (forwardInfo.author != nil) == (otherForwardInfo.author != nil) {
if let authorSignature = forwardInfo.authorSignature, let otherAuthorSignature = otherForwardInfo.authorSignature {
if authorSignature != otherAuthorSignature {
return false
}
} else if let authorId = forwardInfo.author?.id, let otherAuthorId = other.forwardInfo?.author?.id {
} else if let authorId = forwardInfo.author?.id, let otherAuthorId = otherForwardInfo.author?.id {
if authorId != otherAuthorId {
return false
}
}
} else {
return false
}
} else if let forwardInfo = self.forwardInfo, forwardInfo.flags.contains(.isImported) {
return false
} else if let otherForwardInfo = other.forwardInfo, otherForwardInfo.flags.contains(.isImported) {

View File

@ -131,11 +131,15 @@ private func messagesShouldBeMerged(accountPeerId: PeerId, _ lhs: Message, _ rhs
lhsEffectiveTimestamp = lhsForwardInfo.date
rhsEffectiveTimestamp = rhsForwardInfo.date
if (lhsForwardInfo.author?.id != nil) == (rhsForwardInfo.author?.id != nil) && (lhsForwardInfo.authorSignature != nil) == (rhsForwardInfo.authorSignature != nil) {
if let lhsAuthorId = lhsForwardInfo.author?.id, let rhsAuthorId = rhsForwardInfo.author?.id {
sameAuthor = lhsAuthorId == rhsAuthorId
} else if let lhsAuthorSignature = lhsForwardInfo.authorSignature, let rhsAuthorSignature = rhsForwardInfo.authorSignature {
sameAuthor = lhsAuthorSignature == rhsAuthorSignature
}
} else {
sameAuthor = false
}
}
if lhs.id.peerId.isRepliesOrSavedMessages(accountPeerId: accountPeerId) {