[WIP] Saved messages

This commit is contained in:
Isaac 2024-01-06 00:43:58 +04:00
parent c2b9891de1
commit 6a89f938db
86 changed files with 1660 additions and 478 deletions

View file

@ -3640,6 +3640,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",
@ -3691,6 +3692,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",
@ -3721,6 +3723,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",
@ -3751,6 +3754,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",
@ -3781,6 +3785,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",

View file

@ -174,6 +174,7 @@ public final class ChatListShimmerNode: ASDisplayNode {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: peer1,
text: "Text",

View file

@ -2252,6 +2252,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
public var reactionsTitle: String?
public var animationCache: AnimationCache?
public var alwaysAllowPremiumReactions: Bool
public var allPresetReactionsAreAvailable: Bool
public var getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?
public var disablePositionLock: Bool
public var tip: Tip?
@ -2267,6 +2268,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
reactionsTitle: String? = nil,
animationCache: AnimationCache? = nil,
alwaysAllowPremiumReactions: Bool = false,
allPresetReactionsAreAvailable: Bool = false,
getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)? = nil,
disablePositionLock: Bool = false,
tip: Tip? = nil,
@ -2281,6 +2283,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
self.selectedReactionItems = selectedReactionItems
self.reactionsTitle = reactionsTitle
self.alwaysAllowPremiumReactions = alwaysAllowPremiumReactions
self.allPresetReactionsAreAvailable = allPresetReactionsAreAvailable
self.getEmojiContent = getEmojiContent
self.disablePositionLock = disablePositionLock
self.tip = tip
@ -2296,6 +2299,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
self.selectedReactionItems = Set()
self.reactionsTitle = nil
self.alwaysAllowPremiumReactions = false
self.allPresetReactionsAreAvailable = false
self.getEmojiContent = nil
self.disablePositionLock = false
self.tip = nil

View file

