mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user