Various improvements

This commit is contained in:
Isaac 2024-01-30 14:53:23 +01:00
parent 8a0fbe7f21
commit 0f2eca17bd
11 changed files with 132 additions and 97 deletions

View File

@ -2517,7 +2517,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
switch item.content {
case let .peer(peerData):
if let peer = peerData.messages.last?.author {
if peer.isScam {
if case .savedMessagesChats = item.chatListLocation, peer.id == item.context.account.peerId {
currentCredibilityIconContent = nil
} else if peer.isScam {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
} else if peer.isFake {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
@ -2537,7 +2539,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
break
}
} else if case let .chat(itemPeer) = contentPeer, let peer = itemPeer.chatMainPeer {
if peer.isScam {
if case .savedMessagesChats = item.chatListLocation, peer.id == item.context.account.peerId {
currentCredibilityIconContent = nil
} else if peer.isScam {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
} else if peer.isFake {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())

View File

@ -18,10 +18,40 @@ public enum UpdateMessageReaction {
}
}
public func updateMessageReactionsInteractively(account: Account, messageId: MessageId, reactions: [UpdateMessageReaction], isLarge: Bool, storeAsRecentlyUsed: Bool, add: Bool = false) -> Signal<Never, NoError> {
public func updateMessageReactionsInteractively(account: Account, messageIds: [MessageId], reactions: [UpdateMessageReaction], isLarge: Bool, storeAsRecentlyUsed: Bool, add: Bool = false) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Void in
guard let chatPeerId = messageIds.first?.peerId else {
return
}
var messagesWithoutGroups: [Message] = []
var messagesByGroupId: [Int64: [Message]] = [:]
let messages = messageIds.compactMap { transaction.getMessage($0) }
for message in messages {
if let groupingKey = message.groupingKey {
if messagesByGroupId[groupingKey] == nil {
messagesByGroupId[groupingKey] = [message]
} else {
messagesByGroupId[groupingKey]?.append(message)
}
} else {
messagesWithoutGroups.append(message)
}
}
var messageIds: [MessageId] = []
for message in messagesWithoutGroups {
messageIds.append(message.id)
}
for (_, messages) in messagesByGroupId {
if let minMessageId = messages.map(\.id).min() {
messageIds.append(minMessageId)
}
}
var sendAsPeerId = account.peerId
if let cachedData = transaction.getPeerCachedData(peerId: messageId.peerId) {
if let cachedData = transaction.getPeerCachedData(peerId: chatPeerId) {
if let cachedData = cachedData as? CachedChannelData {
if let sendAsPeerIdValue = cachedData.sendAsPeerId {
sendAsPeerId = sendAsPeerIdValue
@ -39,94 +69,96 @@ public func updateMessageReactionsInteractively(account: Account, messageId: Mes
maxCount = 1
}
var mappedReactions: [PendingReactionsMessageAttribute.PendingReaction] = []
var reactions: [UpdateMessageReaction] = reactions
if add {
if let message = transaction.getMessage(messageId), let effectiveReactions = message.effectiveReactions(isTags: message.areReactionsTags(accountPeerId: account.peerId)) {
for reaction in effectiveReactions {
if !reactions.contains(where: { $0.reaction == reaction.value }) {
let mappedValue: UpdateMessageReaction
switch reaction.value {
case let .builtin(value):
mappedValue = .builtin(value)
case let .custom(fileId):
mappedValue = .custom(fileId: fileId, file: nil)
for messageId in messageIds {
var mappedReactions: [PendingReactionsMessageAttribute.PendingReaction] = []
var reactions: [UpdateMessageReaction] = reactions
if add {
if let message = transaction.getMessage(messageId), let effectiveReactions = message.effectiveReactions(isTags: message.areReactionsTags(accountPeerId: account.peerId)) {
for reaction in effectiveReactions {
if !reactions.contains(where: { $0.reaction == reaction.value }) {
let mappedValue: UpdateMessageReaction
switch reaction.value {
case let .builtin(value):
mappedValue = .builtin(value)
case let .custom(fileId):
mappedValue = .custom(fileId: fileId, file: nil)
}
reactions.append(mappedValue)
}
reactions.append(mappedValue)
}
}
}
}
for reaction in reactions {
switch reaction {
case let .custom(fileId, file):
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .custom(fileId), sendAsPeerId: sendAsPeerId))
if let file = file {
transaction.storeMediaIfNotPresent(media: file)
for reaction in reactions {
switch reaction {
case let .custom(fileId, file):
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .custom(fileId), sendAsPeerId: sendAsPeerId))
if let file = file {
transaction.storeMediaIfNotPresent(media: file)
}
case let .builtin(value):
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .builtin(value), sendAsPeerId: sendAsPeerId))
}
case let .builtin(value):
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .builtin(value), sendAsPeerId: sendAsPeerId))
}
}
transaction.setPendingMessageAction(type: .updateReaction, id: messageId, action: UpdateMessageReactionsAction())
transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var attributes = currentMessage.attributes
transaction.setPendingMessageAction(type: .updateReaction, id: messageId, action: UpdateMessageReactionsAction())
transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var attributes = currentMessage.attributes
loop: for j in 0 ..< attributes.count {
if let _ = attributes[j] as? PendingReactionsMessageAttribute {
attributes.remove(at: j)
break loop
}
}
if storeAsRecentlyUsed {
let isTags = currentMessage.areReactionsTags(accountPeerId: account.peerId)
if !isTags {
let effectiveReactions = currentMessage.effectiveReactions(isTags: isTags) ?? []
for updatedReaction in reactions {
if !effectiveReactions.contains(where: { $0.value == updatedReaction.reaction && $0.isSelected }) {
let recentReactionItem: RecentReactionItem
switch updatedReaction {
case let .builtin(value):
recentReactionItem = RecentReactionItem(.builtin(value))
case let .custom(fileId, file):
if let file = file ?? (transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile) {
recentReactionItem = RecentReactionItem(.custom(file))
} else {
continue
if storeAsRecentlyUsed {
let isTags = currentMessage.areReactionsTags(accountPeerId: account.peerId)
if !isTags {
let effectiveReactions = currentMessage.effectiveReactions(isTags: isTags) ?? []
for updatedReaction in reactions {
if !effectiveReactions.contains(where: { $0.value == updatedReaction.reaction && $0.isSelected }) {
let recentReactionItem: RecentReactionItem
switch updatedReaction {
case let .builtin(value):
recentReactionItem = RecentReactionItem(.builtin(value))
case let .custom(fileId, file):
if let file = file ?? (transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile) {
recentReactionItem = RecentReactionItem(.custom(file))
} else {
continue
}
}
if let entry = CodableEntry(recentReactionItem) {
let itemEntry = OrderedItemListEntry(id: recentReactionItem.id.rawValue, contents: entry)
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentReactions, item: itemEntry, removeTailIfCountExceeds: 50)
}
}
if let entry = CodableEntry(recentReactionItem) {
let itemEntry = OrderedItemListEntry(id: recentReactionItem.id.rawValue, contents: entry)
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentReactions, item: itemEntry, removeTailIfCountExceeds: 50)
}
}
}
}
}
var mappedReactions = mappedReactions
let updatedReactions = mergedMessageReactions(attributes: attributes + [PendingReactionsMessageAttribute(accountPeerId: account.peerId, reactions: mappedReactions, isLarge: isLarge, storeAsRecentlyUsed: storeAsRecentlyUsed, isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId))], isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId))?.reactions ?? []
let updatedOutgoingReactions = updatedReactions.filter(\.isSelected)
if updatedOutgoingReactions.count > maxCount {
let sortedOutgoingReactions = updatedOutgoingReactions.sorted(by: { $0.chosenOrder! < $1.chosenOrder! })
mappedReactions = Array(sortedOutgoingReactions.suffix(maxCount).map { reaction -> PendingReactionsMessageAttribute.PendingReaction in
return PendingReactionsMessageAttribute.PendingReaction(value: reaction.value, sendAsPeerId: sendAsPeerId)
})
}
attributes.append(PendingReactionsMessageAttribute(accountPeerId: account.peerId, reactions: mappedReactions, isLarge: isLarge, storeAsRecentlyUsed: storeAsRecentlyUsed, isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId)))
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
var mappedReactions = mappedReactions
let updatedReactions = mergedMessageReactions(attributes: attributes + [PendingReactionsMessageAttribute(accountPeerId: account.peerId, reactions: mappedReactions, isLarge: isLarge, storeAsRecentlyUsed: storeAsRecentlyUsed, isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId))], isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId))?.reactions ?? []
let updatedOutgoingReactions = updatedReactions.filter(\.isSelected)
if updatedOutgoingReactions.count > maxCount {
let sortedOutgoingReactions = updatedOutgoingReactions.sorted(by: { $0.chosenOrder! < $1.chosenOrder! })
mappedReactions = Array(sortedOutgoingReactions.suffix(maxCount).map { reaction -> PendingReactionsMessageAttribute.PendingReaction in
return PendingReactionsMessageAttribute.PendingReaction(value: reaction.value, sendAsPeerId: sendAsPeerId)
})
}
attributes.append(PendingReactionsMessageAttribute(accountPeerId: account.peerId, reactions: mappedReactions, isLarge: isLarge, storeAsRecentlyUsed: storeAsRecentlyUsed, isTags: currentMessage.areReactionsTags(accountPeerId: account.peerId)))
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
}
}
|> ignoreValues
}

View File

@ -333,24 +333,27 @@ public extension TelegramEngine.EngineData.Item {
public struct ReactionTagMessageCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public struct ItemKey: Hashable {
public var peerId: EnginePeer.Id
public var threadId: Int64?
public var reaction: MessageReaction.Reaction
}
public typealias Result = Int?
fileprivate var peerId: EnginePeer.Id
fileprivate var threadId: Int64?
fileprivate var reaction: MessageReaction.Reaction
public var mapKey: ItemKey {
return ItemKey(peerId: self.peerId, reaction: self.reaction)
return ItemKey(peerId: self.peerId, threadId: self.threadId, reaction: self.reaction)
}
public init(peerId: EnginePeer.Id, reaction: MessageReaction.Reaction) {
public init(peerId: EnginePeer.Id, threadId: Int64?, reaction: MessageReaction.Reaction) {
self.peerId = peerId
self.threadId = threadId
self.reaction = reaction
}
var key: PostboxViewKey {
return .historyTagSummaryView(tag: [], peerId: self.peerId, threadId: nil, namespace: Namespaces.Message.Cloud, customTag: ReactionsMessageAttribute.messageTag(reaction: self.reaction))
return .historyTagSummaryView(tag: [], peerId: self.peerId, threadId: self.threadId, namespace: Namespaces.Message.Cloud, customTag: ReactionsMessageAttribute.messageTag(reaction: self.reaction))
}
func extract(view: PostboxView) -> Result {

View File

@ -299,12 +299,12 @@ public extension TelegramEngine {
}
public func setMessageReactions(
id: EngineMessage.Id,
ids: [EngineMessage.Id],
reactions: [UpdateMessageReaction]
) {
let _ = updateMessageReactionsInteractively(
account: self.account,
messageId: id,
messageIds: ids,
reactions: reactions,
isLarge: false,
storeAsRecentlyUsed: false,
@ -313,12 +313,12 @@ public extension TelegramEngine {
}
public func addMessageReactions(
id: EngineMessage.Id,
ids: [EngineMessage.Id],
reactions: [UpdateMessageReaction]
) {
let _ = updateMessageReactionsInteractively(
account: self.account,
messageId: id,
messageIds: ids,
reactions: reactions,
isLarge: false,
storeAsRecentlyUsed: false,

View File

@ -324,15 +324,11 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
}
}
if let selectionState = presentationInterfaceState.interfaceState.selectionState {
for id in selectionState.selectedIds {
context.engine.messages.setMessageReactions(id: id, reactions: mappedUpdatedReactions)
}
context.engine.messages.setMessageReactions(ids: Array(selectionState.selectedIds), reactions: mappedUpdatedReactions)
}
} else {
if let selectionState = presentationInterfaceState.interfaceState.selectionState {
for id in selectionState.selectedIds {
context.engine.messages.addMessageReactions(id: id, reactions: [updateReaction])
}
context.engine.messages.addMessageReactions(ids: Array(selectionState.selectedIds), reactions: [updateReaction])
}
}

View File

@ -430,7 +430,7 @@ extension ChatControllerImpl {
}
}
let _ = updateMessageReactionsInteractively(account: self.context.account, messageId: message.id, reactions: mappedUpdatedReactions, isLarge: isLarge, storeAsRecentlyUsed: true).startStandalone()
let _ = updateMessageReactionsInteractively(account: self.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: isLarge, storeAsRecentlyUsed: true).startStandalone()
}
self.forEachController({ controller in

View File

@ -1565,7 +1565,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
let _ = updateMessageReactionsInteractively(account: strongSelf.context.account, messageId: message.id, reactions: mappedUpdatedReactions, isLarge: false, storeAsRecentlyUsed: false).startStandalone()
let _ = updateMessageReactionsInteractively(account: strongSelf.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: false, storeAsRecentlyUsed: false).startStandalone()
}
})
}, activateMessagePinch: { [weak self] sourceNode in
@ -10927,7 +10927,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let tag = updatedFilter.customTag
let _ = (self.context.engine.data.get(
TelegramEngine.EngineData.Item.Messages.ReactionTagMessageCount(peerId: self.context.account.peerId, reaction: reaction)
TelegramEngine.EngineData.Item.Messages.ReactionTagMessageCount(peerId: self.context.account.peerId, threadId: self.chatLocation.threadId, reaction: reaction)
)
|> deliverOnMainQueue).start(next: { [weak self] count in
guard let self else {

View File

@ -297,7 +297,7 @@ extension ChatControllerImpl {
return
}
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil))
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil, forceOpenChat: true))
})
return true
}