@ -35,6 +35,28 @@ public protocol ContextControllerActionsStackItemNode: ASDisplayNode {
func increaseHighlightedIndex()
}
public struct ContextControllerReactionItems {
public var context: AccountContext
public var reactionItems: [ReactionContextItem]
public var selectedReactionItems: Set<MessageReaction.Reaction>
public var reactionsTitle: String?
public var animationCache: AnimationCache
public var alwaysAllowPremiumReactions: Bool
public var allPresetReactionsAreAvailable: Bool
public var getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?
public init(context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, allPresetReactionsAreAvailable: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?) {
self.context = context
self.reactionItems = reactionItems
self.selectedReactionItems = selectedReactionItems
self.reactionsTitle = reactionsTitle
self.animationCache = animationCache
self.alwaysAllowPremiumReactions = alwaysAllowPremiumReactions
self.allPresetReactionsAreAvailable = allPresetReactionsAreAvailable
self.getEmojiContent = getEmojiContent
}
}
public protocol ContextControllerActionsStackItem: AnyObject {
func node(
getController: @escaping () -> ContextControllerProtocol?,
@ -46,7 +68,7 @@ public protocol ContextControllerActionsStackItem: AnyObject {
var id: AnyHashable? { get }
var tip: ContextController.Tip? { get }
var tipSignal: Signal<ContextController.Tip?, NoError>? { get }
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? { get }
var reactionItems: ContextControllerReactionItems? { get }
var dismissed: (() -> Void)? { get }
}
@ -911,7 +933,7 @@ final class ContextControllerActionsListStackItem: ContextControllerActionsStack
let id: AnyHashable?
let items: [ContextMenuItem]
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
let reactionItems: ContextControllerReactionItems?
let tip: ContextController.Tip?
let tipSignal: Signal<ContextController.Tip?, NoError>?
let dismissed: (() -> Void)?
@ -919,7 +941,7 @@ final class ContextControllerActionsListStackItem: ContextControllerActionsStack
init(
id: AnyHashable?,
items: [ContextMenuItem],
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
reactionItems: ContextControllerReactionItems?,
tip: ContextController.Tip?,
tipSignal: Signal<ContextController.Tip?, NoError>?,
dismissed: (() -> Void)?
@ -1009,7 +1031,7 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
let id: AnyHashable?
private let content: ContextControllerItemsContent
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
let reactionItems: ContextControllerReactionItems?
let tip: ContextController.Tip?
let tipSignal: Signal<ContextController.Tip?, NoError>?
let dismissed: (() -> Void)?
@ -1017,7 +1039,7 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
init(
id: AnyHashable?,
content: ContextControllerItemsContent,
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
reactionItems: ContextControllerReactionItems?,
tip: ContextController.Tip?,
tipSignal: Signal<ContextController.Tip?, NoError>?,
dismissed: (() -> Void)?
@ -1046,9 +1068,18 @@ final class ContextControllerActionsCustomStackItem: ContextControllerActionsSta
}
func makeContextControllerActionsStackItem(items: ContextController.Items) -> [ContextControllerActionsStackItem] {
var reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
var reactionItems: ContextControllerReactionItems?
if let context = items.context, let animationCache = items.animationCache, !items.reactionItems.isEmpty {
reactionItems = (context, items.reactionItems, items.selectedReactionItems, reactionsTitle: items.reactionsTitle, animationCache, alwaysAllowPremiumReactions: items.alwaysAllowPremiumReactions, items.getEmojiContent)
reactionItems = ContextControllerReactionItems(
context: context,
reactionItems: items.reactionItems,
selectedReactionItems: items.selectedReactionItems,
reactionsTitle: items.reactionsTitle,
animationCache: animationCache,
alwaysAllowPremiumReactions: items.alwaysAllowPremiumReactions,
allPresetReactionsAreAvailable: items.allPresetReactionsAreAvailable,
getEmojiContent: items.getEmojiContent
)
}
switch items.content {
case let .list(listItems):
@ -1172,7 +1203,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
var tip: ContextController.Tip?
let tipSignal: Signal<ContextController.Tip?, NoError>?
var tipNode: InnerTextSelectionTipContainerNode?
let reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?
let reactionItems: ContextControllerReactionItems?
let itemDismissed: (() -> Void)?
var storedScrollingState: CGFloat?
let positionLock: CGFloat?
@ -1187,7 +1218,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
item: ContextControllerActionsStackItem,
tip: ContextController.Tip?,
tipSignal: Signal<ContextController.Tip?, NoError>?,
reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)?,
reactionItems: ContextControllerReactionItems?,
itemDismissed: (() -> Void)?,
positionLock: CGFloat?
) {
@ -1338,7 +1369,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode {
private var selectionPanGesture: UIPanGestureRecognizer?
var topReactionItems: (context: AccountContext, reactionItems: [ReactionContextItem], selectedReactionItems: Set<MessageReaction.Reaction>, reactionsTitle: String?, animationCache: AnimationCache, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?)? {
var topReactionItems: ContextControllerReactionItems? {
return self.itemContainers.last?.reactionItems
}

View file

@ -650,6 +650,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
selectedItems: reactionItems.selectedReactionItems,
title: reactionItems.reactionsTitle,
alwaysAllowPremiumReactions: reactionItems.alwaysAllowPremiumReactions,
allPresetReactionsAreAvailable: reactionItems.allPresetReactionsAreAvailable,
getEmojiContent: reactionItems.getEmojiContent,
isExpandedUpdated: { [weak self] transition in
guard let strongSelf = self else {

View file

@ -137,6 +137,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView {
selectedItems: Set(),
title: nil,
alwaysAllowPremiumReactions: false,
allPresetReactionsAreAvailable: false,
getEmojiContent: { [weak self] animationCache, animationRenderer in
guard let self else {
preconditionFailure()

View file

@ -725,7 +725,7 @@ public class StickerPickerScreen: ViewController {
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let gallery = GalleryController(context: context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in
}, baseNavigationController: nil)

View file

@ -1427,7 +1427,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
}, showAll: false)
let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let controller = LocationViewController(context: self.context, subject: EngineMessage(message), params: controllerParams)
self.pushController(controller)

View file

@ -858,10 +858,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let previewItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [previewMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: true, isPreview: true)
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let dragItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [dragMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: true, isPreview: true)
let headerItems: [ListViewItem] = [previewItem, dragItem]

View file

@ -979,7 +979,7 @@ final class ChatListTable: Table {
}
var tagSummary: MessageHistoryTagNamespaceSummary?
if let summaryTag = summaryTag {
tagSummary = summaryTable.get(MessageHistoryTagsSummaryKey(tag: summaryTag, peerId: peerIndex.messageIndex.id.peerId, threadId: nil, namespace: namespace))
tagSummary = summaryTable.get(MessageHistoryTagsSummaryKey(tag: summaryTag, peerId: peerIndex.messageIndex.id.peerId, threadId: nil, namespace: namespace, customTag: nil))
}
var topMessageAttributes: [MessageAttribute] = []
if let topMessage = topMessage {

View file

@ -110,7 +110,7 @@ private func updateMessagePeers(_ message: Message, updatedPeers: [PeerId: Peer]
peers[peerId] = currentPeer
}
}
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
}
return nil
}
@ -790,7 +790,7 @@ private final class ChatListViewSpaceState {
return nil
}
let updatedMessageSummary = transaction.currentUpdatedMessageTagSummaries[MessageHistoryTagsSummaryKey(tag: filterMessageTagSummary.addCount.tag, peerId: entryPeer.id, threadId: nil, namespace: filterMessageTagSummary.addCount.namespace)]
let updatedMessageSummary = transaction.currentUpdatedMessageTagSummaries[MessageHistoryTagsSummaryKey(tag: filterMessageTagSummary.addCount.tag, peerId: entryPeer.id, threadId: nil, namespace: filterMessageTagSummary.addCount.namespace, customTag: nil)]
let updatedActionsSummary = transaction.currentUpdatedMessageActionsSummaries[PendingMessageActionsSummaryKey(type: filterMessageTagSummary.subtractCount.type, peerId: entryPeer.id, namespace: filterMessageTagSummary.subtractCount.namespace)]
if updatedMessageSummary != nil || updatedActionsSummary != nil {
@ -923,7 +923,7 @@ private final class ChatListViewSpaceState {
for (key, component) in self.summaryComponents.components {
var updatedTagSummaryCount: Int32?
if let tagSummary = component.tagSummary {
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: entryData.index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace)
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: entryData.index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace, customTag: nil)
if let summary = transaction.currentUpdatedMessageTagSummaries[key] {
updatedTagSummaryCount = summary.count
}
@ -1534,7 +1534,7 @@ struct ChatListViewState {
var actionsSummaryCount: Int32?
if let tagSummary = component.tagSummary {
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace)
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace, customTag: nil)
if let summary = postbox.messageHistoryTagsSummaryTable.get(key) {
tagSummaryCount = summary.count
}

View file

@ -51,7 +51,7 @@ public func persistentHash32(_ string: String) -> Int32 {
private let emptyMemory = malloc(1)!
public class MemoryBuffer: Equatable, CustomStringConvertible {
public class MemoryBuffer: Comparable, Hashable, CustomStringConvertible {
public internal(set) var memory: UnsafeMutableRawPointer
var capacity: Int
public internal(set) var length: Int
@ -122,9 +122,25 @@ public class MemoryBuffer: Equatable, CustomStringConvertible {
f(Data(bytesNoCopy: self.memory, count: self.length, deallocator: .none))
}
public func hash(into hasher: inout Hasher) {
if self.length == 0 {
hasher.combine(0 as Int)
} else {
hasher.combine(bytes: UnsafeRawBufferPointer(start: self.memory, count: self.length))
}
}
public func withRawBufferPointer(_ f: (UnsafeRawBufferPointer) -> Void) {
f(UnsafeRawBufferPointer(start: self.memory, count: self.length))
}
public static func ==(lhs: MemoryBuffer, rhs: MemoryBuffer) -> Bool {
return lhs.length == rhs.length && memcmp(lhs.memory, rhs.memory, lhs.length) == 0
}
public static func <(lhs: MemoryBuffer, rhs: MemoryBuffer) -> Bool {
return mdb_cmp_memn(lhs.memory, lhs.length, rhs.memory, rhs.length) < 0
}
}
public final class WriteBuffer: MemoryBuffer {
@ -134,6 +150,10 @@ public final class WriteBuffer: MemoryBuffer {
super.init(memory: malloc(32), capacity: 32, length: 0, freeWhenDone: true)
}
public init(capacity: Int) {
super.init(memory: malloc(capacity), capacity: capacity, length: 0, freeWhenDone: true)
}
public func makeReadBufferAndReset() -> ReadBuffer {
let buffer = ReadBuffer(memory: self.memory, length: self.offset, freeWhenDone: true)
self.memory = malloc(32)
@ -222,6 +242,12 @@ public final class ReadBuffer: MemoryBuffer {
return result
}
public func readMemoryBuffer(length: Int) -> MemoryBuffer {
let result = MemoryBuffer(memory: malloc(length)!, capacity: length, length: length, freeWhenDone: true)
self.read(result.memory, offset: 0, length: length)
return result
}
public func skip(_ length: Int) {
self.offset += length
}

View file

@ -163,11 +163,11 @@ final class MutableGlobalMessageTagsView: MutablePostboxView {
hasChanges = true
}
case let .intermediateMessage(message):
if self.add(.intermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: message.embeddedMediaData, referencedMedia: message.referencedMedia))) {
if self.add(.intermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: message.embeddedMediaData, referencedMedia: message.referencedMedia))) {
hasChanges = true
}
case let .message(message):
if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories))) {
if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories))) {
hasChanges = true
}
}

View file

@ -43,6 +43,7 @@ class IntermediateMessage {
let tags: MessageTags
let globalTags: GlobalMessageTags
let localTags: LocalMessageTags
let customTags: [MemoryBuffer]
let forwardInfo: IntermediateMessageForwardInfo?
let authorId: PeerId?
let text: String
@ -54,7 +55,7 @@ class IntermediateMessage {
return MessageIndex(id: self.id, timestamp: self.timestamp)
}
init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: IntermediateMessageForwardInfo?, authorId: PeerId?, text: String, attributesData: ReadBuffer, embeddedMediaData: ReadBuffer, referencedMedia: [MediaId]) {
init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, customTags: [MemoryBuffer], forwardInfo: IntermediateMessageForwardInfo?, authorId: PeerId?, text: String, attributesData: ReadBuffer, embeddedMediaData: ReadBuffer, referencedMedia: [MediaId]) {
self.stableId = stableId
self.stableVersion = stableVersion
self.id = id
@ -67,6 +68,7 @@ class IntermediateMessage {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTags
self.forwardInfo = forwardInfo
self.authorId = authorId
self.text = text
@ -76,18 +78,18 @@ class IntermediateMessage {
}
func withUpdatedTimestamp(_ timestamp: Int32) -> IntermediateMessage {
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
}
func withUpdatedGroupingKey(_ groupingKey: Int64?) -> IntermediateMessage {
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
}
func withUpdatedGroupInfo(_ groupInfo: MessageGroupInfo?) -> IntermediateMessage {
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: self.embeddedMediaData, referencedMedia: self.referencedMedia)
}
func withUpdatedEmbeddedMedia(_ embeddedMedia: ReadBuffer) -> IntermediateMessage {
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: embeddedMedia, referencedMedia: self.referencedMedia)
return IntermediateMessage(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, authorId: self.authorId, text: self.text, attributesData: self.attributesData, embeddedMediaData: embeddedMedia, referencedMedia: self.referencedMedia)
}
}

View file

@ -1,3 +1,4 @@
import Foundation
final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView {
private let peerId: PeerId?
@ -13,10 +14,13 @@ final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView
self.tagMask = tagMask
self.namespace = namespace
self.reload(postbox: postbox)
}
private func reload(postbox: PostboxImpl) {
if let peerId = self.peerId {
if let entry = postbox.invalidatedMessageHistoryTagsSummaryTable.get(peerId: peerId, threadId: self.threadId, tagMask: self.tagMask, namespace: self.namespace) {
self.entries.insert(entry)
}
self.entries.removeAll()
self.entries.formUnion(postbox.invalidatedMessageHistoryTagsSummaryTable.getIncludingCustomTags(peerId: peerId, threadId: self.threadId, tagMask: self.tagMask, namespace: self.namespace))
} else {
for entry in postbox.invalidatedMessageHistoryTagsSummaryTable.get(tagMask: tagMask, namespace: namespace) {
self.entries.insert(entry)
@ -45,21 +49,19 @@ final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView
}
if maybeUpdated {
self.entries.removeAll()
if let entry = postbox.invalidatedMessageHistoryTagsSummaryTable.get(peerId: peerId, threadId: self.threadId, tagMask: self.tagMask, namespace: self.namespace) {
self.entries.insert(entry)
}
self.reload(postbox: postbox)
updated = true
}
} else {
for operation in transaction.currentInvalidateMessageTagSummaries {
switch operation {
case let .add(entry):
if entry.key.namespace == self.namespace && entry.key.tagMask == self.tagMask {
if entry.key.namespace == self.namespace && entry.key.tagMask == self.tagMask && entry.key.customTag == nil {
self.entries.insert(entry)
updated = true
}
case let .remove(key):
if key.namespace == self.namespace && key.tagMask == self.tagMask {
if key.namespace == self.namespace && key.tagMask == self.tagMask && key.customTag == nil {
for entry in self.entries {
if entry.key == key {
self.entries.remove(entry)

View file

@ -1,22 +1,64 @@
import Foundation
public struct InvalidatedMessageHistoryTagsSummaryKey: Equatable, Hashable {
public struct InvalidatedMessageHistoryTagsSummaryKey: Comparable, Hashable {
public let peerId: PeerId
public let namespace: MessageId.Namespace
public let tagMask: MessageTags
public let threadId: Int64?
public let customTag: MemoryBuffer?
public init(peerId: PeerId, namespace: MessageId.Namespace, tagMask: MessageTags, threadId: Int64?) {
public init(peerId: PeerId, namespace: MessageId.Namespace, tagMask: MessageTags, threadId: Int64?, customTag: MemoryBuffer?) {
self.peerId = peerId
self.namespace = namespace
self.tagMask = tagMask
self.threadId = threadId
self.customTag = customTag
}
public static func <(lhs: InvalidatedMessageHistoryTagsSummaryKey, rhs: InvalidatedMessageHistoryTagsSummaryKey) -> Bool {
if lhs.peerId != rhs.peerId {
return lhs.peerId < rhs.peerId
}
if lhs.namespace != rhs.namespace {
return lhs.namespace != rhs.namespace
}
if lhs.tagMask != rhs.tagMask {
return lhs.tagMask.rawValue < rhs.tagMask.rawValue
}
if let lhsThreadId = lhs.threadId, let rhsThreadId = rhs.threadId {
if lhsThreadId != rhsThreadId {
return lhsThreadId < rhsThreadId
}
} else if (lhs.threadId == nil) != (rhs.threadId == nil) {
if lhs.threadId != nil {
return true
} else {
return false
}
}
if let lhsCustomTag = lhs.customTag, let rhsCustomTag = rhs.customTag {
if lhsCustomTag != rhsCustomTag {
return lhsCustomTag < rhsCustomTag
}
} else if (lhs.customTag == nil) != (rhs.customTag == nil) {
if lhs.customTag != nil {
return true
} else {
return false
}
}
return false
}
}
public struct InvalidatedMessageHistoryTagsSummaryEntry: Equatable, Hashable {
public let key: InvalidatedMessageHistoryTagsSummaryKey
public let version: Int32
public init(key: InvalidatedMessageHistoryTagsSummaryKey, version: Int32) {
self.key = key
self.version = version
}
}
enum InvalidatedMessageHistoryTagsSummaryEntryOperation {
@ -30,7 +72,34 @@ final class InvalidatedMessageHistoryTagsSummaryTable: Table {
}
private func key(_ key: InvalidatedMessageHistoryTagsSummaryKey) -> ValueBoxKey {
if let threadId = key.threadId {
if let customTag = key.customTag, customTag.length != 0 {
var keyLength = 4 + 4 + 8
keyLength += 8
keyLength += customTag.length
let result = ValueBoxKey(length: keyLength)
var offset = 0
result.setUInt32(offset, value: key.tagMask.rawValue)
offset += 4
result.setInt32(offset, value: key.namespace)
offset += 4
result.setInt64(offset, value: key.peerId.toInt64())
offset += 8
result.setInt64(offset, value: key.threadId ?? 0)
offset += 8
if customTag.length != 0 {
customTag.withRawBufferPointer { buffer in
result.setBytes(offset, value: buffer)
offset += buffer.count
}
}
return result
} else if let threadId = key.threadId {
let result = ValueBoxKey(length: 4 + 4 + 8 + 8)
result.setUInt32(0, value: key.tagMask.rawValue)
result.setInt32(4, value: key.namespace)
@ -64,18 +133,65 @@ final class InvalidatedMessageHistoryTagsSummaryTable: Table {
value.read(&version, offset: 0, length: 4)
var threadId: Int64?
var customTag: MemoryBuffer?
if key.length >= 4 + 4 + 8 + 8 {
threadId = key.getInt64(4 + 4 + 8)
if key.length > 4 + 4 + 8 + 8 {
customTag = key.getMemoryBuffer(4 + 4 + 8 + 8, length: key.length - (4 + 4 + 8 + 8))
if threadId == 0 {
threadId = nil
}
}
}
entries.append(InvalidatedMessageHistoryTagsSummaryEntry(key: InvalidatedMessageHistoryTagsSummaryKey(peerId: PeerId(key.getInt64(4 + 4)), namespace: key.getInt32(4), tagMask: MessageTags(rawValue: key.getUInt32(0)), threadId: threadId), version: version))
entries.append(InvalidatedMessageHistoryTagsSummaryEntry(key: InvalidatedMessageHistoryTagsSummaryKey(peerId: PeerId(key.getInt64(4 + 4)), namespace: key.getInt32(4), tagMask: MessageTags(rawValue: key.getUInt32(0)), threadId: threadId, customTag: customTag), version: version))
return true
}, limit: 0)
return entries
}
func get(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) -> InvalidatedMessageHistoryTagsSummaryEntry? {
return self.get(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId))
func get(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, customTag: MemoryBuffer?) -> InvalidatedMessageHistoryTagsSummaryEntry? {
return self.get(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId, customTag: customTag))
}
func getIncludingCustomTags(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) -> [InvalidatedMessageHistoryTagsSummaryEntry] {
var entries: [InvalidatedMessageHistoryTagsSummaryEntry] = []
let peerKey = self.key(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId, customTag: nil))
self.valueBox.range(
self.table,
start: peerKey.predecessor, end: peerKey.successor, values: { key, value in
var version: Int32 = 0
value.read(&version, offset: 0, length: 4)
var threadId: Int64?
var customTag: MemoryBuffer?
if key.length >= 4 + 4 + 8 + 8 {
threadId = key.getInt64(4 + 4 + 8)
if key.length > 4 + 4 + 8 + 8 {
customTag = key.getMemoryBuffer(4 + 4 + 8 + 8, length: key.length - (4 + 4 + 8 + 8))
if threadId == 0 {
threadId = nil
}
}
}
let entry = InvalidatedMessageHistoryTagsSummaryEntry(key: InvalidatedMessageHistoryTagsSummaryKey(peerId: PeerId(key.getInt64(4 + 4)), namespace: key.getInt32(4), tagMask: MessageTags(rawValue: key.getUInt32(0)), threadId: threadId, customTag: customTag), version: version)
assert(entry.key.peerId == peerId)
assert(entry.key.namespace == namespace)
assert(entry.key.tagMask == tagMask)
assert(entry.key.threadId == threadId)
entries.append(entry)
return true
},
limit: 0
)
return entries
}
private func get(_ key: InvalidatedMessageHistoryTagsSummaryKey) -> InvalidatedMessageHistoryTagsSummaryEntry? {
@ -105,6 +221,13 @@ final class InvalidatedMessageHistoryTagsSummaryTable: Table {
}
}
func removeEntriesWithCustomTags(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags, operations: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation]) {
for entry in self.getIncludingCustomTags(peerId: peerId, threadId: threadId, tagMask: tagMask, namespace: namespace) {
self.valueBox.remove(self.table, key: self.key(entry.key), secure: false)
operations.append(.remove(entry.key))
}
}
override func clearMemoryCache() {
}

View file

@ -613,6 +613,7 @@ public protocol MessageAttribute: AnyObject, PostboxCoding {
var associatedMediaIds: [MediaId] { get }
var automaticTimestampBasedAttribute: (UInt16, Int32)? { get }
var associatedStoryIds: [StoryId] { get }
var customTags: [MemoryBuffer] { get }
}
public extension MessageAttribute {
@ -635,6 +636,10 @@ public extension MessageAttribute {
var associatedStoryIds: [StoryId] {
return []
}
var customTags: [MemoryBuffer] {
return []
}
}
public struct MessageGroupInfo: Equatable {
@ -688,6 +693,7 @@ public final class Message {
public let tags: MessageTags
public let globalTags: GlobalMessageTags
public let localTags: LocalMessageTags
public let customTags: [MemoryBuffer]
public let forwardInfo: MessageForwardInfo?
public let author: Peer?
public let text: String
@ -704,7 +710,7 @@ public final class Message {
return MessageIndex(id: self.id, timestamp: self.timestamp)
}
public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary<PeerId, Peer>, associatedMessages: SimpleDictionary<MessageId, Message>, associatedMessageIds: [MessageId], associatedMedia: [MediaId: Media], associatedThreadInfo: AssociatedThreadInfo?, associatedStories: [StoryId: CodableEntry]) {
public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, customTags: [MemoryBuffer], forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary<PeerId, Peer>, associatedMessages: SimpleDictionary<MessageId, Message>, associatedMessageIds: [MessageId], associatedMedia: [MediaId: Media], associatedThreadInfo: AssociatedThreadInfo?, associatedStories: [StoryId: CodableEntry]) {
self.stableId = stableId
self.stableVersion = stableVersion
self.id = id
@ -717,6 +723,7 @@ public final class Message {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTags
self.forwardInfo = forwardInfo
self.author = author
self.text = text
@ -731,47 +738,47 @@ public final class Message {
}
public func withUpdatedStableVersion(stableVersion: UInt32) -> Message {
return Message(stableId: self.stableId, stableVersion: stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedText(_ text: String) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedTimestamp(_ timestamp: Int32) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedMedia(_ media: [Media]) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedPeers(_ peers: SimpleDictionary<PeerId, Peer>) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedFlags(_ flags: MessageFlags) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
func withUpdatedGroupInfo(_ groupInfo: MessageGroupInfo?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedAttributes(_ attributes: [MessageAttribute]) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
func withUpdatedAssociatedMessages(_ associatedMessages: SimpleDictionary<MessageId, Message>) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedForwardInfo(_ forwardInfo: MessageForwardInfo?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedAuthor(_ author: Peer?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, customTags: self.customTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
}
@ -879,6 +886,21 @@ public struct MessageThreadKey: Hashable {
}
}
private func customTagsFromAttributes(_ attributes: [MessageAttribute]) -> [MemoryBuffer] {
var result: [MemoryBuffer] = []
for attribute in attributes {
for customTag in attribute.customTags {
if !result.contains(customTag) {
result.append(customTag)
}
}
}
if !result.isEmpty {
result.sort()
}
return result
}
public final class StoreMessage {
public let id: StoreMessageId
public let timestamp: Int32
@ -889,6 +911,7 @@ public final class StoreMessage {
public let tags: MessageTags
public let globalTags: GlobalMessageTags
public let localTags: LocalMessageTags
public let customTags: [MemoryBuffer]
public let forwardInfo: StoreMessageForwardInfo?
public let authorId: PeerId?
public let text: String
@ -905,6 +928,7 @@ public final class StoreMessage {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTagsFromAttributes(attributes)
self.forwardInfo = forwardInfo
self.authorId = authorId
self.text = text
@ -922,6 +946,7 @@ public final class StoreMessage {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTagsFromAttributes(attributes)
self.forwardInfo = forwardInfo
self.authorId = authorId
self.text = text
@ -939,6 +964,7 @@ public final class StoreMessage {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTagsFromAttributes(attributes)
self.forwardInfo = forwardInfo
self.authorId = authorId
self.text = text
@ -985,6 +1011,7 @@ final class InternalStoreMessage {
let tags: MessageTags
let globalTags: GlobalMessageTags
let localTags: LocalMessageTags
let customTags: [MemoryBuffer]
let forwardInfo: StoreMessageForwardInfo?
let authorId: PeerId?
let text: String
@ -995,7 +1022,7 @@ final class InternalStoreMessage {
return MessageIndex(id: self.id, timestamp: self.timestamp)
}
init(id: MessageId, timestamp: Int32, globallyUniqueId: Int64?, groupingKey: Int64?, threadId: Int64?, flags: StoreMessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: StoreMessageForwardInfo?, authorId: PeerId?, text: String, attributes: [MessageAttribute], media: [Media]) {
init(id: MessageId, timestamp: Int32, globallyUniqueId: Int64?, groupingKey: Int64?, threadId: Int64?, flags: StoreMessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, customTags: [MemoryBuffer], forwardInfo: StoreMessageForwardInfo?, authorId: PeerId?, text: String, attributes: [MessageAttribute], media: [Media]) {
self.id = id
self.timestamp = timestamp
self.globallyUniqueId = globallyUniqueId
@ -1005,6 +1032,7 @@ final class InternalStoreMessage {
self.tags = tags
self.globalTags = globalTags
self.localTags = localTags
self.customTags = customTags
self.forwardInfo = forwardInfo
self.authorId = authorId
self.text = text

View file

@ -289,8 +289,13 @@ final class MessageHistoryTable: Table {
if let threadId = message.threadId {
self.threadsTable.add(threadId: threadId, index: message.index)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace), id: message.id.id, isNewlyAdded: true, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace, customTag: nil), id: message.id.id, isNewlyAdded: true, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
for customTag in message.customTags {
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: nil, namespace: message.id.namespace, customTag: customTag), id: message.id.id, isNewlyAdded: true, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
let globalTags = message.globalTags.rawValue
if globalTags != 0 {
for i in 0 ..< 32 {
@ -401,11 +406,11 @@ final class MessageHistoryTable: Table {
var internalStoreMessages: [InternalStoreMessage] = []
for message in messages {
switch message.id {
case let .Id(id):
internalStoreMessages.append(InternalStoreMessage(id: id, timestamp: message.timestamp, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, threadId: message.threadId, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributes: message.attributes, media: message.media))
case let .Partial(peerId, namespace):
let id = self.historyMetadataTable.getNextMessageIdAndIncrement(peerId, namespace: namespace)
internalStoreMessages.append(InternalStoreMessage(id: id, timestamp: message.timestamp, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, threadId: message.threadId, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributes: message.attributes, media: message.media))
case let .Id(id):
internalStoreMessages.append(InternalStoreMessage(id: id, timestamp: message.timestamp, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, threadId: message.threadId, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributes: message.attributes, media: message.media))
case let .Partial(peerId, namespace):
let id = self.historyMetadataTable.getNextMessageIdAndIncrement(peerId, namespace: namespace)
internalStoreMessages.append(InternalStoreMessage(id: id, timestamp: message.timestamp, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, threadId: message.threadId, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributes: message.attributes, media: message.media))
}
}
return internalStoreMessages
@ -1270,9 +1275,19 @@ final class MessageHistoryTable: Table {
sharedBuffer.write(&idId, offset: 0, length: 8)
}
var customTagCount: Int32 = Int32(message.customTags.count)
sharedBuffer.write(&customTagCount, offset: 0, length: 4)
for customTag in message.customTags {
var customTagLength: Int32 = Int32(customTag.length)
sharedBuffer.write(&customTagLength, offset: 0, length: 4)
customTag.withRawBufferPointer { buffer in
sharedBuffer.write(buffer.baseAddress!, length: buffer.count)
}
}
self.valueBox.set(self.table, key: self.key(message.index, key: sharedKey), value: sharedBuffer)
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), updatedGroupInfos)
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), updatedGroupInfos)
return result
}
@ -1355,7 +1370,10 @@ final class MessageHistoryTable: Table {
if let threadId = message.threadId {
self.threadsTable.remove(threadId: threadId, index: index)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace), id: message.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace, customTag: nil), id: message.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
for customTag in message.customTags {
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: nil, namespace: message.id.namespace, customTag: customTag), id: message.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
for tag in message.globalTags {
self.globalTagsTable.remove(tag, index: index)
@ -1456,7 +1474,7 @@ final class MessageHistoryTable: Table {
}
withExtendedLifetime(updatedEmbeddedMediaBuffer, {
self.storeIntermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: updatedEmbeddedMediaBuffer.readBufferNoCopy(), referencedMedia: message.referencedMedia), sharedKey: self.key(index))
self.storeIntermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: updatedEmbeddedMediaBuffer.readBufferNoCopy(), referencedMedia: message.referencedMedia), sharedKey: self.key(index))
})
let operation: MessageHistoryOperation = .UpdateEmbeddedMedia(index, updatedEmbeddedMediaBuffer.makeReadBufferAndReset())
@ -1574,13 +1592,22 @@ final class MessageHistoryTable: Table {
if let threadId = previousMessage.threadId {
self.threadsTable.remove(threadId: threadId, index: index)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace), id: index.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace, customTag: nil), id: index.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
if let threadId = message.threadId {
self.threadsTable.add(threadId: threadId, index: message.index)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace), id: message.id.id, isNewlyAdded: false, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: threadId, namespace: message.id.namespace, customTag: nil), id: message.id.id, isNewlyAdded: false, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
}
if previousMessage.customTags != message.customTags || index != message.index {
for customTag in previousMessage.customTags {
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: index.id.peerId, threadId: nil, namespace: index.id.namespace, customTag: customTag), id: index.id.id, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
for customTag in message.customTags {
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: MessageTags(), peerId: message.id.peerId, threadId: nil, namespace: message.id.namespace, customTag: customTag), id: message.id.id, isNewlyAdded: false, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
}
}
@ -1919,9 +1946,19 @@ final class MessageHistoryTable: Table {
sharedBuffer.write(&idId, offset: 0, length: 8)
}
var customTagCount: Int32 = Int32(message.customTags.count)
sharedBuffer.write(&customTagCount, offset: 0, length: 4)
for customTag in message.customTags {
var customTagLength: Int32 = Int32(customTag.length)
sharedBuffer.write(&customTagLength, offset: 0, length: 4)
customTag.withRawBufferPointer { buffer in
sharedBuffer.write(buffer.baseAddress!, length: buffer.count)
}
}
self.valueBox.set(self.table, key: self.key(message.index, key: sharedKey), value: sharedBuffer)
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: tags, globalTags: message.globalTags, localTags: updatedLocalTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), previousMessage.tags)
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: tags, globalTags: message.globalTags, localTags: updatedLocalTags, customTags: message.customTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), previousMessage.tags)
for media in mediaToUpdate {
if let id = media.id {
@ -1999,7 +2036,7 @@ final class MessageHistoryTable: Table {
let updatedIndex = MessageIndex(id: index.id, timestamp: timestamp)
let _ = self.justUpdate(index, message: InternalStoreMessage(id: previousMessage.id, timestamp: timestamp, globallyUniqueId: previousMessage.globallyUniqueId, groupingKey: previousMessage.groupingKey, threadId: previousMessage.threadId, flags: StoreMessageFlags(previousMessage.flags), tags: previousMessage.tags, globalTags: previousMessage.globalTags, localTags: previousMessage.localTags, forwardInfo: storeForwardInfo, authorId: previousMessage.authorId, text: previousMessage.text, attributes: parsedAttributes, media: parsedMedia), keepLocalTags: false, sharedKey: self.key(updatedIndex), sharedBuffer: WriteBuffer(), sharedEncoder: PostboxEncoder(), unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: &timestampBasedMessageAttributesOperations, updatedMedia: &updatedMedia)
let _ = self.justUpdate(index, message: InternalStoreMessage(id: previousMessage.id, timestamp: timestamp, globallyUniqueId: previousMessage.globallyUniqueId, groupingKey: previousMessage.groupingKey, threadId: previousMessage.threadId, flags: StoreMessageFlags(previousMessage.flags), tags: previousMessage.tags, globalTags: previousMessage.globalTags, localTags: previousMessage.localTags, customTags: previousMessage.customTags, forwardInfo: storeForwardInfo, authorId: previousMessage.authorId, text: previousMessage.text, attributes: parsedAttributes, media: parsedMedia), keepLocalTags: false, sharedKey: self.key(updatedIndex), sharedBuffer: WriteBuffer(), sharedEncoder: PostboxEncoder(), unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: &timestampBasedMessageAttributesOperations, updatedMedia: &updatedMedia)
return (previousMessage.tags, previousMessage.globalTags)
} else {
return nil
@ -2039,7 +2076,7 @@ final class MessageHistoryTable: Table {
var updatedReferencedMedia = message.referencedMedia
updatedReferencedMedia.append(extractedMedia.id!)
withExtendedLifetime(updatedEmbeddedMediaBuffer, {
self.storeIntermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: updatedEmbeddedMediaBuffer.readBufferNoCopy(), referencedMedia: updatedReferencedMedia), sharedKey: self.key(index))
self.storeIntermediateMessage(IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: updatedEmbeddedMediaBuffer.readBufferNoCopy(), referencedMedia: updatedReferencedMedia), sharedKey: self.key(index))
})
return extractedMedia
@ -2453,7 +2490,18 @@ final class MessageHistoryTable: Table {
referencedMediaIds.append(MediaId(namespace: idNamespace, id: idId))
}
return IntermediateMessageHistoryEntry(message: IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: index.id, globallyUniqueId: globallyUniqueId, groupingKey: groupingKey, groupInfo: groupInfo, threadId: threadId, timestamp: index.timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: forwardInfo, authorId: authorId, text: text, attributesData: attributesData, embeddedMediaData: embeddedMediaData, referencedMedia: referencedMediaIds))
var customTags: [MemoryBuffer] = []
var customTagCount: Int32 = 0
if value.offset < value.length {
value.read(&customTagCount, offset: 0, length: 4)
for _ in 0 ..< customTagCount {
var customTagLength: Int32 = 0
value.read(&customTagLength, offset: 0, length: 4)
customTags.append(value.readMemoryBuffer(length: Int(customTagLength)))
}
}
return IntermediateMessageHistoryEntry(message: IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: index.id, globallyUniqueId: globallyUniqueId, groupingKey: groupingKey, groupInfo: groupInfo, threadId: threadId, timestamp: index.timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, customTags: customTags, forwardInfo: forwardInfo, authorId: authorId, text: text, attributesData: attributesData, embeddedMediaData: embeddedMediaData, referencedMedia: referencedMediaIds))
} else {
preconditionFailure()
}
@ -2639,7 +2687,7 @@ final class MessageHistoryTable: Table {
associatedThreadInfo = self.seedConfiguration.decodeMessageThreadInfo(data.data)
}
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds, associatedMedia: associatedMedia, associatedThreadInfo: associatedThreadInfo, associatedStories: associatedStories)
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds, associatedMedia: associatedMedia, associatedThreadInfo: associatedThreadInfo, associatedStories: associatedStories)
}
func renderMessagePeers(_ message: Message, peerTable: PeerTable) -> Message {

View file

@ -5,22 +5,24 @@ final class MutableMessageHistoryTagSummaryView: MutablePostboxView {
private let peerId: PeerId
private let threadId: Int64?
private let namespace: MessageId.Namespace
private let customTag: MemoryBuffer?
fileprivate var count: Int32?
init(postbox: PostboxImpl, tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace) {
init(postbox: PostboxImpl, tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, customTag: MemoryBuffer?) {
self.tag = tag
self.peerId = peerId
self.threadId = threadId
self.namespace = namespace
self.customTag = customTag
self.count = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tag, peerId: peerId, threadId: threadId, namespace: namespace))?.count
self.count = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tag, peerId: peerId, threadId: threadId, namespace: namespace, customTag: customTag))?.count
}
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
var hasChanges = false
if let summary = transaction.currentUpdatedMessageTagSummaries[MessageHistoryTagsSummaryKey(tag: self.tag, peerId: self.peerId, threadId: self.threadId, namespace: self.namespace)] {
if let summary = transaction.currentUpdatedMessageTagSummaries[MessageHistoryTagsSummaryKey(tag: self.tag, peerId: self.peerId, threadId: self.threadId, namespace: self.namespace, customTag: self.customTag)] {
self.count = summary.count
hasChanges = true
}
@ -29,13 +31,6 @@ final class MutableMessageHistoryTagSummaryView: MutablePostboxView {
}
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
/*let count = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: self.tag, peerId: self.peerId, namespace: self.namespace))?.count
if self.count != count {
self.count = count
return true
} else {
return false
}*/
return false
}

View file

@ -45,6 +45,15 @@ struct MessageHistoryTagsSummaryKey: Equatable, Hashable {
let peerId: PeerId
let threadId: Int64?
let namespace: MessageId.Namespace
let customTag: MemoryBuffer?
init(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, customTag: MemoryBuffer?) {
self.tag = tag
self.peerId = peerId
self.threadId = threadId
self.namespace = namespace
self.customTag = customTag
}
}
private func readSummary(_ value: ReadBuffer) -> MessageHistoryTagNamespaceSummary {
@ -91,17 +100,62 @@ class MessageHistoryTagsSummaryTable: Table {
}
private func keyShared(key: MessageHistoryTagsSummaryKey) -> ValueBoxKey {
if let threadId = key.threadId {
self.sharedThreadKey.setUInt32(0, value: key.tag.rawValue)
self.sharedThreadKey.setInt64(4, value: key.peerId.toInt64())
self.sharedThreadKey.setInt32(4 + 8, value: key.namespace)
self.sharedThreadKey.setInt64(4 + 8 + 4, value: threadId)
return self.sharedThreadKey
return self.keyInternal(key: key, allowShared: true)
}
private func keyInternal(key: MessageHistoryTagsSummaryKey, allowShared: Bool) -> ValueBoxKey {
if let customTag = key.customTag {
if customTag.length != 10 && customTag.length != 7 {
assert(true)
}
var keyLength = 4 + 8 + 4
keyLength += 8
keyLength += customTag.length
let result = ValueBoxKey(length: keyLength)
var offset = 0
result.setUInt32(offset, value: key.tag.rawValue)
offset += 4
result.setInt64(offset, value: key.peerId.toInt64())
offset += 8
result.setInt32(offset, value: key.namespace)
offset += 4
result.setInt64(offset, value: key.threadId ?? 0)
offset += 8
customTag.withRawBufferPointer { buffer in
result.setBytes(offset, value: buffer)
offset += buffer.count
}
return result
} else if let threadId = key.threadId {
let result: ValueBoxKey
if allowShared {
result = self.sharedThreadKey
} else {
result = ValueBoxKey(length: 4 + 8 + 4 + 8)
}
result.setUInt32(0, value: key.tag.rawValue)
result.setInt64(4, value: key.peerId.toInt64())
result.setInt32(4 + 8, value: key.namespace)
result.setInt64(4 + 8 + 4, value: threadId)
return result
} else {
self.sharedSimpleKey.setUInt32(0, value: key.tag.rawValue)
self.sharedSimpleKey.setInt64(4, value: key.peerId.toInt64())
self.sharedSimpleKey.setInt32(4 + 8, value: key.namespace)
return self.sharedSimpleKey
let result: ValueBoxKey
if allowShared {
result = self.sharedSimpleKey
} else {
result = ValueBoxKey(length: 4 + 8 + 4)
}
result.setUInt32(0, value: key.tag.rawValue)
result.setInt64(4, value: key.peerId.toInt64())
result.setInt32(4 + 8, value: key.namespace)
return result
}
}
@ -118,6 +172,24 @@ class MessageHistoryTagsSummaryTable: Table {
}
}
func getCustomTags(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace) -> [MemoryBuffer] {
let peerKey = self.keyInternal(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: peerId, threadId: threadId, namespace: namespace, customTag: nil), allowShared: false)
let prefixLength = 4 + 8 + 4 + 8
var result: [MemoryBuffer] = []
self.valueBox.range(self.table, start: peerKey.predecessor, end: peerKey.successor, keys: { key in
let testPeerId = key.getInt64(4)
assert(PeerId(testPeerId) == peerId)
let testNamespace = key.getInt32(4 + 8)
assert(testNamespace == namespace)
if key.length > prefixLength {
result.append(key.getMemoryBuffer(prefixLength, length: key.length - prefixLength))
}
return true
}, limit: 0)
return result
}
private func set(_ key: MessageHistoryTagsSummaryKey, summary: MessageHistoryTagNamespaceSummary, updatedSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary]) {
if self.get(key) != summary {
if key.tag.rawValue == 2048 {
@ -134,12 +206,12 @@ class MessageHistoryTagsSummaryTable: Table {
if !isNewlyAdded || !current.range.contains(id) {
self.set(key, summary: current.withAddedCount(1), updatedSummaries: &updatedSummaries)
if current.range.maxId == 0 {
self.invalidateTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: key.peerId, namespace: key.namespace, tagMask: key.tag, threadId: key.threadId), operations: &invalidateSummaries)
self.invalidateTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: key.peerId, namespace: key.namespace, tagMask: key.tag, threadId: key.threadId, customTag: key.customTag), operations: &invalidateSummaries)
}
}
} else {
self.set(key, summary: MessageHistoryTagNamespaceSummary(version: 0, count: 1, range: MessageHistoryTagNamespaceCountValidityRange(maxId: 0)), updatedSummaries: &updatedSummaries)
self.invalidateTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: key.peerId, namespace: key.namespace, tagMask: key.tag, threadId: key.threadId), operations: &invalidateSummaries)
self.invalidateTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: key.peerId, namespace: key.namespace, tagMask: key.tag, threadId: key.threadId, customTag: key.customTag), operations: &invalidateSummaries)
}
}

View file

@ -46,7 +46,7 @@ class MessageHistoryTagsTable: Table {
for tag in tags {
self.valueBox.set(self.table, key: self.key(tag: tag, index: index, key: self.sharedKey), value: MemoryBuffer())
if self.summaryTags.contains(tag) {
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: nil, namespace: index.id.namespace), id: index.id.id, isNewlyAdded: isNewlyAdded, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: nil, namespace: index.id.namespace, customTag: nil), id: index.id.id, isNewlyAdded: isNewlyAdded, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
}
}
}
@ -56,7 +56,7 @@ class MessageHistoryTagsTable: Table {
self.valueBox.remove(self.table, key: self.key(tag: tag, index: index, key: self.sharedKey), secure: false)
if self.summaryTags.contains(tag) {
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: nil, namespace: index.id.namespace), id: index.id.id, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: nil, namespace: index.id.namespace, customTag: nil), id: index.id.id, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
}
}
}

