Update next channel navigation UI

This commit is contained in:
Ali 2021-08-03 16:27:10 +02:00
parent 321f4002ab
commit 0a0517122c
9 changed files with 120 additions and 30 deletions

View File

@ -289,9 +289,10 @@ public final class NavigateToChatControllerParams {
public let animated: Bool public let animated: Bool
public let options: NavigationAnimationOptions public let options: NavigationAnimationOptions
public let parentGroupId: PeerGroupId? public let parentGroupId: PeerGroupId?
public let chatListFilter: ChatListFilterData?
public let completion: (ChatController) -> Void public let completion: (ChatController) -> Void
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping (ChatController) -> Void = { _ in }) { public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: ChatListFilterData? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
self.navigationController = navigationController self.navigationController = navigationController
self.chatController = chatController self.chatController = chatController
self.chatLocationContextHolder = chatLocationContextHolder self.chatLocationContextHolder = chatLocationContextHolder
@ -312,6 +313,7 @@ public final class NavigateToChatControllerParams {
self.animated = animated self.animated = animated
self.options = options self.options = options
self.parentGroupId = parentGroupId self.parentGroupId = parentGroupId
self.chatListFilter = chatListFilter
self.completion = completion self.completion = completion
} }
} }

View File

@ -612,7 +612,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
scrollToEndIfExists = true scrollToEndIfExists = true
} }
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, completion: { [weak self] controller in strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, chatListFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.data, completion: { [weak self] controller in
self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true)
if let promoInfo = promoInfo { if let promoInfo = promoInfo {
switch promoInfo { switch promoInfo {

View File

@ -28,7 +28,7 @@ struct ChatListNodeViewUpdate {
let scrollPosition: ChatListNodeViewScrollPosition? let scrollPosition: ChatListNodeViewScrollPosition?
} }
func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredicate { public func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredicate {
var includePeers = Set(filter.includePeers.peers) var includePeers = Set(filter.includePeers.peers)
var excludePeers = Set(filter.excludePeers) var excludePeers = Set(filter.excludePeers)

View File

@ -495,16 +495,19 @@ public extension TelegramEngine {
return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description) return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description)
} }
public func getNextUnreadChannel(peerId: PeerId) -> Signal<EnginePeer?, NoError> { public func getNextUnreadChannel(peerId: PeerId, filter: ChatListFilterPredicate?) -> Signal<EnginePeer?, NoError> {
return self.account.postbox.transaction { transaction -> EnginePeer? in return self.account.postbox.transaction { transaction -> EnginePeer? in
var peers: [RenderedPeer] = []
peers.append(contentsOf: transaction.getTopChatListEntries(groupId: .root, count: 100))
peers.append(contentsOf: transaction.getTopChatListEntries(groupId: Namespaces.PeerGroup.archive, count: 100))
var results: [(EnginePeer, Int32)] = [] var results: [(EnginePeer, Int32)] = []
for peer in peers { var peerIds: [PeerId] = []
guard let channel = peer.chatMainPeer as? TelegramChannel, case .broadcast = channel.info else { peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: filter))
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: filter))
for listId in peerIds {
guard let peer = transaction.getPeer(listId) else {
continue
}
guard let channel = peer as? TelegramChannel, case .broadcast = channel.info else {
continue continue
} }
if channel.id == peerId { if channel.id == peerId {
@ -516,6 +519,7 @@ public extension TelegramEngine {
guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else { guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else {
continue continue
} }
results.append((EnginePeer(channel), topMessageIndex.timestamp)) results.append((EnginePeer(channel), topMessageIndex.timestamp))
} }

View File

@ -137,6 +137,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case callsTabTip = 18 case callsTabTip = 18
case chatFolderTips = 19 case chatFolderTips = 19
case locationProximityAlertTip = 20 case locationProximityAlertTip = 20
case nextChatSuggestionTip = 21
var key: ValueBoxKey { var key: ValueBoxKey {
let v = ValueBoxKey(length: 4) let v = ValueBoxKey(length: 4)
@ -268,6 +269,10 @@ private struct ApplicationSpecificNoticeKeys {
static func locationProximityAlertTip() -> NoticeEntryKey { static func locationProximityAlertTip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.locationProximityAlertTip.key) return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.locationProximityAlertTip.key)
} }
static func nextChatSuggestionTip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.nextChatSuggestionTip.key)
}
} }
public struct ApplicationSpecificNotice { public struct ApplicationSpecificNotice {
@ -736,6 +741,28 @@ public struct ApplicationSpecificNotice {
} }
} }
public static func getNextChatSuggestionTip(accountManager: AccountManager) -> Signal<Int32, NoError> {
return accountManager.transaction { transaction -> Int32 in
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip()) as? ApplicationSpecificCounterNotice {
return value.value
} else {
return 0
}
}
}
public static func incrementNextChatSuggestionTip(accountManager: AccountManager, count: Int32 = 1) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
var currentValue: Int32 = 0
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip()) as? ApplicationSpecificCounterNotice {
currentValue = value.value
}
currentValue += count
transaction.setNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip(), ApplicationSpecificCounterNotice(value: currentValue))
}
}
public static func reset(accountManager: AccountManager) -> Signal<Void, NoError> { public static func reset(accountManager: AccountManager) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in return accountManager.transaction { transaction -> Void in
} }

