UI improvements

This commit is contained in:
Ali 2022-12-02 14:48:12 +04:00
parent 69952fc374
commit 181fee81d4
5 changed files with 130 additions and 65 deletions

View File

@ -414,6 +414,7 @@ official_apple_pay_merchants = [
"merchant.psbank.test.telegramios", "merchant.psbank.test.telegramios",
"merchant.psbank.prod.telegramios", "merchant.psbank.prod.telegramios",
#"merchant.org.telegram.billinenet.test", #"merchant.org.telegram.billinenet.test",
#"merchant.org.telegram.billinenet.prod",
#"merchant.org.telegram.portmone.test", #"merchant.org.telegram.portmone.test",
] ]

View File

@ -8267,8 +8267,8 @@ Sorry for the inconvenience.";
"Undo.DeletedTopic" = "Topic Deleted"; "Undo.DeletedTopic" = "Topic Deleted";
"ChatList.MaxThreadPinsFinalText_1" = "Sorry, you can't pin more than **%@** thread to the top. Unpin some that are currently pinned."; "ChatList.MaxThreadPinsFinalText_1" = "Sorry, you can't pin more than %@ topics to the top. Unpin some that are currently pinned.";
"ChatList.MaxThreadPinsFinalText_any" = "Sorry, you can't pin more than **%@** threads to the top. Unpin some that are currently pinned."; "ChatList.MaxThreadPinsFinalText_any" = "Sorry, you can't pin more than %@ topics to the top. Unpin some that are currently pinned.";
"EmojiSearch.SearchTopicIconsPlaceholder" = "Search Topic Icons"; "EmojiSearch.SearchTopicIconsPlaceholder" = "Search Topic Icons";
"EmojiSearch.SearchTopicIconsEmptyResult" = "No emoji found"; "EmojiSearch.SearchTopicIconsEmptyResult" = "No emoji found";
@ -8299,8 +8299,8 @@ Sorry for the inconvenience.";
"Notification.ForumTopicHidden" = "Topic hidden"; "Notification.ForumTopicHidden" = "Topic hidden";
"Notification.ForumTopicUnhidden" = "Topic unhidden"; "Notification.ForumTopicUnhidden" = "Topic unhidden";
"Notification.ForumTopicHiddenAuthor" = "%1$@ hid topic"; "Notification.ForumTopicHiddenAuthor" = "%1$@ hid the topic";
"Notification.ForumTopicUnhiddenAuthor" = "%1$@ unhid topic"; "Notification.ForumTopicUnhiddenAuthor" = "%1$@ unhid the topic";
"Notification.OverviewTopicHidden" = "%1$@ hid %2$@ %3$@"; "Notification.OverviewTopicHidden" = "%1$@ hid %2$@ %3$@";
"Notification.OverviewTopicUnhidden" = "%1$@ unhid %2$@ %3$@"; "Notification.OverviewTopicUnhidden" = "%1$@ unhid %2$@ %3$@";

View File

