mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Global search
This commit is contained in:
parent
b8ac955792
commit
e315e6da6e
@ -157,6 +157,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
private let sharedOpenStoryDisposable = MetaDisposable()
|
||||
private var recentAppsDisposable: Disposable?
|
||||
private var refreshedGlobalPostSearchStateDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, filter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openRecentPeerOptions: @escaping (EnginePeer) -> Void, openMessage originalOpenMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, parentController: @escaping () -> ViewController?) {
|
||||
var initialFilter = initialFilter
|
||||
@ -531,6 +532,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
self.recentAppsDisposable = context.engine.peers.managedUpdatedRecentApps().startStrict()
|
||||
self.refreshedGlobalPostSearchStateDisposable = context.engine.messages.refreshGlobalPostSearchState().startStrict()
|
||||
|
||||
self._ready.set(self.paneContainerNode.isReady.get()
|
||||
|> map { _ in Void() })
|
||||
@ -543,6 +545,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
self.shareStatusDisposable?.dispose()
|
||||
self.sharedOpenStoryDisposable.dispose()
|
||||
self.recentAppsDisposable?.dispose()
|
||||
self.refreshedGlobalPostSearchStateDisposable?.dispose()
|
||||
|
||||
self.copyProtectionTooltipController?.dismiss()
|
||||
}
|
||||
|
@ -1298,11 +1298,10 @@ public struct ChatListSearchContainerTransition {
|
||||
public let isLoading: Bool
|
||||
public let query: String?
|
||||
public let approvedGlobalPostQueryState: ApprovedGlobalPostQueryState?
|
||||
public let remainingGlobalSearches: Int
|
||||
public let globalSearchUnlockTimestamp: Int32?
|
||||
public let globalSearchStateValue: TelegramGlobalPostSearchState?
|
||||
public var animated: Bool
|
||||
|
||||
public init(deletions: [ListViewDeleteItem], insertions: [ListViewInsertItem], updates: [ListViewUpdateItem], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, query: String?, approvedGlobalPostQueryState: ApprovedGlobalPostQueryState?, remainingGlobalSearches: Int, globalSearchUnlockTimestamp: Int32?, animated: Bool) {
|
||||
public init(deletions: [ListViewDeleteItem], insertions: [ListViewInsertItem], updates: [ListViewUpdateItem], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, query: String?, approvedGlobalPostQueryState: ApprovedGlobalPostQueryState?, globalSearchStateValue: TelegramGlobalPostSearchState?, animated: Bool) {
|
||||
self.deletions = deletions
|
||||
self.insertions = insertions
|
||||
self.updates = updates
|
||||
@ -1310,8 +1309,7 @@ public struct ChatListSearchContainerTransition {
|
||||
self.isEmpty = isEmpty
|
||||
self.isLoading = isLoading
|
||||
self.approvedGlobalPostQueryState = approvedGlobalPostQueryState
|
||||
self.remainingGlobalSearches = remainingGlobalSearches
|
||||
self.globalSearchUnlockTimestamp = globalSearchUnlockTimestamp
|
||||
self.globalSearchStateValue = globalSearchStateValue
|
||||
self.query = query
|
||||
self.animated = animated
|
||||
}
|
||||
@ -1376,8 +1374,7 @@ public func chatListSearchContainerPreparedTransition(
|
||||
searchPeer: @escaping (EnginePeer) -> Void,
|
||||
searchQuery: String?,
|
||||
approvedGlobalPostQueryState: ApprovedGlobalPostQueryState?,
|
||||
remainingGlobalSearches: Int,
|
||||
globalSearchUnlockTimestamp: Int32?,
|
||||
globalSearchStateValue: TelegramGlobalPostSearchState?,
|
||||
searchOptions: ChatListSearchOptions?,
|
||||
messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?,
|
||||
openClearRecentlyDownloaded: @escaping () -> Void,
|
||||
@ -1393,7 +1390,7 @@ public func chatListSearchContainerPreparedTransition(
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, requestPeerType: requestPeerType, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused, openStories: openStories, openPublicPosts: openPublicPosts, openMessagesFilter: openMessagesFilter, switchMessagesFilter: switchMessagesFilter), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, requestPeerType: requestPeerType, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused, openStories: openStories, openPublicPosts: openPublicPosts, openMessagesFilter: openMessagesFilter, switchMessagesFilter: switchMessagesFilter), directionHint: nil) }
|
||||
|
||||
return ChatListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, displayingResults: displayingResults, isEmpty: isEmpty, isLoading: isLoading, query: searchQuery, approvedGlobalPostQueryState: approvedGlobalPostQueryState, remainingGlobalSearches: remainingGlobalSearches, globalSearchUnlockTimestamp: globalSearchUnlockTimestamp, animated: animated)
|
||||
return ChatListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, displayingResults: displayingResults, isEmpty: isEmpty, isLoading: isLoading, query: searchQuery, approvedGlobalPostQueryState: approvedGlobalPostQueryState, globalSearchStateValue: globalSearchStateValue, animated: animated)
|
||||
}
|
||||
|
||||
private struct ChatListSearchListPaneNodeState: Equatable {
|
||||
@ -1620,16 +1617,6 @@ public struct ApprovedGlobalPostQueryState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
struct TelegramGlobalPostSearchState: Equatable {
|
||||
var remainingSearches: Int
|
||||
var unlockTimestamp: Int32?
|
||||
|
||||
init(remainingSearches: Int, unlockTimestamp: Int32?) {
|
||||
self.remainingSearches = remainingSearches
|
||||
self.unlockTimestamp = unlockTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private let context: AccountContext
|
||||
private let animationCache: AnimationCache
|
||||
@ -1676,7 +1663,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private var searchQueryValue: String?
|
||||
private var searchOptionsValue: ChatListSearchOptions?
|
||||
private var approvedGlobalPostQueryStateValue: ApprovedGlobalPostQueryState?
|
||||
private var globalPostSearchStateValue: TelegramGlobalPostSearchState
|
||||
private var globalPostSearchStateValue: TelegramGlobalPostSearchState?
|
||||
private var globalPostSearchUnlockTimer: Foundation.Timer?
|
||||
private var isPremium: Bool = false
|
||||
|
||||
@ -1737,7 +1724,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private let searchScopePromise = ValuePromise<TelegramSearchPeersScope>(.everywhere)
|
||||
|
||||
private let approvedGlobalPostQueryState = ValuePromise<ApprovedGlobalPostQueryState?>(nil, ignoreRepeated: true)
|
||||
private let globalPostSearchState = Promise<TelegramGlobalPostSearchState>()
|
||||
private let globalPostSearchState = Promise<TelegramGlobalPostSearchState?>()
|
||||
|
||||
private var refreshGlobalPostSearchStateDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, interaction: ChatListSearchInteraction, key: ChatListSearchPaneKey, peersFilter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, searchQuery: Signal<String?, NoError>, searchOptions: Signal<ChatListSearchOptions?, NoError>, navigationController: NavigationController?, parentController: ViewController?, globalPeerSearchContext: GlobalPeerSearchContext?) {
|
||||
self.context = context
|
||||
@ -1752,8 +1741,6 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
let globalPeerSearchContext = globalPeerSearchContext ?? GlobalPeerSearchContext()
|
||||
|
||||
self.globalPeerSearchContext = globalPeerSearchContext
|
||||
|
||||
self.globalPostSearchStateValue = TelegramGlobalPostSearchState(remainingSearches: 2, unlockTimestamp: nil)
|
||||
|
||||
var peersFilter = peersFilter
|
||||
if case .forum = location {
|
||||
@ -2056,6 +2043,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
|
||||
let globalPostSearchStateType = self.globalPostSearchState.get()
|
||||
|> map { state -> Bool in
|
||||
guard let state else {
|
||||
return false
|
||||
}
|
||||
return state.unlockTimestamp != nil
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
@ -3624,7 +3614,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
listInteraction?.searchTextHighightState = query
|
||||
chatListInteraction?.searchTextHighightState = query
|
||||
})
|
||||
self.globalPostSearchState.set(.single(self.globalPostSearchStateValue))
|
||||
self.globalPostSearchState.set(context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Messages.GlobalPostSearchState()
|
||||
))
|
||||
self.approvedSearchQueryDisposable = (combineLatest(queue: .mainQueue(), self.approvedGlobalPostQueryState.get(), self.globalPostSearchState.get(), isPremium)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] approvedGlobalPostQueryState, globalPostSearchState, isPremium in
|
||||
guard let self else {
|
||||
@ -3634,27 +3626,25 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
self.globalPostSearchStateValue = globalPostSearchState
|
||||
self.isPremium = isPremium
|
||||
|
||||
if globalPostSearchState.unlockTimestamp != nil {
|
||||
if let globalPostSearchState, globalPostSearchState.unlockTimestamp != nil {
|
||||
if self.globalPostSearchUnlockTimer == nil {
|
||||
self.globalPostSearchUnlockTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
if let unlockTimestamp = self.globalPostSearchStateValue.unlockTimestamp {
|
||||
if let unlockTimestamp = self.globalPostSearchStateValue?.unlockTimestamp {
|
||||
var remainingTime: Int32 = unlockTimestamp - Int32(Date().timeIntervalSince1970)
|
||||
remainingTime = max(0, remainingTime)
|
||||
if remainingTime == 0 {
|
||||
if let globalPostSearchUnlockTimer = self.globalPostSearchUnlockTimer {
|
||||
self.globalPostSearchUnlockTimer = nil
|
||||
globalPostSearchUnlockTimer.invalidate()
|
||||
if self.refreshGlobalPostSearchStateDisposable == nil {
|
||||
self.refreshGlobalPostSearchStateDisposable = self.context.engine.messages.refreshGlobalPostSearchState().start(completed: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.refreshGlobalPostSearchStateDisposable = nil
|
||||
})
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
var globalPostSearchState = self.globalPostSearchStateValue
|
||||
globalPostSearchState.unlockTimestamp = nil
|
||||
globalPostSearchState.remainingSearches = 2
|
||||
self.globalPostSearchState.set(.single(globalPostSearchState))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -3816,8 +3806,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
},
|
||||
searchQuery: strongSelf.searchQueryValue,
|
||||
approvedGlobalPostQueryState: strongSelf.approvedGlobalPostQueryStateValue,
|
||||
remainingGlobalSearches: strongSelf.globalPostSearchStateValue.remainingSearches,
|
||||
globalSearchUnlockTimestamp: strongSelf.globalPostSearchStateValue.unlockTimestamp,
|
||||
globalSearchStateValue: strongSelf.globalPostSearchStateValue,
|
||||
searchOptions: strongSelf.searchOptionsValue, messageContextAction: { message, node, rect, gesture, paneKey, downloadResource in
|
||||
interaction.messageContextAction(message, node, rect, gesture, paneKey, downloadResource)
|
||||
}, openClearRecentlyDownloaded: {
|
||||
@ -4694,6 +4683,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
self.approvedSearchQueryDisposable?.dispose()
|
||||
self.searchOptionsDisposable?.dispose()
|
||||
self.globalPostSearchUnlockTimer?.invalidate()
|
||||
self.refreshGlobalPostSearchStateDisposable?.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -4767,6 +4757,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let hadValidLayout = self.currentParams != nil
|
||||
let layoutChanged = self.currentParams?.size != size || self.currentParams?.sideInset != sideInset || self.currentParams?.bottomInset != bottomInset || self.currentParams?.visibleHeight != visibleHeight
|
||||
self.currentParams = (size, sideInset, bottomInset, visibleHeight, presentationData)
|
||||
|
||||
var topPanelHeight: CGFloat = 0.0
|
||||
@ -5128,8 +5119,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if let searchQueryValue = self.searchQueryValue, !searchQueryValue.isEmpty, self.approvedGlobalPostQueryStateValue?.query != searchQueryValue {
|
||||
var price: Int?
|
||||
|
||||
var globalPostSearchStateValue = self.globalPostSearchStateValue
|
||||
if globalPostSearchStateValue.remainingSearches == 0 {
|
||||
if let globalPostSearchStateValue = self.globalPostSearchStateValue, globalPostSearchStateValue.remainingFreeSearches == 0 {
|
||||
//TODO:localize
|
||||
price = 10
|
||||
}
|
||||
@ -5139,15 +5129,6 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
price: price
|
||||
))
|
||||
|
||||
|
||||
if globalPostSearchStateValue.remainingSearches > 0 {
|
||||
globalPostSearchStateValue.remainingSearches -= 1
|
||||
if globalPostSearchStateValue.remainingSearches == 0 {
|
||||
globalPostSearchStateValue.unlockTimestamp = Int32(Date().timeIntervalSince1970) + 30
|
||||
}
|
||||
}
|
||||
self.globalPostSearchState.set(.single(globalPostSearchStateValue))
|
||||
|
||||
if let price {
|
||||
//TODO:localize
|
||||
if let controller = self.navigationController?.topViewController as? ViewController {
|
||||
@ -5230,7 +5211,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
emptyTitleY = emptyAnimationY
|
||||
}
|
||||
|
||||
let textTransition = ContainedViewLayoutTransition.immediate
|
||||
let textTransition: ContainedViewLayoutTransition = layoutChanged ? transition : .immediate
|
||||
textTransition.updateFrame(node: self.emptyResultsAnimationNode, frame: CGRect(origin: CGPoint(x: sideInset + padding + (size.width - sideInset * 2.0 - padding * 2.0 - self.emptyResultsAnimationSize.width) / 2.0, y: emptyAnimationY), size: self.emptyResultsAnimationSize))
|
||||
textTransition.updateFrame(node: self.emptyResultsTitleNode, frame: CGRect(origin: CGPoint(x: sideInset + padding + (size.width - sideInset * 2.0 - padding * 2.0 - emptyTitleSize.width) / 2.0, y: emptyTitleY), size: emptyTitleSize))
|
||||
textTransition.updateFrame(node: self.emptyResultsTextNode, frame: CGRect(origin: CGPoint(x: sideInset + padding + (size.width - sideInset * 2.0 - padding * 2.0 - emptyTextSize.width) / 2.0, y: emptyTitleY + emptyTitleSize.height + emptyTextSpacing), size: emptyTextSize))
|
||||
@ -5240,20 +5221,24 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if let emptyButtonView = self.emptyResultsButton?.view, let emptyButtonSize {
|
||||
nextY += emptyButtonSpacing
|
||||
|
||||
var emptyButtonTransition = textTransition
|
||||
if emptyButtonView.superview == nil {
|
||||
emptyButtonTransition = .immediate
|
||||
self.view.insertSubview(emptyButtonView, aboveSubview: self.emptyResultsTextNode.view)
|
||||
}
|
||||
emptyButtonView.frame = CGRect(origin: CGPoint(x: floor((size.width - emptyButtonSize.width) * 0.5), y: nextY), size: emptyButtonSize)
|
||||
emptyButtonTransition.updateFrame(view: emptyButtonView, frame: CGRect(origin: CGPoint(x: floor((size.width - emptyButtonSize.width) * 0.5), y: nextY), size: emptyButtonSize))
|
||||
|
||||
nextY += emptyButtonSize.height
|
||||
}
|
||||
if let emptyButtonSubtitleView = self.emptyResultsButtonSubtitle?.view, let emptyButtonSubtitleSize {
|
||||
nextY += emptyButtonSubtitleSpacing
|
||||
|
||||
var emptyButtonSubtitleTransition = textTransition
|
||||
if emptyButtonSubtitleView.superview == nil {
|
||||
emptyButtonSubtitleTransition = .immediate
|
||||
self.view.insertSubview(emptyButtonSubtitleView, aboveSubview: self.emptyResultsTextNode.view)
|
||||
}
|
||||
emptyButtonSubtitleView.frame = CGRect(origin: CGPoint(x: floor((size.width - emptyButtonSubtitleSize.width) * 0.5), y: nextY), size: emptyButtonSubtitleSize)
|
||||
emptyButtonSubtitleTransition.updateFrame(view: emptyButtonSubtitleView, frame: CGRect(origin: CGPoint(x: floor((size.width - emptyButtonSubtitleSize.width) * 0.5), y: nextY), size: emptyButtonSubtitleSize))
|
||||
|
||||
nextY += emptyButtonSubtitleSize.height
|
||||
}
|
||||
@ -5408,7 +5393,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
var emptyResultsButtonContent: EmptyResultsButton.Content?
|
||||
var emptyResultsButtonSubtitleText: String?
|
||||
|
||||
if strongSelf.key == .globalPosts {
|
||||
if strongSelf.key == .globalPosts, let globalSearchStateValue = transition.globalSearchStateValue {
|
||||
if !strongSelf.isPremium {
|
||||
emptyResultsButtonContent = .premiumRequired
|
||||
emptyResultsTitle = "Global Search"
|
||||
@ -5420,13 +5405,13 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResults
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(query).string
|
||||
} else {
|
||||
if transition.remainingGlobalSearches != 0 {
|
||||
if globalSearchStateValue.remainingFreeSearches != 0 {
|
||||
emptyResultsTitle = "Global Search"
|
||||
emptyResultsText = "Type a keyword to search all posts\nfrom public channels."
|
||||
if transition.remainingGlobalSearches == 1 {
|
||||
if globalSearchStateValue.remainingFreeSearches == 1 {
|
||||
emptyResultsButtonSubtitleText = "1 free search remaining today."
|
||||
} else {
|
||||
emptyResultsButtonSubtitleText = "\(transition.remainingGlobalSearches) free searches remaining today."
|
||||
emptyResultsButtonSubtitleText = "\(globalSearchStateValue.remainingFreeSearches) free searches remaining today."
|
||||
}
|
||||
|
||||
emptyResultsButtonContent = .searchQuery(query)
|
||||
@ -5435,29 +5420,29 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
emptyResultsText = "You can make up to\n10 search queries per day."
|
||||
|
||||
emptyResultsButtonContent = .paidSearch(
|
||||
price: 10,
|
||||
timestamp: transition.globalSearchUnlockTimestamp
|
||||
price: Int(globalSearchStateValue.price.value),
|
||||
timestamp: globalSearchStateValue.unlockTimestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if transition.remainingGlobalSearches != 0 {
|
||||
if globalSearchStateValue.remainingFreeSearches != 0 {
|
||||
emptyResultsButtonContent = .searchEmpty
|
||||
emptyResultsTitle = "Global Search"
|
||||
emptyResultsText = "Type a keyword to search all posts\nfrom public channels."
|
||||
|
||||
if transition.remainingGlobalSearches == 1 {
|
||||
if globalSearchStateValue.remainingFreeSearches == 1 {
|
||||
emptyResultsButtonSubtitleText = "1 free search remaining today."
|
||||
} else {
|
||||
emptyResultsButtonSubtitleText = "\(transition.remainingGlobalSearches) free searches remaining today."
|
||||
emptyResultsButtonSubtitleText = "\(globalSearchStateValue.remainingFreeSearches) free searches remaining today."
|
||||
}
|
||||
} else {
|
||||
emptyResultsTitle = "Limit Reached"
|
||||
emptyResultsText = "You can make up to\n10 search queries per day."
|
||||
|
||||
emptyResultsButtonContent = .paidSearch(
|
||||
price: 10,
|
||||
timestamp: transition.globalSearchUnlockTimestamp
|
||||
price: Int(globalSearchStateValue.price.value),
|
||||
timestamp: globalSearchStateValue.unlockTimestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -881,6 +881,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
|
||||
dict[-881854424] = { return Api.SavedReactionTag.parse_savedReactionTag($0) }
|
||||
dict[514213599] = { return Api.SavedStarGift.parse_savedStarGift($0) }
|
||||
dict[-1810993028] = { return Api.SearchPostsFlood.parse_searchPostsFlood($0) }
|
||||
dict[-911191137] = { return Api.SearchResultsCalendarPeriod.parse_searchResultsCalendarPeriod($0) }
|
||||
dict[2137295719] = { return Api.SearchResultsPosition.parse_searchResultPosition($0) }
|
||||
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
|
||||
@ -1381,7 +1382,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-948520370] = { return Api.messages.Messages.parse_channelMessages($0) }
|
||||
dict[-1938715001] = { return Api.messages.Messages.parse_messages($0) }
|
||||
dict[1951620897] = { return Api.messages.Messages.parse_messagesNotModified($0) }
|
||||
dict[978610270] = { return Api.messages.Messages.parse_messagesSlice($0) }
|
||||
dict[1982539325] = { return Api.messages.Messages.parse_messagesSlice($0) }
|
||||
dict[-83926371] = { return Api.messages.MyStickers.parse_myStickers($0) }
|
||||
dict[863093588] = { return Api.messages.PeerDialogs.parse_peerDialogs($0) }
|
||||
dict[1753266509] = { return Api.messages.PeerSettings.parse_peerSettings($0) }
|
||||
@ -2099,6 +2100,8 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SavedStarGift:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SearchPostsFlood:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SearchResultsCalendarPeriod:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SearchResultsPosition:
|
||||
|
@ -294,6 +294,54 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SearchPostsFlood: TypeConstructorDescription {
|
||||
case searchPostsFlood(flags: Int32, remains: Int32, waitTill: Int32?, starsAmount: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .searchPostsFlood(let flags, let remains, let waitTill, let starsAmount):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1810993028)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(remains, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(waitTill!, buffer: buffer, boxed: false)}
|
||||
serializeInt64(starsAmount, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .searchPostsFlood(let flags, let remains, let waitTill, let starsAmount):
|
||||
return ("searchPostsFlood", [("flags", flags as Any), ("remains", remains as Any), ("waitTill", waitTill as Any), ("starsAmount", starsAmount as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_searchPostsFlood(_ reader: BufferReader) -> SearchPostsFlood? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.SearchPostsFlood.searchPostsFlood(flags: _1!, remains: _2!, waitTill: _3, starsAmount: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SearchResultsCalendarPeriod: TypeConstructorDescription {
|
||||
case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32)
|
||||
|
@ -633,7 +633,7 @@ public extension Api.messages {
|
||||
case channelMessages(flags: Int32, pts: Int32, count: Int32, offsetIdOffset: Int32?, messages: [Api.Message], topics: [Api.ForumTopic], chats: [Api.Chat], users: [Api.User])
|
||||
case messages(messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
case messagesNotModified(count: Int32)
|
||||
case messagesSlice(flags: Int32, count: Int32, nextRate: Int32?, offsetIdOffset: Int32?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
case messagesSlice(flags: Int32, count: Int32, nextRate: Int32?, offsetIdOffset: Int32?, searchFlood: Api.SearchPostsFlood?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -692,14 +692,15 @@ public extension Api.messages {
|
||||
}
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users):
|
||||
case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let searchFlood, let messages, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(978610270)
|
||||
buffer.appendInt32(1982539325)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(nextRate!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {searchFlood!.serialize(buffer, true)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messages.count))
|
||||
for item in messages {
|
||||
@ -727,8 +728,8 @@ public extension Api.messages {
|
||||
return ("messages", [("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .messagesNotModified(let count):
|
||||
return ("messagesNotModified", [("count", count as Any)])
|
||||
case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users):
|
||||
return ("messagesSlice", [("flags", flags as Any), ("count", count as Any), ("nextRate", nextRate as Any), ("offsetIdOffset", offsetIdOffset as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let searchFlood, let messages, let chats, let users):
|
||||
return ("messagesSlice", [("flags", flags as Any), ("count", count as Any), ("nextRate", nextRate as Any), ("offsetIdOffset", offsetIdOffset as Any), ("searchFlood", searchFlood as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -815,27 +816,32 @@ public extension Api.messages {
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
|
||||
var _5: [Api.Message]?
|
||||
var _5: Api.SearchPostsFlood?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.SearchPostsFlood
|
||||
} }
|
||||
var _6: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _6: [Api.Chat]?
|
||||
var _7: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _7: [Api.User]?
|
||||
var _8: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.messages.Messages.messagesSlice(flags: _1!, count: _2!, nextRate: _3, offsetIdOffset: _4, messages: _5!, chats: _6!, users: _7!)
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.messages.Messages.messagesSlice(flags: _1!, count: _2!, nextRate: _3, offsetIdOffset: _4, searchFlood: _5, messages: _6!, chats: _7!, users: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -2756,6 +2756,21 @@ public extension Api.functions.bots {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.channels {
|
||||
static func checkSearchPostsFlood() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.SearchPostsFlood>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1146490591)
|
||||
|
||||
return (FunctionDescription(name: "channels.checkSearchPostsFlood", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SearchPostsFlood? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.SearchPostsFlood?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.SearchPostsFlood
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.channels {
|
||||
static func checkUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -37,7 +37,7 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
|
||||
switch result {
|
||||
case let .messages(_, _, users):
|
||||
apiUsers = users
|
||||
case let .messagesSlice(_, _, _, _, _, _, users):
|
||||
case let .messagesSlice(_, _, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
case let .channelMessages(_, _, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
|
@ -2683,7 +2683,7 @@ private func resolveAssociatedMessages(accountPeerId: PeerId, postbox: Postbox,
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||
let _ = apiTopics
|
||||
@ -2714,7 +2714,7 @@ private func resolveAssociatedMessages(accountPeerId: PeerId, postbox: Postbox,
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||
let _ = apiTopics
|
||||
|
@ -104,7 +104,7 @@ private func fetchWebpage(account: Account, messageId: MessageId, threadId: Int6
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -1087,7 +1087,7 @@ public final class AccountViewTracker {
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, _, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
|
@ -562,7 +562,7 @@ private func validateChannelMessagesBatch(postbox: Postbox, network: Network, ac
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -631,7 +631,7 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -673,7 +673,7 @@ private func validateScheduledMessagesBatch(postbox: Postbox, network: Network,
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -719,7 +719,7 @@ private func validateQuickReplyMessagesBatch(postbox: Postbox, network: Network,
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -803,7 +803,7 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran
|
||||
let _ = apiTopics
|
||||
case let .messages(messages, _, _):
|
||||
apiMessages = messages
|
||||
case let .messagesSlice(_, _, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, _, _):
|
||||
apiMessages = messages
|
||||
case .messagesNotModified:
|
||||
return Set()
|
||||
@ -1052,7 +1052,7 @@ private func validateReplyThreadBatch(postbox: Postbox, network: Network, transa
|
||||
let _ = apiTopics
|
||||
case let .messages(messages, _, _):
|
||||
apiMessages = messages
|
||||
case let .messagesSlice(_, _, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, _, _):
|
||||
apiMessages = messages
|
||||
case .messagesNotModified:
|
||||
return Set()
|
||||
|
@ -256,7 +256,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||
let _ = apiTopics
|
||||
@ -287,7 +287,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||
let _ = apiTopics
|
||||
@ -923,7 +923,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -1221,7 +1221,7 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
|
@ -583,7 +583,7 @@ private func synchronizeMessageHistoryTagSummary(accountPeerId: PeerId, postbox:
|
||||
case let .messagesNotModified(count):
|
||||
apiMessages = []
|
||||
apiCount = count
|
||||
case let .messagesSlice(_, count, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, count, _, _, _, messages, _, _):
|
||||
apiMessages = messages
|
||||
apiCount = count
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ private func synchronizeMarkAllUnseen(transaction: Transaction, postbox: Postbox
|
||||
return .single(messages.compactMap({ $0.id() }))
|
||||
case .messagesNotModified:
|
||||
return .single([])
|
||||
case let .messagesSlice(_, _, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, _, _):
|
||||
return .single(messages.compactMap({ $0.id() }))
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId
|
||||
apiMessages = messages
|
||||
case let .messages(messages, _, _):
|
||||
apiMessages = messages
|
||||
case let .messagesSlice(_, _, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, _, _):
|
||||
apiMessages = messages
|
||||
case .messagesNotModified:
|
||||
apiMessages = []
|
||||
|
@ -317,6 +317,7 @@ private enum PreferencesKeyValues: Int32 {
|
||||
case secureBotStorageState = 43
|
||||
case serverSuggestionInfo = 44
|
||||
case persistentChatInterfaceData = 45
|
||||
case globalPostSearchState = 46
|
||||
}
|
||||
|
||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||
@ -573,6 +574,12 @@ public struct PreferencesKeys {
|
||||
key.setInt64(4, value: peerId.toInt64())
|
||||
return key
|
||||
}
|
||||
|
||||
public static func globalPostSearchState() -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 4 + 8)
|
||||
key.setInt32(0, value: PreferencesKeyValues.globalPostSearchState.rawValue)
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
private enum SharedDataKeyValues: Int32 {
|
||||
|
@ -478,5 +478,23 @@ public extension TelegramEngine.EngineData.Item {
|
||||
return view.info?.data.get(MessageHistoryThreadData.self)
|
||||
}
|
||||
}
|
||||
|
||||
public struct GlobalPostSearchState: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = TelegramGlobalPostSearchState?
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .preferences(keys: Set([PreferencesKeys.globalPostSearchState()]))
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? PreferencesView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
return view.values[PreferencesKeys.globalPostSearchState()]?.get(TelegramGlobalPostSearchState.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
|
||||
switch result {
|
||||
case let .messages(messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .messagesSlice(_, _, _, _, messages, chats, users):
|
||||
case let .messagesSlice(_, _, _, _, _, messages, chats, users):
|
||||
return (peer, messages, chats, users)
|
||||
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
|
||||
let _ = apiTopics
|
||||
|
@ -101,7 +101,7 @@ private func mergedState(transaction: Transaction, seedConfiguration: SeedConfig
|
||||
users = apiUsers
|
||||
totalCount = Int32(messages.count)
|
||||
nextRate = nil
|
||||
case let .messagesSlice(_, count, apiNextRate, _, apiMessages, apiChats, apiUsers):
|
||||
case let .messagesSlice(_, count, apiNextRate, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -288,7 +288,7 @@ func _internal_getSearchMessageCount(account: Account, location: SearchMessagesL
|
||||
return messages.count
|
||||
case let .messagesNotModified(count):
|
||||
return Int(count)
|
||||
case let .messagesSlice(_, count, _, _, _, _, _):
|
||||
case let .messagesSlice(_, count, _, _, _, _, _, _):
|
||||
return Int(count)
|
||||
}
|
||||
}
|
||||
@ -602,6 +602,26 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
||||
}
|
||||
}
|
||||
|
||||
if let result {
|
||||
switch result {
|
||||
case let .messagesSlice(_, _, _, _, searchFlood, _, _, _):
|
||||
if let searchFlood {
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.globalPostSearchState(), { _ in
|
||||
switch searchFlood {
|
||||
case let .searchPostsFlood(_, remains, waitTill, starsAmount):
|
||||
return PreferencesEntry(TelegramGlobalPostSearchState(
|
||||
remainingFreeSearches: remains,
|
||||
price: StarsAmount(value: starsAmount, nanos: 0),
|
||||
unlockTimestamp: waitTill
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, seedConfiguration: account.postbox.seedConfiguration, accountPeerId: account.peerId, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], threadInfo: [:], totalCount: 0, completed: true, nextRate: nil), additional: additional)
|
||||
return (mergedResult(updatedState), updatedState)
|
||||
}
|
||||
@ -682,7 +702,7 @@ func _internal_downloadMessage(accountPeerId: PeerId, postbox: Postbox, network:
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -773,7 +793,7 @@ func fetchRemoteMessage(accountPeerId: PeerId, postbox: Postbox, source: FetchMe
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
@ -839,7 +859,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
messages = apiMessages
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
@ -876,7 +896,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
messages = apiMessages
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
@ -909,7 +929,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
messages = apiMessages
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
@ -933,7 +953,7 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
messages = apiMessages
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, _, _):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
@ -1067,3 +1087,29 @@ func _internal_updatedRemotePeer(accountPeerId: PeerId, postbox: Postbox, networ
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_refreshGlobalPostSearchState(account: Account) -> Signal<Never, NoError> {
|
||||
return account.network.request(Api.functions.channels.checkSearchPostsFlood())
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.SearchPostsFlood?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
guard let result else {
|
||||
return
|
||||
}
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.globalPostSearchState(), { _ in
|
||||
switch result {
|
||||
case let .searchPostsFlood(_, remains, waitTill, starsAmount):
|
||||
return PreferencesEntry(TelegramGlobalPostSearchState(
|
||||
remainingFreeSearches: remains,
|
||||
price: StarsAmount(value: starsAmount, nanos: 0),
|
||||
unlockTimestamp: waitTill
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,31 @@ public final class StoryPreloadInfo {
|
||||
}
|
||||
}
|
||||
|
||||
public final class TelegramGlobalPostSearchState: Codable, Equatable {
|
||||
public let remainingFreeSearches: Int32
|
||||
public let price: StarsAmount
|
||||
public let unlockTimestamp: Int32?
|
||||
|
||||
public init(remainingFreeSearches: Int32, price: StarsAmount, unlockTimestamp: Int32?) {
|
||||
self.remainingFreeSearches = remainingFreeSearches
|
||||
self.price = price
|
||||
self.unlockTimestamp = unlockTimestamp
|
||||
}
|
||||
|
||||
public static func ==(lhs: TelegramGlobalPostSearchState, rhs: TelegramGlobalPostSearchState) -> Bool {
|
||||
if lhs.remainingFreeSearches != rhs.remainingFreeSearches {
|
||||
return false
|
||||
}
|
||||
if lhs.price != rhs.price {
|
||||
return false
|
||||
}
|
||||
if lhs.unlockTimestamp != rhs.unlockTimestamp {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public extension TelegramEngine {
|
||||
final class Messages {
|
||||
private let account: Account
|
||||
@ -514,7 +539,7 @@ public extension TelegramEngine {
|
||||
signals.append(self.account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, savedPeerId: inputSavedPeer, savedReaction: nil, topMsgId: topMsgId, filter: filter, minDate: 0, maxDate: 0, offsetId: 0, addOffset: 0, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> (count: Int32?, topId: Int32?) in
|
||||
switch result {
|
||||
case let .messagesSlice(_, count, _, _, messages, _, _):
|
||||
case let .messagesSlice(_, count, _, _, _, messages, _, _):
|
||||
return (count, messages.first?.id(namespace: Namespaces.Message.Cloud)?.id)
|
||||
case let .channelMessages(_, _, count, _, messages, _, _, _):
|
||||
return (count, messages.first?.id(namespace: Namespaces.Message.Cloud)?.id)
|
||||
@ -1597,6 +1622,10 @@ public extension TelegramEngine {
|
||||
public func monoforumPerformSuggestedPostAction(id: EngineMessage.Id, action: MonoforumSuggestedPostAction) -> Signal<Never, NoError> {
|
||||
return _internal_monoforumPerformSuggestedPostAction(account: self.account, id: id, action: action)
|
||||
}
|
||||
|
||||
public func refreshGlobalPostSearchState() -> Signal<Never, NoError> {
|
||||
return _internal_refreshGlobalPostSearchState(account: self.account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func _internal_requestPeerPhotos(accountPeerId: PeerId, postbox: Postbox, networ
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
case let .messagesSlice(_, _, _, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
|
Loading…
x
Reference in New Issue
Block a user