View File

@ -64,6 +64,7 @@ import TelegramPermissionsUI
import Speak import Speak
import UniversalMediaPlayer import UniversalMediaPlayer
import WallpaperBackgroundNode import WallpaperBackgroundNode
import ChatListUI
#if DEBUG #if DEBUG
import os.signpost import os.signpost
@ -213,6 +214,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
public weak var parentController: ViewController? public weak var parentController: ViewController?
private let currentChatListFilter: ChatListFilterData?
public var peekActions: ChatControllerPeekActions = .standard public var peekActions: ChatControllerPeekActions = .standard
private var didSetup3dTouch: Bool = false private var didSetup3dTouch: Bool = false
@ -283,6 +286,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var preloadHistoryPeerId: PeerId? private var preloadHistoryPeerId: PeerId?
private let preloadHistoryPeerIdDisposable = MetaDisposable() private let preloadHistoryPeerIdDisposable = MetaDisposable()
private var preloadNextChatPeerId: PeerId?
private let preloadNextChatPeerIdDisposable = MetaDisposable()
private let botCallbackAlertMessage = Promise<String?>(nil) private let botCallbackAlertMessage = Promise<String?>(nil)
private var botCallbackAlertMessageDisposable: Disposable? private var botCallbackAlertMessageDisposable: Disposable?
@ -459,7 +465,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var nextChannelToReadDisposable: Disposable? private var nextChannelToReadDisposable: Disposable?
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil) { public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: ChatListFilterData? = nil) {
let _ = ChatControllerCount.modify { value in let _ = ChatControllerCount.modify { value in
return value + 1 return value + 1
} }
@ -470,6 +476,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.subject = subject self.subject = subject
self.botStart = botStart self.botStart = botStart
self.peekData = peekData self.peekData = peekData
self.currentChatListFilter = chatListFilter
var useSharedAnimationPhase = false var useSharedAnimationPhase = false
switch mode { switch mode {
@ -3306,16 +3313,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info { if let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
if strongSelf.nextChannelToReadDisposable == nil { if strongSelf.nextChannelToReadDisposable == nil {
strongSelf.nextChannelToReadDisposable = (strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id) strongSelf.nextChannelToReadDisposable = (combineLatest(queue: .mainQueue(),
|> deliverOnMainQueue strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, filter: strongSelf.currentChatListFilter.flatMap(chatListFilterPredicate)),
ApplicationSpecificNotice.getNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager)
)
|> then(.complete() |> delay(1.0, queue: .mainQueue())) |> then(.complete() |> delay(1.0, queue: .mainQueue()))
|> restart).start(next: { nextPeer in |> restart).start(next: { nextPeer, nextChatSuggestionTip in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
strongSelf.chatDisplayNode.historyNode.offerNextChannelToRead = true strongSelf.chatDisplayNode.historyNode.offerNextChannelToRead = true
strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer
strongSelf.chatDisplayNode.historyNode.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
let nextPeerId = nextPeer?.id
if strongSelf.preloadNextChatPeerId != nextPeerId {
strongSelf.preloadNextChatPeerId = nextPeerId
if let nextPeerId = nextPeerId {
let combinedDisposable = DisposableSet()
strongSelf.preloadNextChatPeerIdDisposable.set(combinedDisposable)
combinedDisposable.add(strongSelf.context.account.viewTracker.polledChannel(peerId: nextPeerId).start())
combinedDisposable.add(strongSelf.context.account.addAdditionalPreloadHistoryPeerId(peerId: nextPeerId))
} else {
strongSelf.preloadNextChatPeerIdDisposable.set(nil)
}
}
}) })
} }
} }
@ -3878,6 +3902,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.shareStatusDisposable?.dispose() self.shareStatusDisposable?.dispose()
self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeTarget(self) self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeTarget(self)
self.preloadHistoryPeerIdDisposable.dispose() self.preloadHistoryPeerIdDisposable.dispose()
self.preloadNextChatPeerIdDisposable.dispose()
self.reportIrrelvantGeoDisposable?.dispose() self.reportIrrelvantGeoDisposable?.dispose()
self.reminderActivity?.invalidate() self.reminderActivity?.invalidate()
self.updateSlowmodeStatusDisposable.dispose() self.updateSlowmodeStatusDisposable.dispose()
@ -7053,11 +7078,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
if let navigationController = strongSelf.effectiveNavigationController { if let navigationController = strongSelf.effectiveNavigationController {
ApplicationSpecificNotice.incrementNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager).start()
let snapshotState = strongSelf.chatDisplayNode.prepareSnapshotState( let snapshotState = strongSelf.chatDisplayNode.prepareSnapshotState(
titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(), titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(),
avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState() avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState()
) )
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, completion: { nextController in strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: strongSelf.currentChatListFilter, completion: { nextController in
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState) (nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
})) }))
} }

