Pinned messages improvements

This commit is contained in:
Ali 2020-10-23 01:27:13 +04:00
parent 27c6b78465
commit 24953abc59
9 changed files with 1945 additions and 1934 deletions

View File

@ -5882,3 +5882,6 @@ Any member of this group will be able to see messages in the channel.";
"Chat.PinnedListPreview.ShowAllMessages" = "Show All Messages"; "Chat.PinnedListPreview.ShowAllMessages" = "Show All Messages";
"Chat.PinnedListPreview.UnpinAllMessages" = "Unpin All Messages"; "Chat.PinnedListPreview.UnpinAllMessages" = "Unpin All Messages";
"Chat.PinnedListPreview.HidePinnedMessages" = "Hide Pinned Messages"; "Chat.PinnedListPreview.HidePinnedMessages" = "Hide Pinned Messages";
"Conversation.PinMessagesForMe" = "Pin for me";
"Conversation.PinMessagesFor" = "Pin for me and %@";

View File

@ -11,7 +11,7 @@ public enum UpdatePinnedMessageError {
} }
public enum PinnedMessageUpdate { public enum PinnedMessageUpdate {
case pin(id: MessageId, silent: Bool) case pin(id: MessageId, silent: Bool, forThisPeerOnlyIfPossible: Bool)
case clear(id: MessageId) case clear(id: MessageId)
} }
@ -20,7 +20,6 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId)) return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
} }
|> mapError { _ -> UpdatePinnedMessageError in |> mapError { _ -> UpdatePinnedMessageError in
return .generic
} }
|> mapToSignal { peer, cachedPeerData -> Signal<Void, UpdatePinnedMessageError> in |> mapToSignal { peer, cachedPeerData -> Signal<Void, UpdatePinnedMessageError> in
guard let peer = peer, let inputPeer = apiInputPeer(peer) else { guard let peer = peer, let inputPeer = apiInputPeer(peer) else {
@ -52,11 +51,14 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
var flags: Int32 = 0 var flags: Int32 = 0
let messageId: Int32 let messageId: Int32
switch update { switch update {
case let .pin(id, silent): case let .pin(id, silent, forThisPeerOnlyIfPossible):
messageId = id.id messageId = id.id
if silent { if silent {
flags |= (1 << 0) flags |= (1 << 0)
} }
if forThisPeerOnlyIfPossible {
flags |= (1 << 2)
}
case let .clear(id): case let .clear(id):
messageId = id.id messageId = id.id
flags |= 1 << 1 flags |= 1 << 1
@ -77,7 +79,7 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
if peerId.namespace == Namespaces.Peer.CloudChannel { if peerId.namespace == Namespaces.Peer.CloudChannel {
let messageId: MessageId let messageId: MessageId
switch update { switch update {
case let .pin(id, _): case let .pin(id, _, _):
messageId = id messageId = id
case let .clear(id): case let .clear(id):
messageId = id messageId = id
@ -103,7 +105,6 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
} }
} }
|> mapError { _ -> UpdatePinnedMessageError in |> mapError { _ -> UpdatePinnedMessageError in
return .generic
} }
} }
} }
@ -114,7 +115,6 @@ public func requestUnpinAllMessages(account: Account, peerId: PeerId) -> Signal<
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId)) return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
} }
|> mapError { _ -> UpdatePinnedMessageError in |> mapError { _ -> UpdatePinnedMessageError in
return .generic
} }
|> mapToSignal { peer, cachedPeerData -> Signal<Never, UpdatePinnedMessageError> in |> mapToSignal { peer, cachedPeerData -> Signal<Never, UpdatePinnedMessageError> in
guard let peer = peer, let inputPeer = apiInputPeer(peer) else { guard let peer = peer, let inputPeer = apiInputPeer(peer) else {

View File

@ -2230,7 +2230,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return items return items
} }
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: items, reactionItems: [], gesture: gesture) let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items, reactionItems: [], gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController) strongSelf.presentInGlobalOverlay(contextController)
}) })
}, openMessageReplies: { [weak self] messageId, isChannelPost, displayModalProgress in }, openMessageReplies: { [weak self] messageId, isChannelPost, displayModalProgress in
@ -2387,7 +2387,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return items return items
} }
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: items, reactionItems: [], gesture: gesture) let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items, reactionItems: [], gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController) strongSelf.presentInGlobalOverlay(contextController)
} }
chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)! chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)!
@ -5080,29 +5080,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, unblockPeer: { [weak self] in }, unblockPeer: { [weak self] in
self?.unblockPeer() self?.unblockPeer()
}, pinMessage: { [weak self] messageId in }, pinMessage: { [weak self] messageId, contextController in
if let strongSelf = self, case let .peer(currentPeerId) = strongSelf.chatLocation { if let strongSelf = self, case let .peer(currentPeerId) = strongSelf.chatLocation {
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer { if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
var canManagePin = false if strongSelf.canManagePin() {
if let channel = peer as? TelegramChannel { let pinAction: (Bool, Bool) -> Void = { notify, forThisPeerOnlyIfPossible in
canManagePin = channel.hasPermission(.pinMessages)
} else if let group = peer as? TelegramGroup {
switch group.role {
case .creator, .admin:
canManagePin = true
default:
if let defaultBannedRights = group.defaultBannedRights {
canManagePin = !defaultBannedRights.flags.contains(.banPinMessages)
} else {
canManagePin = true
}
}
} else if let _ = peer as? TelegramUser, strongSelf.presentationInterfaceState.explicitelyCanPinMessages {
canManagePin = true
}
if canManagePin {
let pinAction: (Bool) -> Void = { notify in
if let strongSelf = self { if let strongSelf = self {
let disposable: MetaDisposable let disposable: MetaDisposable
if let current = strongSelf.unpinMessageDisposable { if let current = strongSelf.unpinMessageDisposable {
@ -5111,10 +5093,32 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
disposable = MetaDisposable() disposable = MetaDisposable()
strongSelf.unpinMessageDisposable = disposable strongSelf.unpinMessageDisposable = disposable
} }
disposable.set(requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: currentPeerId, update: .pin(id: messageId, silent: !notify)).start()) disposable.set(requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: currentPeerId, update: .pin(id: messageId, silent: !notify, forThisPeerOnlyIfPossible: forThisPeerOnlyIfPossible)).start())
} }
} }
if let peer = peer as? TelegramUser, let contextController = contextController {
var contextItems: [ContextMenuItem] = []
contextItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_PinMessagesFor(peer.compactDisplayTitle).0, textColor: .primary, icon: { _ in nil }, action: { c, _ in
c.dismiss(completion: {
pinAction(true, true)
})
})))
contextItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_PinMessagesForMe, textColor: .primary, icon: { _ in nil }, action: { c, _ in
c.dismiss(completion: {
pinAction(true, false)
})
})))
contextController.setItems(.single(contextItems))
return
} else {
contextController?.dismiss(completion: {})
}
var pinImmediately = false var pinImmediately = false
if let channel = peer as? TelegramChannel, case .broadcast = channel.info { if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
pinImmediately = true pinImmediately = true
@ -5123,7 +5127,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if pinImmediately { if pinImmediately {
pinAction(true) pinAction(true, false)
} else { } else {
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = strongSelf.topPinnedMessageSignal(latest: true) let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = strongSelf.topPinnedMessageSignal(latest: true)
|> take(1) |> take(1)
@ -5144,7 +5148,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
actionLayout = .vertical actionLayout = .vertical
actions = [ actions = [
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlertPin, action: { TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlertPin, action: {
pinAction(false) pinAction(false, false)
}), }),
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}) })
@ -5155,10 +5159,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
actionLayout = .horizontal actionLayout = .horizontal
actions = [ actions = [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: { TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: {
pinAction(false) pinAction(false, false)
}), }),
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: { TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
pinAction(true) pinAction(true, false)
}) })
] ]
} }
@ -5758,7 +5762,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peerId), subject: .pinnedMessages(id: nil), botStart: nil, mode: .standard(previewing: true)) let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peerId), subject: .pinnedMessages(id: nil), botStart: nil, mode: .standard(previewing: true))
chatController.canReadHistory.set(false) chatController.canReadHistory.set(false)
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, passthroughTouches: true)), items: .single(items), reactionItems: [], gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController) strongSelf.presentInGlobalOverlay(contextController)
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get())) }, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get()))
@ -11016,11 +11020,12 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent
let navigationController: NavigationController? = nil let navigationController: NavigationController? = nil
let passthroughTouches: Bool = false let passthroughTouches: Bool
init(controller: ViewController, sourceNode: ASDisplayNode?) { init(controller: ViewController, sourceNode: ASDisplayNode?, passthroughTouches: Bool) {
self.controller = controller self.controller = controller
self.sourceNode = sourceNode self.sourceNode = sourceNode
self.passthroughTouches = passthroughTouches
} }
func transitionInfo() -> ContextControllerTakeControllerInfo? { func transitionInfo() -> ContextControllerTakeControllerInfo? {

View File

@ -682,9 +682,8 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
} else { } else {
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Pin, icon: { theme in actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Pin, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Pin"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Pin"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in }, action: { c, _ in
interfaceInteraction.pinMessage(messages[0].id) interfaceInteraction.pinMessage(messages[0].id, c)
f(.dismissWithoutContent)
}))) })))
} }
} }

