mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
081713ec6f
@ -5232,62 +5232,104 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
}
|
||||
}, unpinMessage: { [weak self] id, askForConfirmation in
|
||||
if let strongSelf = self {
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if strongSelf.canManagePin() {
|
||||
let action: () -> Void = {
|
||||
if let strongSelf = self {
|
||||
let disposable: MetaDisposable
|
||||
if let current = strongSelf.unpinMessageDisposable {
|
||||
disposable = current
|
||||
} else {
|
||||
disposable = MetaDisposable()
|
||||
strongSelf.unpinMessageDisposable = disposable
|
||||
}
|
||||
|
||||
if askForConfirmation {
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = true
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(true)
|
||||
})
|
||||
|
||||
}, unpinMessage: { [weak self] id, askForConfirmation, contextController in
|
||||
let impl: () -> Void = {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
|
||||
if strongSelf.canManagePin() {
|
||||
let action: () -> Void = {
|
||||
if let strongSelf = self {
|
||||
let disposable: MetaDisposable
|
||||
if let current = strongSelf.unpinMessageDisposable {
|
||||
disposable = current
|
||||
} else {
|
||||
disposable = MetaDisposable()
|
||||
strongSelf.unpinMessageDisposable = disposable
|
||||
}
|
||||
|
||||
if askForConfirmation {
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = true
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(true)
|
||||
})
|
||||
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .messagesUnpinned(
|
||||
title: strongSelf.presentationData.strings.Chat_MessagesUnpinned(1),
|
||||
text: "",
|
||||
undo: askForConfirmation,
|
||||
isHidden: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
switch action {
|
||||
case .commit:
|
||||
disposable.set((requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: peer.id, update: .clear(id: id))
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
})
|
||||
}, completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
})
|
||||
}))
|
||||
case .undo:
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
} else {
|
||||
if case .pinnedMessages = strongSelf.presentationInterfaceState.subject {
|
||||
strongSelf.chatDisplayNode.historyNode.pendingRemovedMessages.insert(id)
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .messagesUnpinned(
|
||||
title: strongSelf.presentationData.strings.Chat_MessagesUnpinned(1),
|
||||
text: "",
|
||||
undo: askForConfirmation,
|
||||
undo: true,
|
||||
isHidden: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
guard let strongSelf = self else {
|
||||
return true
|
||||
}
|
||||
switch action {
|
||||
case .commit:
|
||||
disposable.set((requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: peer.id, update: .clear(id: id))
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
let _ = (requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: peer.id, update: .clear(id: id))
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
})
|
||||
}, completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
})
|
||||
}))
|
||||
case .undo:
|
||||
strongSelf.chatDisplayNode.historyNode.pendingUnpinnedAllMessages = false
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedPendingUnpinnedAllMessages(false)
|
||||
strongSelf.chatDisplayNode.historyNode.pendingRemovedMessages.remove(id)
|
||||
})
|
||||
case .undo:
|
||||
strongSelf.chatDisplayNode.historyNode.pendingRemovedMessages.remove(id)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -5302,62 +5344,70 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
}
|
||||
if askForConfirmation {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UnpinMessageAlert, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_Unpin, action: {
|
||||
action()
|
||||
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
|
||||
} else {
|
||||
}
|
||||
if askForConfirmation {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UnpinMessageAlert, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_Unpin, action: {
|
||||
action()
|
||||
}
|
||||
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
|
||||
} else {
|
||||
if let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage {
|
||||
let previousClosedPinnedMessageId = strongSelf.presentationInterfaceState.interfaceState.messageActionsState.closedPinnedMessageId
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedInterfaceState({ $0.withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.closedPinnedMessageId = pinnedMessage.topMessageId
|
||||
return value
|
||||
}) })
|
||||
})
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .messagesUnpinned(
|
||||
title: strongSelf.presentationData.strings.Chat_PinnedMessagesHiddenTitle,
|
||||
text: strongSelf.presentationData.strings.Chat_PinnedMessagesHiddenText,
|
||||
undo: true,
|
||||
isHidden: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
guard let strongSelf = self else {
|
||||
return true
|
||||
}
|
||||
switch action {
|
||||
case .commit:
|
||||
break
|
||||
case .undo:
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedInterfaceState({ $0.withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.closedPinnedMessageId = previousClosedPinnedMessageId
|
||||
return value
|
||||
}) })
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
action()
|
||||
}
|
||||
} else {
|
||||
if let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage {
|
||||
let previousClosedPinnedMessageId = strongSelf.presentationInterfaceState.interfaceState.messageActionsState.closedPinnedMessageId
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedInterfaceState({ $0.withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.closedPinnedMessageId = pinnedMessage.topMessageId
|
||||
return value
|
||||
}) })
|
||||
})
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .messagesUnpinned(
|
||||
title: strongSelf.presentationData.strings.Chat_PinnedMessagesHiddenTitle,
|
||||
text: strongSelf.presentationData.strings.Chat_PinnedMessagesHiddenText,
|
||||
undo: true,
|
||||
isHidden: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
guard let strongSelf = self else {
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
strongSelf.updatedClosedPinnedMessageId?(pinnedMessage.topMessageId)
|
||||
}
|
||||
switch action {
|
||||
case .commit:
|
||||
break
|
||||
case .undo:
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedInterfaceState({ $0.withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.closedPinnedMessageId = previousClosedPinnedMessageId
|
||||
return value
|
||||
}) })
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
strongSelf.updatedClosedPinnedMessageId?(pinnedMessage.topMessageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let contextController = contextController {
|
||||
contextController.dismiss(completion: {
|
||||
impl()
|
||||
})
|
||||
} else {
|
||||
impl()
|
||||
}
|
||||
}, unpinAllMessages: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -8,7 +8,7 @@ import AccountContext
|
||||
import TelegramPresentationData
|
||||
|
||||
|
||||
func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, includeUnreadEntry: Bool, includeEmptyEntry: Bool, includeChatInfoEntry: Bool, includeSearchEntry: Bool, reverse: Bool, groupMessages: Bool, selectedMessages: Set<MessageId>?, presentationData: ChatPresentationData, historyAppearsCleared: Bool, pendingUnpinnedAllMessages: Bool, associatedData: ChatMessageItemAssociatedData, updatingMedia: [MessageId: ChatUpdatingMessageMedia], customChannelDiscussionReadState: MessageId?, customThreadOutgoingReadState: MessageId?) -> [ChatHistoryEntry] {
|
||||
func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, includeUnreadEntry: Bool, includeEmptyEntry: Bool, includeChatInfoEntry: Bool, includeSearchEntry: Bool, reverse: Bool, groupMessages: Bool, selectedMessages: Set<MessageId>?, presentationData: ChatPresentationData, historyAppearsCleared: Bool, pendingUnpinnedAllMessages: Bool, pendingRemovedMessages: Set<MessageId>, associatedData: ChatMessageItemAssociatedData, updatingMedia: [MessageId: ChatUpdatingMessageMedia], customChannelDiscussionReadState: MessageId?, customThreadOutgoingReadState: MessageId?) -> [ChatHistoryEntry] {
|
||||
if historyAppearsCleared {
|
||||
return []
|
||||
}
|
||||
@ -34,6 +34,10 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
||||
var message = entry.message
|
||||
var isRead = entry.isRead
|
||||
|
||||
if pendingRemovedMessages.contains(message.id) {
|
||||
continue
|
||||
}
|
||||
|
||||
if let customThreadOutgoingReadState = customThreadOutgoingReadState {
|
||||
isRead = customThreadOutgoingReadState >= message.id
|
||||
}
|
||||
|
@ -565,6 +565,15 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
}
|
||||
}
|
||||
|
||||
private let pendingRemovedMessagesPromise = ValuePromise<Set<MessageId>>(Set())
|
||||
var pendingRemovedMessages: Set<MessageId> = Set() {
|
||||
didSet {
|
||||
if self.pendingRemovedMessages != oldValue {
|
||||
self.pendingRemovedMessagesPromise.set(self.pendingRemovedMessages)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var isScrollAtBottomPosition = false
|
||||
public var isScrollAtBottomPositionUpdated: (() -> Void)?
|
||||
|
||||
@ -846,10 +855,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
automaticDownloadNetworkType,
|
||||
self.historyAppearsClearedPromise.get(),
|
||||
self.pendingUnpinnedAllMessagesPromise.get(),
|
||||
self.pendingRemovedMessagesPromise.get(),
|
||||
animatedEmojiStickers,
|
||||
customChannelDiscussionReadState,
|
||||
customThreadOutgoingReadState
|
||||
).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, historyAppearsCleared, pendingUnpinnedAllMessages, animatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState in
|
||||
).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, animatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState in
|
||||
func applyHole() {
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
@ -930,7 +940,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
|
||||
let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, animatedEmojiStickers: animatedEmojiStickers, subject: subject)
|
||||
|
||||
let filteredEntries = chatHistoryEntriesForView(location: chatLocation, view: view, includeUnreadEntry: mode == .bubbles, includeEmptyEntry: mode == .bubbles && tagMask == nil, includeChatInfoEntry: mode == .bubbles, includeSearchEntry: includeSearchEntry && tagMask != nil, reverse: reverse, groupMessages: mode == .bubbles, selectedMessages: selectedMessages, presentationData: chatPresentationData, historyAppearsCleared: historyAppearsCleared, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, associatedData: associatedData, updatingMedia: updatingMedia, customChannelDiscussionReadState: customChannelDiscussionReadState, customThreadOutgoingReadState: customThreadOutgoingReadState)
|
||||
let filteredEntries = chatHistoryEntriesForView(location: chatLocation, view: view, includeUnreadEntry: mode == .bubbles, includeEmptyEntry: mode == .bubbles && tagMask == nil, includeChatInfoEntry: mode == .bubbles, includeSearchEntry: includeSearchEntry && tagMask != nil, reverse: reverse, groupMessages: mode == .bubbles, selectedMessages: selectedMessages, presentationData: chatPresentationData, historyAppearsCleared: historyAppearsCleared, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, pendingRemovedMessages: pendingRemovedMessages, associatedData: associatedData, updatingMedia: updatingMedia, customChannelDiscussionReadState: customChannelDiscussionReadState, customThreadOutgoingReadState: customThreadOutgoingReadState)
|
||||
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
||||
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id)
|
||||
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages))
|
||||
|
@ -690,9 +690,8 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
||||
if let pinnedSelectedMessageId = pinnedSelectedMessageId {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Unpin, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Unpin"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
interfaceInteraction.unpinMessage(pinnedSelectedMessageId, false)
|
||||
f(.default)
|
||||
}, action: { c, _ in
|
||||
interfaceInteraction.unpinMessage(pinnedSelectedMessageId, false, c)
|
||||
})))
|
||||
} else {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Pin, icon: { theme in
|
||||
|
@ -95,7 +95,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Bool
|
||||
let unblockPeer: () -> Void
|
||||
let pinMessage: (MessageId, ContextController?) -> Void
|
||||
let unpinMessage: (MessageId, Bool) -> Void
|
||||
let unpinMessage: (MessageId, Bool, ContextController?) -> Void
|
||||
let unpinAllMessages: () -> Void
|
||||
let openPinnedList: (MessageId) -> Void
|
||||
let shareAccountContact: () -> Void
|
||||
@ -174,7 +174,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool,
|
||||
unblockPeer: @escaping () -> Void,
|
||||
pinMessage: @escaping (MessageId, ContextController?) -> Void,
|
||||
unpinMessage: @escaping (MessageId, Bool) -> Void,
|
||||
unpinMessage: @escaping (MessageId, Bool, ContextController?) -> Void,
|
||||
unpinAllMessages: @escaping () -> Void,
|
||||
openPinnedList: @escaping (MessageId) -> Void,
|
||||
shareAccountContact: @escaping () -> Void,
|
||||
|
@ -462,7 +462,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
|
||||
@objc func closePressed() {
|
||||
if let interfaceInteraction = self.interfaceInteraction, let message = self.currentMessage {
|
||||
interfaceInteraction.unpinMessage(message.message.id, true)
|
||||
interfaceInteraction.unpinMessage(message.message.id, true, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ final class ChatRecentActionsController: TelegramBaseController {
|
||||
return false
|
||||
}, unblockPeer: {
|
||||
}, pinMessage: { _, _ in
|
||||
}, unpinMessage: { _, _ in
|
||||
}, unpinMessage: { _, _, _ in
|
||||
}, unpinAllMessages: {
|
||||
}, openPinnedList: { _ in
|
||||
}, shareAccountContact: {
|
||||
|
@ -406,7 +406,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
return false
|
||||
}, unblockPeer: {
|
||||
}, pinMessage: { _, _ in
|
||||
}, unpinMessage: { _, _ in
|
||||
}, unpinMessage: { _, _, _ in
|
||||
}, unpinAllMessages: {
|
||||
}, openPinnedList: { _ in
|
||||
}, shareAccountContact: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user