@ -865,6 +865,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if let layout = self.validLayout { if let layout = self.validLayout {
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.effectiveContainerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.effectiveContainerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.effectiveContainerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.effectiveContainerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
self.requestUpdateHeaderContent(transition: .immediate)
} }
if self.isNodeLoaded { if self.isNodeLoaded {

View File

@ -721,7 +721,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
}) })
case .index: case .index:
var headerType: ChatListSearchItemHeaderType = .messages(location: nil) var headerType: ChatListSearchItemHeaderType = .messages(location: nil)
if case .forum = location, let peer = peer.peer { if case let .forum(peerId) = location, let peer = peer.peer, peer.id == peerId {
headerType = .messages(location: peer.compactDisplayTitle) headerType = .messages(location: peer.compactDisplayTitle)
} }
header = ChatListSearchItemHeader(type: headerType, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) header = ChatListSearchItemHeader(type: headerType, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil)
@ -741,12 +741,16 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
switch location { switch location {
case .chatList: case .chatList:
index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index))
case .forum: case let .forum(peerId):
if let threadId = message.threadId, let threadInfo = threadInfo { if message.id.peerId == peerId, !"".isEmpty {
chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwnedByMe: false, isClosed: false, isHidden: false) if let threadId = message.threadId, let threadInfo = threadInfo {
index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id) chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwnedByMe: false, isClosed: false, isHidden: false)
index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id)
} else {
index = .chatList( EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index))
}
} else { } else {
index = .chatList( EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index))
} }
} }
return ChatListItem(presentationData: presentationData, context: context, chatListLocation: location, filterData: nil, index: index, content: .peer(ChatListItemContent.PeerData( return ChatListItem(presentationData: presentationData, context: context, chatListLocation: location, filterData: nil, index: index, content: .peer(ChatListItemContent.PeerData(
@ -762,7 +766,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
inputActivities: nil, inputActivities: nil,
promoInfo: nil, promoInfo: nil,
ignoreUnreadBadge: true, ignoreUnreadBadge: true,
displayAsMessage: false, displayAsMessage: true,
hasFailedMessages: false, hasFailedMessages: false,
forumTopicData: nil, forumTopicData: nil,
topForumTopicItems: [], topForumTopicItems: [],
@ -1217,7 +1221,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
} }
let previousRecentlySearchedPeersState = Atomic<SearchedPeersState?>(value: nil) let previousRecentlySearchedPeersState = Atomic<SearchedPeersState?>(value: nil)
let foundItems = combineLatest(queue: .mainQueue(), searchQuery, searchOptions, downloadItems) let foundItems: Signal<([ChatListSearchEntry], Bool)?, NoError> = combineLatest(queue: .mainQueue(), searchQuery, searchOptions, downloadItems)
|> mapToSignal { [weak self] query, options, downloadItems -> Signal<([ChatListSearchEntry], Bool)?, NoError> in |> mapToSignal { [weak self] query, options, downloadItems -> Signal<([ChatListSearchEntry], Bool)?, NoError> in
if query == nil && options == nil && [.chats, .topics].contains(key) { if query == nil && options == nil && [.chats, .topics].contains(key) {
let _ = currentRemotePeers.swap(nil) let _ = currentRemotePeers.swap(nil)
@ -1464,9 +1468,24 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
updateSearchContexts { _ in updateSearchContexts { _ in
return ([:], true) return ([:], true)
} }
let foundRemoteMessages: Signal<(([EngineMessage], [EnginePeer.Id: EnginePeerReadCounters], [EngineMessage.Id: MessageHistoryThreadData], Int32), Bool), NoError>
struct FoundRemoteMessages {
var messages: [EngineMessage]
var readCounters: [EnginePeer.Id: EnginePeerReadCounters]
var threadsData: [EngineMessage.Id: MessageHistoryThreadData]
var totalCount: Int32
init(messages: [EngineMessage], readCounters: [EnginePeer.Id: EnginePeerReadCounters], threadsData: [EngineMessage.Id: MessageHistoryThreadData], totalCount: Int32) {
self.messages = messages
self.readCounters = readCounters
self.threadsData = threadsData
self.totalCount = totalCount
}
}
let foundRemoteMessages: Signal<([FoundRemoteMessages], Bool), NoError>
if peersFilter.contains(.doNotSearchMessages) { if peersFilter.contains(.doNotSearchMessages) {
foundRemoteMessages = .single((([], [:], [:], 0), false)) foundRemoteMessages = .single(([FoundRemoteMessages(messages: [], readCounters: [:], threadsData: [:], totalCount: 0)], false))
} else { } else {
if !finalQuery.isEmpty { if !finalQuery.isEmpty {
addAppLogEvent(postbox: context.account.postbox, type: "search_global_query") addAppLogEvent(postbox: context.account.postbox, type: "search_global_query")
@ -1477,42 +1496,73 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
} }
let searchSignal = combineLatest(searchSignals) let searchSignal = combineLatest(searchSignals)
|> map { results -> ChatListSearchMessagesResult in |> map { results -> [ChatListSearchMessagesResult] in
let (result, updatedState) = results[0] var mappedResults: [ChatListSearchMessagesResult] = []
return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.map({ EngineMessage($0) }).sorted(by: { $0.index > $1.index }), readStates: result.readStates.mapValues { EnginePeerReadCounters(state: $0, isMuted: false) }, threadInfo: result.threadInfo, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState) for resultData in results {
let (result, updatedState) = resultData
mappedResults.append(ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.map({ EngineMessage($0) }).sorted(by: { $0.index > $1.index }), readStates: result.readStates.mapValues { EnginePeerReadCounters(state: $0, isMuted: false) }, threadInfo: result.threadInfo, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState))
}
return mappedResults
} }
let loadMore = searchContexts.get() let loadMore = searchContexts.get()
|> mapToSignal { searchContexts -> Signal<(([EngineMessage], [EnginePeer.Id: EnginePeerReadCounters], [EngineMessage.Id: MessageHistoryThreadData], Int32), Bool), NoError> in |> mapToSignal { searchContexts -> Signal<([FoundRemoteMessages], Bool), NoError> in
if let searchContext = searchContexts[0], searchContext.result.hasMore { for i in 0 ..< 2 {
if let _ = searchContext.loadMoreIndex { if let searchContext = searchContexts[i], searchContext.result.hasMore {
return context.engine.messages.searchMessages(location: searchLocations[0], query: finalQuery, state: searchContext.result.state, limit: 80) var restResults: [Int: FoundRemoteMessages] = [:]
|> map { result, updatedState -> ChatListSearchMessagesResult in for j in 0 ..< 2 {
return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.map({ EngineMessage($0) }).sorted(by: { $0.index > $1.index }), readStates: result.readStates.mapValues { EnginePeerReadCounters(state: $0, isMuted: false) }, threadInfo: result.threadInfo, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState) if j != i {
} if let otherContext = searchContexts[j] {
|> mapToSignal { foundMessages -> Signal<(([EngineMessage], [EnginePeer.Id: EnginePeerReadCounters], [EngineMessage.Id: MessageHistoryThreadData], Int32), Bool), NoError> in restResults[j] = FoundRemoteMessages(messages: otherContext.result.messages, readCounters: otherContext.result.readStates, threadsData: otherContext.result.threadInfo, totalCount: otherContext.result.totalCount)
updateSearchContexts { previous in }
let updated = ChatListSearchMessagesContext(result: foundMessages, loadMoreIndex: nil)
return ([0: updated], true)
} }
return .complete()
} }
} else { if let _ = searchContext.loadMoreIndex {
return .single(((searchContext.result.messages, searchContext.result.readStates, searchContext.result.threadInfo, searchContext.result.totalCount), false)) return context.engine.messages.searchMessages(location: searchLocations[i], query: finalQuery, state: searchContext.result.state, limit: 80)
|> map { result, updatedState -> ChatListSearchMessagesResult in
return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.map({ EngineMessage($0) }).sorted(by: { $0.index > $1.index }), readStates: result.readStates.mapValues { EnginePeerReadCounters(state: $0, isMuted: false) }, threadInfo: result.threadInfo, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState)
}
|> mapToSignal { foundMessages -> Signal<([FoundRemoteMessages], Bool), NoError> in
updateSearchContexts { previous in
let updated = ChatListSearchMessagesContext(result: foundMessages, loadMoreIndex: nil)
var previous = previous
previous[i] = updated
return (previous, true)
}
return .complete()
}
} else {
var currentResults: [FoundRemoteMessages] = []
for i in 0 ..< 2 {
if let currentContext = searchContexts[i] {
currentResults.append(FoundRemoteMessages(messages: currentContext.result.messages, readCounters: currentContext.result.readStates, threadsData: currentContext.result.threadInfo, totalCount: currentContext.result.totalCount))
}
}
return .single((currentResults, false))
}
} }
} else {
return .complete()
} }
return .complete()
} }
foundRemoteMessages = .single((([], [:], [:], 0), true)) foundRemoteMessages = .single(([FoundRemoteMessages(messages: [], readCounters: [:], threadsData: [:], totalCount: 0)], true))
|> then( |> then(
searchSignal searchSignal
|> map { foundMessages -> (([EngineMessage], [EnginePeer.Id: EnginePeerReadCounters], [EngineMessage.Id: MessageHistoryThreadData], Int32), Bool) in |> map { foundMessages -> ([FoundRemoteMessages], Bool) in
updateSearchContexts { _ in updateSearchContexts { _ in
return ([0: ChatListSearchMessagesContext(result: foundMessages, loadMoreIndex: nil)], true) var resultContexts: [Int: ChatListSearchMessagesContext] = [:]
for i in 0 ..< foundMessages.count {
resultContexts[i] = ChatListSearchMessagesContext(result: foundMessages[i], loadMoreIndex: nil)
}
return (resultContexts, true)
} }
return ((foundMessages.messages, foundMessages.readStates, foundMessages.threadInfo, foundMessages.totalCount), false) var result: [FoundRemoteMessages] = []
for i in 0 ..< foundMessages.count {
result.append(FoundRemoteMessages(messages: foundMessages[i].messages, readCounters: foundMessages[i].readStates, threadsData: foundMessages[i].threadInfo, totalCount: foundMessages[i].totalCount))
}
return (result, false)
} }
|> delay(0.2, queue: Queue.concurrentDefaultQueue()) |> delay(0.2, queue: Queue.concurrentDefaultQueue())
|> then(loadMore) |> then(loadMore)
@ -1766,25 +1816,33 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
var firstHeaderId: Int64? var firstHeaderId: Int64?
if !foundRemotePeers.2 { if !foundRemotePeers.2 {
index = 0 index = 0
for message in foundRemoteMessages.0.0 { var existingMessageIds = Set<MessageId>()
if searchState.deletedMessageIds.contains(message.id) { for foundRemoteMessageSet in foundRemoteMessages.0 {
continue for message in foundRemoteMessageSet.messages {
} else if message.id.namespace == Namespaces.Message.Cloud && searchState.deletedGlobalMessageIds.contains(message.id.id) { if existingMessageIds.contains(message.id) {
continue continue
}
let headerId = listMessageDateHeaderId(timestamp: message.timestamp)
if firstHeaderId == nil {
firstHeaderId = headerId
}
var peer = EngineRenderedPeer(message: message)
if let group = message.peers[message.id.peerId] as? TelegramGroup, let migrationReference = group.migrationReference {
if let channelPeer = message.peers[migrationReference.peerId] {
peer = EngineRenderedPeer(peer: EnginePeer(channelPeer))
} }
existingMessageIds.insert(message.id)
if searchState.deletedMessageIds.contains(message.id) {
continue
} else if message.id.namespace == Namespaces.Message.Cloud && searchState.deletedGlobalMessageIds.contains(message.id.id) {
continue
}
let headerId = listMessageDateHeaderId(timestamp: message.timestamp)
if firstHeaderId == nil {
firstHeaderId = headerId
}
var peer = EngineRenderedPeer(message: message)
if let group = message.peers[message.id.peerId] as? TelegramGroup, let migrationReference = group.migrationReference {
if let channelPeer = message.peers[migrationReference.peerId] {
peer = EngineRenderedPeer(peer: EnginePeer(channelPeer))
}
}
entries.append(.message(message, peer, foundRemoteMessageSet.readCounters[message.id.peerId], foundRemoteMessageSet.threadsData[message.id]?.info, presentationData, foundRemoteMessageSet.totalCount, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false))
index += 1
} }
entries.append(.message(message, peer, foundRemoteMessages.0.1[message.id.peerId], foundRemoteMessages.0.2[message.id]?.info, presentationData, foundRemoteMessages.0.3, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false))
index += 1
} }
} }
@ -1919,6 +1977,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
self.listNode.clearHighlightAnimated(true) self.listNode.clearHighlightAnimated(true)
}) })
}) })
chatListInteraction.isSearchMode = true
let listInteraction = ListMessageItemInteraction(openMessage: { [weak self] message, mode -> Bool in let listInteraction = ListMessageItemInteraction(openMessage: { [weak self] message, mode -> Bool in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -2023,25 +2082,25 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
}) })
self.searchDisposable.set((foundItems self.searchDisposable.set((foundItems
|> deliverOnMainQueue).start(next: { [weak self] entriesAndFlags in |> deliverOnMainQueue).start(next: { [weak self] foundItems in
if let strongSelf = self { if let strongSelf = self {
let previousSelectedMessageIds = previousSelectedMessages.swap(strongSelf.selectedMessages) let previousSelectedMessageIds = previousSelectedMessages.swap(strongSelf.selectedMessages)
let isSearching = entriesAndFlags?.1 ?? false var entriesAndFlags = foundItems?.0
let isSearching = foundItems?.1 ?? false
strongSelf._isSearching.set(isSearching) strongSelf._isSearching.set(isSearching)
if strongSelf.tagMask == .photoOrVideo { if strongSelf.tagMask == .photoOrVideo {
var entries: [ChatListSearchEntry]? = entriesAndFlags?.0 ?? [] var entries: [ChatListSearchEntry]? = entriesAndFlags ?? []
if isSearching && (entries?.isEmpty ?? true) { if isSearching && (entries?.isEmpty ?? true) {
entries = nil entries = nil
} }
strongSelf.mediaNode.updateHistory(entries: entries, totalCount: 0, updateType: .Initial) strongSelf.mediaNode.updateHistory(entries: entries, totalCount: 0, updateType: .Initial)
} }
var entriesAndFlags = entriesAndFlags
var peers: [EnginePeer] = [] var peers: [EnginePeer] = []
if let entries = entriesAndFlags?.0 { if let entries = entriesAndFlags {
var filteredEntries: [ChatListSearchEntry] = [] var filteredEntries: [ChatListSearchEntry] = []
for entry in entries { for entry in entries {
if case let .localPeer(peer, _, _, _, _, _, _, _, _) = entry { if case let .localPeer(peer, _, _, _, _, _, _, _, _) = entry {
@ -2053,16 +2112,16 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
} }
if strongSelf.tagMask != nil || strongSelf.searchOptionsValue?.date != nil || strongSelf.searchOptionsValue?.peer != nil { if strongSelf.tagMask != nil || strongSelf.searchOptionsValue?.date != nil || strongSelf.searchOptionsValue?.peer != nil {
entriesAndFlags?.0 = filteredEntries entriesAndFlags = filteredEntries
} }
} }
let previousEntries = previousSearchItems.swap(entriesAndFlags?.0) let previousEntries = previousSearchItems.swap(entriesAndFlags)
let newEntries = entriesAndFlags?.0 ?? [] let newEntries = entriesAndFlags ?? []
let animated = (previousSelectedMessageIds == nil) != (strongSelf.selectedMessages == nil) let animated = (previousSelectedMessageIds == nil) != (strongSelf.selectedMessages == nil)
let firstTime = previousEntries == nil let firstTime = previousEntries == nil
var transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: newEntries, displayingResults: entriesAndFlags?.0 != nil, isEmpty: !isSearching && (entriesAndFlags?.0.isEmpty ?? false), isLoading: isSearching, animated: animated, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: peersFilter, location: location, key: strongSelf.key, tagMask: tagMask, interaction: chatListInteraction, listInteraction: listInteraction, peerContextAction: { message, node, rect, gesture, location in var transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: newEntries, displayingResults: entriesAndFlags != nil, isEmpty: !isSearching && (entriesAndFlags?.isEmpty ?? false), isLoading: isSearching, animated: animated, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: peersFilter, location: location, key: strongSelf.key, tagMask: tagMask, interaction: chatListInteraction, listInteraction: listInteraction, peerContextAction: { message, node, rect, gesture, location in
interaction.peerContextAction?(message, node, rect, gesture, location) interaction.peerContextAction?(message, node, rect, gesture, location)
}, toggleExpandLocalResults: { }, toggleExpandLocalResults: {
guard let strongSelf = self else { guard let strongSelf = self else {
@ -3115,8 +3174,9 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
}, present: { _ in }, openForumThread: { _, _ in }) }, present: { _ in }, openForumThread: { _, _ in })
var isInlineMode = false var isInlineMode = false
if case .topics = key { if case .topics = key {
isInlineMode = true isInlineMode = false
} }
interaction.isSearchMode = true
interaction.isInlineMode = isInlineMode interaction.isInlineMode = isInlineMode
let items = (0 ..< 2).compactMap { _ -> ListViewItem? in let items = (0 ..< 2).compactMap { _ -> ListViewItem? in

View File

@ -95,6 +95,8 @@ public final class ChatListNodeInteraction {
public var searchTextHighightState: String? public var searchTextHighightState: String?
var highlightedChatLocation: ChatListHighlightedLocation? var highlightedChatLocation: ChatListHighlightedLocation?
var isSearchMode: Bool = false
var isInlineMode: Bool = false var isInlineMode: Bool = false
var inlineNavigationLocation: ChatListHighlightedLocation? var inlineNavigationLocation: ChatListHighlightedLocation?