Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin
2021-09-25 17:22:08 +03:00
1864 changed files with 60797 additions and 27315 deletions

View File

@@ -1,7 +1,6 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Postbox
import Display
import SwiftSignalKit
import TelegramCore
@@ -20,8 +19,23 @@ import ContextUI
import ChatInterfaceState
public enum ChatListItemContent {
case peer(messages: [Message], peer: RenderedPeer, combinedReadState: CombinedPeerReadState?, isRemovedFromTotalUnreadCount: Bool, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, embeddedState: StoredPeerChatInterfaceState?, inputActivities: [(Peer, PeerInputActivity)]?, promoInfo: ChatListNodeEntryPromoInfo?, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool)
case groupReference(groupId: PeerGroupId, peers: [ChatListGroupReferencePeer], message: Message?, unreadState: PeerGroupUnreadCountersCombinedSummary, hiddenByDefault: Bool)
public final class DraftState: Equatable {
let text: String
public init(text: String) {
self.text = text
}
public static func ==(lhs: DraftState, rhs: DraftState) -> Bool {
if lhs.text != rhs.text {
return false
}
return true
}
}
case peer(messages: [EngineMessage], peer: EngineRenderedPeer, combinedReadState: EnginePeerReadCounters?, isRemovedFromTotalUnreadCount: Bool, presence: EnginePeer.Presence?, hasUnseenMentions: Bool, draftState: DraftState?, inputActivities: [(EnginePeer, PeerInputActivity)]?, promoInfo: ChatListNodeEntryPromoInfo?, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool)
case groupReference(groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, unreadCount: Int, hiddenByDefault: Bool)
public var chatLocation: ChatLocation? {
switch self {
@@ -36,9 +50,9 @@ public enum ChatListItemContent {
public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
let presentationData: ChatListPresentationData
let context: AccountContext
let peerGroupId: PeerGroupId
let peerGroupId: EngineChatList.Group
let filterData: ChatListItemFilterData?
let index: ChatListIndex
let index: EngineChatList.Item.Index
public let content: ChatListItemContent
let editing: Bool
let hasActiveRevealControls: Bool
@@ -59,7 +73,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
return self.index.pinningIndex != nil
}
public init(presentationData: ChatListPresentationData, context: AccountContext, peerGroupId: PeerGroupId, filterData: ChatListItemFilterData?, index: ChatListIndex, content: ChatListItemContent, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, header: ListViewItemHeader?, enableContextActions: Bool, hiddenOffset: Bool, interaction: ChatListNodeInteraction) {
public init(presentationData: ChatListPresentationData, context: AccountContext, peerGroupId: EngineChatList.Group, filterData: ChatListItemFilterData?, index: EngineChatList.Item.Index, content: ChatListItemContent, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, header: ListViewItemHeader?, enableContextActions: Bool, hiddenOffset: Bool, interaction: ChatListNodeInteraction) {
self.presentationData = presentationData
self.peerGroupId = peerGroupId
self.filterData = filterData
@@ -195,7 +209,7 @@ private enum RevealOptionKey: Int32 {
case hidePsa
}
private func canArchivePeer(id: PeerId, accountPeerId: PeerId) -> Bool {
private func canArchivePeer(id: EnginePeer.Id, accountPeerId: EnginePeer.Id) -> Bool {
if id.namespace == Namespaces.Peer.CloudUser && id.id._internalGetInt64Value() == 777000 {
return false
}
@@ -213,10 +227,10 @@ public struct ChatListItemFilterData: Equatable {
}
}
private func revealOptions(strings: PresentationStrings, theme: PresentationTheme, isPinned: Bool, isMuted: Bool?, groupId: PeerGroupId, peerId: PeerId, accountPeerId: PeerId, canDelete: Bool, isEditing: Bool, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
private func revealOptions(strings: PresentationStrings, theme: PresentationTheme, isPinned: Bool, isMuted: Bool?, groupId: EngineChatList.Group, peerId: EnginePeer.Id, accountPeerId: EnginePeer.Id, canDelete: Bool, isEditing: Bool, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
var options: [ItemListRevealOption] = []
if !isEditing {
if case .group = groupId {
if case .archive = groupId {
if isPinned {
options.append(ItemListRevealOption(key: RevealOptionKey.unpin.rawValue, title: strings.DialogList_Unpin, icon: unpinIcon, color: theme.list.itemDisclosureActions.constructive.fillColor, textColor: theme.list.itemDisclosureActions.constructive.foregroundColor))
} else {
@@ -272,8 +286,8 @@ private func groupReferenceRevealOptions(strings: PresentationStrings, theme: Pr
return options
}
private func leftRevealOptions(strings: PresentationStrings, theme: PresentationTheme, isUnread: Bool, isEditing: Bool, isPinned: Bool, isSavedMessages: Bool, groupId: PeerGroupId, peer: Peer, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
if case .group = groupId {
private func leftRevealOptions(strings: PresentationStrings, theme: PresentationTheme, isUnread: Bool, isEditing: Bool, isPinned: Bool, isSavedMessages: Bool, groupId: EngineChatList.Group, peer: EnginePeer, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
if case .archive = groupId {
return []
}
var options: [ItemListRevealOption] = []
@@ -332,8 +346,8 @@ private let playIconImage = UIImage(bundleImageName: "Chat List/MiniThumbnailPla
private final class ChatListMediaPreviewNode: ASDisplayNode {
private let context: AccountContext
private let message: Message
private let media: Media
private let message: EngineMessage
private let media: EngineMedia
private let imageNode: TransformImageNode
private let playIcon: ASImageNode
@@ -341,7 +355,7 @@ private final class ChatListMediaPreviewNode: ASDisplayNode {
private var requestedImage: Bool = false
private var disposable: Disposable?
init(context: AccountContext, message: Message, media: Media) {
init(context: AccountContext, message: EngineMessage, media: EngineMedia) {
self.context = context
self.message = message
self.media = media
@@ -366,17 +380,17 @@ private final class ChatListMediaPreviewNode: ASDisplayNode {
}
var dimensions = CGSize(width: 100.0, height: 100.0)
if let image = self.media as? TelegramMediaImage {
if case let .image(image) = self.media {
self.playIcon.isHidden = true
if let largest = largestImageRepresentation(image.representations) {
dimensions = largest.dimensions.cgSize
if !self.requestedImage {
self.requestedImage = true
let signal = mediaGridMessagePhoto(account: self.context.account, photoReference: .message(message: MessageReference(self.message), media: image), fullRepresentationSize: CGSize(width: 36.0, height: 36.0), synchronousLoad: synchronousLoads)
let signal = mediaGridMessagePhoto(account: self.context.account, photoReference: .message(message: MessageReference(self.message._asMessage()), media: image), fullRepresentationSize: CGSize(width: 36.0, height: 36.0), synchronousLoad: synchronousLoads)
self.imageNode.setSignal(signal, attemptSynchronously: synchronousLoads)
}
}
} else if let file = self.media as? TelegramMediaFile {
} else if case let .file(file) = self.media {
if file.isAnimated {
self.playIcon.isHidden = true
} else {
@@ -386,7 +400,7 @@ private final class ChatListMediaPreviewNode: ASDisplayNode {
dimensions = mediaDimensions.cgSize
if !self.requestedImage {
self.requestedImage = true
let signal = mediaGridMessageVideo(postbox: self.context.account.postbox, videoReference: .message(message: MessageReference(self.message), media: file), synchronousLoad: synchronousLoads, autoFetchFullSizeThumbnail: true, useMiniThumbnailIfAvailable: true)
let signal = mediaGridMessageVideo(postbox: self.context.account.postbox, videoReference: .message(message: MessageReference(self.message._asMessage()), media: file), synchronousLoad: synchronousLoads, autoFetchFullSizeThumbnail: true, useMiniThumbnailIfAvailable: true)
self.imageNode.setSignal(signal, attemptSynchronously: synchronousLoads)
}
}
@@ -426,8 +440,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let mutedIconNode: ASImageNode
private var currentTextLeftCutout: CGFloat = 0.0
private var currentMediaPreviewSpecs: [(message: Message, media: Media, size: CGSize)] = []
private var mediaPreviewNodes: [MediaId: ChatListMediaPreviewNode] = [:]
private var currentMediaPreviewSpecs: [(message: EngineMessage, media: EngineMedia, size: CGSize)] = []
private var mediaPreviewNodes: [EngineMedia.Id: ChatListMediaPreviewNode] = [:]
var selectableControlNode: ItemListSelectableControlNode?
var reorderControlNode: ItemListEditableReorderControlNode?
@@ -477,11 +491,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
return nil
}
switch item.content {
case let .groupReference(_, _, _, unreadState, _):
case let .groupReference(_, _, _, unreadCount, _):
var result = item.presentationData.strings.ChatList_ArchivedChatsTitle
let allCount = unreadState.count(countingCategory: .chats, mutedCategory: .all)
let allCount = unreadCount
if allCount > 0 {
result += "\n\(item.presentationData.strings.VoiceOver_Chat_UnreadMessages(allCount))"
result += "\n\(item.presentationData.strings.VoiceOver_Chat_UnreadMessages(Int32(allCount)))"
}
return result
case let .peer(_, peer, combinedReadState, _, _, _, _, _, _, _, _, _):
@@ -519,7 +533,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
}
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, author is TelegramUser {
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
}
result += "\n\(messageText)"
@@ -553,7 +567,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
}
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, author is TelegramUser {
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
}
if !message.flags.contains(.Incoming), let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) {
@@ -662,14 +676,14 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let previousItem = self.item
self.item = item
var peer: Peer?
var peer: EnginePeer?
var displayAsMessage = false
var enablePreview = true
switch item.content {
case let .peer(messages, peerValue, _, _, _, _, _, _, _, _, displayAsMessageValue, _):
displayAsMessage = displayAsMessageValue
if displayAsMessage, let author = messages.last?.author as? TelegramUser {
peer = author
if displayAsMessage, case let .user(author) = messages.last?.author {
peer = .user(author)
} else {
peer = peerValue.chatMainPeer
}
@@ -681,7 +695,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
UIView.transition(with: self.avatarNode.view, duration: 0.3, options: [.transitionCrossDissolve], animations: {
}, completion: nil)
}
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer.flatMap(EnginePeer.init), overrideImage: .archivedChatsIcon(hiddenByDefault: hiddenByDefault), emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: .archivedChatsIcon(hiddenByDefault: hiddenByDefault), emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
}
if let peer = peer {
@@ -693,7 +707,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else if peer.isDeleted {
overrideImage = .deletedIcon
}
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: EnginePeer(peer), overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0))
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0))
}
self.contextContainer.isGestureEnabled = enablePreview && !item.editing
@@ -804,19 +818,19 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let badgeFont = Font.with(size: floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0), design: .regular, weight: .regular, traits: [.monospacedNumbers])
let account = item.context.account
var messages: [Message]
var messages: [EngineMessage]
enum ContentPeer {
case chat(RenderedPeer)
case group([ChatListGroupReferencePeer])
case chat(EngineRenderedPeer)
case group([EngineChatList.GroupItem.Item])
}
let contentPeer: ContentPeer
let combinedReadState: CombinedPeerReadState?
let combinedReadState: EnginePeerReadCounters?
let unreadCount: (count: Int32, unread: Bool, muted: Bool, mutedCount: Int32?)
let isRemovedFromTotalUnreadCount: Bool
let peerPresence: PeerPresence?
let embeddedState: StoredPeerChatInterfaceState?
let summaryInfo: ChatListMessageTagSummaryInfo
let inputActivities: [(Peer, PeerInputActivity)]?
let peerPresence: EnginePeer.Presence?
let draftState: ChatListItemContent.DraftState?
let hasUnseenMentions: Bool
let inputActivities: [(EnginePeer, PeerInputActivity)]?
let isPeerGroup: Bool
let promoInfo: ChatListNodeEntryPromoInfo?
let displayAsMessage: Bool
@@ -825,7 +839,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var groupHiddenByDefault = false
switch item.content {
case let .peer(messagesValue, peerValue, combinedReadStateValue, isRemovedFromTotalUnreadCountValue, peerPresenceValue, summaryInfoValue, embeddedStateValue, inputActivitiesValue, promoInfoValue, ignoreUnreadBadge, displayAsMessageValue, _):
case let .peer(messagesValue, peerValue, combinedReadStateValue, isRemovedFromTotalUnreadCountValue, peerPresenceValue, hasUnseenMentionsValue, draftStateValue, inputActivitiesValue, promoInfoValue, ignoreUnreadBadge, displayAsMessageValue, _):
messages = messagesValue
contentPeer = .chat(peerValue)
combinedReadState = combinedReadStateValue
@@ -839,15 +853,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else {
isRemovedFromTotalUnreadCount = isRemovedFromTotalUnreadCountValue
}
peerPresence = (peerPresenceValue as? TelegramUserPresence).flatMap { presence -> TelegramUserPresence in
TelegramUserPresence(status: presence.status, lastActivity: 0)
peerPresence = peerPresenceValue.flatMap { presence -> EnginePeer.Presence in
return EnginePeer.Presence(status: presence.status, lastActivity: 0)
}
embeddedState = embeddedStateValue
summaryInfo = summaryInfoValue
draftState = draftStateValue
hasUnseenMentions = hasUnseenMentionsValue
switch peerValue.peer {
case _ as TelegramUser, _ as TelegramSecretChat:
if let peerPresence = peerPresence as? TelegramUserPresence, case .present = peerPresence.status {
case .user, .secretChat:
if let peerPresence = peerPresence, case .present = peerPresence.status {
inputActivities = inputActivitiesValue
} else {
inputActivities = nil
@@ -860,7 +874,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
promoInfo = promoInfoValue
displayAsMessage = displayAsMessageValue
hasFailedMessages = messagesValue.last?.flags.contains(.Failed) ?? false // hasFailedMessagesValue
case let .groupReference(_, peers, messageValue, unreadState, hiddenByDefault):
case let .groupReference(_, peers, messageValue, unreadCountValue, hiddenByDefault):
if let _ = messageValue, !peers.isEmpty {
contentPeer = .chat(peers[0].peer)
} else {
@@ -873,13 +887,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
}
combinedReadState = nil
isRemovedFromTotalUnreadCount = false
embeddedState = nil
summaryInfo = ChatListMessageTagSummaryInfo()
draftState = nil
hasUnseenMentions = false
inputActivities = nil
isPeerGroup = true
groupHiddenByDefault = hiddenByDefault
let allCount = unreadState.count(countingCategory: .chats, mutedCategory: .all)
unreadCount = (allCount, allCount != 0, true, nil)
unreadCount = (Int32(unreadCountValue), unreadCountValue != 0, true, nil)
peerPresence = nil
promoInfo = nil
displayAsMessage = false
@@ -949,8 +962,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let leftInset: CGFloat = params.leftInset + avatarLeftInset
enum ContentData {
case chat(itemPeer: RenderedPeer, peer: Peer?, hideAuthor: Bool, messageText: String)
case group(peers: [ChatListGroupReferencePeer])
case chat(itemPeer: EngineRenderedPeer, peer: EnginePeer?, hideAuthor: Bool, messageText: String)
case group(peers: [EngineChatList.GroupItem.Item])
}
let contentData: ContentData
@@ -977,11 +990,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var inlineAuthorPrefix: String?
if case .groupReference = item.content {
if let author = messages.last?.author as? TelegramUser {
if case let .user(author) = messages.last?.author {
if author.id == item.context.account.peerId {
inlineAuthorPrefix = item.presentationData.strings.DialogList_You
} else if messages.last?.id.peerId.namespace != Namespaces.Peer.CloudUser && messages.last?.id.peerId.namespace != Namespaces.Peer.SecretChat {
inlineAuthorPrefix = author.compactDisplayTitle
inlineAuthorPrefix = EnginePeer.user(author).compactDisplayTitle
}
}
}
@@ -993,22 +1006,27 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let contentImageSize = CGSize(width: contentImageSide, height: contentImageSide)
let contentImageSpacing: CGFloat = 2.0
let contentImageTrailingSpace: CGFloat = 5.0
var contentImageSpecs: [(message: Message, media: Media, size: CGSize)] = []
var contentImageSpecs: [(message: EngineMessage, media: EngineMedia, size: CGSize)] = []
switch contentData {
case let .chat(itemPeer, _, _, text):
var isUser = false
if case .user = itemPeer.chatMainPeer {
isUser = true
}
var peerText: String?
if case .groupReference = item.content {
if let messagePeer = itemPeer.chatMainPeer {
peerText = messagePeer.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
} else if let message = messages.last, let author = message.author as? TelegramUser, let peer = itemPeer.chatMainPeer, !(peer is TelegramUser) {
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
} else if let message = messages.last, case let .user(author) = message.author, let peer = itemPeer.chatMainPeer, !isUser {
if case let .channel(peer) = peer, case .broadcast = peer.info {
} else if !displayAsMessage {
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature {
peerText = authorSignature
} else {
peerText = author.id == account.peerId ? item.presentationData.strings.DialogList_You : author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
peerText = author.id == account.peerId ? item.presentationData.strings.DialogList_You : EnginePeer(author).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
}
}
@@ -1022,13 +1040,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
chatListText = (text, messageText)
}
if inlineAuthorPrefix == nil, let embeddedState = embeddedState, embeddedState.overrideChatTimestamp != nil, let opaqueState = _internal_decodeStoredChatInterfaceState(state: embeddedState) {
let interfaceState = ChatInterfaceState.parse(opaqueState)
if inlineAuthorPrefix == nil, let draftState = draftState {
hasDraft = true
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
let draftText: String = interfaceState.composeInputState.inputText.string
let draftText: String = draftState.text
attributedText = NSAttributedString(string: foldLineBreaks(draftText.replacingOccurrences(of: "\n\n", with: " ")), font: textFont, textColor: theme.messageTextColor)
} else if let message = messages.last {
@@ -1081,7 +1097,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
}
var displayMediaPreviews = true
if message.containsSecretMedia {
if message._asMessage().containsSecretMedia {
displayMediaPreviews = false
} else if let _ = message.peers[message.id.peerId] as? TelegramSecretChat {
displayMediaPreviews = false
@@ -1096,34 +1112,28 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
inner: for media in message.media {
if let image = media as? TelegramMediaImage {
if let _ = largestImageRepresentation(image.representations) {
//let imageSize = largest.dimensions.cgSize
//let fitSize = imageSize.aspectFilled(contentImageFillSize)
let fitSize = contentImageSize
contentImageSpecs.append((message, image, fitSize))
contentImageSpecs.append((message, .image(image), fitSize))
}
break inner
} else if let file = media as? TelegramMediaFile {
if file.isVideo, !file.isInstantVideo, let _ = file.dimensions {
//let imageSize = dimensions.cgSize
//let fitSize = imageSize.aspectFilled(contentImageFillSize)
let fitSize = contentImageSize
contentImageSpecs.append((message, file, fitSize))
contentImageSpecs.append((message, .file(file), fitSize))
}
break inner
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
let imageTypes = ["photo", "video", "embed", "gif", "document", "telegram_album"]
if let image = content.image, let type = content.type, imageTypes.contains(type) {
if let _ = largestImageRepresentation(image.representations) {
//let imageSize = largest.dimensions.cgSize
let fitSize = contentImageSize
contentImageSpecs.append((message, image, fitSize))
contentImageSpecs.append((message, .image(image), fitSize))
}
break inner
} else if let file = content.file {
if file.isVideo, !file.isInstantVideo, let _ = file.dimensions {
//let imageSize = dimensions.cgSize
let fitSize = contentImageSize
contentImageSpecs.append((message, file, fitSize))
contentImageSpecs.append((message, .file(file), fitSize))
}
break inner
}
@@ -1176,15 +1186,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
switch contentData {
case let .chat(itemPeer, _, _, _):
if let message = messages.last, let author = message.author as? TelegramUser, displayAsMessage {
titleAttributedString = NSAttributedString(string: author.id == account.peerId ? item.presentationData.strings.DialogList_You : author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: titleFont, textColor: theme.titleColor)
if let message = messages.last, case let .user(author) = message.author, displayAsMessage {
titleAttributedString = NSAttributedString(string: author.id == account.peerId ? item.presentationData.strings.DialogList_You : EnginePeer.user(author).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: titleFont, textColor: theme.titleColor)
} else if isPeerGroup {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.ChatList_ArchivedChatsTitle, font: titleFont, textColor: theme.titleColor)
} else if itemPeer.chatMainPeer?.id == item.context.account.peerId {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleFont, textColor: theme.titleColor)
} else if let id = itemPeer.chatMainPeer?.id, id.isReplies {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleFont, textColor: theme.titleColor)
} else if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
} else if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: item.index.messageIndex.id.peerId.namespace == Namespaces.Peer.SecretChat ? theme.secretTitleColor : theme.titleColor)
}
case .group:
@@ -1221,7 +1231,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
}
if !isPeerGroup, let message = messages.last, message.author?.id == account.peerId && !hasDraft {
if message.flags.isSending && !message.isSentOrAcknowledged {
if message.flags.isSending && !message._asMessage().isSentOrAcknowledged {
statusState = .clock(PresentationResourcesChatList.clockFrameImage(item.presentationData.theme), PresentationResourcesChatList.clockMinImage(item.presentationData.theme))
} else if message.id.peerId != account.peerId {
if hasFailedMessages {
@@ -1263,13 +1273,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
}
}
}
let tagSummaryCount = summaryInfo.tagSummaryCount ?? 0
let actionsSummaryCount = summaryInfo.actionsSummaryCount ?? 0
let totalMentionCount = tagSummaryCount - actionsSummaryCount
if !isPeerGroup {
if totalMentionCount > 0 {
if Namespaces.PeerGroup.archive == item.peerGroupId {
if hasUnseenMentions {
if case .archive = item.peerGroupId {
currentMentionBadgeImage = PresentationResourcesChatList.badgeBackgroundInactiveMention(item.presentationData.theme, diameter: badgeDiameter)
} else {
currentMentionBadgeImage = PresentationResourcesChatList.badgeBackgroundMention(item.presentationData.theme, diameter: badgeDiameter)
@@ -1414,20 +1421,20 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
switch item.content {
case let .peer(_, renderedPeer, _, _, presence, _ ,_ ,_, _, _, displayAsMessage, _):
if !displayAsMessage {
if let peer = renderedPeer.chatMainPeer as? TelegramUser, let presence = presence as? TelegramUserPresence, !isServicePeer(peer) && !peer.flags.contains(.isSupport) && peer.id != item.context.account.peerId {
let updatedPresence = TelegramUserPresence(status: presence.status, lastActivity: 0)
let relativeStatus = relativeUserPresenceStatus(EnginePeer.Presence(updatedPresence), relativeTo: timestamp)
if case let .user(peer) = renderedPeer.chatMainPeer, let presence = presence, !isServicePeer(peer) && !peer.flags.contains(.isSupport) && peer.id != item.context.account.peerId {
let updatedPresence = EnginePeer.Presence(status: presence.status, lastActivity: 0)
let relativeStatus = relativeUserPresenceStatus(updatedPresence, relativeTo: timestamp)
if case .online = relativeStatus {
online = true
}
animateOnline = true
} else if let channel = renderedPeer.peer as? TelegramChannel {
} else if case let .channel(channel) = renderedPeer.peer {
onlineIsVoiceChat = true
if channel.flags.contains(.hasActiveVoiceChat) && item.interaction.searchTextHighightState == nil {
online = true
}
animateOnline = true
} else if let group = renderedPeer.peer as? TelegramGroup {
} else if case let .legacyGroup(group) = renderedPeer.peer {
onlineIsVoiceChat = true
if group.flags.contains(.hasActiveVoiceChat) && item.interaction.searchTextHighightState == nil {
online = true
@@ -1780,7 +1787,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
inputActivitiesApply?()
var mediaPreviewOffset = textNodeFrame.origin.offsetBy(dx: 1.0, dy: floor((measureLayout.size.height - contentImageSize.height) / 2.0))
var validMediaIds: [MediaId] = []
var validMediaIds: [EngineMedia.Id] = []
for (message, media, mediaSize) in contentImageSpecs {
guard let mediaId = media.id else {
continue
@@ -1803,7 +1810,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
previewNodeTransition.updateFrame(node: previewNode, frame: CGRect(origin: mediaPreviewOffset, size: mediaSize))
mediaPreviewOffset.x += mediaSize.width + contentImageSpacing
}
var removeMediaIds: [MediaId] = []
var removeMediaIds: [EngineMedia.Id] = []
for (mediaId, itemNode) in strongSelf.mediaPreviewNodes {
if !validMediaIds.contains(mediaId) {
removeMediaIds.append(mediaId)
@@ -1864,8 +1871,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let topNegativeInset: CGFloat = 0.0
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: layoutOffset - separatorHeight - topNegativeInset), size: CGSize(width: layout.contentSize.width, height: layout.contentSize.height + separatorHeight + topNegativeInset))
if let peerPresence = peerPresence as? TelegramUserPresence {
strongSelf.peerPresenceManager?.reset(presence: TelegramUserPresence(status: peerPresence.status, lastActivity: 0), isOnline: online)
if let peerPresence = peerPresence {
strongSelf.peerPresenceManager?.reset(presence: EnginePeer.Presence(status: peerPresence.status, lastActivity: 0), isOnline: online)
}
strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
@@ -2057,7 +2064,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
case RevealOptionKey.pin.rawValue:
switch item.content {
case .peer:
let itemId: PinnedItemId = .peer(item.index.messageIndex.id.peerId)
let itemId: EngineChatList.PinnedItem.Id = .peer(item.index.messageIndex.id.peerId)
item.interaction.setItemPinned(itemId, true)
case .groupReference:
break
@@ -2065,7 +2072,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
case RevealOptionKey.unpin.rawValue:
switch item.content {
case .peer:
let itemId: PinnedItemId = .peer(item.index.messageIndex.id.peerId)
let itemId: EngineChatList.PinnedItem.Id = .peer(item.index.messageIndex.id.peerId)
item.interaction.setItemPinned(itemId, false)
case .groupReference:
break