View file

@ -79,7 +79,7 @@ final class MutableMessageHistoryThreadIndexView: MutablePostboxView {
var actionsSummaryCount: Int32?
if let tagSummary = component.tagSummary {
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: self.peerId, threadId: item.threadId, namespace: tagSummary.namespace)
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: self.peerId, threadId: item.threadId, namespace: tagSummary.namespace, customTag: nil)
if let summary = postbox.messageHistoryTagsSummaryTable.get(key) {
tagSummaryCount = summary.count
}

View file

@ -229,7 +229,7 @@ class MessageHistoryThreadTagsTable: Table {
for tag in tags {
self.valueBox.set(self.table, key: self.key(tag: tag, threadId: threadId, index: index, key: self.sharedKey), value: MemoryBuffer())
if self.summaryTags.contains(tag) {
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace), id: index.id.id, isNewlyAdded: isNewlyAdded, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
self.summaryTable.addMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace, customTag: nil), id: index.id.id, isNewlyAdded: isNewlyAdded, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
}
}
}
@ -238,7 +238,7 @@ class MessageHistoryThreadTagsTable: Table {
for tag in tags {
self.valueBox.remove(self.table, key: self.key(tag: tag, threadId: threadId, index: index, key: self.sharedKey), secure: false)
if self.summaryTags.contains(tag) {
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace), id: index.id.id, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
self.summaryTable.removeMessage(key: MessageHistoryTagsSummaryKey(tag: tag, peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace, customTag: nil), id: index.id.id, updatedSummaries: &updatedSummaries, invalidateSummaries: &invalidateSummaries)
}
}
}

View file

@ -133,11 +133,11 @@ enum MutableMessageHistoryEntry {
func updatedTimestamp(_ timestamp: Int32) -> MutableMessageHistoryEntry {
switch self {
case let .IntermediateMessageEntry(message, location, monthLocation):
let updatedMessage = IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: message.embeddedMediaData, referencedMedia: message.referencedMedia)
let updatedMessage = IntermediateMessage(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: message.embeddedMediaData, referencedMedia: message.referencedMedia)
return .IntermediateMessageEntry(updatedMessage, location, monthLocation)
case let .MessageEntry(value, reloadAssociatedMessages, reloadPeers):
let message = value.message
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
}
}

View file

@ -1442,7 +1442,7 @@ final class HistoryViewLoadedState {
messageMedia.append(media)
}
}
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
}
case .IntermediateMessageEntry:
@ -1499,7 +1499,7 @@ final class HistoryViewLoadedState {
}
}
}
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: associatedStories)
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: associatedStories)
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
}
case .IntermediateMessageEntry:

View file

@ -0,0 +1,59 @@
import Foundation
final class MutableMessageHistoryCustomTagSummariesView: MutablePostboxView {
private let peerId: PeerId
private let namespace: MessageId.Namespace
fileprivate var tags: [MemoryBuffer: Int] = [:]
init(postbox: PostboxImpl, peerId: PeerId, namespace: MessageId.Namespace) {
self.peerId = peerId
self.namespace = namespace
self.reload(postbox: postbox)
}
private func reload(postbox: PostboxImpl) {
self.tags.removeAll()
for tag in postbox.messageHistoryTagsSummaryTable.getCustomTags(tag: [], peerId: self.peerId, threadId: nil, namespace: self.namespace) {
if let summary = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: [], peerId: self.peerId, threadId: nil, namespace: self.namespace, customTag: tag)) {
if summary.count > 0 {
self.tags[tag] = Int(summary.count)
}
}
}
}
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
var hasChanges = false
for key in transaction.currentUpdatedMessageTagSummaries.keys {
if key.peerId == self.peerId && key.namespace == self.namespace && key.customTag != nil {
hasChanges = true
break
}
}
if hasChanges {
self.reload(postbox: postbox)
}
return hasChanges
}
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
return false
}
func immutableView() -> PostboxView {
return MessageHistoryCustomTagSummariesView(self)
}
}
public final class MessageHistoryCustomTagSummariesView: PostboxView {
public let tags: [MemoryBuffer: Int]
init(_ view: MutableMessageHistoryCustomTagSummariesView) {
self.tags = view.tags
}
}

View file

@ -241,7 +241,7 @@ class PeerThreadsSummaryTable: Table {
}
for tag in self.seedConfiguration.messageTagsWithThreadSummary {
if let value = tagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tag, peerId: peerId, threadId: item.threadId, namespace: 0)) {
if let value = tagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tag, peerId: peerId, threadId: item.threadId, namespace: 0, customTag: nil)) {
tagSummaries.append(StoredPeerThreadsSummary.ThreadsTagSummary(tag: tag, count: value.count))
}
}

View file

@ -1035,14 +1035,19 @@ public final class Transaction {
return self.postbox?.getPendingMessageAction(type: type, id: id)
}
public func getMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) -> MessageHistoryTagNamespaceSummary? {
public func getMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, customTag: MemoryBuffer?) -> MessageHistoryTagNamespaceSummary? {
assert(!self.disposed)
return self.postbox?.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tagMask, peerId: peerId, threadId: threadId, namespace: namespace))
return self.postbox?.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: tagMask, peerId: peerId, threadId: threadId, namespace: namespace, customTag: customTag))
}
public func replaceMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, count: Int32, maxId: MessageId.Id) {
public func getMessageTagSummaryCustomTags(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) -> [MemoryBuffer] {
assert(!self.disposed)
self.postbox?.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tagMask, namespace: namespace, count: count, maxId: maxId)
return self.postbox!.messageHistoryTagsSummaryTable.getCustomTags(tag: tagMask, peerId: peerId, threadId: threadId, namespace: namespace)
}
public func replaceMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, customTag: MemoryBuffer?, count: Int32, maxId: MessageId.Id) {
assert(!self.disposed)
self.postbox?.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tagMask, namespace: namespace, customTag: customTag, count: count, maxId: maxId)
}
public func getPendingMessageActionsSummary(peerId: PeerId, type: PendingMessageActionType, namespace: MessageId.Namespace) -> Int32? {
@ -1109,9 +1114,9 @@ public final class Transaction {
return view!
}
public func invalidateMessageHistoryTagsSummary(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags) {
public func invalidateMessageHistoryTagsSummary(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags, customTag: MemoryBuffer?) {
assert(!self.disposed)
self.postbox?.invalidateMessageHistoryTagsSummary(peerId: peerId, threadId: threadId, namespace: namespace, tagMask: tagMask)
self.postbox?.invalidateMessageHistoryTagsSummary(peerId: peerId, threadId: threadId, namespace: namespace, tagMask: tagMask, customTag: customTag)
}
public func removeInvalidatedMessageHistoryTagsSummaryEntry(_ entry: InvalidatedMessageHistoryTagsSummaryEntry) {
@ -1119,6 +1124,10 @@ public final class Transaction {
self.postbox?.removeInvalidatedMessageHistoryTagsSummaryEntry(entry)
}
public func removeInvalidatedMessageHistoryTagsSummaryEntriesWithCustomTags(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags) {
self.postbox?.removeInvalidatedMessageHistoryTagsSummaryEntriesWithCustomTags(peerId: peerId, threadId: threadId, namespace: namespace, tagMask: tagMask)
}
public func getRelativeUnreadChatListIndex(filtered: Bool, position: ChatListRelativePosition, groupId: PeerGroupId) -> ChatListIndex? {
assert(!self.disposed)
return self.postbox?.getRelativeUnreadChatListIndex(currentTransaction: self, filtered: filtered, position: position, groupId: groupId)
@ -2857,8 +2866,8 @@ final class PostboxImpl {
return self.pendingMessageActionsTable.getAction(id: id, type: type)
}
fileprivate func replaceMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, count: Int32, maxId: MessageId.Id) {
let key = MessageHistoryTagsSummaryKey(tag: tagMask, peerId: peerId, threadId: threadId, namespace: namespace)
fileprivate func replaceMessageTagSummary(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace, customTag: MemoryBuffer?, count: Int32, maxId: MessageId.Id) {
let key = MessageHistoryTagsSummaryKey(tag: tagMask, peerId: peerId, threadId: threadId, namespace: namespace, customTag: customTag)
self.messageHistoryTagsSummaryTable.replace(key: key, count: count, maxId: maxId, updatedSummaries: &self.currentUpdatedMessageTagSummaries)
}
@ -4025,14 +4034,18 @@ final class PostboxImpl {
}
}
fileprivate func invalidateMessageHistoryTagsSummary(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags) {
self.invalidatedMessageHistoryTagsSummaryTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId), operations: &self.currentInvalidateMessageTagSummaries)
fileprivate func invalidateMessageHistoryTagsSummary(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags, customTag: MemoryBuffer?) {
self.invalidatedMessageHistoryTagsSummaryTable.insert(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId, customTag: customTag), operations: &self.currentInvalidateMessageTagSummaries)
}
fileprivate func removeInvalidatedMessageHistoryTagsSummaryEntry(_ entry: InvalidatedMessageHistoryTagsSummaryEntry) {
self.invalidatedMessageHistoryTagsSummaryTable.remove(entry, operations: &self.currentInvalidateMessageTagSummaries)
}
fileprivate func removeInvalidatedMessageHistoryTagsSummaryEntriesWithCustomTags(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, tagMask: MessageTags) {
self.invalidatedMessageHistoryTagsSummaryTable.removeEntriesWithCustomTags(peerId: peerId, threadId: threadId, namespace: namespace, tagMask: tagMask, operations: &self.currentInvalidateMessageTagSummaries)
}
fileprivate func getRelativeUnreadChatListIndex(currentTransaction: Transaction, filtered: Bool, position: ChatListRelativePosition, groupId: PeerGroupId) -> ChatListIndex? {
return self.chatListTable.getRelativeUnreadChatListIndex(postbox: self, currentTransaction: currentTransaction, filtered: filtered, position: position, groupId: groupId)
}

View file

@ -49,7 +49,7 @@ func resolveChatListMessageTagSummaryResultCalculation(postbox: PostboxImpl, pee
guard let calculation = calculation else {
return nil
}
let addSummary = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: calculation.addCount.tag, peerId: peerId, threadId: threadId, namespace: calculation.addCount.namespace))
let addSummary = postbox.messageHistoryTagsSummaryTable.get(MessageHistoryTagsSummaryKey(tag: calculation.addCount.tag, peerId: peerId, threadId: threadId, namespace: calculation.addCount.namespace, customTag: nil))
let subtractSummary = postbox.pendingMessageActionsMetadataTable.getCount(.peerNamespaceAction(peerId, calculation.subtractCount.namespace, calculation.subtractCount.type))
let count = (addSummary?.count ?? 0) - subtractSummary
return count > 0