View File

@ -2478,6 +2478,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
let context = self.context
let chatLocation = self.chatLocation
let _ = inlineSearchResults.update(
transition: inlineSearchResultsTransition,
component: AnyComponent(ChatInlineSearchResultsListComponent(
@ -2560,7 +2562,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
input,
ignoreMessagesInTimestampRange: nil,
context: context,
chatLocation: .peer(id: peerId),
chatLocation: chatLocation,
chatLocationContextHolder: Atomic(value: nil),
scheduled: false,
fixedCombinedReadStates: nil,

View File

@ -61,9 +61,7 @@ func chatShareToSavedMessagesAdditionalView(_ chatController: ChatControllerImpl
return
}
if !messageIds.isEmpty {
for messageId in messageIds {
let _ = chatController.context.engine.messages.setMessageReactions(id: messageId, reactions: [updateReaction])
}
let _ = chatController.context.engine.messages.setMessageReactions(ids: messageIds, reactions: [updateReaction])
var isBuiltinReaction = false
if case .builtin = updateReaction {

View File

@ -123,7 +123,7 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode {
if self.tagMessageCount?.disposable == nil {
if let context = self.context {
self.tagMessageCount?.disposable = (context.engine.data.subscribe(
TelegramEngine.EngineData.Item.Messages.ReactionTagMessageCount(peerId: context.account.peerId, reaction: reaction)
TelegramEngine.EngineData.Item.Messages.ReactionTagMessageCount(peerId: context.account.peerId, threadId: params.interfaceState.chatLocation.threadId, reaction: reaction)
)
|> deliverOnMainQueue).startStrict(next: { [weak self] count in
guard let self else {