View File

@ -551,6 +551,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
private var overscrollView: ComponentHostView<Empty>? private var overscrollView: ComponentHostView<Empty>?
var nextChannelToRead: EnginePeer? var nextChannelToRead: EnginePeer?
var offerNextChannelToRead: Bool = false var offerNextChannelToRead: Bool = false
var nextChannelToReadDisplayName: Bool = false
private var currentOverscrollExpandProgress: CGFloat = 0.0 private var currentOverscrollExpandProgress: CGFloat = 0.0
private var feedback: HapticFeedback? private var feedback: HapticFeedback?
var openNextChannelToRead: ((EnginePeer) -> Void)? var openNextChannelToRead: ((EnginePeer) -> Void)?
@ -1217,16 +1218,26 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
self.view.addSubview(overscrollView) self.view.addSubview(overscrollView)
} }
let expandProgress: CGFloat = min(1.0, max(-offset, 0.0) / 110.0) let expandDistance = max(-offset - 12.0, 0.0)
let expandProgress: CGFloat = min(1.0, expandDistance / 90.0)
let text: String let text: String
if self.nextChannelToRead != nil { if let nextChannelToRead = nextChannelToRead {
if self.nextChannelToReadDisplayName {
if expandProgress >= 0.99 {
//TODO:localize
text = "Release to go to \(nextChannelToRead.compactDisplayTitle)"
} else {
text = "Swipe up to go to \(nextChannelToRead.compactDisplayTitle)"
}
} else {
if expandProgress >= 0.99 { if expandProgress >= 0.99 {
//TODO:localize //TODO:localize
text = "Release to go to the next unread channel" text = "Release to go to the next unread channel"
} else { } else {
text = "Swipe up to go to the next unread channel" text = "Swipe up to go to the next unread channel"
} }
}
let previousType = self.currentOverscrollExpandProgress >= 0.99 let previousType = self.currentOverscrollExpandProgress >= 0.99
let currentType = expandProgress >= 0.99 let currentType = expandProgress >= 0.99
@ -1251,7 +1262,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
foregroundColor: bubbleVariableColor(variableColor: self.currentPresentationData.theme.theme.chat.serviceMessage.dateTextColor, wallpaper: self.currentPresentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: self.currentPresentationData.theme.theme.chat.serviceMessage.dateTextColor, wallpaper: self.currentPresentationData.theme.wallpaper),
peer: self.nextChannelToRead, peer: self.nextChannelToRead,
context: self.context, context: self.context,
expandProgress: expandProgress expandDistance: expandDistance
)), )),
environment: {}, environment: {},
containerSize: CGSize(width: self.bounds.width, height: 200.0) containerSize: CGSize(width: self.bounds.width, height: 200.0)