View file

@ -47,6 +47,11 @@ public struct ValueBoxKey: Equatable, Hashable, CustomStringConvertible, Compara
}
}
public func setBytes(_ offset: Int, value: UnsafeRawBufferPointer) {
assert(offset >= 0 && offset + value.count <= self.length)
memcpy(self.memory + offset, value.baseAddress!.assumingMemoryBound(to: UInt8.self), value.count)
}
public func setInt32(_ offset: Int, value: Int32) {
assert(offset >= 0 && offset + 4 <= self.length)
var bigEndianValue = Int32(bigEndian: value)
@ -92,6 +97,13 @@ public struct ValueBoxKey: Equatable, Hashable, CustomStringConvertible, Compara
return value
}
public func getMemoryBuffer(_ offset: Int, length: Int) -> MemoryBuffer {
assert(offset >= 0 && offset + length <= self.length)
let result = MemoryBuffer(memory: malloc(length)!, capacity: length, length: length, freeWhenDone: true)
memcpy(result.memory, self.memory + offset, length)
return result
}
public func getInt32(_ offset: Int) -> Int32 {
assert(offset >= 0 && offset + 4 <= self.length)
var value: Int32 = 0
@ -259,7 +271,7 @@ public struct ValueBoxKey: Equatable, Hashable, CustomStringConvertible, Compara
}
}
private func mdb_cmp_memn(_ a_memory: UnsafeMutableRawPointer, _ a_length: Int, _ b_memory: UnsafeMutableRawPointer, _ b_length: Int) -> Int
func mdb_cmp_memn(_ a_memory: UnsafeMutableRawPointer, _ a_length: Int, _ b_memory: UnsafeMutableRawPointer, _ b_length: Int) -> Int
{
var diff: Int = 0
var len_diff: Int = 0

View file

@ -12,7 +12,8 @@ public enum PostboxViewKey: Hashable {
case pendingMessageActions(type: PendingMessageActionType)
case invalidatedMessageHistoryTagSummaries(peerId: PeerId?, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace)
case pendingMessageActionsSummary(type: PendingMessageActionType, peerId: PeerId, namespace: MessageId.Namespace)
case historyTagSummaryView(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace)
case historyTagSummaryView(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, customTag: MemoryBuffer?)
case historyCustomTagSummariesView(peerId: PeerId, namespace: MessageId.Namespace)
case cachedPeerData(peerId: PeerId)
case unreadCounts(items: [UnreadMessageCountsItem])
case combinedReadState(peerId: PeerId, handleThreads: Bool)
@ -78,11 +79,15 @@ public enum PostboxViewKey: Hashable {
hasher.combine(type)
hasher.combine(peerId)
hasher.combine(namespace)
case let .historyTagSummaryView(tag, peerId, threadId, namespace):
case let .historyTagSummaryView(tag, peerId, threadId, namespace, customTag):
hasher.combine(tag)
hasher.combine(peerId)
hasher.combine(threadId)
hasher.combine(namespace)
hasher.combine(customTag)
case let .historyCustomTagSummariesView(peerId, namespace):
hasher.combine(peerId)
hasher.combine(namespace)
case let .cachedPeerData(peerId):
hasher.combine(peerId)
case .unreadCounts:
@ -230,8 +235,14 @@ public enum PostboxViewKey: Hashable {
} else {
return false
}
case let .historyTagSummaryView(tag, peerId, threadId, namespace):
if case .historyTagSummaryView(tag, peerId, threadId, namespace) = rhs {
case let .historyTagSummaryView(tag, peerId, threadId, namespace, customTag):
if case .historyTagSummaryView(tag, peerId, threadId, namespace, customTag) = rhs {
return true
} else {
return false
}
case let .historyCustomTagSummariesView(peerId, namespace):
if case .historyCustomTagSummariesView(peerId, namespace) = rhs {
return true
} else {
return false
@ -474,8 +485,10 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
return MutableInvalidatedMessageHistoryTagSummariesView(postbox: postbox, peerId: peerId, threadId: threadId, tagMask: tagMask, namespace: namespace)
case let .pendingMessageActionsSummary(type, peerId, namespace):
return MutablePendingMessageActionsSummaryView(postbox: postbox, type: type, peerId: peerId, namespace: namespace)
case let .historyTagSummaryView(tag, peerId, threadId, namespace):
return MutableMessageHistoryTagSummaryView(postbox: postbox, tag: tag, peerId: peerId, threadId: threadId, namespace: namespace)
case let .historyTagSummaryView(tag, peerId, threadId, namespace, customTag):
return MutableMessageHistoryTagSummaryView(postbox: postbox, tag: tag, peerId: peerId, threadId: threadId, namespace: namespace, customTag: customTag)
case let .historyCustomTagSummariesView(peerId, namespace):
return MutableMessageHistoryCustomTagSummariesView(postbox: postbox, peerId: peerId, namespace: namespace)
case let .cachedPeerData(peerId):
return MutableCachedPeerDataView(postbox: postbox, peerId: peerId)
case let .unreadCounts(items):

View file

@ -328,6 +328,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
private var hasPremium: Bool?
private var hasPremiumDisposable: Disposable?
private var allPresetReactionsAreAvailable: Bool
private var genericReactionEffectDisposable: Disposable?
private var genericReactionEffect: String?
@ -371,7 +373,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
}
}
public init(context: AccountContext, animationCache: AnimationCache, presentationData: PresentationData, items: [ReactionContextItem], selectedItems: Set<MessageReaction.Reaction>, title: String? = nil, alwaysAllowPremiumReactions: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?, isExpandedUpdated: @escaping (ContainedViewLayoutTransition) -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, requestUpdateOverlayWantsToBeBelowKeyboard: @escaping (ContainedViewLayoutTransition) -> Void) {
public init(context: AccountContext, animationCache: AnimationCache, presentationData: PresentationData, items: [ReactionContextItem], selectedItems: Set<MessageReaction.Reaction>, title: String? = nil, alwaysAllowPremiumReactions: Bool, allPresetReactionsAreAvailable: Bool, getEmojiContent: ((AnimationCache, MultiAnimationRenderer) -> Signal<EmojiPagerContentComponent, NoError>)?, isExpandedUpdated: @escaping (ContainedViewLayoutTransition) -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, requestUpdateOverlayWantsToBeBelowKeyboard: @escaping (ContainedViewLayoutTransition) -> Void) {
self.context = context
self.presentationData = presentationData
self.items = items
@ -472,6 +474,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
}
self.alwaysAllowPremiumReactions = alwaysAllowPremiumReactions
self.allPresetReactionsAreAvailable = allPresetReactionsAreAvailable
super.init()
@ -1422,7 +1425,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
isCustom: false
)
if case .custom = reactionItem.updateMessageReaction, let hasPremium = strongSelf.hasPremium, !hasPremium {
if case .locked = item.icon {
strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation)
} else {
strongSelf.customReactionSource = (sourceView, sourceRect, sourceLayer, reactionItem)
@ -1444,7 +1447,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
isCustom: true
)
strongSelf.customReactionSource = (sourceView, sourceRect, sourceLayer, reactionItem)
if case .custom = reactionItem.updateMessageReaction, let hasPremium = strongSelf.hasPremium, !hasPremium {
if case .locked = item.icon {
strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation)
} else {
strongSelf.reactionSelected?(reactionItem.updateMessageReaction, isLongPress)
@ -2423,7 +2426,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
} else if let reaction = self.reaction(at: point) {
switch reaction {
case let .reaction(reactionItem):
if case .custom = reactionItem.updateMessageReaction, let hasPremium = self.hasPremium, !hasPremium {
if case .custom = reactionItem.updateMessageReaction, let hasPremium = self.hasPremium, !hasPremium, !self.allPresetReactionsAreAvailable {
self.premiumReactionsSelected?(reactionItem.stillAnimation)
} else {
self.reactionSelected?(reactionItem.updateMessageReaction, false)

View file

@ -50,12 +50,13 @@ public struct SearchBarToken {
public let iconOffset: CGFloat?
public let peer: (EnginePeer, AccountContext, PresentationTheme)?
public let isTag: Bool
public let reaction: MessageReaction.Reaction?
public let emojiFile: TelegramMediaFile?
public let title: String
public let style: Style?
public let permanent: Bool
public init(id: AnyHashable, context: AccountContext? = nil, icon: UIImage?, iconOffset: CGFloat? = 0.0, peer: (EnginePeer, AccountContext, PresentationTheme)? = nil, isTag: Bool = false, emojiFile: TelegramMediaFile? = nil, title: String, style: Style? = nil, permanent: Bool) {
public init(id: AnyHashable, context: AccountContext? = nil, icon: UIImage?, iconOffset: CGFloat? = 0.0, peer: (EnginePeer, AccountContext, PresentationTheme)? = nil, isTag: Bool = false, reaction: MessageReaction.Reaction? = nil, emojiFile: TelegramMediaFile? = nil, title: String, style: Style? = nil, permanent: Bool) {
self.id = id
self.context = context
self.icon = icon
@ -63,6 +64,7 @@ public struct SearchBarToken {
self.peer = peer
self.isTag = isTag
self.emojiFile = emojiFile
self.reaction = reaction
self.title = title
self.style = style
self.permanent = permanent
@ -230,7 +232,12 @@ private final class TokenNode: ASDisplayNode {
emojiView = ComponentView()
self.emojiView = emojiView
}
let emojiViewSize = emojiView.update(
let emojiSize = CGSize(width: 14.0, height: 14.0)
var visibleEmojiSize = emojiSize
if case .builtin = self.token.reaction {
visibleEmojiSize = CGSize(width: visibleEmojiSize.width * 2.0, height: visibleEmojiSize.height * 2.0)
}
let _ = emojiView.update(
transition: .immediate,
component: AnyComponent(EmojiStatusComponent(
context: context,
@ -238,7 +245,7 @@ private final class TokenNode: ASDisplayNode {
animationRenderer: context.animationRenderer,
content: .animation(
content: .file(file: emojiFile),
size: CGSize(width: 32.0, height: 32.0),
size: visibleEmojiSize,
placeholderColor: self.theme.primaryText.withMultipliedAlpha(0.2),
themeColor: self.theme.primaryText,
loopMode: .forever
@ -249,22 +256,20 @@ private final class TokenNode: ASDisplayNode {
emojiFileUpdated: nil
)),
environment: {},
containerSize: CGSize(width: 14.0, height: 14.0)
containerSize: visibleEmojiSize
)
if let emojiComponentView = emojiView.view {
if emojiComponentView.superview == nil {
self.containerNode.view.addSubview(emojiComponentView)
}
emojiComponentView.frame = CGRect(origin: CGPoint(x: leftInset + 2.0, y: floor((height - emojiViewSize.height) * 0.5)), size: emojiViewSize)
let emojiFrame = CGRect(origin: CGPoint(x: leftInset + 2.0, y: floor((height - emojiSize.height) * 0.5)), size: emojiSize)
emojiComponentView.frame = visibleEmojiSize.centered(around: emojiFrame.center)
}
emojiFileSize = emojiViewSize
emojiFileSize = emojiSize
}
if self.token.isTag {
leftInset += 2.0
}
if let emojiFileSize {
leftInset += emojiFileSize.width + 7.0
}
let iconSize = self.token.icon?.size ?? CGSize()
let titleSize = self.titleNode.measure(CGSize(width: constrainedSize.width - 6.0, height: constrainedSize.height))
@ -272,8 +277,12 @@ private final class TokenNode: ASDisplayNode {
if !iconSize.width.isZero {
width += iconSize.width + 7.0
}
if let emojiFileSize {
leftInset += emojiFileSize.width + 6.0
width += emojiFileSize.width + 6.0
}
if self.token.isTag {
width += 19.0
width += 16.0
}
let size: CGSize

View file

@ -167,22 +167,22 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel
peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let width: CGFloat

View file

@ -149,7 +149,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode {
let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: [])
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true)
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true)
var node: ListViewItemNode?
if let current = currentNode {

View file

@ -35,12 +35,13 @@ private final class PrivacyAndSecurityControllerArguments {
let openTwoStepVerification: (TwoStepVerificationAccessConfiguration?) -> Void
let openActiveSessions: () -> Void
let toggleArchiveAndMuteNonContacts: (Bool) -> Void
let toggleOnlyAllowPremiumNonContacts: (Bool) -> Void
let setupAccountAutoremove: () -> Void
let setupMessageAutoremove: () -> Void
let openDataSettings: () -> Void
let openEmailSettings: (String?) -> Void
init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void) {
init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, toggleOnlyAllowPremiumNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void) {
self.account = account
self.openBlockedUsers = openBlockedUsers
self.openLastSeenPrivacy = openLastSeenPrivacy
@ -55,6 +56,7 @@ private final class PrivacyAndSecurityControllerArguments {
self.openTwoStepVerification = openTwoStepVerification
self.openActiveSessions = openActiveSessions
self.toggleArchiveAndMuteNonContacts = toggleArchiveAndMuteNonContacts
self.toggleOnlyAllowPremiumNonContacts = toggleOnlyAllowPremiumNonContacts
self.setupAccountAutoremove = setupAccountAutoremove
self.setupMessageAutoremove = setupMessageAutoremove
self.openDataSettings = openDataSettings
@ -66,6 +68,7 @@ private enum PrivacyAndSecuritySection: Int32 {
case general
case privacy
case autoArchive
case onlyAllowPremiumNonContacts
case account
case messageAutoremove
case dataSettings
@ -105,6 +108,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
case autoArchiveHeader(String)
case autoArchive(String, Bool)
case autoArchiveInfo(String)
case onlyAllowPremiumNonContacts(String, Bool)
case onlyAllowPremiumNonContactsInfo(String)
case accountHeader(PresentationTheme, String)
case accountTimeout(PresentationTheme, String, String)
case accountInfo(PresentationTheme, String)
@ -121,6 +126,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
return PrivacyAndSecuritySection.privacy.rawValue
case .autoArchiveHeader, .autoArchive, .autoArchiveInfo:
return PrivacyAndSecuritySection.autoArchive.rawValue
case .onlyAllowPremiumNonContacts, .onlyAllowPremiumNonContactsInfo:
return PrivacyAndSecuritySection.onlyAllowPremiumNonContacts.rawValue
case .accountHeader, .accountTimeout, .accountInfo:
return PrivacyAndSecuritySection.account.rawValue
case .dataSettings, .dataSettingsInfo:
@ -172,16 +179,20 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
return 20
case .autoArchiveInfo:
return 21
case .accountHeader:
case .onlyAllowPremiumNonContacts:
return 22
case .accountTimeout:
case .onlyAllowPremiumNonContactsInfo:
return 23
case .accountInfo:
case .accountHeader:
return 24
case .dataSettings:
case .accountTimeout:
return 25
case .dataSettingsInfo:
case .accountInfo:
return 26
case .dataSettings:
return 27
case .dataSettingsInfo:
return 28
}
}
@ -301,6 +312,18 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
} else {
return false
}
case let .onlyAllowPremiumNonContacts(text, value):
if case .onlyAllowPremiumNonContacts(text, value) = rhs {
return true
} else {
return false
}
case let .onlyAllowPremiumNonContactsInfo(text):
if case .onlyAllowPremiumNonContactsInfo(text) = rhs {
return true
} else {
return false
}
case let .accountHeader(lhsTheme, lhsText):
if case let .accountHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
@ -425,6 +448,12 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
}, tag: PrivacyAndSecurityEntryTag.autoArchive)
case let .autoArchiveInfo(text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .onlyAllowPremiumNonContacts(text, value):
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
arguments.toggleOnlyAllowPremiumNonContacts(value)
}, tag: PrivacyAndSecurityEntryTag.autoArchive)
case let .onlyAllowPremiumNonContactsInfo(text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .accountHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .accountTimeout(_, text, value):
@ -447,6 +476,7 @@ private struct PrivacyAndSecurityControllerState: Equatable {
var updatingAccountTimeoutValue: Int32? = nil
var updatingAutomaticallyArchiveAndMuteNonContacts: Bool? = nil
var updatingMessageAutoremoveTimeoutValue: Int32? = nil
var updatingOnlyAllowPremiumNonContacts: Bool? = nil
}
private func countForSelectivePeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> Int {
@ -611,6 +641,15 @@ private func privacyAndSecurityControllerEntries(
entries.append(.autoArchiveInfo(presentationData.strings.PrivacySettings_AutoArchiveInfo))
}
//TODO:localize
let onlyAllowPremiumNonContactsValue = state.updatingOnlyAllowPremiumNonContacts ?? privacySettings?.globalSettings.nonContactChatsRequirePremium ?? false
entries.append(.onlyAllowPremiumNonContacts("Only Allow Premium Chats", onlyAllowPremiumNonContactsValue))
if !onlyAllowPremiumNonContactsValue {
entries.append(.onlyAllowPremiumNonContactsInfo("Non-premium users are allowed to send you a message."))
} else {
entries.append(.onlyAllowPremiumNonContactsInfo("Non-premium users are not allowed to send you a message."))
}
entries.append(.accountHeader(presentationData.theme, presentationData.strings.PrivacySettings_DeleteAccountTitle.uppercased()))
if let privacySettings = privacySettings {
let value: Int32
@ -775,7 +814,7 @@ public func privacyAndSecurityController(
|> deliverOnMainQueue
|> mapToSignal { value -> Signal<Void, NoError> in
if let value = value {
privacySettingsPromise.set(.single(AccountPrivacySettings(presence: updated, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, bio: value.bio, globalSettings: value.globalSettings, accountRemovalTimeout: value.accountRemovalTimeout, messageAutoremoveTimeout: value.messageAutoremoveTimeout)))
privacySettingsPromise.set(.single(AccountPrivacySettings(presence: updated, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, bio: value.bio, globalSettings: updatedGlobalSettings ?? value.globalSettings, accountRemovalTimeout: value.accountRemovalTimeout, messageAutoremoveTimeout: value.messageAutoremoveTimeout)))
}
return .complete()
}
@ -1061,6 +1100,36 @@ public func privacyAndSecurityController(
return state
}
}))
}, toggleOnlyAllowPremiumNonContacts: { settingValue in
updateState { state in
var state = state
state.updatingOnlyAllowPremiumNonContacts = settingValue
return state
}
let applyTimeout: Signal<Void, NoError> = privacySettingsPromise.get()
|> filter { $0 != nil }
|> take(1)
|> deliverOnMainQueue
|> mapToSignal { value -> Signal<Void, NoError> in
if let value = value {
var globalSettings = value.globalSettings
globalSettings.nonContactChatsRequirePremium = settingValue
privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, bio: value.bio, globalSettings: globalSettings, accountRemovalTimeout: value.accountRemovalTimeout, messageAutoremoveTimeout: value.messageAutoremoveTimeout)))
}
return .complete()
}
updateAutoArchiveDisposable.set((context.engine.privacy.updateNonContactChatsRequirePremium(value: settingValue)
|> mapToSignal { _ -> Signal<Void, NoError> in }
|> then(applyTimeout)
|> deliverOnMainQueue).start(completed: {
updateState { state in
var state = state
state.updatingOnlyAllowPremiumNonContacts = nil
return state
}
}))
}, setupAccountAutoremove: {
let signal = privacySettingsPromise.get()
|> take(1)

View file

@ -907,7 +907,7 @@ func selectivePrivacySettingsController(
}
//TODO:replace hideReadTimeEnabled with actual value
let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, disableFor: initialDisableFor, enableForCloseFriends: initialEnableForCloseFriends, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callP2PEnableForCloseFriends: initialCallEnableForCloseFriends, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: globalSettings?.keepArchivedFolders, uploadedPhoto: nil)
let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, disableFor: initialDisableFor, enableForCloseFriends: initialEnableForCloseFriends, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callP2PEnableForCloseFriends: initialCallEnableForCloseFriends, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: globalSettings?.hideReadTime, uploadedPhoto: nil)
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState)
@ -1314,10 +1314,8 @@ func selectivePrivacySettingsController(
var updateGlobalSettingsSignal: Signal<Never, NoError> = Signal.complete()
var updatedGlobalSettings: GlobalPrivacySettings?
if let updateHideReadTime = arguments.updateHideReadTime, let globalSettings {
//TODO:update global settings
let _ = updateHideReadTime
updatedGlobalSettings = GlobalPrivacySettings(automaticallyArchiveAndMuteNonContacts: globalSettings.automaticallyArchiveAndMuteNonContacts, keepArchivedUnmuted: globalSettings.keepArchivedUnmuted, keepArchivedFolders: globalSettings.keepArchivedFolders)
if let _ = arguments.updateHideReadTime, let globalSettings {
updatedGlobalSettings = GlobalPrivacySettings(automaticallyArchiveAndMuteNonContacts: globalSettings.automaticallyArchiveAndMuteNonContacts, keepArchivedUnmuted: globalSettings.keepArchivedUnmuted, keepArchivedFolders: globalSettings.keepArchivedFolders, hideReadTime: hideReadTimeEnabled ?? globalSettings.hideReadTime, nonContactChatsRequirePremium: globalSettings.nonContactChatsRequirePremium)
if let updatedGlobalSettings {
updateGlobalSettingsSignal = context.engine.privacy.updateGlobalPrivacySettings(settings: updatedGlobalSettings)
}

View file

@ -262,6 +262,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: author,
text: text,
@ -432,22 +433,22 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
let width: CGFloat

View file

@ -409,6 +409,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: author,
text: text,
@ -588,20 +589,20 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
var sampleMessages: [Message] = []
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message1)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message2)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message3)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message4.id] = message4
sampleMessages.append(message4)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message5.id] = message5
sampleMessages.append(message5)
@ -609,13 +610,13 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message6)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message7)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message8)
items = sampleMessages.reversed().map { message in

View file

@ -164,10 +164,10 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
if let (author, text) = messageItem.reply {
peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
}
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
}

View file

@ -972,8 +972,8 @@ func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: T
transaction.setMessageHistoryThreadInfo(peerId: result.peerId, threadId: item.threadId, info: info)
transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: item.unreadMentionsCount, maxId: item.topMessage)
transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: item.unreadReactionsCount, maxId: item.topMessage)
transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: item.unreadMentionsCount, maxId: item.topMessage)
transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: item.unreadReactionsCount, maxId: item.topMessage)
if item.topMessage != 0 {
transaction.removeHole(peerId: result.peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: item.topMessage ... (Int32.max - 1))

View file

@ -251,21 +251,29 @@ public struct GlobalPrivacySettings: Equatable, Codable {
public static var `default` = GlobalPrivacySettings(
automaticallyArchiveAndMuteNonContacts: false,
keepArchivedUnmuted: true,
keepArchivedFolders: true
keepArchivedFolders: true,
hideReadTime: false,
nonContactChatsRequirePremium: false
)
public var automaticallyArchiveAndMuteNonContacts: Bool
public var keepArchivedUnmuted: Bool
public var keepArchivedFolders: Bool
public var hideReadTime: Bool
public var nonContactChatsRequirePremium: Bool
public init(
automaticallyArchiveAndMuteNonContacts: Bool,
keepArchivedUnmuted: Bool,
keepArchivedFolders: Bool
keepArchivedFolders: Bool,
hideReadTime: Bool,
nonContactChatsRequirePremium: Bool
) {
self.automaticallyArchiveAndMuteNonContacts = automaticallyArchiveAndMuteNonContacts
self.keepArchivedUnmuted = keepArchivedUnmuted
self.keepArchivedFolders = keepArchivedFolders
self.hideReadTime = hideReadTime
self.nonContactChatsRequirePremium = nonContactChatsRequirePremium
}
}

View file

@ -2046,8 +2046,8 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: entry)
}
transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: unreadMentionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: unreadReactionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: unreadMentionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: unreadReactionsCount, maxId: topMessage)
case .forumTopicDeleted:
break
}
@ -4028,7 +4028,7 @@ func replayFinalState(
case let .UpdatePeerChatUnreadMark(peerId, namespace, value):
transaction.applyMarkUnread(peerId: peerId, namespace: namespace, value: value, interactive: false)
case let .ResetMessageTagSummary(peerId, tag, namespace, count, range):
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: tag, namespace: namespace, count: count, maxId: range.maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: tag, namespace: namespace, customTag: nil, count: count, maxId: range.maxId)
if count == 0 {
transaction.removeHole(peerId: peerId, threadId: nil, namespace: namespace, space: .tag(tag), range: 1 ... (Int32.max - 1))
if tag == .unseenPersonalMessage {
@ -4608,8 +4608,8 @@ func replayFinalState(
} else {
assertionFailure()
}
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: data.unreadReactionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
}
case let .UpdateStory(peerId, story):
var updatedPeerEntries: [StoryItemsTableEntry] = transaction.getStoryItems(peerId: peerId)

View file

@ -1392,13 +1392,13 @@ public final class AccountViewTracker {
})
}
if let summary = transaction.getMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), summary.count > 0 {
if let summary = transaction.getMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil), summary.count > 0 {
var maxId: Int32 = summary.range.maxId
if let index = transaction.getTopPeerMessageIndex(peerId: peerId, namespace: Namespaces.Message.Cloud) {
maxId = index.id.id
}
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: 0, maxId: maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: maxId)
addSynchronizeMarkAllUnseenPersonalMessagesOperation(transaction: transaction, peerId: peerId, maxId: summary.range.maxId)
}
@ -1475,13 +1475,13 @@ public final class AccountViewTracker {
})
}
if let summary = transaction.getMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud) {
if let summary = transaction.getMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil) {
var maxId: Int32 = summary.range.maxId
if let index = transaction.getTopPeerMessageIndex(peerId: peerId, namespace: Namespaces.Message.Cloud) {
maxId = index.id.id
}
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: 0, maxId: maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: maxId)
addSynchronizeMarkAllUnseenReactionsOperation(transaction: transaction, peerId: peerId, maxId: summary.range.maxId)
}
@ -2202,10 +2202,10 @@ public final class AccountViewTracker {
public func unseenPersonalMessagesAndReactionCount(peerId: PeerId, threadId: Int64?) -> Signal<(mentionCount: Int32, reactionCount: Int32), NoError> {
if let account = self.account {
let pendingMentionsKey: PostboxViewKey = .pendingMessageActionsSummary(type: .consumeUnseenPersonalMessage, peerId: peerId, namespace: Namespaces.Message.Cloud)
let summaryMentionsKey: PostboxViewKey = .historyTagSummaryView(tag: .unseenPersonalMessage, peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud)
let summaryMentionsKey: PostboxViewKey = .historyTagSummaryView(tag: .unseenPersonalMessage, peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, customTag: nil)
let pendingReactionsKey: PostboxViewKey = .pendingMessageActionsSummary(type: .readReaction, peerId: peerId, namespace: Namespaces.Message.Cloud)
let summaryReactionsKey: PostboxViewKey = .historyTagSummaryView(tag: .unseenReaction, peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud)
let summaryReactionsKey: PostboxViewKey = .historyTagSummaryView(tag: .unseenReaction, peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, customTag: nil)
return account.postbox.combinedView(keys: [pendingMentionsKey, summaryMentionsKey, pendingReactionsKey, summaryReactionsKey])
|> map { views -> (mentionCount: Int32, reactionCount: Int32) in

View file

@ -955,8 +955,8 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
if let entry = StoredMessageHistoryThreadInfo(data.data) {
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
}
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: data.unreadReactionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
}
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
@ -1024,10 +1024,10 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
}
for (peerId, summary) in fetchedChats.mentionTagSummaries {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
}
for (peerId, summary) in fetchedChats.reactionTagSummaries {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
}
for (groupId, summary) in fetchedChats.folderSummaries {

View file

@ -377,7 +377,7 @@ private func synchronizeUnseenPersonalMentionsTag(postbox: Postbox, network: Net
}
return postbox.transaction { transaction -> Void in
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, count: apiUnreadMentionsCount, maxId: apiTopMessage)
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: apiUnreadMentionsCount, maxId: apiTopMessage)
}
} else {
return .complete()
@ -419,7 +419,7 @@ private func synchronizeUnseenReactionsTag(postbox: Postbox, network: Network, e
}
return postbox.transaction { transaction -> Void in
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, count: apiUnreadReactionsCount, maxId: apiTopMessage)
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: apiUnreadReactionsCount, maxId: apiTopMessage)
}
} else {
return .complete()
@ -435,7 +435,7 @@ private func synchronizeUnseenReactionsTag(postbox: Postbox, network: Network, e
} |> switchToLatest
}
func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, threadId: Int64) -> Signal<Void, NoError> {
func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, threadId: Int64?) -> Signal<Void, NoError> {
return Signal { _ in
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
@ -445,6 +445,10 @@ func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Net
if let v = view.views[invalidateKey] as? InvalidatedMessageHistoryTagSummariesView {
invalidateEntries = v.entries
}
if invalidateEntries.contains(where: { $0.key.customTag != nil }) {
invalidateEntries = invalidateEntries.filter({ $0.key.customTag == nil })
invalidateEntries.insert(InvalidatedMessageHistoryTagsSummaryEntry(key: InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: Namespaces.Message.Cloud, tagMask: [], threadId: threadId, customTag: MemoryBuffer()), version: 0))
}
let (disposeOperations, _, beginValidateOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)], beginValidateOperations: [(InvalidatedMessageHistoryTagsSummaryEntry, MetaDisposable)]) in
return helper.update(entries: [], invalidateEntries: invalidateEntries)
@ -455,11 +459,29 @@ func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Net
}
for (entry, disposable) in beginValidateOperations {
let signal = synchronizeMessageHistoryTagSummary(postbox: postbox, network: network, entry: entry)
|> then(postbox.transaction { transaction -> Void in
transaction.removeInvalidatedMessageHistoryTagsSummaryEntry(entry)
})
disposable.set(signal.start())
if entry.key.customTag != nil {
if peerId == stateManager.accountPeerId {
let signal = synchronizeSavedMessageTags(postbox: postbox, network: network, peerId: peerId)
|> map { _ -> Void in
}
|> then(postbox.transaction { transaction -> Void in
transaction.removeInvalidatedMessageHistoryTagsSummaryEntriesWithCustomTags(peerId: peerId, threadId: nil, namespace: Namespaces.Message.Cloud, tagMask: [])
})
disposable.set(signal.start())
} else {
assertionFailure()
let signal = postbox.transaction { transaction -> Void in
transaction.removeInvalidatedMessageHistoryTagsSummaryEntriesWithCustomTags(peerId: peerId, threadId: nil, namespace: Namespaces.Message.Cloud, tagMask: [])
}
disposable.set(signal.start())
}
} else {
let signal = synchronizeMessageHistoryTagSummary(postbox: postbox, network: network, entry: entry)
|> then(postbox.transaction { transaction -> Void in
transaction.removeInvalidatedMessageHistoryTagsSummaryEntry(entry)
})
disposable.set(signal.start())
}
}
})
@ -494,7 +516,7 @@ private func synchronizeMessageHistoryTagSummary(postbox: Postbox, network: Netw
switch result {
case let .channelMessages(_, _, count, _, messages, _, _, _):
let topId: Int32 = messages.first?.id(namespace: Namespaces.Message.Cloud)?.id ?? 1
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: threadId, tagMask: entry.key.tagMask, namespace: entry.key.namespace, count: count, maxId: topId)
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: threadId, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: count, maxId: topId)
default:
break
}
@ -506,3 +528,62 @@ private func synchronizeMessageHistoryTagSummary(postbox: Postbox, network: Netw
}
|> switchToLatest
}
private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<Never, NoError> {
return (network.request(Api.functions.messages.getSavedReactionTags(hash: 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.SavedReactionTags?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<Never, NoError> in
guard let result = result else {
return .complete()
}
switch result {
case .savedReactionTagsNotModified:
return .complete()
case let .savedReactionTags(tags, _):
var customFileIds: [Int64] = []
var parsedTags: [SavedMessageTags.Tag] = []
for tag in tags {
switch tag {
case let .savedReactionTag(_, reaction, title, count):
guard let reaction = MessageReaction.Reaction(apiReaction: reaction) else {
continue
}
parsedTags.append(SavedMessageTags.Tag(
reaction: reaction,
title: title,
count: Int(count)
))
if case let .custom(fileId) = reaction {
customFileIds.append(fileId)
}
}
}
let _ = customFileIds
return postbox.transaction { transaction -> Void in
let previousTags = transaction.getMessageTagSummaryCustomTags(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud)
let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud)?.id ?? 1
var validTags: [MemoryBuffer] = []
for tag in parsedTags {
let customTag = ReactionsMessageAttribute.messageTag(reaction: tag.reaction)
validTags.append(customTag)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: customTag, count: Int32(tag.count), maxId: topMessageId)
}
for tag in previousTags {
if !validTags.contains(tag) {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag, count: 0, maxId: topMessageId)
}
}
}
|> ignoreValues
}
})
}

