mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
83c7c54616
commit
8a0fbe7f21
@ -10860,6 +10860,7 @@ Sorry for the inconvenience.";
|
||||
"Chat.PanelStatusAuthorHidden" = "Senders of these messages restricted to link\ntheir name when forwarding.";
|
||||
"Chat.SavedMessagesChatsTooltip" = "Tap to view your Saved Messages organized by type or source";
|
||||
|
||||
"Chat.ConfirmationDeleteFromSavedMessages" = "Delete from Saved Messages";
|
||||
"Chat.ConfirmationRemoveFromSavedMessages" = "Remove from Saved Messages";
|
||||
|
||||
"Premium.MaxSavedPinsText" = "Sorry, you can't pin more than **%1$@** chats to the top. Unpin some that are currently pinned or subscribe to **Telegram Premium** to double the limit to **%2$@** chats.";
|
||||
@ -10964,6 +10965,7 @@ Sorry for the inconvenience.";
|
||||
"PrivacyInfo.ShowReadTime.AlwaysToast.Text" = "Set **Last Seen** privacy to 'Nobody' or 'My Contacts.'";
|
||||
|
||||
"Chat.ToastMessageTagged.Text" = "Message tagged with %@";
|
||||
"Chat.ToastMessagesTagged.Text" = "Messages tagged with %@";
|
||||
"Chat.ToastMessageTagged.Action" = "View";
|
||||
|
||||
"Chat.PrivateMessageSeenTimestamp.Date" = "read %@";
|
||||
|
@ -24,16 +24,17 @@ public final class ChatShareMessageTagView: UIView, UndoOverlayControllerAdditio
|
||||
private var reactionContextNode: ReactionContextNode?
|
||||
private var params: Params?
|
||||
|
||||
public init(context: AccountContext, presentationData: PresentationData, reactionItems: [ReactionItem], completion: @escaping (TelegramMediaFile, UpdateMessageReaction) -> Void) {
|
||||
public init(context: AccountContext, presentationData: PresentationData, isSingleMessage: Bool, reactionItems: [ReactionItem], completion: @escaping (TelegramMediaFile, UpdateMessageReaction) -> Void) {
|
||||
super.init(frame: CGRect())
|
||||
|
||||
//TODO:localize
|
||||
let reactionContextNode = ReactionContextNode(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
presentationData: presentationData,
|
||||
items: reactionItems.map(ReactionContextItem.reaction),
|
||||
selectedItems: Set(),
|
||||
title: presentationData.strings.Chat_ContextMenuTagsTitle,
|
||||
title: isSingleMessage ? presentationData.strings.Chat_ContextMenuTagsTitle : "You can add a tag to messages",
|
||||
reactionsLocked: false,
|
||||
alwaysAllowPremiumReactions: false,
|
||||
allPresetReactionsAreAvailable: true,
|
||||
|
@ -16649,72 +16649,133 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
func presentDeleteMessageOptions(messageIds: Set<MessageId>, options: ChatAvailableMessageActionOptions, contextController: ContextControllerProtocol?, completion: @escaping (ContextMenuActionResult) -> Void) {
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
var personalPeerName: String?
|
||||
var isChannel = false
|
||||
if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser {
|
||||
personalPeerName = EnginePeer(user).compactDisplayTitle
|
||||
} else if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat, let associatedPeerId = peer.associatedPeerId, let user = self.presentationInterfaceState.renderedPeer?.peers[associatedPeerId] as? TelegramUser {
|
||||
personalPeerName = EnginePeer(user).compactDisplayTitle
|
||||
} else if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
isChannel = true
|
||||
}
|
||||
|
||||
if options.contains(.cancelSending) {
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_ContextMenuCancelSending, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
var contextItems: [ContextMenuItem] = []
|
||||
var canDisplayContextMenu = true
|
||||
|
||||
var unsendPersonalMessages = false
|
||||
if options.contains(.unsendPersonal) {
|
||||
canDisplayContextMenu = false
|
||||
items.append(ActionSheetTextItem(title: self.presentationData.strings.Chat_UnsendMyMessagesAlertTitle(personalPeerName ?? "").string))
|
||||
items.append(ActionSheetSwitchItem(title: self.presentationData.strings.Chat_UnsendMyMessages, isOn: false, action: { value in
|
||||
unsendPersonalMessages = value
|
||||
}))
|
||||
} else if options.contains(.deleteGlobally) {
|
||||
let globalTitle: String
|
||||
if isChannel {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
} else if let personalPeerName = personalPeerName {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
||||
} else {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
let _ = (self.context.engine.data.get(
|
||||
EngineDataMap(messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init(id:)))
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] messages in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
contextItems.append(.action(ContextMenuActionItem(text: globalTitle, textColor: .destructive, icon: { _ in nil }, action: { [weak self] c, f in
|
||||
if let strongSelf = self {
|
||||
var giveaway: TelegramMediaGiveaway?
|
||||
for messageId in messageIds {
|
||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
|
||||
if let media = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway {
|
||||
giveaway = media
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
let commit = {
|
||||
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
var personalPeerName: String?
|
||||
var isChannel = false
|
||||
if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser {
|
||||
personalPeerName = EnginePeer(user).compactDisplayTitle
|
||||
} else if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat, let associatedPeerId = peer.associatedPeerId, let user = self.presentationInterfaceState.renderedPeer?.peers[associatedPeerId] as? TelegramUser {
|
||||
personalPeerName = EnginePeer(user).compactDisplayTitle
|
||||
} else if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
isChannel = true
|
||||
}
|
||||
|
||||
if options.contains(.cancelSending) {
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_ContextMenuCancelSending, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
if let giveaway {
|
||||
Queue.mainQueue().after(0.2) {
|
||||
let dateString = stringForDate(timestamp: giveaway.untilDate, timeZone: .current, strings: strongSelf.presentationData.strings)
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.Chat_Giveaway_DeleteConfirmation_Title, text: strongSelf.presentationData.strings.Chat_Giveaway_DeleteConfirmation_Text(dateString).string, actions: [TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.Common_Delete, action: {
|
||||
commit()
|
||||
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
|
||||
})], parseMarkdown: true), in: .window(.root))
|
||||
}))
|
||||
}
|
||||
|
||||
var contextItems: [ContextMenuItem] = []
|
||||
var canDisplayContextMenu = true
|
||||
|
||||
var unsendPersonalMessages = false
|
||||
if options.contains(.unsendPersonal) {
|
||||
canDisplayContextMenu = false
|
||||
items.append(ActionSheetTextItem(title: self.presentationData.strings.Chat_UnsendMyMessagesAlertTitle(personalPeerName ?? "").string))
|
||||
items.append(ActionSheetSwitchItem(title: self.presentationData.strings.Chat_UnsendMyMessages, isOn: false, action: { value in
|
||||
unsendPersonalMessages = value
|
||||
}))
|
||||
} else if options.contains(.deleteGlobally) {
|
||||
let globalTitle: String
|
||||
if isChannel {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
} else if let personalPeerName = personalPeerName {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
||||
} else {
|
||||
globalTitle = self.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
}
|
||||
contextItems.append(.action(ContextMenuActionItem(text: globalTitle, textColor: .destructive, icon: { _ in nil }, action: { [weak self] c, f in
|
||||
if let strongSelf = self {
|
||||
var giveaway: TelegramMediaGiveaway?
|
||||
for messageId in messageIds {
|
||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
|
||||
if let media = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway {
|
||||
giveaway = media
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
f(.default)
|
||||
let commit = {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
if let giveaway {
|
||||
Queue.mainQueue().after(0.2) {
|
||||
let dateString = stringForDate(timestamp: giveaway.untilDate, timeZone: .current, strings: strongSelf.presentationData.strings)
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.Chat_Giveaway_DeleteConfirmation_Title, text: strongSelf.presentationData.strings.Chat_Giveaway_DeleteConfirmation_Text(dateString).string, actions: [TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.Common_Delete, action: {
|
||||
commit()
|
||||
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
|
||||
})], parseMarkdown: true), in: .window(.root))
|
||||
}
|
||||
f(.default)
|
||||
} else {
|
||||
if "".isEmpty {
|
||||
f(.dismissWithoutContent)
|
||||
commit()
|
||||
} else {
|
||||
c.dismiss(completion: {
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1, execute: {
|
||||
commit()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})))
|
||||
items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
}))
|
||||
}
|
||||
if options.contains(.deleteLocally) {
|
||||
var localOptionText = self.presentationData.strings.Conversation_DeleteMessagesForMe
|
||||
if self.chatLocation.peerId == self.context.account.peerId {
|
||||
if case .peer(self.context.account.peerId) = self.chatLocation, messages.values.allSatisfy({ message in message?._asMessage().effectivelyIncoming(self.context.account.peerId) ?? false }) {
|
||||
localOptionText = self.presentationData.strings.Chat_ConfirmationRemoveFromSavedMessages
|
||||
} else {
|
||||
localOptionText = self.presentationData.strings.Chat_ConfirmationDeleteFromSavedMessages
|
||||
}
|
||||
} else if case .scheduledMessages = self.presentationInterfaceState.subject {
|
||||
localOptionText = messageIds.count > 1 ? self.presentationData.strings.ScheduledMessages_DeleteMany : self.presentationData.strings.ScheduledMessages_Delete
|
||||
} else {
|
||||
if options.contains(.unsendPersonal) {
|
||||
localOptionText = self.presentationData.strings.Chat_DeleteMessagesConfirmation(Int32(messageIds.count))
|
||||
} else if case .peer(self.context.account.peerId) = self.chatLocation {
|
||||
if messageIds.count == 1 {
|
||||
localOptionText = self.presentationData.strings.Conversation_Moderate_Delete
|
||||
} else {
|
||||
localOptionText = self.presentationData.strings.Conversation_DeleteManyMessages
|
||||
}
|
||||
}
|
||||
}
|
||||
contextItems.append(.action(ContextMenuActionItem(text: localOptionText, textColor: .destructive, icon: { _ in nil }, action: { [weak self] c, f in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
|
||||
let commit: () -> Void = {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
}
|
||||
|
||||
if "".isEmpty {
|
||||
f(.dismissWithoutContent)
|
||||
commit()
|
||||
@ -16726,85 +16787,37 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})))
|
||||
items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
}))
|
||||
}
|
||||
if options.contains(.deleteLocally) {
|
||||
var localOptionText = self.presentationData.strings.Conversation_DeleteMessagesForMe
|
||||
if self.chatLocation.peerId == self.context.account.peerId {
|
||||
localOptionText = self.presentationData.strings.Chat_ConfirmationRemoveFromSavedMessages
|
||||
} else if case .scheduledMessages = self.presentationInterfaceState.subject {
|
||||
localOptionText = messageIds.count > 1 ? self.presentationData.strings.ScheduledMessages_DeleteMany : self.presentationData.strings.ScheduledMessages_Delete
|
||||
} else {
|
||||
if options.contains(.unsendPersonal) {
|
||||
localOptionText = self.presentationData.strings.Chat_DeleteMessagesConfirmation(Int32(messageIds.count))
|
||||
} else if case .peer(self.context.account.peerId) = self.chatLocation {
|
||||
if messageIds.count == 1 {
|
||||
localOptionText = self.presentationData.strings.Conversation_Moderate_Delete
|
||||
} else {
|
||||
localOptionText = self.presentationData.strings.Conversation_DeleteManyMessages
|
||||
}
|
||||
}
|
||||
}
|
||||
contextItems.append(.action(ContextMenuActionItem(text: localOptionText, textColor: .destructive, icon: { _ in nil }, action: { [weak self] c, f in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
|
||||
let commit: () -> Void = {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
}
|
||||
|
||||
if "".isEmpty {
|
||||
f(.dismissWithoutContent)
|
||||
commit()
|
||||
} else {
|
||||
c.dismiss(completion: {
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1, execute: {
|
||||
commit()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})))
|
||||
items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
if canDisplayContextMenu, let contextController = contextController {
|
||||
contextController.setItems(.single(ContextController.Items(content: .list(contextItems))), minHeight: nil, animated: true)
|
||||
} else {
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
})))
|
||||
items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
|
||||
if let contextController = contextController {
|
||||
contextController.dismiss(completion: { [weak self] in
|
||||
self?.present(actionSheet, in: .window(.root))
|
||||
})
|
||||
} else {
|
||||
self.chatDisplayNode.dismissInput()
|
||||
self.present(actionSheet, in: .window(.root))
|
||||
completion(.default)
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
if canDisplayContextMenu, let contextController = contextController {
|
||||
contextController.setItems(.single(ContextController.Items(content: .list(contextItems))), minHeight: nil, animated: true)
|
||||
} else {
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
|
||||
if let contextController = contextController {
|
||||
contextController.dismiss(completion: { [weak self] in
|
||||
self?.present(actionSheet, in: .window(.root))
|
||||
})
|
||||
} else {
|
||||
self.chatDisplayNode.dismissInput()
|
||||
self.present(actionSheet, in: .window(.root))
|
||||
completion(.default)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func presentClearCacheSuggestion() {
|
||||
|
@ -186,7 +186,7 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
let reactionItems: Signal<[ReactionItem], NoError>
|
||||
if savedMessages && messages.count == 1 {
|
||||
if savedMessages && messages.count > 0 {
|
||||
reactionItems = tagMessageReactions(context: strongSelf.context)
|
||||
} else {
|
||||
reactionItems = .single([])
|
||||
@ -198,7 +198,7 @@ extension ChatControllerImpl {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, position: savedMessages && messages.count == 1 ? .top : .bottom, animateInAsReplacement: true, action: { action in
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, position: savedMessages && messages.count > 0 ? .top : .bottom, animateInAsReplacement: true, action: { action in
|
||||
if savedMessages, let self, action == .info {
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
@ -212,7 +212,7 @@ extension ChatControllerImpl {
|
||||
})
|
||||
}
|
||||
return false
|
||||
}, additionalView: (savedMessages && messages.count == 1) ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationId: correlationIds.first) : nil), in: .current)
|
||||
}, additionalView: (savedMessages && messages.count > 0) ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationIds: correlationIds) : nil), in: .current)
|
||||
})
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
let reactionItems: Signal<[ReactionItem], NoError>
|
||||
if messages.count == 1 {
|
||||
if messages.count > 0 {
|
||||
reactionItems = tagMessageReactions(context: strongSelf.context)
|
||||
} else {
|
||||
reactionItems = .single([])
|
||||
@ -289,7 +289,7 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, position: messages.count == 1 ? .top : .bottom, animateInAsReplacement: true, action: { [weak self] value in
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, position: .top, animateInAsReplacement: true, action: { [weak self] value in
|
||||
if case .info = value, let strongSelf = self {
|
||||
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.context.account.peerId))
|
||||
|> deliverOnMainQueue).startStandalone(next: { peer in
|
||||
@ -302,7 +302,7 @@ extension ChatControllerImpl {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}, additionalView: messages.count == 1 ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationId: correlationIds.first) : nil), in: .current)
|
||||
}, additionalView: messages.count > 0 ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationIds: correlationIds) : nil), in: .current)
|
||||
})
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: mappedMessages)
|
||||
|
@ -15,30 +15,33 @@ import ChatShareMessageTagView
|
||||
import ReactionSelectionNode
|
||||
import TopMessageReactions
|
||||
|
||||
func chatShareToSavedMessagesAdditionalView(_ chatController: ChatControllerImpl, reactionItems: [ReactionItem], correlationId: Int64?) -> (() -> UndoOverlayControllerAdditionalView?)? {
|
||||
func chatShareToSavedMessagesAdditionalView(_ chatController: ChatControllerImpl, reactionItems: [ReactionItem], correlationIds: [Int64]) -> (() -> UndoOverlayControllerAdditionalView?)? {
|
||||
if !chatController.presentationInterfaceState.isPremium {
|
||||
return nil
|
||||
}
|
||||
guard let correlationId else {
|
||||
if correlationIds.count < 1 {
|
||||
return nil
|
||||
}
|
||||
return { [weak chatController] () -> UndoOverlayControllerAdditionalView? in
|
||||
guard let chatController else {
|
||||
return nil
|
||||
}
|
||||
return ChatShareMessageTagView(context: chatController.context, presentationData: chatController.presentationData, reactionItems: reactionItems, completion: { [weak chatController] file, updateReaction in
|
||||
return ChatShareMessageTagView(context: chatController.context, presentationData: chatController.presentationData, isSingleMessage: correlationIds.count == 1, reactionItems: reactionItems, completion: { [weak chatController] file, updateReaction in
|
||||
guard let chatController else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (chatController.context.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: chatController.context.account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 45, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: [])
|
||||
|> map { view, _, _ -> [EngineMessage.Id] in
|
||||
guard let messageId = chatController.context.engine.messages.synchronouslyLookupCorrelationId(correlationId: correlationId) else {
|
||||
let messageIds = correlationIds.compactMap { correlationId in
|
||||
return chatController.context.engine.messages.synchronouslyLookupCorrelationId(correlationId: correlationId)
|
||||
}
|
||||
if messageIds.isEmpty {
|
||||
return []
|
||||
}
|
||||
|
||||
let exactResult = view.entries.compactMap { entry -> EngineMessage.Id? in
|
||||
if entry.message.id == messageId {
|
||||
if messageIds.contains(entry.message.id) {
|
||||
return entry.message.id
|
||||
} else {
|
||||
return nil
|
||||
@ -57,15 +60,17 @@ func chatShareToSavedMessagesAdditionalView(_ chatController: ChatControllerImpl
|
||||
guard let chatController else {
|
||||
return
|
||||
}
|
||||
if let messageId = messageIds.first {
|
||||
let _ = chatController.context.engine.messages.setMessageReactions(id: messageId, reactions: [updateReaction])
|
||||
if !messageIds.isEmpty {
|
||||
for messageId in messageIds {
|
||||
let _ = chatController.context.engine.messages.setMessageReactions(id: messageId, reactions: [updateReaction])
|
||||
}
|
||||
|
||||
var isBuiltinReaction = false
|
||||
if case .builtin = updateReaction {
|
||||
isBuiltinReaction = true
|
||||
}
|
||||
let presentationData = chatController.context.sharedContext.currentPresentationData.with { $0 }
|
||||
chatController.present(UndoOverlayController(presentationData: presentationData, content: .messageTagged(context: chatController.context, customEmoji: file, isBuiltinReaction: isBuiltinReaction, customUndoText: presentationData.strings.Chat_ToastMessageTagged_Action), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { [weak chatController] action in
|
||||
chatController.present(UndoOverlayController(presentationData: presentationData, content: .messageTagged(context: chatController.context, isSingleMessage: messageIds.count == 1, customEmoji: file, isBuiltinReaction: isBuiltinReaction, customUndoText: presentationData.strings.Chat_ToastMessageTagged_Action), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { [weak chatController] action in
|
||||
if (action == .info || action == .undo), let chatController {
|
||||
let _ = (chatController.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: chatController.context.account.peerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak chatController] peer in
|
||||
@ -226,7 +231,7 @@ extension ChatControllerImpl {
|
||||
})
|
||||
}
|
||||
return false
|
||||
}, additionalView: savedMessages ? chatShareToSavedMessagesAdditionalView(self, reactionItems: reactionItems, correlationId: correlationIds.first) : nil), in: .current)
|
||||
}, additionalView: savedMessages ? chatShareToSavedMessagesAdditionalView(self, reactionItems: reactionItems, correlationIds: correlationIds) : nil), in: .current)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -82,8 +82,19 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
||||
var preloaded = false
|
||||
var fadeIn = false
|
||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
||||
if let tag {
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics)
|
||||
|
||||
var requestAroundId = false
|
||||
var preFixedReadState: MessageHistoryViewReadState?
|
||||
if tag != nil {
|
||||
requestAroundId = true
|
||||
}
|
||||
if case let .replyThread(message) = chatLocation, message.peerId == context.account.peerId {
|
||||
requestAroundId = true
|
||||
preFixedReadState = .peer([:])
|
||||
}
|
||||
|
||||
if requestAroundId {
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: preFixedReadState, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics)
|
||||
} else {
|
||||
signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public enum UndoOverlayContent {
|
||||
case universal(animation: String, scale: CGFloat, colors: [String: UIColor], title: String?, text: String, customUndoText: String?, timeout: Double?)
|
||||
case premiumPaywall(title: String?, text: String, customUndoText: String?, timeout: Double?, linkAction: ((String) -> Void)?)
|
||||
case peers(context: AccountContext, peers: [EnginePeer], title: String?, text: String, customUndoText: String?)
|
||||
case messageTagged(context: AccountContext, customEmoji: TelegramMediaFile, isBuiltinReaction: Bool, customUndoText: String?)
|
||||
case messageTagged(context: AccountContext, isSingleMessage: Bool, customEmoji: TelegramMediaFile, isBuiltinReaction: Bool, customUndoText: String?)
|
||||
}
|
||||
|
||||
public enum UndoOverlayAction {
|
||||
|
@ -1159,14 +1159,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
} else {
|
||||
displayUndo = false
|
||||
}
|
||||
case let .messageTagged(context, customEmoji, isBuiltinReaction, customUndoText):
|
||||
case let .messageTagged(context, isSingleMessage, customEmoji, isBuiltinReaction, customUndoText):
|
||||
self.avatarNode = nil
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
self.animationNode = AnimationNode(animation: "anim_savedmessages", colors: [:], scale: 0.066)
|
||||
self.animatedStickerNode = nil
|
||||
|
||||
let rawText = presentationData.strings.Chat_ToastMessageTagged_Text(".")
|
||||
let rawText = isSingleMessage ? presentationData.strings.Chat_ToastMessageTagged_Text(".") : presentationData.strings.Chat_ToastMessagesTagged_Text(".")
|
||||
let attributedText = NSMutableAttributedString(string: rawText.string, font: Font.regular(14.0), textColor: .white)
|
||||
for range in rawText.ranges {
|
||||
attributedText.addAttributes([ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: customEmoji.fileId.id, file: customEmoji, custom: nil)], range: range.range)
|
||||
|
Loading…
x
Reference in New Issue
Block a user