Add search results list tooltip

This commit is contained in:
Ilya Laktyushin 2019-10-20 23:41:25 +04:00
parent 89bfb95fb9
commit 97fea57795
6 changed files with 64 additions and 12 deletions

View File

@ -4638,12 +4638,12 @@ Any member of this group will be able to see messages in the channel.";
"Conversation.SendMessage.SetReminder" = "Set a Reminder";
"Conversation.SelectedMessages_1" = "%@ Message Selected";
"Conversation.SelectedMessages_2" = "%@ Messages Selected";
"Conversation.SelectedMessages_3_10" = "%@ Messages Selected";
"Conversation.SelectedMessages_any" = "%@ Messages Selected";
"Conversation.SelectedMessages_many" = "%@ Messages Selected";
"Conversation.SelectedMessages_0" = "%@ Messages Selected";
"Conversation.SelectedMessages_1" = "%@ Selected";
"Conversation.SelectedMessages_2" = "%@ Selected";
"Conversation.SelectedMessages_3_10" = "%@ Selected";
"Conversation.SelectedMessages_any" = "%@ Selected";
"Conversation.SelectedMessages_many" = "%@ Selected";
"Conversation.SelectedMessages_0" = "%@ Selected";
"AccentColor.Title" = "Accent Color";

View File

