Recent Actions improvements

This commit is contained in:
Ilya Laktyushin
2024-04-17 21:04:14 +04:00
parent 60652f34ee
commit ff09220634
23 changed files with 440 additions and 85 deletions

View File

@@ -11,6 +11,7 @@ import AlertUI
import PresentationDataUtils
import ChatPresentationInterfaceState
import ChatNavigationButton
import CounterControllerTitleView
public final class ChatRecentActionsController: TelegramBaseController {
private var controllerNode: ChatRecentActionsControllerNode {
@@ -28,10 +29,10 @@ public final class ChatRecentActionsController: TelegramBaseController {
private var presentationDataDisposable: Disposable?
private var didSetPresentationData = false
private var interaction: ChatRecentActionsInteraction!
private var panelInteraction: ChatPanelInterfaceInteraction!
private let titleView: ChatRecentActionsTitleView
private let titleView: CounterControllerTitleView
private var rightBarButton: ChatNavigationButton?
public init(context: AccountContext, peer: Peer, adminPeerId: PeerId?) {
self.context = context
@@ -40,7 +41,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.titleView = ChatRecentActionsTitleView(color: self.presentationData.theme.rootController.navigationBar.primaryTextColor)
self.titleView = CounterControllerTitleView(theme: self.presentationData.theme)
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), mediaAccessoryPanelVisibility: .specific(size: .compact), locationBroadcastPanelSource: .none, groupCallPanelSource: .none)
@@ -48,18 +49,6 @@ public final class ChatRecentActionsController: TelegramBaseController {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.interaction = ChatRecentActionsInteraction(displayInfoAlert: { [weak self] in
if let strongSelf = self {
let text: String
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.Channel_AdminLog_InfoPanelChannelAlertText
} else {
text = strongSelf.presentationData.strings.Channel_AdminLog_InfoPanelAlertText
}
self?.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.Channel_AdminLog_InfoPanelAlertTitle, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
})
self.panelInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
}, setupEditMessage: { _, _ in
}, beginMessageSelection: { _, _ in
@@ -181,13 +170,10 @@ public final class ChatRecentActionsController: TelegramBaseController {
self.navigationItem.titleView = self.titleView
let rightButton = ChatNavigationButton(action: .search(hasTags: false), buttonItem: UIBarButtonItem(image: PresentationResourcesRootController.navigationCompactSearchIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.activateSearch)))
self.navigationItem.setRightBarButton(rightButton.buttonItem, animated: false)
let rightBarButton = ChatNavigationButton(action: .search(hasTags: false), buttonItem: UIBarButtonItem(image: PresentationResourcesRootController.navigationCompactSearchIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.activateSearch)))
self.rightBarButton = rightBarButton
self.titleView.title = self.presentationData.strings.Channel_AdminLog_TitleAllEvents
self.titleView.pressed = { [weak self] in
self?.openFilterSetup()
}
self.titleView.title = CounterControllerTitle(title: EnginePeer(peer).compactDisplayTitle, counter: self.presentationData.strings.Channel_AdminLog_TitleAllEvents)
let themeEmoticon = self.context.account.postbox.peerView(id: peer.id)
|> map { view -> String? in
@@ -238,7 +224,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
}
private func updateThemeAndStrings() {
self.titleView.color = self.presentationData.theme.rootController.navigationBar.primaryTextColor
self.titleView.theme = self.presentationData.theme
self.updateTitle()
let rightButton = ChatNavigationButton(action: .search(hasTags: false), buttonItem: UIBarButtonItem(image: PresentationResourcesRootController.navigationCompactSearchIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.activateSearch)))
@@ -251,14 +237,19 @@ public final class ChatRecentActionsController: TelegramBaseController {
}
override public func loadDisplayNode() {
self.displayNode = ChatRecentActionsControllerNode(context: self.context, controller: self, peer: self.peer, presentationData: self.presentationData, interaction: self.interaction, pushController: { [weak self] c in
self.displayNode = ChatRecentActionsControllerNode(context: self.context, controller: self, peer: self.peer, presentationData: self.presentationData, pushController: { [weak self] c in
(self?.navigationController as? NavigationController)?.pushViewController(c)
}, presentController: { [weak self] c, t, a in
self?.present(c, in: t, with: a, blockInteraction: true)
}, getNavigationController: { [weak self] in
return self?.navigationController as? NavigationController
})
self.controllerNode.isEmptyUpdated = { [weak self] isEmpty in
guard let self, let rightBarButton = self.rightBarButton else {
return
}
self.navigationItem.setRightBarButton(isEmpty ? nil : rightBarButton.buttonItem, animated: true)
}
if let adminPeerId = self.initialAdminPeerId {
self.controllerNode.updateFilter(events: .all, adminPeerIds: [adminPeerId])
self.updateTitle()
@@ -300,7 +291,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
self.updateTitle()
}
private func openFilterSetup() {
func openFilterSetup() {
self.present(channelRecentActionsFilterController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: self.peer, events: self.controllerNode.filter.events, adminPeerIds: self.controllerNode.filter.adminPeerIds, apply: { [weak self] events, adminPeerIds in
self?.controllerNode.updateFilter(events: events, adminPeerIds: adminPeerIds)
self?.updateTitle()
@@ -308,10 +299,13 @@ public final class ChatRecentActionsController: TelegramBaseController {
}
private func updateTitle() {
let title = EnginePeer(self.peer).compactDisplayTitle
let subtitle: String
if self.controllerNode.filter.isEmpty {
self.titleView.title = self.presentationData.strings.Channel_AdminLog_TitleAllEvents
subtitle = self.presentationData.strings.Channel_AdminLog_TitleAllEvents
} else {
self.titleView.title = self.presentationData.strings.Channel_AdminLog_TitleSelectedEvents
subtitle = self.presentationData.strings.Channel_AdminLog_TitleSelectedEvents
}
self.titleView.title = CounterControllerTitle(title: title, counter: subtitle)
}
}

View File

@@ -49,8 +49,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
private let pushController: (ViewController) -> Void
private let presentController: (ViewController, PresentationContextType, Any?) -> Void
private let getNavigationController: () -> NavigationController?
var isEmptyUpdated: (Bool) -> Void = { _ in }
private let interaction: ChatRecentActionsInteraction
private var controllerInteraction: ChatControllerInteraction!
private let galleryHiddenMesageAndMediaDisposable = MetaDisposable()
@@ -68,6 +68,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
private let panelBackgroundNode: NavigationBackgroundNode
private let panelSeparatorNode: ASDisplayNode
private let panelButtonNode: HighlightableButtonNode
private let panelInfoButtonNode: HighlightableButtonNode
fileprivate let listNode: ListView
private let loadingNode: ChatLoadingNode
@@ -99,12 +100,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
private weak var controller: ChatRecentActionsController?
init(context: AccountContext, controller: ChatRecentActionsController, peer: Peer, presentationData: PresentationData, interaction: ChatRecentActionsInteraction, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, PresentationContextType, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?) {
init(context: AccountContext, controller: ChatRecentActionsController, peer: Peer, presentationData: PresentationData, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, PresentationContextType, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?) {
self.context = context
self.controller = controller
self.peer = peer
self.presentationData = presentationData
self.interaction = interaction
self.pushController = pushController
self.presentController = presentController
self.getNavigationController = getNavigationController
@@ -118,7 +118,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
self.panelSeparatorNode = ASDisplayNode()
self.panelSeparatorNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelSeparatorColor
self.panelButtonNode = HighlightableButtonNode()
self.panelButtonNode.setTitle(self.presentationData.strings.Channel_AdminLog_InfoPanelTitle, with: Font.regular(17.0), with: self.presentationData.theme.chat.inputPanel.panelControlAccentColor, for: [])
self.panelButtonNode.setTitle(self.presentationData.strings.Channel_AdminLog_Settings, with: Font.regular(17.0), with: self.presentationData.theme.chat.inputPanel.panelControlAccentColor, for: [])
self.panelInfoButtonNode = HighlightableButtonNode()
self.listNode = ListView()
self.listNode.dynamicBounceEnabled = false
@@ -145,8 +146,10 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
self.addSubnode(self.panelBackgroundNode)
self.addSubnode(self.panelSeparatorNode)
self.addSubnode(self.panelButtonNode)
self.addSubnode(self.panelInfoButtonNode)
self.panelButtonNode.addTarget(self, action: #selector(self.infoButtonPressed), forControlEvents: .touchUpInside)
self.panelButtonNode.addTarget(self, action: #selector(self.settingsButtonPressed), forControlEvents: .touchUpInside)
self.panelInfoButtonNode.addTarget(self, action: #selector(self.infoButtonPressed), forControlEvents: .touchUpInside)
let (adminsDisposable, _) = self.context.peerChannelMemberCategoriesContextsManager.admins(engine: self.context.engine, postbox: self.context.account.postbox, network: self.context.account.network, accountPeerId: context.account.peerId, peerId: self.peer.id, searchQuery: nil, updated: { [weak self] state in
self?.adminsState = state
@@ -275,7 +278,10 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, activateMessagePinch: { _ in
}, openMessageContextActions: { _, _, _, _ in
}, navigateToMessage: { _, _, _ in }, navigateToMessageStandalone: { _ in
}, navigateToThreadMessage: { _, _, _ in
}, navigateToThreadMessage: { [weak self] peerId, threadId, _ in
if let context = self?.context, let navigationController = self?.getNavigationController() {
let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .always).startStandalone()
}
}, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _, _ in }, openUrl: { [weak self] url in
self?.openUrl(url.url)
}, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { [weak self] message, associatedData in
@@ -674,7 +680,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
self.panelBackgroundNode.updateColor(color: presentationData.theme.chat.inputPanel.panelBackgroundColor, transition: .immediate)
self.panelSeparatorNode.backgroundColor = presentationData.theme.chat.inputPanel.panelSeparatorColor
self.panelButtonNode.setTitle(presentationData.strings.Channel_AdminLog_InfoPanelTitle, with: Font.regular(17.0), with: presentationData.theme.chat.inputPanel.panelControlAccentColor, for: [])
self.panelButtonNode.setTitle(presentationData.strings.Channel_AdminLog_Settings, with: Font.regular(17.0), with: presentationData.theme.chat.inputPanel.panelControlAccentColor, for: [])
self.panelInfoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Recent Actions/Info"), color: presentationData.theme.chat.inputPanel.panelControlAccentColor), for: .normal)
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
@@ -695,7 +702,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
transition.updateFrame(node: self.panelBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)))
self.panelBackgroundNode.update(size: self.panelBackgroundNode.bounds.size, transition: transition)
transition.updateFrame(node: self.panelSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - panelHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
transition.updateFrame(node: self.panelButtonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - panelHeight), size: CGSize(width: layout.size.width, height: intrinsicPanelHeight)))
let infoButtonSize = CGSize(width: 56.0, height: intrinsicPanelHeight)
transition.updateFrame(node: self.panelButtonNode, frame: CGRect(origin: CGPoint(x: insets.left + infoButtonSize.width, y: layout.size.height - panelHeight), size: CGSize(width: layout.size.width - insets.left - insets.right - infoButtonSize.width * 2.0, height: intrinsicPanelHeight)))
transition.updateFrame(node: self.panelInfoButtonNode, frame: CGRect(origin: CGPoint(x: layout.size.width - insets.right - infoButtonSize.width, y: layout.size.height - panelHeight), size: infoButtonSize))
self.visibleAreaInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: panelHeight, right: 0.0)
@@ -788,6 +799,12 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
strongSelf.listNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
}
strongSelf.isLoading = isLoading
var isEmpty = false
if strongSelf.filter.isEmpty && (transition.isEmpty || isLoading) {
isEmpty = true
}
strongSelf.isEmptyUpdated(isEmpty)
}
})
} else {
@@ -796,8 +813,22 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}
}
@objc func settingsButtonPressed() {
self.controller?.openFilterSetup()
}
@objc func infoButtonPressed() {
self.interaction.displayInfoAlert()
guard let controller = self.controller else {
return
}
let text: String
if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info {
text = self.presentationData.strings.Channel_AdminLog_InfoPanelChannelAlertText
} else {
text = self.presentationData.strings.Channel_AdminLog_InfoPanelAlertText
}
controller.present(textAlertController(context: self.context, updatedPresentationData: controller.updatedPresentationData, title: self.presentationData.strings.Channel_AdminLog_InfoPanelAlertTitle, text: text, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
func updateSearchQuery(_ query: String) {
@@ -936,6 +967,40 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}
}))
)
actions.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Conversation_ContextMenuBanFull, textColor: .destructive, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Ban"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] _, f in
if let strongSelf = self {
f(.default)
strongSelf.banDisposables.set((strongSelf.context.engine.peers.fetchChannelParticipant(peerId: strongSelf.peer.id, participantId: author.id)
|> deliverOnMainQueue).startStrict(next: { participant in
if let strongSelf = self {
let initialUserBannedRights = participant?.banInfo?.rights
strongSelf.banDisposables.set(strongSelf.context.engine.peers.removePeerMember(peerId: strongSelf.peer.id, memberId: author.id).startStandalone(), forKey: author.id)
strongSelf.presentController(UndoOverlayController(
presentationData: strongSelf.presentationData,
content: .actionSucceeded(title: nil, text: "**\(EnginePeer(author).compactDisplayTitle)** was banned.", cancel: strongSelf.presentationData.strings.Undo_Undo, destructive: false),
elevatedLayout: false,
action: { [weak self] action in
guard let self else {
return true
}
switch action {
case .commit:
break
case .undo:
let _ = self.context.engine.peers.updateChannelMemberBannedRights(peerId: self.peer.id, memberId: author.id, rights: initialUserBannedRights).startStandalone()
default:
break
}
return true
}
), .current, nil)
}
}), forKey: author.id)
}
}))
)
}
}