View File

@ -341,7 +341,7 @@ final class ChatOverscrollControl: CombinedComponent {
let foregroundColor: UIColor let foregroundColor: UIColor
let peer: EnginePeer? let peer: EnginePeer?
let context: AccountContext let context: AccountContext
let expandProgress: CGFloat let expandDistance: CGFloat
init( init(
text: String, text: String,
@ -349,14 +349,14 @@ final class ChatOverscrollControl: CombinedComponent {
foregroundColor: UIColor, foregroundColor: UIColor,
peer: EnginePeer?, peer: EnginePeer?,
context: AccountContext, context: AccountContext,
expandProgress: CGFloat expandDistance: CGFloat
) { ) {
self.text = text self.text = text
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
self.foregroundColor = foregroundColor self.foregroundColor = foregroundColor
self.peer = peer self.peer = peer
self.context = context self.context = context
self.expandProgress = expandProgress self.expandDistance = expandDistance
} }
static func ==(lhs: ChatOverscrollControl, rhs: ChatOverscrollControl) -> Bool { static func ==(lhs: ChatOverscrollControl, rhs: ChatOverscrollControl) -> Bool {
@ -375,7 +375,7 @@ final class ChatOverscrollControl: CombinedComponent {
if lhs.context !== rhs.context { if lhs.context !== rhs.context {
return false return false
} }
if lhs.expandProgress != rhs.expandProgress { if lhs.expandDistance != rhs.expandDistance {
return false return false
} }
return true return true
@ -431,13 +431,32 @@ final class ChatOverscrollControl: CombinedComponent {
) )
}) })
let progressSize = avatarBackground.size.width - avatarProgressPadding * 2.0
let halfDistance = progressSize
let quarterDistance = halfDistance / 2.0
let clippedDistance = max(0.0, min(halfDistance * 2.0, context.component.expandDistance))
var mappedProgress: CGFloat
if clippedDistance <= quarterDistance {
mappedProgress = acos(1.0 - clippedDistance / quarterDistance) / (CGFloat.pi * 2.0)
} else if clippedDistance <= halfDistance {
let sectionDistance = halfDistance - clippedDistance
mappedProgress = 0.25 + asin(1.0 - sectionDistance / quarterDistance) / (CGFloat.pi * 2.0)
} else {
let restDistance = clippedDistance - halfDistance
mappedProgress = min(1.0, 0.5 + restDistance / 60.0)
}
mappedProgress = max(0.01, mappedProgress)
let avatarExpandProgress = avatarExpandProgress.update( let avatarExpandProgress = avatarExpandProgress.update(
component: RadialProgressComponent( component: RadialProgressComponent(
color: context.component.foregroundColor, color: context.component.foregroundColor,
lineWidth: 2.5, lineWidth: 2.5,
value: context.component.peer == nil ? 0.0 : context.component.expandProgress value: context.component.peer == nil ? 0.0 : mappedProgress
), ),
availableSize: CGSize(width: avatarBackground.size.width - avatarProgressPadding * 2.0, height: avatarBackground.size.height - avatarProgressPadding * 2.0), availableSize: CGSize(width: progressSize, height: progressSize),
transition: context.transition transition: context.transition
) )

View File

@ -70,7 +70,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
}) })
} }
} else { } else {
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData) controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter)
} }
controller.purposefulAction = params.purposefulAction controller.purposefulAction = params.purposefulAction
if let search = params.activateMessageSearch { if let search = params.activateMessageSearch {