View file

@ -1895,6 +1895,7 @@ private func sendStandaloneMessage(auxiliaryMethods: AccountAuxiliaryMethods, po
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: nil,
text: contents.text,

View file

@ -46,8 +46,8 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
if let entry = StoredMessageHistoryThreadInfo(data.data) {
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
}
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: data.unreadReactionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
}
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
@ -125,16 +125,24 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
}
for (peerId, summary) in fetchedChats.mentionTagSummaries {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
}
for (peerId, summary) in fetchedChats.reactionTagSummaries {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
}
for (groupId, summary) in fetchedChats.folderSummaries {
transaction.resetPeerGroupSummary(groupId: groupId, namespace: Namespaces.Message.Cloud, summary: summary)
}
let savedMessageTags = transaction.getMessageTagSummaryCustomTags(peerId: accountPeerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud)
if !savedMessageTags.isEmpty {
for tag in savedMessageTags {
transaction.replaceMessageTagSummary(peerId: accountPeerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag, count: 0, maxId: 1)
}
transaction.invalidateMessageHistoryTagsSummary(peerId: accountPeerId, threadId: nil, namespace: Namespaces.Message.Cloud, tagMask: [], customTag: savedMessageTags[0])
}
transaction.reindexUnreadCounters()
if let currentState = transaction.getState() as? AuthorizedAccountState {

View file

@ -104,6 +104,13 @@ func _internal_savedMessageTags(postbox: Postbox) -> Signal<SavedMessageTags?, N
}
}
func _internal_savedMessageTagsCacheKey() -> ItemCacheEntryId {
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: 0)
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.savedMessageTags, key: key)
}
func _internal_savedMessageTags(transaction: Transaction) -> SavedMessageTags? {
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: 0)

View file

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 171
return 172
}
public func parseMessage(_ data: Data!) -> Any! {

View file

@ -1,8 +1,9 @@
import Foundation
import Postbox
import TelegramApi
public struct MessageReaction: Equatable, PostboxCoding, Codable {
public enum Reaction: Hashable, Codable, PostboxCoding {
public enum Reaction: Hashable, Comparable, Codable, PostboxCoding {
case builtin(String)
case custom(Int64)
@ -43,6 +44,25 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
encoder.encodeInt64(fileId, forKey: "cfid")
}
}
public static func <(lhs: Reaction, rhs: Reaction) -> Bool {
switch lhs {
case let .builtin(lhsValue):
switch rhs {
case let .builtin(rhsValue):
return lhsValue < rhsValue
case .custom:
return true
}
case let .custom(lhsValue):
switch rhs {
case .builtin:
return false
case let .custom(rhsValue):
return lhsValue < rhsValue
}
}
}
}
public var value: Reaction
@ -145,6 +165,71 @@ extension MessageReaction.Reaction {
}
public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
public static func messageTag(reaction: MessageReaction.Reaction) -> MemoryBuffer {
let buffer = WriteBuffer()
var prefix: UInt8 = 0
buffer.write(&prefix, offset: 0, length: 1)
switch reaction {
case let .builtin(value):
var stringData = value.data(using: .utf8) ?? Data()
var length: UInt8 = UInt8(clamping: stringData.count)
if stringData.count > Int(length) {
stringData.count = Int(length)
}
var typeId: UInt8 = 0
buffer.write(&typeId, offset: 0, length: 1)
buffer.write(&length, offset: 0, length: 1)
buffer.write(stringData)
case var .custom(fileId):
var typeId: UInt8 = 1
buffer.write(&typeId, offset: 0, length: 1)
buffer.write(&fileId, offset: 0, length: 8)
}
return buffer
}
public static func reactionFromMessageTag(tag: MemoryBuffer) -> MessageReaction.Reaction? {
if tag.length < 2 {
return nil
}
let readBuffer = ReadBuffer(memoryBufferNoCopy: tag)
var prefix: UInt8 = 0
readBuffer.read(&prefix, offset: 0, length: 1)
if prefix != 0 {
return nil
}
var typeId: UInt8 = 0
readBuffer.read(&typeId, offset: 0, length: 1)
switch typeId {
case 0:
var length8: UInt8 = 0
readBuffer.read(&length8, offset: 0, length: 1)
let length = Int(length8)
if readBuffer.offset + length > readBuffer.length {
return nil
}
let data = readBuffer.readData(length: length)
guard let string = String(data: data, encoding: .utf8) else {
return nil
}
return .builtin(string)
case 1:
if readBuffer.offset + 8 > readBuffer.length {
return nil
}
var fileId: Int64 = 0
readBuffer.read(&fileId, offset: 0, length: 8)
return .custom(fileId)
default:
return nil
}
}
public struct RecentPeer: Equatable, PostboxCoding {
public var value: MessageReaction.Reaction
public var isLarge: Bool
@ -221,6 +306,18 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
return result
}
public var customTags: [MemoryBuffer] {
if self.isTags {
var result: [MemoryBuffer] = []
for reaction in self.reactions {
result.append(ReactionsMessageAttribute.messageTag(reaction: reaction.value))
}
return result
} else {
return []
}
}
public init(canViewList: Bool, isTags: Bool, reactions: [MessageReaction], recentPeers: [RecentPeer]) {
self.canViewList = canViewList
self.isTags = isTags

View file

@ -319,7 +319,38 @@ public extension TelegramEngine.EngineData.Item {
}
var key: PostboxViewKey {
return .historyTagSummaryView(tag: self.tag, peerId: self.peerId, threadId: self.threadId, namespace: Namespaces.Message.Cloud)
return .historyTagSummaryView(tag: self.tag, peerId: self.peerId, threadId: self.threadId, namespace: Namespaces.Message.Cloud, customTag: nil)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? MessageHistoryTagSummaryView else {
preconditionFailure()
}
return view.count.flatMap(Int.init)
}
}
public struct ReactionTagMessageCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public struct ItemKey: Hashable {
public var peerId: EnginePeer.Id
public var reaction: MessageReaction.Reaction
}
public typealias Result = Int?
fileprivate var peerId: EnginePeer.Id
fileprivate var reaction: MessageReaction.Reaction
public var mapKey: ItemKey {
return ItemKey(peerId: self.peerId, reaction: self.reaction)
}
public init(peerId: EnginePeer.Id, reaction: MessageReaction.Reaction) {
self.peerId = peerId
self.reaction = reaction
}
var key: PostboxViewKey {
return .historyTagSummaryView(tag: [], peerId: self.peerId, threadId: nil, namespace: Namespaces.Message.Cloud, customTag: ReactionsMessageAttribute.messageTag(reaction: self.reaction))
}
func extract(view: PostboxView) -> Result {
@ -356,5 +387,32 @@ public extension TelegramEngine.EngineData.Item {
return EngineMessage(message)
}
}
public struct SavedMessageTagStats: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = [MessageReaction.Reaction: Int]
fileprivate var peerId: EnginePeer.Id
public init(peerId: EnginePeer.Id) {
self.peerId = peerId
}
var key: PostboxViewKey {
return .historyCustomTagSummariesView(peerId: self.peerId, namespace: Namespaces.Message.Cloud)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? MessageHistoryCustomTagSummariesView else {
preconditionFailure()
}
var result: [MessageReaction.Reaction: Int] = [:]
for (key, value) in view.tags {
if let reaction = ReactionsMessageAttribute.reactionFromMessageTag(tag: key) {
result[reaction] = value
}
}
return result
}
}
}
}