View File

@ -94,7 +94,7 @@ final class ChatPanelInterfaceInteraction {
let setupMessageAutoremoveTimeout: () -> Void let setupMessageAutoremoveTimeout: () -> Void
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Bool let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Bool
let unblockPeer: () -> Void let unblockPeer: () -> Void
let pinMessage: (MessageId) -> Void let pinMessage: (MessageId, ContextController?) -> Void
let unpinMessage: (MessageId, Bool) -> Void let unpinMessage: (MessageId, Bool) -> Void
let unpinAllMessages: () -> Void let unpinAllMessages: () -> Void
let openPinnedList: (MessageId) -> Void let openPinnedList: (MessageId) -> Void
@ -173,7 +173,7 @@ final class ChatPanelInterfaceInteraction {
setupMessageAutoremoveTimeout: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void,
sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool,
unblockPeer: @escaping () -> Void, unblockPeer: @escaping () -> Void,
pinMessage: @escaping (MessageId) -> Void, pinMessage: @escaping (MessageId, ContextController?) -> Void,
unpinMessage: @escaping (MessageId, Bool) -> Void, unpinMessage: @escaping (MessageId, Bool) -> Void,
unpinAllMessages: @escaping () -> Void, unpinAllMessages: @escaping () -> Void,
openPinnedList: @escaping (MessageId) -> Void, openPinnedList: @escaping (MessageId) -> Void,

View File

@ -99,7 +99,7 @@ final class ChatRecentActionsController: TelegramBaseController {
}, sendSticker: { _, _, _ in }, sendSticker: { _, _, _ in
return false return false
}, unblockPeer: { }, unblockPeer: {
}, pinMessage: { _ in }, pinMessage: { _, _ in
}, unpinMessage: { _, _ in }, unpinMessage: { _, _ in
}, unpinAllMessages: { }, unpinAllMessages: {
}, openPinnedList: { _ in }, openPinnedList: { _ in

View File

@ -405,7 +405,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
}, sendSticker: { _, _, _ in }, sendSticker: { _, _, _ in
return false return false
}, unblockPeer: { }, unblockPeer: {
}, pinMessage: { _ in }, pinMessage: { _, _ in
}, unpinMessage: { _, _ in }, unpinMessage: { _, _ in
}, unpinAllMessages: { }, unpinAllMessages: {
}, openPinnedList: { _ in }, openPinnedList: { _ in