View File

@@ -7,14 +7,15 @@ import TelegramPresentationData
import WallpaperBackgroundNode
import ChatPresentationInterfaceState
private let titleFont = Font.medium(16.0)
private let textFont = Font.regular(15.0)
private let titleFont = Font.semibold(15.0)
private let textFont = Font.regular(13.0)
public final class ChatRecentActionsEmptyNode: ASDisplayNode {
private var theme: PresentationTheme
private var chatWallpaper: TelegramWallpaper
private let backgroundNode: NavigationBackgroundNode
private let iconNode: ASImageNode
private let titleNode: TextNode
private let textNode: TextNode
@@ -34,6 +35,9 @@ public final class ChatRecentActionsEmptyNode: ASDisplayNode {
self.backgroundNode = NavigationBackgroundNode(color: .clear)
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
@@ -45,6 +49,7 @@ public final class ChatRecentActionsEmptyNode: ASDisplayNode {
self.allowsGroupOpacity = true
self.addSubnode(self.backgroundNode)
self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
}
@@ -63,14 +68,15 @@ public final class ChatRecentActionsEmptyNode: ASDisplayNode {
self.wallpaperBackgroundNode = backgroundNode
self.layoutParams = (size, presentationData)
let themeUpdated = self.theme !== presentationData.theme.theme
self.theme = presentationData.theme.theme
self.chatWallpaper = presentationData.theme.wallpaper
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), transition: .immediate)
let insets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
let insets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 25.0, right: 16.0)
let maxTextWidth = size.width - insets.left - insets.right - 18.0 * 2.0
let maxTextWidth = min(196.0, size.width - insets.left - insets.right - 18.0 * 2.0)
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeTextLayout = TextNode.asyncLayout(self.textNode)
@@ -78,17 +84,28 @@ public final class ChatRecentActionsEmptyNode: ASDisplayNode {
let serviceColor = serviceMessageColorComponents(theme: self.theme, wallpaper: self.chatWallpaper)
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: self.title, font: titleFont, textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let spacing: CGFloat = titleLayout.size.height.isZero ? 0.0 : 5.0
let spacing: CGFloat = titleLayout.size.height.isZero ? 0.0 : 7.0
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: self.text, font: textFont, textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let contentSize = CGSize(width: max(titleLayout.size.width, textLayout.size.width) + insets.left + insets.right, height: insets.top + insets.bottom + titleLayout.size.height + spacing + textLayout.size.height)
if themeUpdated || self.iconNode.image == nil {
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Recent Actions/Placeholder"), color: serviceColor.primaryText)
}
let iconSize = self.iconNode.image?.size ?? .zero
let contentSize = CGSize(width: max(titleLayout.size.width, textLayout.size.width) + insets.left + insets.right, height: 5.0 + insets.bottom + iconSize.height - 2.0 + titleLayout.size.height + spacing + textLayout.size.height)
let backgroundFrame = CGRect(origin: CGPoint(x: floor((size.width - contentSize.width) / 2.0), y: floor((size.height - contentSize.height) / 2.0)), size: contentSize)
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(14.0, self.backgroundNode.bounds.height / 2.0), transition: transition)
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((contentSize.width - titleLayout.size.width) / 2.0), y: backgroundFrame.minY + insets.top), size: titleLayout.size))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((contentSize.width - textLayout.size.width) / 2.0), y: backgroundFrame.minY + insets.top + titleLayout.size.height + spacing), size: textLayout.size))
let iconFrame = CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((contentSize.width - iconSize.width) / 2.0), y: backgroundFrame.minY + 5.0), size: iconSize)
transition.updateFrame(node: self.iconNode, frame: iconFrame)
let titleFrame = CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((contentSize.width - titleLayout.size.width) / 2.0), y: iconFrame.maxY - 2.0), size: titleLayout.size)
transition.updateFrame(node: self.titleNode, frame: titleFrame)
let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((contentSize.width - textLayout.size.width) / 2.0), y: titleFrame.maxY + spacing), size: textLayout.size)
transition.updateFrame(node: self.textNode, frame: textFrame)
let _ = titleApply()
let _ = textApply()