View file

@ -364,6 +364,7 @@ private class AdMessagesHistoryContextImpl {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: author,
text: self.text,

View file

@ -195,7 +195,7 @@ func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, netwo
}
if !hasUnread && peerId.namespace == Namespaces.Peer.SecretChat {
let unseenSummary = transaction.getMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud)
let unseenSummary = transaction.getMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil)
let actionSummary = transaction.getPendingMessageActionsSummary(peerId: peerId, type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)
if (unseenSummary?.count ?? 0) - (actionSummary ?? 0) > 0 {
hasUnread = true

View file

@ -53,7 +53,7 @@ func _internal_earliestUnseenPersonalMentionMessage(account: Account, peerId: Pe
} else {
return account.postbox.transaction { transaction -> EarliestUnseenPersonalMentionMessageResult in
if let topId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: 0, maxId: topId.id)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topId.id)
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, space: .tag(.unseenPersonalMessage), range: 1 ... (Int32.max - 1))
let ids = transaction.getMessageIndicesWithTag(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, tag: .unseenPersonalMessage).map({ $0.id })
@ -120,7 +120,7 @@ func _internal_earliestUnseenPersonalReactionMessage(account: Account, peerId: P
} else {
return account.postbox.transaction { transaction -> EarliestUnseenPersonalMentionMessageResult in
if let topId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: 0, maxId: topId.id)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topId.id)
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, space: .tag(.unseenReaction), range: 1 ... (Int32.max - 1))
let ids = transaction.getMessageIndicesWithTag(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, tag: .unseenReaction).map({ $0.id })

View file

@ -10,6 +10,7 @@ public final class EngineMessage: Equatable {
public typealias GlobalTags = GlobalMessageTags
public typealias LocalTags = LocalMessageTags
public typealias ForwardInfo = MessageForwardInfo
public typealias CustomTag = MemoryBuffer
private let impl: Message
@ -102,6 +103,7 @@ public final class EngineMessage: Equatable {
tags: EngineMessage.Tags,
globalTags: EngineMessage.GlobalTags,
localTags: EngineMessage.LocalTags,
customTags: [EngineMessage.CustomTag],
forwardInfo: EngineMessage.ForwardInfo?,
author: EnginePeer?,
text: String,
@ -137,6 +139,7 @@ public final class EngineMessage: Equatable {
tags: tags,
globalTags: globalTags,
localTags: localTags,
customTags: customTags,
forwardInfo: forwardInfo,
author: author?._asPeer(),
text: text,

View file

@ -15,86 +15,103 @@ public final class MessageReadStats {
}
func _internal_messageReadStats(account: Account, id: MessageId) -> Signal<MessageReadStats?, NoError> {
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(id.peerId).flatMap(apiInputPeer)
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(id.peerId)
}
|> mapToSignal { inputPeer -> Signal<MessageReadStats?, NoError> in
guard let inputPeer = inputPeer else {
|> mapToSignal { peer -> Signal<MessageReadStats?, NoError> in
guard let peer, let inputPeer = apiInputPeer(peer) else {
return .single(nil)
}
if id.namespace != Namespaces.Message.Cloud {
return .single(nil)
}
let readPeers: Signal<[(Int64, Int32)]?, NoError> = account.network.request(Api.functions.messages.getMessageReadParticipants(peer: inputPeer, msgId: id.id))
|> map { result -> [(Int64, Int32)]? in
var items: [(Int64, Int32)] = []
for item in result {
switch item {
case let .readParticipantDate(userId, date):
items.append((userId, date))
if id.peerId.namespace == Namespaces.Peer.CloudUser {
return account.network.request(Api.functions.messages.getOutboxReadDate(peer: inputPeer, msgId: id.id))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.OutboxReadDate?, NoError> in
return .single(nil)
}
|> map { result -> MessageReadStats? in
guard let result else {
return MessageReadStats(reactionCount: 0, peers: [], readTimestamps: [:])
}
switch result {
case let .outboxReadDate(date):
return MessageReadStats(reactionCount: 0, peers: [EnginePeer(peer)], readTimestamps: [peer.id: date])
}
}
return items
}
|> `catch` { _ -> Signal<[(Int64, Int32)]?, NoError> in
return .single(nil)
}
let reactionCount: Signal<Int, NoError> = account.network.request(Api.functions.messages.getMessageReactionsList(flags: 0, peer: inputPeer, id: id.id, reaction: nil, offset: nil, limit: 1))
|> map { result -> Int in
switch result {
case let .messageReactionsList(_, count, _, _, _, _):
return Int(count)
}
}
|> `catch` { _ -> Signal<Int, NoError> in
return .single(0)
}
return combineLatest(readPeers, reactionCount)
|> mapToSignal { result, reactionCount -> Signal<MessageReadStats?, NoError> in
return account.postbox.transaction { transaction -> (peerIds: [PeerId], readTimestamps: [PeerId: Int32], missingPeerIds: [PeerId]) in
var peerIds: [PeerId] = []
var readTimestamps: [PeerId: Int32] = [:]
var missingPeerIds: [PeerId] = []
let authorId = transaction.getMessage(id)?.author?.id
if let result = result {
for (id, timestamp) in result {
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))
readTimestamps[peerId] = timestamp
if peerId == account.peerId {
continue
}
if peerId == authorId {
continue
}
peerIds.append(peerId)
if transaction.getPeer(peerId) == nil {
missingPeerIds.append(peerId)
}
} else {
let readPeers: Signal<[(Int64, Int32)]?, NoError> = account.network.request(Api.functions.messages.getMessageReadParticipants(peer: inputPeer, msgId: id.id))
|> map { result -> [(Int64, Int32)]? in
var items: [(Int64, Int32)] = []
for item in result {
switch item {
case let .readParticipantDate(userId, date):
items.append((userId, date))
}
}
return (peerIds: peerIds, readTimestamps: readTimestamps, missingPeerIds: missingPeerIds)
return items
}
|> mapToSignal { peerIds, readTimestamps, missingPeerIds -> Signal<MessageReadStats?, NoError> in
if missingPeerIds.isEmpty || id.peerId.namespace != Namespaces.Peer.CloudChannel {
return account.postbox.transaction { transaction -> MessageReadStats? in
return MessageReadStats(reactionCount: reactionCount, peers: peerIds.compactMap { peerId -> EnginePeer? in
return transaction.getPeer(peerId).flatMap(EnginePeer.init)
}, readTimestamps: readTimestamps)
|> `catch` { _ -> Signal<[(Int64, Int32)]?, NoError> in
return .single(nil)
}
let reactionCount: Signal<Int, NoError> = account.network.request(Api.functions.messages.getMessageReactionsList(flags: 0, peer: inputPeer, id: id.id, reaction: nil, offset: nil, limit: 1))
|> map { result -> Int in
switch result {
case let .messageReactionsList(_, count, _, _, _, _):
return Int(count)
}
}
|> `catch` { _ -> Signal<Int, NoError> in
return .single(0)
}
return combineLatest(readPeers, reactionCount)
|> mapToSignal { result, reactionCount -> Signal<MessageReadStats?, NoError> in
return account.postbox.transaction { transaction -> (peerIds: [PeerId], readTimestamps: [PeerId: Int32], missingPeerIds: [PeerId]) in
var peerIds: [PeerId] = []
var readTimestamps: [PeerId: Int32] = [:]
var missingPeerIds: [PeerId] = []
let authorId = transaction.getMessage(id)?.author?.id
if let result = result {
for (id, timestamp) in result {
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))
readTimestamps[peerId] = timestamp
if peerId == account.peerId {
continue
}
if peerId == authorId {
continue
}
peerIds.append(peerId)
if transaction.getPeer(peerId) == nil {
missingPeerIds.append(peerId)
}
}
}
} else {
return _internal_channelMembers(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, peerId: id.peerId, category: .recent(.all), offset: 0, limit: 50, hash: 0)
|> mapToSignal { _ -> Signal<MessageReadStats?, NoError> in
return (peerIds: peerIds, readTimestamps: readTimestamps, missingPeerIds: missingPeerIds)
}
|> mapToSignal { peerIds, readTimestamps, missingPeerIds -> Signal<MessageReadStats?, NoError> in
if missingPeerIds.isEmpty || id.peerId.namespace != Namespaces.Peer.CloudChannel {
return account.postbox.transaction { transaction -> MessageReadStats? in
return MessageReadStats(reactionCount: reactionCount, peers: peerIds.compactMap { peerId -> EnginePeer? in
return transaction.getPeer(peerId).flatMap(EnginePeer.init)
}, readTimestamps: readTimestamps)
}
} else {
return _internal_channelMembers(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, peerId: id.peerId, category: .recent(.all), offset: 0, limit: 50, hash: 0)
|> mapToSignal { _ -> Signal<MessageReadStats?, NoError> in
return account.postbox.transaction { transaction -> MessageReadStats? in
return MessageReadStats(reactionCount: reactionCount, peers: peerIds.compactMap { peerId -> EnginePeer? in
return transaction.getPeer(peerId).flatMap(EnginePeer.init)
}, readTimestamps: readTimestamps)
}
}
}
}
}

View file

@ -479,9 +479,9 @@ public extension TelegramEngine {
maxId = max(maxId, message.id.id)
return true
})
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, count: Int32(localCount), maxId: maxId)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, customTag: nil, count: Int32(localCount), maxId: maxId)
} else {
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, count: count, maxId: maxId ?? 1)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, customTag: nil, count: count, maxId: maxId ?? 1)
}
}
}
@ -694,6 +694,11 @@ public extension TelegramEngine {
|> ignoreValues
}
public func keepMessageCountersSyncrhonized(peerId: EnginePeer.Id) -> Signal<Never, NoError> {
return managedSynchronizeMessageHistoryTagSummaries(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, threadId: nil)
|> ignoreValues
}
public func getSynchronizeAutosaveItemOperations() -> Signal<[(index: Int32, message: Message, mediaId: MediaId)], NoError> {
return self.account.postbox.transaction { transaction -> [(index: Int32, message: Message, mediaId: MediaId)] in
return _internal_getSynchronizeAutosaveItemOperations(transaction: transaction)

View file

@ -791,8 +791,8 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
transaction.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud: .idBased(maxIncomingReadId: readInboxMaxId, maxOutgoingReadId: readOutboxMaxId, maxKnownId: topMessage, count: unreadCount, markedUnread: false)]])
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: unreadMentionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: unreadReactionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: unreadMentionsCount, maxId: topMessage)
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: unreadReactionsCount, maxId: topMessage)
if let pts = pts {
if transaction.getPeerChatState(peerId) == nil {

View file

@ -37,6 +37,10 @@ public extension TelegramEngine {
return _internal_updateAccountAutoArchiveChats(account: self.account, value: value)
}
public func updateNonContactChatsRequirePremium(value: Bool) -> Signal<Never, NoError> {
return _internal_updateNonContactChatsRequirePremium(account: self.account, value: value)
}
public func updateAccountKeepArchivedFolders(value: Bool) -> Signal<Never, NoError> {
return _internal_updateAccountKeepArchivedFolders(account: self.account, value: value)
}

View file

@ -20,10 +20,15 @@ func _internal_updateGlobalPrivacySettings(account: Account) -> Signal<Never, No
let automaticallyArchiveAndMuteNonContacts = (flags & (1 << 0)) != 0
let keepArchivedUnmuted = (flags & (1 << 1)) != 0
let keepArchivedFolders = (flags & (1 << 2)) != 0
let hideReadTime = (flags & (1 << 3)) != 0
let nonContactChatsRequirePremium = (flags & (1 << 4)) != 0
globalSettings = GlobalPrivacySettings(
automaticallyArchiveAndMuteNonContacts: automaticallyArchiveAndMuteNonContacts,
keepArchivedUnmuted: keepArchivedUnmuted,
keepArchivedFolders: keepArchivedFolders
keepArchivedFolders: keepArchivedFolders,
hideReadTime: hideReadTime,
nonContactChatsRequirePremium: nonContactChatsRequirePremium
)
}
updateGlobalPrivacySettings(transaction: transaction, { _ in
@ -185,10 +190,14 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
let automaticallyArchiveAndMuteNonContacts = (flags & (1 << 0)) != 0
let keepArchivedUnmuted = (flags & (1 << 1)) != 0
let keepArchivedFolders = (flags & (1 << 2)) != 0
let hideReadTime = (flags & (1 << 3)) != 0
let nonContactChatsRequirePremium = (flags & (1 << 4)) != 0
globalSettings = GlobalPrivacySettings(
automaticallyArchiveAndMuteNonContacts: automaticallyArchiveAndMuteNonContacts,
keepArchivedUnmuted: keepArchivedUnmuted,
keepArchivedFolders: keepArchivedFolders
keepArchivedFolders: keepArchivedFolders,
hideReadTime: hideReadTime,
nonContactChatsRequirePremium: nonContactChatsRequirePremium
)
}
@ -237,6 +246,17 @@ func _internal_updateAccountAutoArchiveChats(account: Account, value: Bool) -> S
}
}
func _internal_updateNonContactChatsRequirePremium(account: Account, value: Bool) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> GlobalPrivacySettings in
return fetchGlobalPrivacySettings(transaction: transaction)
}
|> mapToSignal { settings -> Signal<Never, NoError> in
var settings = settings
settings.nonContactChatsRequirePremium = value
return _internal_updateGlobalPrivacySettings(account: account, settings: settings)
}
}
func _internal_updateAccountKeepArchivedFolders(account: Account, value: Bool) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> GlobalPrivacySettings in
return fetchGlobalPrivacySettings(transaction: transaction)
@ -276,6 +296,13 @@ func _internal_updateGlobalPrivacySettings(account: Account, settings: GlobalPri
if settings.keepArchivedFolders {
flags |= 1 << 2
}
if settings.hideReadTime {
flags |= 1 << 3
}
if settings.nonContactChatsRequirePremium {
flags |= 1 << 4
}
return account.network.request(Api.functions.account.setGlobalPrivacySettings(
settings: .globalPrivacySettings(flags: flags)
))

View file

@ -110,23 +110,33 @@ public extension TelegramEngine {
}
public func savedMessageTags() -> Signal<([SavedMessageTags.Tag], [Int64: TelegramMediaFile]), NoError> {
return self.account.postbox.transaction { transaction -> ([SavedMessageTags.Tag], [Int64: TelegramMediaFile]) in
guard let savedMessageTags = _internal_savedMessageTags(transaction: transaction) else {
return ([], [:])
return self.account.postbox.combinedView(keys: [PostboxViewKey.cachedItem(_internal_savedMessageTagsCacheKey())])
|> mapToSignal { views -> Signal<([SavedMessageTags.Tag], [Int64: TelegramMediaFile]), NoError> in
guard let views = views.views[PostboxViewKey.cachedItem(_internal_savedMessageTagsCacheKey())] as? CachedItemView else {
return .single(([], [:]))
}
var files: [Int64: TelegramMediaFile] = [:]
for tag in savedMessageTags.tags {
if case let .custom(fileId) = tag.reaction {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
files[fileId] = file
guard let savedMessageTags = views.value?.get(SavedMessageTags.self) else {
return .single(([], [:]))
}
return self.account.postbox.transaction { transaction -> ([SavedMessageTags.Tag], [Int64: TelegramMediaFile]) in
var files: [Int64: TelegramMediaFile] = [:]
for tag in savedMessageTags.tags {
if case let .custom(fileId) = tag.reaction {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
files[fileId] = file
}
}
}
return (savedMessageTags.tags, files)
}
return (savedMessageTags.tags, files)
}
}
public func refreshSavedMessageTags() -> Signal<Never, NoError> {
return managedSynchronizeSavedMessageTags(postbox: self.account.postbox, network: self.account.network)
}
public func emojiSearchCategories(kind: EmojiSearchCategories.Kind) -> Signal<EmojiSearchCategories?, NoError> {
return _internal_cachedEmojiSearchCategories(postbox: self.account.postbox, kind: kind)
}

View file

@ -234,7 +234,7 @@ func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer], associ
let second = UInt32(hashValue & 0xffffffff)
let stableId = first &+ second
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
}
func locallyRenderedMessage(message: StoreMessage, peers: AccumulatedPeers, associatedThreadInfo: Message.AssociatedThreadInfo? = nil) -> Message? {
@ -290,7 +290,7 @@ func locallyRenderedMessage(message: StoreMessage, peers: AccumulatedPeers, asso
let second = UInt32(hashValue & 0xffffffff)
let stableId = first &+ second
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, customTags: message.customTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
}
public extension Message {

View file

@ -804,7 +804,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
animationFileId: animationFileId
),
count: Int(reaction.count),
peers: peers,
peers: arguments.areReactionsTags ? [] : peers,
chosenOrder: reaction.chosenOrder
)
},

View file

@ -133,7 +133,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
peers[peer.id] = peer
let action = TelegramMediaActionType.titleUpdated(title: new)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeAbout(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -164,14 +164,14 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
let peers = SimpleDictionary<PeerId, Peer>()
let attributes: [MessageAttribute] = []
let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousDescription(prevMessage) : nil)
}
case let .changeUsername(prev, new):
@ -202,7 +202,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var previousAttributes: [MessageAttribute] = []
@ -220,8 +220,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)]))
}
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil)
}
case let .changeUsernames(prev, new):
@ -252,7 +252,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var previousAttributes: [MessageAttribute] = []
@ -289,8 +289,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)]))
}
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil)
}
case let .changePhoto(_, new):
@ -309,7 +309,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.photoUpdated(image: photo)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleInvites(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -336,7 +336,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleSignatures(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -363,7 +363,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updatePinned(message):
switch self.id.contentIndex {
@ -394,7 +394,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
if let message = message {
@ -412,7 +412,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
} else {
var peers = SimpleDictionary<PeerId, Peer>()
@ -434,7 +434,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
}
@ -479,7 +479,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -496,7 +496,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.text.isEmpty || !message.text.isEmpty ? .eventLogPreviousMessage(filterOriginalMessageFlags(prev)) : nil)
}
case let .deleteMessage(message):
@ -522,7 +522,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -549,7 +549,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let peer = self.entry.peers[self.entry.event.peerId] {
peers[peer.id] = peer
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: message.id.id), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: message.id.id), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case .participantJoin, .participantLeave:
@ -567,7 +567,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
} else {
action = TelegramMediaActionType.removedMembers(peerIds: [self.entry.event.peerId])
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantInvite(participant):
var peers = SimpleDictionary<PeerId, Peer>()
@ -584,7 +584,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action: TelegramMediaActionType
action = TelegramMediaActionType.addedMembers(peerIds: [participant.peer.id])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantToggleBan(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -715,7 +715,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantToggleAdmin(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -952,7 +952,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeStickerPack(_, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -981,7 +981,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .togglePreHistoryHidden(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1011,7 +1011,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updateDefaultBannedRights(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1070,7 +1070,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .pollStopped(message):
switch self.id.contentIndex {
@ -1098,7 +1098,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1115,7 +1115,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: nil)
}
case let .linkedPeerUpdated(previous, updated):
@ -1171,7 +1171,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeGeoLocation(_, updated):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1193,12 +1193,12 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let mediaMap = TelegramMediaMap(latitude: updated.latitude, longitude: updated.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
} else {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case let .updateSlowmode(_, newValue):
@ -1229,7 +1229,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .startGroupCall, .endGroupCall:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1266,7 +1266,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .groupCallUpdateParticipantMuteStatus(participantId, isMuted):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1300,7 +1300,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updateGroupCallSettings(joinMuted):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1329,7 +1329,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .groupCallUpdateParticipantVolume(participantId, volume):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1360,7 +1360,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .deleteExportedInvitation(invite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1386,7 +1386,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .revokeExportedInvitation(invite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1412,7 +1412,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .editExportedInvitation(_, updatedInvite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1438,7 +1438,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantJoinedViaInvite(invite, joinedViaFolderLink):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1469,7 +1469,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeHistoryTTL(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1500,7 +1500,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeAvailableReactions(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1571,7 +1571,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeTheme(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1602,7 +1602,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantJoinByRequest(invite, approvedBy):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1642,7 +1642,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleCopyProtection(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1669,7 +1669,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .sendMessage(message):
switch self.id.contentIndex {
@ -1694,7 +1694,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1711,7 +1711,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case let .createTopic(info):
@ -1731,7 +1731,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
return []
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .deleteTopic(info):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1752,7 +1752,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .editTopic(prevInfo, newInfo):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1825,7 +1825,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .pinTopic(prevInfo, newInfo):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1863,7 +1863,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleForum(isForum):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1884,7 +1884,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleAntiSpam(isEnabled):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1905,7 +1905,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeNameColor(_, _, updatedColor, updatedIcon):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1974,7 +1974,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: TelegramMediaActionType.CustomTextAttributes(attributes: additionalAttributes))
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeProfileColor(_, _, updatedColor, updatedIcon):
var peers = SimpleDictionary<PeerId, Peer>()
@ -2053,7 +2053,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: TelegramMediaActionType.CustomTextAttributes(attributes: additionalAttributes))
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeStatus(_, status):
var peers = SimpleDictionary<PeerId, Peer>()
@ -2088,7 +2088,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeWallpaper(_, wallpaper):
var peers = SimpleDictionary<PeerId, Peer>()
@ -2116,7 +2116,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
}

View file

@ -1999,7 +1999,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
}
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in
}, baseNavigationController: nil)

View file

@ -23,15 +23,18 @@ public enum PeerInfoPaneKey: Int32 {
public struct PeerInfoStatusData: Equatable {
public var text: String
public var isActivity: Bool
public var isHiddenStatus: Bool
public var key: PeerInfoPaneKey?
public init(
text: String,
isActivity: Bool,
isHiddenStatus: Bool = false,
key: PeerInfoPaneKey?
) {
self.text = text
self.isActivity = isActivity
self.isHiddenStatus = isHiddenStatus
self.key = key
}
}

View file

@ -727,7 +727,11 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
if let presence = manager.currentValue {
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
let (text, isActivity) = stringAndActivityForUserPresence(strings: strings, dateTimeFormat: dateTimeFormat, presence: EnginePeer.Presence(presence), relativeTo: Int32(timestamp), expanded: true)
return PeerInfoStatusData(text: text, isActivity: isActivity, key: nil)
var isHiddenStatus = false
if case .hidden = presence.status {
isHiddenStatus = true
}
return PeerInfoStatusData(text: text, isActivity: isActivity, isHiddenStatus: isHiddenStatus, key: nil)
} else {
return nil
}

View file

@ -125,6 +125,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var subtitleBackgroundNode: ASDisplayNode?
var subtitleBackgroundButton: HighlightTrackingButtonNode?
var subtitleArrowNode: ASImageNode?
var subtitleBadgeView: PeerInfoSubtitleBadgeView?
let panelSubtitleNode: MultiScaleTextNode
let usernameNodeContainer: ASDisplayNode
let usernameNodeRawContainer: ASDisplayNode
@ -153,6 +154,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var displayEmojiPackTooltip: (() -> Void)?
var displayPremiumIntro: ((UIView, PeerEmojiStatus?, Signal<(TelegramMediaFile, LoadedStickerPack)?, NoError>, Bool) -> Void)?
var displayStatusPremiumIntro: (() -> Void)?
var navigateToForum: (() -> Void)?
@ -1209,9 +1211,30 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let titleSize = titleNodeLayout[TitleNodeStateRegular]!.size
let titleExpandedSize = titleNodeLayout[TitleNodeStateExpanded]!.size
let subtitleSize = subtitleNodeLayout[TitleNodeStateRegular]!.size
var subtitleBadgeSize: CGSize?
let _ = panelSubtitleNodeLayout[TitleNodeStateRegular]!.size
let usernameSize = usernameNodeLayout[TitleNodeStateRegular]!.size
if let statusData, statusData.isHiddenStatus {
let subtitleBadgeView: PeerInfoSubtitleBadgeView
if let current = self.subtitleBadgeView {
subtitleBadgeView = current
} else {
subtitleBadgeView = PeerInfoSubtitleBadgeView(action: { [weak self] in
guard let self else {
return
}
self.displayStatusPremiumIntro?()
})
self.subtitleBadgeView = subtitleBadgeView
self.subtitleNodeContainer.view.addSubview(subtitleBadgeView)
}
subtitleBadgeSize = subtitleBadgeView.update(fillColor: contentButtonBackgroundColor, foregroundColor: contentButtonForegroundColor)
} else if let subtitleBadgeView = self.subtitleBadgeView {
subtitleBadgeView.removeFromSuperview()
}
var titleHorizontalOffset: CGFloat = 0.0
var nextIconX: CGFloat = titleSize.width
var nextExpandedIconX: CGFloat = titleExpandedSize.width
@ -1272,9 +1295,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} else {
titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 9.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize)
let totalSubtitleWidth = subtitleSize.width + usernameSpacing + usernameSize.width
var effectiveSubtitleWidth = subtitleSize.width
if let subtitleBadgeSize {
effectiveSubtitleWidth += subtitleBadgeSize.width + 7.0
}
let totalSubtitleWidth = effectiveSubtitleWidth + usernameSpacing + usernameSize.width
if usernameSize.width == 0.0 {
subtitleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize)
subtitleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - effectiveSubtitleWidth) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize)
usernameFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - usernameSize.width) / 2.0), y: subtitleFrame.maxY + 1.0), size: usernameSize)
} else {
subtitleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - totalSubtitleWidth) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize)
@ -1703,6 +1731,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
}
if let subtitleBadgeView = self.subtitleBadgeView, let subtitleBadgeSize {
let subtitleBadgeFrame = CGRect(origin: CGPoint(x: (subtitleSize.width + 7.0) * 0.5, y: floor((-subtitleBadgeSize.height) * 0.5)), size: subtitleBadgeSize)
transition.updateFrameAdditive(view: subtitleBadgeView, frame: subtitleBadgeFrame)
transition.updateAlpha(layer: subtitleBadgeView.layer, alpha: 1.0 - transitionFraction)
}
let buttonsTransitionDistance: CGFloat = -min(0.0, apparentBackgroundHeight - backgroundHeight)
let buttonsTransitionDistanceNorm: CGFloat = 40.0
@ -2044,6 +2078,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
}
if let subtitleBadgeView = self.subtitleBadgeView, let result = subtitleBadgeView.hitTest(self.view.convert(point, to: subtitleBadgeView), with: event) {
return result
}
if result.isDescendant(of: self.navigationButtonContainer.view) {
return result
}

