mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update message group rendering
This commit is contained in:
parent
7b7b403c00
commit
dd457ae82f
@ -14,6 +14,12 @@ public struct Namespaces {
|
|||||||
public static let allScheduled: Set<Int32> = Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal])
|
public static let allScheduled: Set<Int32> = Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal])
|
||||||
public static let allQuickReply: Set<Int32> = Set([Namespaces.Message.QuickReplyCloud, Namespaces.Message.QuickReplyLocal])
|
public static let allQuickReply: Set<Int32> = Set([Namespaces.Message.QuickReplyCloud, Namespaces.Message.QuickReplyLocal])
|
||||||
public static let allNonRegular: Set<Int32> = Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal, Namespaces.Message.QuickReplyCloud, Namespaces.Message.QuickReplyLocal])
|
public static let allNonRegular: Set<Int32> = Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal, Namespaces.Message.QuickReplyCloud, Namespaces.Message.QuickReplyLocal])
|
||||||
|
public static let allLocal: [Int32] = [
|
||||||
|
Namespaces.Message.Local,
|
||||||
|
Namespaces.Message.SecretIncoming,
|
||||||
|
Namespaces.Message.ScheduledLocal,
|
||||||
|
Namespaces.Message.QuickReplyLocal
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Media {
|
public struct Media {
|
||||||
|
@ -43,7 +43,7 @@ public struct ChatMessageEntryAttributes: Equatable {
|
|||||||
|
|
||||||
public enum ChatHistoryEntry: Identifiable, Comparable {
|
public enum ChatHistoryEntry: Identifiable, Comparable {
|
||||||
case MessageEntry(Message, ChatPresentationData, Bool, MessageHistoryEntryLocation?, ChatHistoryMessageSelection, ChatMessageEntryAttributes)
|
case MessageEntry(Message, ChatPresentationData, Bool, MessageHistoryEntryLocation?, ChatHistoryMessageSelection, ChatMessageEntryAttributes)
|
||||||
case MessageGroupEntry(MessageGroupInfo, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)], ChatPresentationData)
|
case MessageGroupEntry(Int64, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)], ChatPresentationData)
|
||||||
case UnreadEntry(MessageIndex, ChatPresentationData)
|
case UnreadEntry(MessageIndex, ChatPresentationData)
|
||||||
case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData)
|
case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData)
|
||||||
case ChatInfoEntry(String, String, TelegramMediaImage?, TelegramMediaFile?, ChatPresentationData)
|
case ChatInfoEntry(String, String, TelegramMediaImage?, TelegramMediaFile?, ChatPresentationData)
|
||||||
@ -63,7 +63,7 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
|
|||||||
}
|
}
|
||||||
return UInt64(message.stableId) | ((type << 40))
|
return UInt64(message.stableId) | ((type << 40))
|
||||||
case let .MessageGroupEntry(groupInfo, _, _):
|
case let .MessageGroupEntry(groupInfo, _, _):
|
||||||
return UInt64(groupInfo.stableId) | ((UInt64(2) << 40))
|
return UInt64(bitPattern: groupInfo) | ((UInt64(2) << 40))
|
||||||
case .UnreadEntry:
|
case .UnreadEntry:
|
||||||
return UInt64(4) << 40
|
return UInt64(4) << 40
|
||||||
case .ReplyCountEntry:
|
case .ReplyCountEntry:
|
||||||
|
@ -12,7 +12,28 @@ import TextFormat
|
|||||||
import Markdown
|
import Markdown
|
||||||
import Display
|
import Display
|
||||||
|
|
||||||
|
struct ChatHistoryEntriesForViewState {
|
||||||
|
private var messageStableIdToLocalId: [UInt32: Int64] = [:]
|
||||||
|
|
||||||
|
init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func messageGroupStableId(messageStableId: UInt32, groupId: Int64, isLocal: Bool) -> Int64 {
|
||||||
|
if isLocal {
|
||||||
|
self.messageStableIdToLocalId[messageStableId] = groupId
|
||||||
|
return groupId
|
||||||
|
} else {
|
||||||
|
if let value = self.messageStableIdToLocalId[messageStableId] {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
return groupId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func chatHistoryEntriesForView(
|
func chatHistoryEntriesForView(
|
||||||
|
currentState: ChatHistoryEntriesForViewState,
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
location: ChatLocation,
|
location: ChatLocation,
|
||||||
view: MessageHistoryView,
|
view: MessageHistoryView,
|
||||||
@ -37,9 +58,11 @@ func chatHistoryEntriesForView(
|
|||||||
cachedData: CachedPeerData?,
|
cachedData: CachedPeerData?,
|
||||||
adMessage: Message?,
|
adMessage: Message?,
|
||||||
dynamicAdMessages: [Message]
|
dynamicAdMessages: [Message]
|
||||||
) -> [ChatHistoryEntry] {
|
) -> ([ChatHistoryEntry], ChatHistoryEntriesForViewState) {
|
||||||
|
var currentState = currentState
|
||||||
|
|
||||||
if historyAppearsCleared {
|
if historyAppearsCleared {
|
||||||
return []
|
return ([], currentState)
|
||||||
}
|
}
|
||||||
var entries: [ChatHistoryEntry] = []
|
var entries: [ChatHistoryEntry] = []
|
||||||
var adminRanks: [PeerId: CachedChannelAdminRank] = [:]
|
var adminRanks: [PeerId: CachedChannelAdminRank] = [:]
|
||||||
@ -121,8 +144,8 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingGroupStableIds: [UInt32] = []
|
//var existingGroupStableIds: [UInt32] = []
|
||||||
var groupBucket: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)] = []
|
//var groupBucket: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)] = []
|
||||||
var count = 0
|
var count = 0
|
||||||
loop: for entry in view.entries {
|
loop: for entry in view.entries {
|
||||||
var message = entry.message
|
var message = entry.message
|
||||||
@ -199,7 +222,7 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if groupMessages || reverseGroupedMessages {
|
if groupMessages || reverseGroupedMessages {
|
||||||
if !groupBucket.isEmpty && message.groupInfo != groupBucket[0].0.groupInfo {
|
/*if !groupBucket.isEmpty && message.groupInfo != groupBucket[0].0.groupInfo {
|
||||||
if reverseGroupedMessages {
|
if reverseGroupedMessages {
|
||||||
groupBucket.reverse()
|
groupBucket.reverse()
|
||||||
}
|
}
|
||||||
@ -215,15 +238,61 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
groupBucket.removeAll()
|
groupBucket.removeAll()
|
||||||
}
|
}*/
|
||||||
if let _ = message.groupInfo {
|
if let messageGroupingKey = message.groupingKey, (groupMessages || reverseGroupedMessages) {
|
||||||
let selection: ChatHistoryMessageSelection
|
let selection: ChatHistoryMessageSelection
|
||||||
if let selectedMessages = selectedMessages {
|
if let selectedMessages = selectedMessages {
|
||||||
selection = .selectable(selected: selectedMessages.contains(message.id))
|
selection = .selectable(selected: selectedMessages.contains(message.id))
|
||||||
} else {
|
} else {
|
||||||
selection = .none
|
selection = .none
|
||||||
}
|
}
|
||||||
groupBucket.append((message, isRead, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: false, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }), entry.location))
|
|
||||||
|
var isCentered = false
|
||||||
|
if case let .messageOptions(_, _, info) = associatedData.subject, case let .link(link) = info {
|
||||||
|
isCentered = link.isCentered
|
||||||
|
}
|
||||||
|
|
||||||
|
let attributes = ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: message.index == associatedData.currentlyPlayingMessageId, isCentered: isCentered, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] })
|
||||||
|
|
||||||
|
let groupStableId = currentState.messageGroupStableId(messageStableId: message.stableId, groupId: messageGroupingKey, isLocal: Namespaces.Message.allLocal.contains(message.id.namespace))
|
||||||
|
var found = false
|
||||||
|
for i in 0 ..< entries.count {
|
||||||
|
if case let .MessageEntry(currentMessage, _, currentIsRead, currentLocation, currentSelection, currentAttributes) = entries[i], let currentGroupingKey = currentMessage.groupingKey, currentState.messageGroupStableId(messageStableId: currentMessage.stableId, groupId: currentGroupingKey, isLocal: Namespaces.Message.allLocal.contains(currentMessage.id.namespace)) == groupStableId {
|
||||||
|
found = true
|
||||||
|
|
||||||
|
var currentMessages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)] = []
|
||||||
|
|
||||||
|
currentMessages.append((currentMessage, currentIsRead, currentSelection, currentAttributes, currentLocation))
|
||||||
|
if reverseGroupedMessages {
|
||||||
|
currentMessages.insert((message, isRead, selection, attributes, entry.location), at: 0)
|
||||||
|
} else {
|
||||||
|
currentMessages.append((message, isRead, selection, attributes, entry.location))
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[i] = .MessageGroupEntry(groupStableId, currentMessages, presentationData)
|
||||||
|
} else if case let .MessageGroupEntry(currentGroupStableId, currentMessages, _) = entries[i], currentGroupStableId == groupStableId {
|
||||||
|
found = true
|
||||||
|
|
||||||
|
var currentMessages = currentMessages
|
||||||
|
if reverseGroupedMessages {
|
||||||
|
currentMessages.insert((message, isRead, selection, attributes, entry.location), at: 0)
|
||||||
|
} else {
|
||||||
|
currentMessages.append((message, isRead, selection, attributes, entry.location))
|
||||||
|
}
|
||||||
|
entries[i] = .MessageGroupEntry(currentGroupStableId, currentMessages, presentationData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
entries.append(.MessageEntry(message, presentationData, isRead, entry.location, selection, attributes))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*let selection: ChatHistoryMessageSelection
|
||||||
|
if let selectedMessages = selectedMessages {
|
||||||
|
selection = .selectable(selected: selectedMessages.contains(message.id))
|
||||||
|
} else {
|
||||||
|
selection = .none
|
||||||
|
}
|
||||||
|
groupBucket.append((message, isRead, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: false, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }), entry.location))*/
|
||||||
} else {
|
} else {
|
||||||
let selection: ChatHistoryMessageSelection
|
let selection: ChatHistoryMessageSelection
|
||||||
if let selectedMessages = selectedMessages {
|
if let selectedMessages = selectedMessages {
|
||||||
@ -250,7 +319,7 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !groupBucket.isEmpty {
|
/*if !groupBucket.isEmpty {
|
||||||
assert(groupMessages || reverseGroupedMessages)
|
assert(groupMessages || reverseGroupedMessages)
|
||||||
if reverseGroupedMessages {
|
if reverseGroupedMessages {
|
||||||
groupBucket.reverse()
|
groupBucket.reverse()
|
||||||
@ -266,7 +335,7 @@ func chatHistoryEntriesForView(
|
|||||||
entries.append(.MessageEntry(message, presentationData, isRead, location, selection, attributes))
|
entries.append(.MessageEntry(message, presentationData, isRead, location, selection, attributes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if let lowerTimestamp = view.entries.last?.message.timestamp, let upperTimestamp = view.entries.first?.message.timestamp {
|
if let lowerTimestamp = view.entries.last?.message.timestamp, let upperTimestamp = view.entries.first?.message.timestamp {
|
||||||
if let joinMessage {
|
if let joinMessage {
|
||||||
@ -341,12 +410,12 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
addedThreadHead = true
|
addedThreadHead = true
|
||||||
if messages.count > 1, let groupInfo = messages[0].groupInfo {
|
if messages.count > 1, let groupingKey = messages[0].groupingKey {
|
||||||
var groupMessages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)] = []
|
var groupMessages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)] = []
|
||||||
for message in messages {
|
for message in messages {
|
||||||
groupMessages.append((message, false, .none, ChatMessageEntryAttributes(rank: adminRank, isContact: false, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: false, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }), nil))
|
groupMessages.append((message, false, .none, ChatMessageEntryAttributes(rank: adminRank, isContact: false, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: false, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }), nil))
|
||||||
}
|
}
|
||||||
entries.insert(.MessageGroupEntry(groupInfo, groupMessages, presentationData), at: 0)
|
entries.insert(.MessageGroupEntry(groupingKey, groupMessages, presentationData), at: 0)
|
||||||
} else {
|
} else {
|
||||||
if !hasTopicCreated {
|
if !hasTopicCreated {
|
||||||
entries.insert(.MessageEntry(messages[0], presentationData, false, nil, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: false, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[messages[0].id], isPlaying: false, isCentered: false, authorStoryStats: messages[0].author.flatMap { view.peerStoryStats[$0.id] })), at: 0)
|
entries.insert(.MessageEntry(messages[0], presentationData, false, nil, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: false, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[messages[0].id], isPlaying: false, isCentered: false, authorStoryStats: messages[0].author.flatMap { view.peerStoryStats[$0.id] })), at: 0)
|
||||||
@ -583,8 +652,8 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if reverse {
|
if reverse {
|
||||||
return entries.reversed()
|
return (entries.reversed(), currentState)
|
||||||
} else {
|
} else {
|
||||||
return entries
|
return (entries, currentState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1419,6 +1419,8 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
let chatHistoryEntriesForViewState = Atomic<ChatHistoryEntriesForViewState>(value: ChatHistoryEntriesForViewState())
|
||||||
|
|
||||||
let animatedEmojiStickers: Signal<[String: [StickerPackItem]], NoError> = context.animatedEmojiStickers
|
let animatedEmojiStickers: Signal<[String: [StickerPackItem]], NoError> = context.animatedEmojiStickers
|
||||||
let additionalAnimatedEmojiStickers = context.additionalAnimatedEmojiStickers
|
let additionalAnimatedEmojiStickers = context.additionalAnimatedEmojiStickers
|
||||||
|
|
||||||
@ -1857,7 +1859,10 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
includeEmbeddedSavedChatInfo = true
|
includeEmbeddedSavedChatInfo = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let filteredEntries = chatHistoryEntriesForView(
|
let previousChatHistoryEntriesForViewState = chatHistoryEntriesForViewState.with({ $0 })
|
||||||
|
|
||||||
|
let (filteredEntries, updatedChatHistoryEntriesForViewState) = chatHistoryEntriesForView(
|
||||||
|
currentState: previousChatHistoryEntriesForViewState,
|
||||||
context: context,
|
context: context,
|
||||||
location: chatLocation,
|
location: chatLocation,
|
||||||
view: view,
|
view: view,
|
||||||
@ -1886,6 +1891,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
||||||
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3, ignoreMessageIds: update.4)
|
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3, ignoreMessageIds: update.4)
|
||||||
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, allAdMessages.version))
|
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, allAdMessages.version))
|
||||||
|
let _ = chatHistoryEntriesForViewState.swap(updatedChatHistoryEntriesForViewState)
|
||||||
let previous = previousValueAndVersion?.0
|
let previous = previousValueAndVersion?.0
|
||||||
let previousSelectedMessages = previousValueAndVersion?.2
|
let previousSelectedMessages = previousValueAndVersion?.2
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user