View File

@@ -404,6 +404,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let attribute = attribute as? TextEntitiesMessageAttribute {
attributes.append(attribute)
}
if let attribute = attribute as? ReplyMessageAttribute {
attributes.append(attribute)
}
}
for attribute in attributes {
for peerId in attribute.associatedPeerIds {
@@ -412,7 +415,10 @@ 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: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
if let peer = self.entry.peers[message.id.peerId] {
peers[peer.id] = peer
}
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: message.threadId, 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: message.associatedThreadInfo, 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, savedMessageTags: 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>()
@@ -488,6 +494,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let attribute = attribute as? TextEntitiesMessageAttribute {
attributes.append(attribute)
}
if let attribute = attribute as? ReplyMessageAttribute {
attributes.append(attribute)
}
}
for attribute in attributes {
for peerId in attribute.associatedPeerIds {
@@ -496,7 +505,10 @@ 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: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
if let peer = self.entry.peers[message.id.peerId] {
peers[peer.id] = peer
}
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: message.threadId, 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: message.associatedMessages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: message.associatedThreadInfo, 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, savedMessageTags: 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):
@@ -531,6 +543,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let attribute = attribute as? TextEntitiesMessageAttribute {
attributes.append(attribute)
}
if let attribute = attribute as? ReplyMessageAttribute {
attributes.append(attribute)
}
}
for attribute in attributes {
for peerId in attribute.associatedPeerIds {
@@ -549,7 +564,10 @@ 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: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
if let peer = self.entry.peers[message.id.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: message.threadId, 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: message.associatedMessages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: message.associatedThreadInfo, 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, savedMessageTags: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case .participantJoin, .participantLeave:
@@ -1110,6 +1128,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let attribute = attribute as? TextEntitiesMessageAttribute {
attributes.append(attribute)
}
if let attribute = attribute as? ReplyMessageAttribute {
attributes.append(attribute)
}
}
for attribute in attributes {
for peerId in attribute.associatedPeerIds {
@@ -1118,7 +1139,10 @@ 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: [], customTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
if let peer = self.entry.peers[message.id.peerId] {
peers[peer.id] = peer
}
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: message.associatedMessages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: message.associatedThreadInfo, 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, savedMessageTags: 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):
@@ -1706,6 +1730,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let attribute = attribute as? TextEntitiesMessageAttribute {
attributes.append(attribute)
}
if let attribute = attribute as? ReplyMessageAttribute {
attributes.append(attribute)
}
}
for attribute in attributes {
for peerId in attribute.associatedPeerIds {
@@ -1714,7 +1741,10 @@ 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: [], customTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
if let peer = self.entry.peers[message.id.peerId] {
peers[peer.id] = peer
}
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: message.threadId, 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: message.associatedMessages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: message.associatedThreadInfo, 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, savedMessageTags: 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):