View file

@ -3934,6 +3934,21 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
})
}
self.headerNode.displayStatusPremiumIntro = { [weak self] in
guard let self else {
return
}
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumDemoScreen(context: context, subject: .emojiStatus, action: {
let controller = PremiumIntroScreen(context: context, source: .settings)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
self.controller?.push(controller)
}
self.headerNode.displayAvatarContextMenu = { [weak self] node, gesture in
guard let strongSelf = self, let peer = strongSelf.data?.peer else {
return
@ -7451,7 +7466,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, openPeer: { _ in
}, showAll: false)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let controller = LocationViewController(context: context, updatedPresentationData: self.controller?.updatedPresentationData, subject: EngineMessage(message), params: controllerParams)
self.controller?.push(controller)

View file

@ -0,0 +1,91 @@
import Foundation
import UIKit
import AsyncDisplayKit
import ContextUI
import AnimationUI
import Display
import TelegramPresentationData
import ComponentFlow
final class PeerInfoSubtitleBadgeView: HighlightTrackingButton {
private let action: () -> Void
private let backgroundView: BlurredBackgroundView
private let labelView = ComponentView<Empty>()
init(action: @escaping () -> Void) {
self.action = action
self.backgroundView = BlurredBackgroundView(color: nil, enableBlur: true)
self.backgroundView.isUserInteractionEnabled = false
super.init(frame: CGRect())
self.addSubview(self.backgroundView)
self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
self.highligthedChanged = { [weak self] highlighted in
if let self, self.bounds.width > 0.0 {
let topScale: CGFloat = (self.bounds.width - 8.0) / self.bounds.width
let maxScale: CGFloat = (self.bounds.width + 2.0) / self.bounds.width
if highlighted {
self.layer.removeAnimation(forKey: "opacity")
self.layer.removeAnimation(forKey: "sublayerTransform")
self.alpha = 0.7
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)
transition.updateTransformScale(layer: self.layer, scale: topScale)
} else {
self.alpha = 1.0
self.layer.animateAlpha(from: 0.7, to: 1.0, duration: 0.2)
let transition: ContainedViewLayoutTransition = .immediate
transition.updateTransformScale(layer: self.layer, scale: 1.0)
self.layer.animateScale(from: topScale, to: maxScale, duration: 0.13, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in
guard let self else {
return
}
self.layer.animateScale(from: maxScale, to: 1.0, duration: 0.1, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue)
})
}
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func pressed() {
self.action()
}
func update(fillColor: UIColor, foregroundColor: UIColor) -> CGSize {
//TODO:localize
let labelSize = self.labelView.update(
transition: .immediate,
component: AnyComponent(Text(text: "show", font: Font.regular(11.0), color: foregroundColor)),
environment: {},
containerSize: CGSize(width: 100.0, height: 100.0)
)
let size = CGSize(width: labelSize.width + 7.0 * 2.0, height: labelSize.height + 4.0 * 2.0)
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
self.backgroundView.updateColor(color: fillColor, transition: .immediate)
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, transition: .immediate)
if let labelComponentView = self.labelView.view {
if labelComponentView.superview == nil {
labelComponentView.isUserInteractionEnabled = false
self.addSubview(labelComponentView)
}
labelComponentView.frame = CGRect(origin: CGPoint(x: floor((size.width - labelSize.width) * 0.5), y: floor((size.height - labelSize.height) * 0.5)), size: labelSize)
}
return size
}
}

View file

@ -719,6 +719,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: nil,
text: "",
@ -2129,6 +2130,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: nil,
text: "",

View file

@ -227,7 +227,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode {
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
if let (_, text) = messageItem.reply {
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[authorPeerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
}
var media: [Media] = []
@ -235,7 +235,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode {
media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))))
}
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
}

View file

@ -292,7 +292,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode {
attributes.append(ReactionsMessageAttribute(canViewList: false, isTags: false, reactions: [MessageReaction(value: reaction, count: 1, chosenOrder: 0)], recentPeers: recentPeers))
}
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, accountPeer: item.accountPeer, isCentered: true, isPreview: true)
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, accountPeer: item.accountPeer, isCentered: true, isPreview: true)
var node: ListViewItemNode?
if let current = currentNode {

View file

@ -904,6 +904,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: author,
text: text,
@ -1045,20 +1046,20 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
var sampleMessages: [Message] = []
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message1)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message2)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message3)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message4.id] = message4
sampleMessages.append(message4)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message5.id] = message5
sampleMessages.append(message5)
@ -1066,13 +1067,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message6)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message7)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message8)
items = sampleMessages.reversed().map { message in

View file

@ -1523,7 +1523,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
messageAuthor = peer._asPeer()
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messageAttributes = [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)]
}
@ -1621,19 +1621,19 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let theme = self.presentationData.theme
if !bottomMessageText.isEmpty {
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
}
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: messageAttributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: messageAttributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
if let serviceMessageText {
let attributedText = convertMarkdownToAttributes(NSAttributedString(string: serviceMessageText))
let entities = generateChatInputTextEntities(attributedText)
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities, additionalAttributes: nil))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities, additionalAttributes: nil))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true))
}

View file

