import Foundation import Postbox import SwiftSignalKit import TelegramApi public enum ServerProvidedSuggestion: String { case autoarchivePopular = "AUTOARCHIVE_POPULAR" case newcomerTicks = "NEWCOMER_TICKS" case validatePhoneNumber = "VALIDATE_PHONE_NUMBER" case validatePassword = "VALIDATE_PASSWORD" case setupPassword = "SETUP_PASSWORD" case upgradePremium = "PREMIUM_UPGRADE" case annualPremium = "PREMIUM_ANNUAL" case restorePremium = "PREMIUM_RESTORE" case xmasPremiumGift = "PREMIUM_CHRISTMAS" case setupBirthday = "BIRTHDAY_SETUP" case todayBirthdays = "BIRTHDAY_CONTACTS_TODAY" case gracePremium = "PREMIUM_GRACE" case starsSubscriptionLowBalance = "STARS_SUBSCRIPTION_LOW_BALANCE" } private var dismissedSuggestionsPromise = ValuePromise<[AccountRecordId: Set]>([:]) private var dismissedSuggestions: [AccountRecordId: Set] = [:] { didSet { dismissedSuggestionsPromise.set(dismissedSuggestions) } } func _internal_getServerProvidedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> { let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration])) return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get()) |> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set() guard let view = views.views[key] as? PreferencesView else { return [] } guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else { return [] } guard let data = appConfiguration.data, let listItems = data["pending_suggestions"] as? [String] else { return [] } return listItems.compactMap { item -> ServerProvidedSuggestion? in return ServerProvidedSuggestion(rawValue: item) }.filter { !dismissedSuggestions.contains($0) } } |> distinctUntilChanged } func _internal_getServerDismissedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> { let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration])) return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get()) |> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set() guard let view = views.views[key] as? PreferencesView else { return [] } guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else { return [] } var listItems: [String] = [] if let data = appConfiguration.data, let listItemsValues = data["dismissed_suggestions"] as? [String] { listItems.append(contentsOf: listItemsValues) } var items = listItems.compactMap { item -> ServerProvidedSuggestion? in return ServerProvidedSuggestion(rawValue: item) } items.append(contentsOf: dismissedSuggestions) return items } |> distinctUntilChanged } func _internal_dismissServerProvidedSuggestion(account: Account, suggestion: ServerProvidedSuggestion) -> Signal { if let _ = dismissedSuggestions[account.id] { dismissedSuggestions[account.id]?.insert(suggestion) } else { dismissedSuggestions[account.id] = Set([suggestion]) } return account.network.request(Api.functions.help.dismissSuggestion(peer: .inputPeerEmpty, suggestion: suggestion.rawValue)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> ignoreValues } public enum PeerSpecificServerProvidedSuggestion: String { case convertToGigagroup = "CONVERT_GIGAGROUP" } func _internal_getPeerSpecificServerProvidedSuggestions(postbox: Postbox, peerId: PeerId) -> Signal<[PeerSpecificServerProvidedSuggestion], NoError> { return postbox.peerView(id: peerId) |> map { view in if let cachedData = view.cachedData as? CachedChannelData { return cachedData.pendingSuggestions.compactMap { item -> PeerSpecificServerProvidedSuggestion? in return PeerSpecificServerProvidedSuggestion(rawValue: item) } } return [] } |> distinctUntilChanged } func _internal_dismissPeerSpecificServerProvidedSuggestion(account: Account, peerId: PeerId, suggestion: PeerSpecificServerProvidedSuggestion) -> Signal { return account.postbox.loadedPeerWithId(peerId) |> mapToSignal { peer -> Signal in guard let inputPeer = apiInputPeer(peer) else { return .never() } return account.network.request(Api.functions.help.dismissSuggestion(peer: inputPeer, suggestion: suggestion.rawValue)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { a -> Signal in return account.postbox.transaction { transaction in transaction.updatePeerCachedData(peerIds: [peerId]) { (_, current) -> CachedPeerData? in var updated = current if let cachedData = current as? CachedChannelData { var pendingSuggestions = cachedData.pendingSuggestions pendingSuggestions.removeAll(where: { $0 == suggestion.rawValue }) updated = cachedData.withUpdatedPendingSuggestions(pendingSuggestions) } return updated } } |> ignoreValues } } }