@ -265,6 +265,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var raiseToListen: RaiseToListenManager?
private var voicePlaylistDidEndTimestamp: Double = 0.0
private weak var searchResultsTooltipController: TooltipController?
private weak var messageTooltipController: TooltipController?
private weak var videoUnmuteTooltipController: TooltipController?
private weak var silentPostTooltipController: TooltipController?
@ -1522,9 +1523,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self {
strongSelf.context.sharedContext.applicationBindings.openAppStorePage()
}
}, displayMessageTooltip: { [weak self] messageId, text, sourceNode, sourceFrame in
}, displayMessageTooltip: { [weak self] messageId, text, node, nodeRect in
if let strongSelf = self {
if let sourceNode = sourceNode {
if let node = node {
strongSelf.messageTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(text), dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
strongSelf.messageTooltipController = tooltipController
@ -1535,9 +1536,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: {
if let strongSelf = self {
var rect = sourceNode.view.convert(sourceNode.view.bounds, to: strongSelf.chatDisplayNode.view)
if let sourceFrame = sourceFrame {
rect = CGRect(origin: rect.origin.offsetBy(dx: sourceFrame.minX, dy: sourceFrame.minY - sourceNode.bounds.minY), size: sourceFrame.size)
var rect = node.view.convert(node.view.bounds, to: strongSelf.chatDisplayNode.view)
if let nodeRect = nodeRect {
rect = CGRect(origin: rect.origin.offsetBy(dx: nodeRect.minX, dy: nodeRect.minY - node.bounds.minY), size: nodeRect.size)
}
return (strongSelf.chatDisplayNode, rect)
}
@ -4088,6 +4089,25 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self {
strongSelf.openScheduledMessages()
}
}, displaySearchResultsTooltip: { [weak self] node, nodeRect in
if let strongSelf = self {
strongSelf.searchResultsTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.ChatSearch_ResultsTooltip), dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
strongSelf.searchResultsTooltipController = tooltipController
tooltipController.dismissed = { [weak tooltipController] _ in
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.searchResultsTooltipController === tooltipController {
strongSelf.searchResultsTooltipController = nil
}
}
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: {
if let strongSelf = self {
var rect = node.view.convert(node.view.bounds, to: strongSelf.chatDisplayNode.view)
rect = CGRect(origin: rect.origin.offsetBy(dx: nodeRect.minX, dy: nodeRect.minY - node.bounds.minY), size: nodeRect.size)
return (strongSelf.chatDisplayNode, rect)
}
return nil
}))
}
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get()))
switch self.chatLocation {
@ -7817,6 +7837,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
private func dismissAllTooltips() {
self.searchResultsTooltipController?.dismiss()
self.messageTooltipController?.dismiss()
self.videoUnmuteTooltipController?.dismiss()
self.silentPostTooltipController?.dismiss()

View File

@ -112,9 +112,10 @@ final class ChatPanelInterfaceInteraction {
let displaySlowmodeTooltip: (ASDisplayNode, CGRect) -> Void
let displaySendMessageOptions: () -> Void
let openScheduledMessages: () -> Void
let displaySearchResultsTooltip: (ASDisplayNode, CGRect) -> Void
let statuses: ChatPanelInterfaceInteractionStatuses?
init(setupReplyMessage: @escaping (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message], ContextController?) -> Void, deleteMessages: @escaping ([Message], ContextController?, @escaping (ContextMenuActionResult) -> Void) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, openSearchResults: @escaping () -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, displaySendMessageOptions: @escaping () -> Void, openScheduledMessages: @escaping () -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) {
init(setupReplyMessage: @escaping (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message], ContextController?) -> Void, deleteMessages: @escaping ([Message], ContextController?, @escaping (ContextMenuActionResult) -> Void) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, openSearchResults: @escaping () -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, displaySendMessageOptions: @escaping () -> Void, openScheduledMessages: @escaping () -> Void, displaySearchResultsTooltip: @escaping (ASDisplayNode, CGRect) -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) {
self.setupReplyMessage = setupReplyMessage
self.setupEditMessage = setupEditMessage
self.beginMessageSelection = beginMessageSelection
@ -181,6 +182,7 @@ final class ChatPanelInterfaceInteraction {
self.displaySlowmodeTooltip = displaySlowmodeTooltip
self.displaySendMessageOptions = displaySendMessageOptions
self.openScheduledMessages = openScheduledMessages
self.displaySearchResultsTooltip = displaySearchResultsTooltip
self.statuses = statuses
}
}

View File

@ -113,6 +113,7 @@ final class ChatRecentActionsController: TelegramBaseController {
}, displaySlowmodeTooltip: { _, _ in
}, displaySendMessageOptions: {
}, openScheduledMessages: {
}, displaySearchResultsTooltip: { _, _ in
}, statuses: nil)
self.navigationItem.titleView = self.titleView

View File

@ -5,6 +5,7 @@ import Display
import TelegramCore
import Postbox
import SwiftSignalKit
import TelegramNotices
import TelegramPresentationData
import ActivityIndicator
@ -24,6 +25,8 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
private let activityDisposable = MetaDisposable()
private var displayActivity = false
private var needsSearchResultsTooltip = true
private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, LayoutMetrics)?
override var interfaceInteraction: ChatPanelInterfaceInteraction? {
@ -79,6 +82,26 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
@objc func upPressed() {
self.interfaceInteraction?.navigateMessageSearch(.earlier)
guard self.needsSearchResultsTooltip, let context = self.context else {
return
}
let _ = (ApplicationSpecificNotice.getChatMessageSearchResultsTip(accountManager: context.sharedContext.accountManager)
|> deliverOnMainQueue).start(next: { [weak self] counter in
guard let strongSelf = self else {
return
}
if counter >= 3 {
strongSelf.needsSearchResultsTooltip = false
} else if arc4random_uniform(4) == 1 {
strongSelf.needsSearchResultsTooltip = false
let _ = ApplicationSpecificNotice.incrementChatMessageSearchResultsTip(accountManager: context.sharedContext.accountManager).start()
strongSelf.interfaceInteraction?.displaySearchResultsTooltip(strongSelf.resultsButton, strongSelf.resultsButton.bounds)
}
})
}
@objc func downPressed() {
@ -95,6 +118,10 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
@objc func resultsPressed() {
self.interfaceInteraction?.openSearchResults()
if let context = self.context {
let _ = ApplicationSpecificNotice.incrementChatMessageSearchResultsTip(accountManager: context.sharedContext.accountManager, count: 4).start()
}
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {

View File

@ -519,6 +519,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
}, displaySlowmodeTooltip: { _, _ in
}, displaySendMessageOptions: {
}, openScheduledMessages: {
}, displaySearchResultsTooltip: { _, _ in
}, statuses: nil)
self.updateInterfaceState(animated: false, { return $0 })