@ -4376,6 +4376,7 @@ public final class StoryItemSetContainerComponent: Component {
selectedItems: component.slice.item.storyItem.myReaction.flatMap { Set([$0]) } ?? Set(),
title: self.displayLikeReactions ? nil : component.strings.Story_SendReactionAsMessage,
alwaysAllowPremiumReactions: false,
allPresetReactionsAreAvailable: false,
getEmojiContent: { [weak self] animationCache, animationRenderer in
guard let self, let component = self.component else {
preconditionFailure()

View file

@ -3295,7 +3295,7 @@ final class StoryItemSetContainerSendMessage {
switch mediaArea {
case let .venue(_, venue):
let action = { [weak controller, weak view] in
let subject = EngineMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: PeerId(0), namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [.geo(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue.venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))], peers: [:], associatedMessages: [:], associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let subject = EngineMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: PeerId(0), namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [.geo(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue.venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))], peers: [:], associatedMessages: [:], associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let locationController = LocationViewController(
context: context,
updatedPresentationData: updatedPresentationData,

View file

@ -113,6 +113,7 @@ extension ChatControllerImpl {
if message.areReactionsTags(accountPeerId: self.context.account.peerId) {
//TODO:localize
actions.reactionsTitle = "Tag the message with an emoji for quick access later"
actions.allPresetReactionsAreAvailable = true
}
actions.selectedReactionItems = selectedReactions.reactions
@ -344,29 +345,23 @@ extension ChatControllerImpl {
isFirst = !currentReactions.contains(where: { $0.value == chosenReaction })
}
/*guard let allowedReactions = allowedReactions else {
itemNode.openMessageContextMenu()
return
}
switch allowedReactions {
case let .set(set):
if !messageAlreadyHasThisReaction && updatedReactions.contains(where: { !set.contains($0) }) {
itemNode.openMessageContextMenu()
return
}
case .all:
break
}*/
if removedReaction == nil, case .custom = chosenReaction {
if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
} else {
if message.areReactionsTags(accountPeerId: self.context.account.peerId) {
if removedReaction == nil, !topReactions.contains(where: { $0.reaction.rawValue == chosenReaction }) {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
} else {
if removedReaction == nil, case .custom = chosenReaction {
if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
} else {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
}
}
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in

View file

@ -5758,8 +5758,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return .single((message, nil, 0))
}
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: peerId, threadId: replyThreadId)
let countViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: replyThreadId, namespace: Namespaces.Message.Cloud)
let localCountViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: replyThreadId, namespace: Namespaces.Message.Local)
let countViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: replyThreadId, namespace: Namespaces.Message.Cloud, customTag: nil)
let localCountViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: replyThreadId, namespace: Namespaces.Message.Local, customTag: nil)
return context.account.postbox.combinedView(keys: [viewKey, countViewKey, localCountViewKey])
|> map { views -> (message: Message?, threadData: MessageHistoryThreadData?, messageCount: Int) in
guard let view = views.views[viewKey] as? MessageHistoryThreadInfoView else {
@ -5791,7 +5791,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let savedMessagesPeerId {
let threadPeerId = savedMessagesPeerId
let basicPeerKey: PostboxViewKey = .basicPeer(threadPeerId)
let countViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: savedMessagesPeerId.toInt64(), namespace: Namespaces.Message.Cloud)
let countViewKey: PostboxViewKey = .historyTagSummaryView(tag: MessageTags(), peerId: peerId, threadId: savedMessagesPeerId.toInt64(), namespace: Namespaces.Message.Cloud, customTag: nil)
savedMessagesPeer = context.account.postbox.combinedView(keys: [basicPeerKey, countViewKey])
|> map { views -> (peer: EnginePeer?, messageCount: Int)? in
let peer = ((views.views[basicPeerKey] as? BasicPeerView)?.peer).flatMap(EnginePeer.init)
@ -11409,6 +11409,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if self.keepMessageCountersSyncrhonizedDisposable == nil {
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.peerId, threadId: message.threadId).startStrict()
}
} else if case .peer(self.context.account.peerId) = self.chatLocation {
if self.keepMessageCountersSyncrhonizedDisposable == nil {
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: self.context.account.peerId).startStrict()
}
}
if let scheduledActivateInput = scheduledActivateInput, case .text = scheduledActivateInput {

View file

@ -561,6 +561,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: accountPeer,
text: options.messageText,

View file

@ -72,6 +72,7 @@ func chatHistoryEntriesForView(
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: channelPeer,
text: "",
@ -98,6 +99,7 @@ func chatHistoryEntriesForView(
tags: [],
globalTags: [],
localTags: [],
customTags: [],
forwardInfo: nil,
author: channelPeer,
text: "",
@ -428,6 +430,7 @@ func chatHistoryEntriesForView(
tags: message.tags,
globalTags: message.globalTags,
localTags: message.localTags,
customTags: message.customTags,
forwardInfo: message.forwardInfo,
author: message.author,
text: /*"\(message.adAttribute!.opaqueId.hashValue)" + */message.text,

View file

@ -2144,6 +2144,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
tags: initialMessage.tags,
globalTags: initialMessage.globalTags,
localTags: initialMessage.localTags,
customTags: initialMessage.customTags,
forwardInfo: initialMessage.forwardInfo,
author: initialMessage.author,
text: /*"\(initialMessage.adAttribute!.opaqueId.hashValue)" + */initialMessage.text,

View file

@ -215,8 +215,15 @@ private func canViewReadStats(message: Message, participantCount: Int?, isMessag
if let value = data["chat_read_mark_size_threshold"] as? Double {
maxParticipantCount = Int(value)
}
if let value = data["chat_read_mark_expire_period"] as? Double {
maxTimeout = Int(value)
switch peer {
case _ as TelegramUser:
if let value = data["pm_read_date_expire_period"] as? Double {
maxTimeout = Int(value)
}
default:
if let value = data["chat_read_mark_expire_period"] as? Double {
maxTimeout = Int(value)
}
}
}
@ -237,6 +244,8 @@ private func canViewReadStats(message: Message, participantCount: Int?, isMessag
if group.participantCount > maxParticipantCount {
return false
}
case _ as TelegramUser:
break
default:
return false
}
@ -1712,6 +1721,11 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
if canViewStats {
hasReadReports = true
}
} else if let _ = peer as? TelegramUser {
reactionCount = 0
if canViewStats {
hasReadReports = true
}
} else {
reactionCount = 0
}
@ -1727,7 +1741,21 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}
actions.insert(.custom(ChatReadReportContextItem(context: context, message: message, hasReadReports: hasReadReports, stats: readStats, action: { c, f, stats, customReactionEmojiPacks, firstCustomEmojiReaction in
if reactionCount == 0, let stats = stats, stats.peers.count == 1, !"".isEmpty {
if message.id.peerId.namespace == Namespaces.Peer.CloudUser {
if let stats, stats.peers.isEmpty {
c.dismiss(completion: {
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumDemoScreen(context: context, subject: .emojiStatus, action: {
let controller = PremiumIntroScreen(context: context, source: .settings)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
controllerInteraction.navigationController()?.pushViewController(controller)
})
}
} else if reactionCount == 0, let stats = stats, stats.peers.count == 1, !"".isEmpty {
c.dismiss(completion: {
controllerInteraction.openPeer(stats.peers[0], .default, nil, .default)
})
@ -2517,7 +2545,11 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
}
if let currentStats = self.currentStats {
self.buttonNode.isUserInteractionEnabled = !currentStats.peers.isEmpty || reactionCount != 0
if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
self.buttonNode.isUserInteractionEnabled = currentStats.peers.isEmpty
} else {
self.buttonNode.isUserInteractionEnabled = !currentStats.peers.isEmpty || reactionCount != 0
}
} else {
self.buttonNode.isUserInteractionEnabled = reactionCount != 0
@ -2557,7 +2589,11 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
private var validLayout: (calculatedWidth: CGFloat, size: CGSize)?
func updateStats(stats: MessageReadStats, transition: ContainedViewLayoutTransition) {
self.buttonNode.isUserInteractionEnabled = !stats.peers.isEmpty || stats.reactionCount != 0
if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
self.buttonNode.isUserInteractionEnabled = stats.peers.isEmpty
} else {
self.buttonNode.isUserInteractionEnabled = !stats.peers.isEmpty || stats.reactionCount != 0
}
guard let (calculatedWidth, size) = self.validLayout else {
return
@ -2590,31 +2626,47 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
reactionCount = currentStats.reactionCount
if currentStats.peers.isEmpty {
if reactionCount != 0 {
let text: String = self.presentationData.strings.Chat_ContextReactionCount(Int32(reactionCount))
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
//TODO:localize
self.textNode.attributedText = NSAttributedString(string: "Show Read Time", font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
var text = self.presentationData.strings.Conversation_ContextMenuNoViews
for media in self.item.message.media {
if let file = media as? TelegramMediaFile {
if file.isVoice {
text = self.presentationData.strings.Conversation_ContextMenuNobodyListened
} else if file.isInstantVideo {
text = self.presentationData.strings.Conversation_ContextMenuNobodyWatched
if reactionCount != 0 {
let text: String = self.presentationData.strings.Chat_ContextReactionCount(Int32(reactionCount))
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
var text = self.presentationData.strings.Conversation_ContextMenuNoViews
for media in self.item.message.media {
if let file = media as? TelegramMediaFile {
if file.isVoice {
text = self.presentationData.strings.Conversation_ContextMenuNobodyListened
} else if file.isInstantVideo {
text = self.presentationData.strings.Conversation_ContextMenuNobodyWatched
}
}
}
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.secondaryColor)
}
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.secondaryColor)
}
}/* else if currentStats.peers.count == 1 {
if reactionCount != 0 {
let text: String = self.presentationData.strings.Chat_OutgoingContextReactionCount(Int32(reactionCount))
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
self.textNode.attributedText = NSAttributedString(string: currentStats.peers[0].displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
}
}*/ else {
} else if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser, let timestamp = currentStats.readTimestamps.first?.value {
let dateText = humanReadableStringForTimestamp(strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, timestamp: timestamp, alwaysShowTime: true, allowYesterday: true, format: HumanReadableStringFormat(
dateFormatString: { value in
return PresentationStrings.FormattedString(string: self.presentationData.strings.Chat_MessageSeenTimestamp_Date(value).string, ranges: [])
},
tomorrowFormatString: { value in
return PresentationStrings.FormattedString(string: self.presentationData.strings.Chat_MessageSeenTimestamp_TodayAt(value).string, ranges: [])
},
todayFormatString: { value in
return PresentationStrings.FormattedString(string: self.presentationData.strings.Chat_MessageSeenTimestamp_TodayAt(value).string, ranges: [])
},
yesterdayFormatString: { value in
return PresentationStrings.FormattedString(string: self.presentationData.strings.Chat_MessageSeenTimestamp_YesterdayAt(value).string, ranges: [])
}
)).string
//TODO:localize
self.textNode.attributedText = NSAttributedString(string: "read \(dateText)", font: Font.regular(floor(self.presentationData.listsFontSize.baseDisplaySize * 0.8)), textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
if reactionCount != 0 {
let text: String
if reactionCount >= currentStats.peers.count {
@ -2683,7 +2735,8 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
let placeholderAvatarsContent: AnimatedAvatarSetContext.Content
var avatarsPeers: [EnginePeer] = []
if let recentPeers = self.item.message.reactionsAttribute?.recentPeers, !recentPeers.isEmpty {
if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
} else if let recentPeers = self.item.message.reactionsAttribute?.recentPeers, !recentPeers.isEmpty {
for recentPeer in recentPeers {
if let peer = self.item.message.peers[recentPeer.peerId] {
if !avatarsPeers.contains(where: { $0.id == peer.id }) {
@ -2702,7 +2755,12 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
}
}
avatarsContent = self.avatarsContext.update(peers: avatarsPeers, animated: false)
placeholderAvatarsContent = self.avatarsContext.updatePlaceholder(color: shimmeringForegroundColor, count: 3, animated: false)
if self.item.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
placeholderAvatarsContent = self.avatarsContext.updatePlaceholder(color: shimmeringForegroundColor, count: 0, animated: false)
} else {
placeholderAvatarsContent = self.avatarsContext.updatePlaceholder(color: shimmeringForegroundColor, count: 3, animated: false)
}
let avatarsSize = self.avatarsNode.update(context: self.item.context, content: avatarsContent, itemSize: CGSize(width: 24.0, height: 24.0), customSpacing: 10.0, animated: false, synchronousLoad: true)
self.avatarsNode.frame = CGRect(origin: CGPoint(x: size.width - sideInset - 12.0 - avatarsSize.width, y: floor((size.height - avatarsSize.height) / 2.0)), size: avatarsSize)

View file

@ -125,7 +125,7 @@ final class ChatSearchNavigationContentNode: NavigationBarContentNode {
let placeholderText = "Search"
self.searchBar.placeholderString = NSAttributedString(string: placeholderText, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
//TODO:localize
self.searchBar.tokens = [SearchBarToken(id: AnyHashable(tag), context: self.context, icon: nil, isTag: true, emojiFile: file, title: "Tag", permanent: false)]
self.searchBar.tokens = [SearchBarToken(id: AnyHashable(tag), context: self.context, icon: nil, isTag: true, reaction: tag, emojiFile: file, title: "Tag", permanent: false)]
case .members:
self.searchBar.tokens = []
self.searchBar.prefixString = NSAttributedString(string: strings.Conversation_SearchByName_Prefix, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputTextColor)

View file

@ -56,72 +56,129 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
}
}
private final class ItemView: UIView {
private final class ItemView: HighlightTrackingButton {
private let context: AccountContext
private let item: Item
private let action: () -> Void
private let view = ComponentView<Empty>()
private let icon = ComponentView<Empty>()
private let counter = ComponentView<Empty>()
init(context: AccountContext, item: Item, action: @escaping (() -> Void)) {
init(context: AccountContext, action: @escaping (() -> Void)) {
self.context = context
self.item = item
self.action = action
super.init(frame: CGRect())
self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
self.highligthedChanged = { [weak self] highlighted in
if let self, self.bounds.width > 0.0 {
let topScale: CGFloat = (self.bounds.width - 8.0) / self.bounds.width
let maxScale: CGFloat = (self.bounds.width + 2.0) / self.bounds.width
if highlighted {
self.layer.removeAnimation(forKey: "opacity")
self.layer.removeAnimation(forKey: "sublayerTransform")
self.alpha = 0.7
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)
transition.updateTransformScale(layer: self.layer, scale: topScale)
} else {
self.alpha = 1.0
self.layer.animateAlpha(from: 0.7, to: 1.0, duration: 0.2)
let transition: ContainedViewLayoutTransition = .immediate
transition.updateTransformScale(layer: self.layer, scale: 1.0)
self.layer.animateScale(from: topScale, to: maxScale, duration: 0.13, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in
guard let self else {
return
}
self.layer.animateScale(from: maxScale, to: 1.0, duration: 0.1, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue)
})
}
}
}
}
required init?(coder: NSCoder) {
preconditionFailure()
}
func update(theme: PresentationTheme, height: CGFloat, transition: Transition) -> CGSize {
let viewSize = self.view.update(
transition: transition,
component: AnyComponent(PlainButtonComponent(
content: AnyComponent(HStack([
AnyComponentWithIdentity(id: 0, component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.context.animationCache,
animationRenderer: self.context.animationRenderer,
content: .animation(
content: .file(file: self.item.file),
size: CGSize(width: 32.0, height: 32.0),
placeholderColor: theme.list.mediaPlaceholderColor,
themeColor: theme.list.itemPrimaryTextColor,
loopMode: .forever
),
size: CGSize(width: 16.0, height: 16.0),
isVisibleForAnimations: false,
useSharedAnimation: true,
action: nil,
emojiFileUpdated: nil
))),
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "\(self.item.count)", font: Font.regular(15.0), textColor: theme.rootController.navigationBar.secondaryTextColor))
)))
], spacing: 4.0)),
effectAlignment: .center,
minSize: CGSize(width: 0.0, height: height),
contentInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0),
action: { [weak self] in
guard let self else {
return
}
self.action()
},
isEnabled: true
@objc private func pressed() {
self.action()
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var mappedPoint = point
if self.bounds.insetBy(dx: -8.0, dy: -4.0).contains(point) {
mappedPoint = self.bounds.center
}
return super.hitTest(mappedPoint, with: event)
}
func update(item: Item, theme: PresentationTheme, height: CGFloat, transition: Transition) -> CGSize {
let spacing: CGFloat = 4.0
let reactionSize = CGSize(width: 16.0, height: 16.0)
var reactionDisplaySize = reactionSize
if case .builtin = item.reaction {
reactionDisplaySize = CGSize(width: reactionDisplaySize.width * 2.0, height: reactionDisplaySize.height * 2.0)
}
let _ = self.icon.update(
transition: .immediate,
component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.context.animationCache,
animationRenderer: self.context.animationRenderer,
content: .animation(
content: .file(file: item.file),
size: reactionDisplaySize,
placeholderColor: theme.list.mediaPlaceholderColor,
themeColor: theme.list.itemPrimaryTextColor,
loopMode: .forever
),
isVisibleForAnimations: false,
useSharedAnimation: true,
action: nil,
emojiFileUpdated: nil
)),
environment: {},
containerSize: CGSize(width: 100.0, height: 32.0)
containerSize: reactionDisplaySize
)
if let componentView = self.view.view {
if componentView.superview == nil {
self.addSubview(componentView)
let counterSize = self.counter.update(
transition: .immediate,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: "\(item.count)", font: Font.regular(14.0), textColor: theme.rootController.navigationBar.secondaryTextColor))
)),
environment: {},
containerSize: CGSize(width: 100.0, height: 100.0)
)
let size = CGSize(width: reactionSize.width + spacing + counterSize.width, height: height)
let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: floor((size.height - reactionSize.height) * 0.5)), size: reactionSize)
let counterFrame = CGRect(origin: CGPoint(x: iconFrame.maxX + spacing, y: floor((size.height - counterSize.height) * 0.5)), size: counterSize)
if let iconView = self.icon.view {
if iconView.superview == nil {
iconView.isUserInteractionEnabled = false
self.addSubview(iconView)
}
transition.setFrame(view: componentView, frame: CGRect(origin: CGPoint(), size: viewSize))
iconView.frame = reactionDisplaySize.centered(around: iconFrame.center)
}
return viewSize
if let counterView = self.counter.view {
if counterView.superview == nil {
counterView.isUserInteractionEnabled = false
self.addSubview(counterView)
}
counterView.frame = counterFrame
}
return size
}
}
@ -171,23 +228,66 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
self.scrollView.disablesInteractiveTransitionGestureRecognizer = true
self.itemsDisposable = (context.engine.stickers.savedMessageTags()
|> deliverOnMainQueue).start(next: { [weak self] tags, files in
let tagsAndFiles: Signal<([MessageReaction.Reaction: Int], [Int64: TelegramMediaFile]), NoError> = context.engine.data.subscribe(
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId)
)
|> distinctUntilChanged
|> mapToSignal { tags -> Signal<([MessageReaction.Reaction: Int], [Int64: TelegramMediaFile]), NoError> in
var customFileIds: [Int64] = []
for (reaction, _) in tags {
switch reaction {
case .builtin:
break
case let .custom(fileId):
customFileIds.append(fileId)
}
}
return context.engine.stickers.resolveInlineStickers(fileIds: customFileIds)
|> map { files in
return (tags, files)
}
}
var isFirstUpdate = true
self.itemsDisposable = (combineLatest(
context.engine.stickers.availableReactions(),
tagsAndFiles
)
|> deliverOnMainQueue).start(next: { [weak self] availableReactions, tagsAndFiles in
guard let self else {
return
}
self.items = tags.compactMap { tag -> Item? in
switch tag.reaction {
self.items.removeAll()
let (tags, files) = tagsAndFiles
for (reaction, count) in tags {
switch reaction {
case .builtin:
return nil
case let .custom(fileId):
guard let file = files[fileId] else {
return nil
if let availableReactions {
inner: for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction {
if let file = availableReaction.centerAnimation {
self.items.append(Item(reaction: reaction, count: count, file: file))
}
break inner
}
}
}
case let .custom(fileId):
if let file = files[fileId] {
self.items.append(Item(reaction: reaction, count: count, file: file))
}
return Item(reaction: tag.reaction, count: tag.count, file: file)
}
}
self.update(transition: .immediate)
self.items.sort(by: { lhs, rhs in
if lhs.count != rhs.count {
return lhs.count > rhs.count
}
return lhs.reaction < rhs.reaction
})
self.update(transition: isFirstUpdate ? .immediate : .animated(duration: 0.3, curve: .easeInOut))
isFirstUpdate = false
})
}
@ -216,8 +316,8 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
private func update(params: Params, transition: ContainedViewLayoutTransition) {
let panelHeight: CGFloat = 33.0
let containerInsets = UIEdgeInsets(top: 0.0, left: params.leftInset + 2.0, bottom: 0.0, right: params.rightInset + 2.0)
let itemSpacing: CGFloat = 2.0
let containerInsets = UIEdgeInsets(top: 0.0, left: params.leftInset + 14.0, bottom: 0.0, right: params.rightInset + 14.0)
let itemSpacing: CGFloat = 20.0
var contentSize = CGSize(width: 0.0, height: panelHeight)
contentSize.width += containerInsets.left
@ -233,11 +333,15 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
let itemId = item.reaction
validIds.append(itemId)
var itemTransition = transition
var animateIn = false
let itemView: ItemView
if let current = self.itemViews[itemId] {
itemView = current
} else {
itemView = ItemView(context: self.context, item: item, action: { [weak self] in
itemTransition = .immediate
animateIn = true
itemView = ItemView(context: self.context, action: { [weak self] in
guard let self else {
return
}
@ -247,15 +351,32 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
self.scrollView.addSubview(itemView)
}
let itemSize = itemView.update(theme: params.interfaceState.theme, height: panelHeight, transition: .immediate)
itemView.frame = CGRect(origin: CGPoint(x: contentSize.width, y: 0.0), size: itemSize)
let itemSize = itemView.update(item: item, theme: params.interfaceState.theme, height: panelHeight, transition: .immediate)
let itemFrame = CGRect(origin: CGPoint(x: contentSize.width, y: 0.0), size: itemSize)
itemTransition.updatePosition(layer: itemView.layer, position: itemFrame.center)
if animateIn && transition.isAnimated {
itemView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
transition.animateTransformScale(view: itemView, from: 0.001)
}
itemView.bounds = CGRect(origin: CGPoint(), size: itemFrame.size)
contentSize.width += itemSize.width
}
var removedIds: [MessageReaction.Reaction] = []
for (id, itemView) in self.itemViews {
if !validIds.contains(id) {
removedIds.append(id)
itemView.removeFromSuperview()
if transition.isAnimated {
itemView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak itemView] _ in
itemView?.removeFromSuperview()
})
transition.updateTransformScale(layer: itemView.layer, scale: 0.001)
} else {
itemView.removeFromSuperview()
}
}
}
for id in removedIds {