mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-08 01:40:09 +00:00
Various improvements
This commit is contained in:
parent
149805e914
commit
57e7e6906b
@ -890,7 +890,7 @@ public protocol AccountContext: AnyObject {
|
|||||||
|
|
||||||
public struct PremiumConfiguration {
|
public struct PremiumConfiguration {
|
||||||
public static var defaultValue: PremiumConfiguration {
|
public static var defaultValue: PremiumConfiguration {
|
||||||
return PremiumConfiguration(isPremiumDisabled: false)
|
return PremiumConfiguration(isPremiumDisabled: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public let isPremiumDisabled: Bool
|
public let isPremiumDisabled: Bool
|
||||||
|
|||||||
@ -1034,14 +1034,14 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
|
|||||||
let controller = internalChatListFilterExcludeChatsController(context: context, filter: filter, allFilters: filters, applyAutomatically: false, updated: { filter in
|
let controller = internalChatListFilterExcludeChatsController(context: context, filter: filter, allFilters: filters, applyAutomatically: false, updated: { filter in
|
||||||
skipStateAnimation = true
|
skipStateAnimation = true
|
||||||
updateState { state in
|
updateState { state in
|
||||||
var state = state
|
var updatedState = state
|
||||||
state.additionallyIncludePeers = filter.data?.includePeers.peers ?? []
|
updatedState.additionallyIncludePeers = filter.data?.includePeers.peers ?? []
|
||||||
state.additionallyExcludePeers = filter.data?.excludePeers ?? []
|
updatedState.additionallyExcludePeers = filter.data?.excludePeers ?? []
|
||||||
state.includeCategories = filter.data?.categories ?? []
|
updatedState.includeCategories = filter.data?.categories ?? []
|
||||||
state.excludeRead = filter.data?.excludeRead ?? false
|
updatedState.excludeRead = filter.data?.excludeRead ?? false
|
||||||
state.excludeMuted = filter.data?.excludeMuted ?? false
|
updatedState.excludeMuted = filter.data?.excludeMuted ?? false
|
||||||
state.excludeArchived = filter.data?.excludeArchived ?? false
|
updatedState.excludeArchived = filter.data?.excludeArchived ?? false
|
||||||
return state
|
return updatedState
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||||
@ -1125,7 +1125,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
|
|||||||
var found = false
|
var found = false
|
||||||
for i in 0 ..< filters.count {
|
for i in 0 ..< filters.count {
|
||||||
if filters[i].id == updatedFilter.id, case let .filter(_, _, _, data) = filters[i] {
|
if filters[i].id == updatedFilter.id, case let .filter(_, _, _, data) = filters[i] {
|
||||||
var updatedData = data
|
var updatedData = updatedFilter.data ?? data
|
||||||
var includePeers = updatedData.includePeers
|
var includePeers = updatedData.includePeers
|
||||||
includePeers.setPeers(state.additionallyIncludePeers)
|
includePeers.setPeers(state.additionallyIncludePeers)
|
||||||
updatedData.includePeers = includePeers
|
updatedData.includePeers = includePeers
|
||||||
|
|||||||
@ -1484,6 +1484,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
currentSecretIconImage = PresentationResourcesChatList.secretIcon(item.presentationData.theme)
|
currentSecretIconImage = PresentationResourcesChatList.secretIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
if !isPeerGroup && item.index.messageIndex.id.peerId != item.context.account.peerId {
|
if !isPeerGroup && item.index.messageIndex.id.peerId != item.context.account.peerId {
|
||||||
if displayAsMessage {
|
if displayAsMessage {
|
||||||
switch item.content {
|
switch item.content {
|
||||||
@ -1495,7 +1496,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
} else if peer.isPremium {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1509,7 +1510,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
} else if peer.isPremium {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -563,6 +563,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
var currentCredibilityIconImage: UIImage?
|
var currentCredibilityIconImage: UIImage?
|
||||||
switch item.peer {
|
switch item.peer {
|
||||||
case let .peer(peer, _):
|
case let .peer(peer, _):
|
||||||
@ -573,7 +575,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
} else if peer.isPremium {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ swift_library(
|
|||||||
"//submodules/AppBundle:AppBundle",
|
"//submodules/AppBundle:AppBundle",
|
||||||
"//submodules/GZip:GZip",
|
"//submodules/GZip:GZip",
|
||||||
"//third-party/ZipArchive:ZipArchive",
|
"//third-party/ZipArchive:ZipArchive",
|
||||||
|
"//submodules/InAppPurchaseManager:InAppPurchaseManager",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import AccountContext
|
|||||||
import AppBundle
|
import AppBundle
|
||||||
import ZipArchive
|
import ZipArchive
|
||||||
import WebKit
|
import WebKit
|
||||||
|
import InAppPurchaseManager
|
||||||
|
|
||||||
@objc private final class DebugControllerMailComposeDelegate: NSObject, MFMailComposeViewControllerDelegate {
|
@objc private final class DebugControllerMailComposeDelegate: NSObject, MFMailComposeViewControllerDelegate {
|
||||||
public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||||
@ -86,13 +87,13 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
case experimentalBackground(Bool)
|
case experimentalBackground(Bool)
|
||||||
case inlineStickers(Bool)
|
case inlineStickers(Bool)
|
||||||
case localTranscription(Bool)
|
case localTranscription(Bool)
|
||||||
case snow(Bool)
|
|
||||||
case playerEmbedding(Bool)
|
case playerEmbedding(Bool)
|
||||||
case playlistPlayback(Bool)
|
case playlistPlayback(Bool)
|
||||||
case voiceConference
|
case voiceConference
|
||||||
case preferredVideoCodec(Int, String, String?, Bool)
|
case preferredVideoCodec(Int, String, String?, Bool)
|
||||||
case disableVideoAspectScaling(Bool)
|
case disableVideoAspectScaling(Bool)
|
||||||
case enableVoipTcp(Bool)
|
case enableVoipTcp(Bool)
|
||||||
|
case resetInAppPurchases(PresentationTheme)
|
||||||
case hostInfo(PresentationTheme, String)
|
case hostInfo(PresentationTheme, String)
|
||||||
case versionInfo(PresentationTheme)
|
case versionInfo(PresentationTheme)
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
return DebugControllerSection.logging.rawValue
|
return DebugControllerSection.logging.rawValue
|
||||||
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
|
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
|
||||||
return DebugControllerSection.experiments.rawValue
|
return DebugControllerSection.experiments.rawValue
|
||||||
case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineStickers, .localTranscription, .snow:
|
case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineStickers, .localTranscription, .resetInAppPurchases:
|
||||||
return DebugControllerSection.experiments.rawValue
|
return DebugControllerSection.experiments.rawValue
|
||||||
case .preferredVideoCodec:
|
case .preferredVideoCodec:
|
||||||
return DebugControllerSection.videoExperiments.rawValue
|
return DebugControllerSection.videoExperiments.rawValue
|
||||||
@ -187,7 +188,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
return 31
|
return 31
|
||||||
case .localTranscription:
|
case .localTranscription:
|
||||||
return 32
|
return 32
|
||||||
case .snow:
|
case .resetInAppPurchases:
|
||||||
return 33
|
return 33
|
||||||
case .playerEmbedding:
|
case .playerEmbedding:
|
||||||
return 34
|
return 34
|
||||||
@ -969,16 +970,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
})
|
})
|
||||||
}).start()
|
}).start()
|
||||||
})
|
})
|
||||||
case let .snow(value):
|
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: "Snow", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
|
||||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
|
||||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
|
|
||||||
var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
|
|
||||||
settings.snow = value
|
|
||||||
return PreferencesEntry(settings)
|
|
||||||
})
|
|
||||||
}).start()
|
|
||||||
})
|
|
||||||
case let .playerEmbedding(value):
|
case let .playerEmbedding(value):
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: "Player Embedding", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
return ItemListSwitchItem(presentationData: presentationData, title: "Player Embedding", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
||||||
@ -1035,6 +1026,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
})
|
})
|
||||||
}).start()
|
}).start()
|
||||||
})
|
})
|
||||||
|
case .resetInAppPurchases:
|
||||||
|
return ItemListActionItem(presentationData: presentationData, title: "Reset IAP Transactions", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||||
|
arguments.context?.inAppPurchaseManager?.finishAllTransactions()
|
||||||
|
})
|
||||||
case let .hostInfo(_, string):
|
case let .hostInfo(_, string):
|
||||||
return ItemListTextItem(presentationData: presentationData, text: .plain(string), sectionId: self.section)
|
return ItemListTextItem(presentationData: presentationData, text: .plain(string), sectionId: self.section)
|
||||||
case .versionInfo:
|
case .versionInfo:
|
||||||
@ -1096,6 +1091,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present
|
|||||||
entries.append(.experimentalBackground(experimentalSettings.experimentalBackground))
|
entries.append(.experimentalBackground(experimentalSettings.experimentalBackground))
|
||||||
entries.append(.inlineStickers(experimentalSettings.inlineStickers))
|
entries.append(.inlineStickers(experimentalSettings.inlineStickers))
|
||||||
entries.append(.localTranscription(experimentalSettings.localTranscription))
|
entries.append(.localTranscription(experimentalSettings.localTranscription))
|
||||||
|
entries.append(.resetInAppPurchases(presentationData.theme))
|
||||||
entries.append(.playerEmbedding(experimentalSettings.playerEmbedding))
|
entries.append(.playerEmbedding(experimentalSettings.playerEmbedding))
|
||||||
entries.append(.playlistPlayback(experimentalSettings.playlistPlayback))
|
entries.append(.playlistPlayback(experimentalSettings.playlistPlayback))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,14 @@ public final class InAppPurchaseManager: NSObject {
|
|||||||
return self.productsPromise.get()
|
return self.productsPromise.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func finishAllTransactions() {
|
||||||
|
let paymentQueue = SKPaymentQueue.default()
|
||||||
|
let transactions = paymentQueue.transactions
|
||||||
|
for transaction in transactions {
|
||||||
|
paymentQueue.finishTransaction(transaction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func buyProduct(_ product: Product, account: Account) -> Signal<PurchaseState, PurchaseError> {
|
public func buyProduct(_ product: Product, account: Account) -> Signal<PurchaseState, PurchaseError> {
|
||||||
let payment = SKPayment(product: product.skProduct)
|
let payment = SKPayment(product: product.skProduct)
|
||||||
SKPaymentQueue.default().add(payment)
|
SKPaymentQueue.default().add(payment)
|
||||||
@ -159,6 +167,18 @@ extension InAppPurchaseManager: SKProductsRequestDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func getReceiptData() -> Data? {
|
||||||
|
var receiptData: Data?
|
||||||
|
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
|
||||||
|
do {
|
||||||
|
receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
|
||||||
|
} catch {
|
||||||
|
Logger.shared.log("InAppPurchaseManager", "Couldn't read receipt data with error: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return receiptData
|
||||||
|
}
|
||||||
|
|
||||||
extension InAppPurchaseManager: SKPaymentTransactionObserver {
|
extension InAppPurchaseManager: SKPaymentTransactionObserver {
|
||||||
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||||
for transaction in transactions {
|
for transaction in transactions {
|
||||||
@ -167,23 +187,28 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver {
|
|||||||
let transactionState: TransactionState?
|
let transactionState: TransactionState?
|
||||||
switch transaction.transactionState {
|
switch transaction.transactionState {
|
||||||
case .purchased:
|
case .purchased:
|
||||||
|
if transaction.original == nil {
|
||||||
transactionState = .purchased(transactionId: transaction.transactionIdentifier)
|
transactionState = .purchased(transactionId: transaction.transactionIdentifier)
|
||||||
if let transactionIdentifier = transaction.transactionIdentifier {
|
if let transactionIdentifier = transaction.transactionIdentifier {
|
||||||
self.disposableSet.set(
|
self.disposableSet.set(
|
||||||
self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier).start(error: { error in
|
self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier, receipt: getReceiptData() ?? Data(), restore: false).start(error: { _ in
|
||||||
|
queue.finishTransaction(transaction)
|
||||||
}, completed: {
|
}, completed: {
|
||||||
queue.finishTransaction(transaction)
|
queue.finishTransaction(transaction)
|
||||||
}),
|
}),
|
||||||
forKey: transaction.transactionIdentifier ?? ""
|
forKey: transaction.transactionIdentifier ?? ""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
transactionState = nil
|
||||||
|
queue.finishTransaction(transaction)
|
||||||
|
}
|
||||||
case .restored:
|
case .restored:
|
||||||
transactionState = .restored(transactionId: transaction.transactionIdentifier)
|
transactionState = .restored(transactionId: transaction.original?.transactionIdentifier)
|
||||||
if let transactionIdentifier = transaction.transactionIdentifier {
|
if let transactionIdentifier = transaction.original?.transactionIdentifier {
|
||||||
self.disposableSet.set(
|
self.disposableSet.set(
|
||||||
self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier).start(error: { error in
|
self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier, receipt: getReceiptData() ?? Data(), restore: true).start(error: { _ in
|
||||||
|
queue.finishTransaction(transaction)
|
||||||
}, completed: {
|
}, completed: {
|
||||||
queue.finishTransaction(transaction)
|
queue.finishTransaction(transaction)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -358,6 +358,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
updatedTheme = item.presentationData.theme
|
updatedTheme = item.presentationData.theme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.accountContext.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
var credibilityIconImage: UIImage?
|
var credibilityIconImage: UIImage?
|
||||||
var credibilityIconOffset: CGFloat = 4.0
|
var credibilityIconOffset: CGFloat = 4.0
|
||||||
if let peer = item.peer {
|
if let peer = item.peer {
|
||||||
@ -369,6 +371,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
credibilityIconOffset = 2.0
|
credibilityIconOffset = 2.0
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
credibilityIconImage = PresentationResourcesItemList.verifiedPeerIcon(item.presentationData.theme)
|
credibilityIconImage = PresentationResourcesItemList.verifiedPeerIcon(item.presentationData.theme)
|
||||||
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
|
credibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -603,6 +603,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
var updatedLabelBadgeImage: UIImage?
|
var updatedLabelBadgeImage: UIImage?
|
||||||
var currentCredibilityIconImage: UIImage?
|
var currentCredibilityIconImage: UIImage?
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
if case .threatSelfAsSaved = item.aliasHandling, item.peer.id == item.context.account.peerId {
|
if case .threatSelfAsSaved = item.aliasHandling, item.peer.id == item.context.account.peerId {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -612,7 +614,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
|
||||||
} else if item.peer.isVerified {
|
} else if item.peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
} else if item.peer.isPremium {
|
} else if item.peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -622,9 +622,16 @@ private struct ChannelVisibilityControllerState: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func channelVisibilityControllerEntries(presentationData: PresentationData, mode: ChannelVisibilityControllerMode, view: PeerView, publicChannelsToRevoke: [Peer]?, importers: PeerInvitationImportersState?, state: ChannelVisibilityControllerState, limits: EngineConfiguration.UserLimits, premiumLimits: EngineConfiguration.UserLimits, isPremium: Bool) -> [ChannelVisibilityEntry] {
|
private func channelVisibilityControllerEntries(presentationData: PresentationData, mode: ChannelVisibilityControllerMode, view: PeerView, publicChannelsToRevoke: [Peer]?, importers: PeerInvitationImportersState?, state: ChannelVisibilityControllerState, limits: EngineConfiguration.UserLimits, premiumLimits: EngineConfiguration.UserLimits, isPremium: Bool, isPremiumDisabled: Bool) -> [ChannelVisibilityEntry] {
|
||||||
var entries: [ChannelVisibilityEntry] = []
|
var entries: [ChannelVisibilityEntry] = []
|
||||||
|
|
||||||
|
let isInitialSetup: Bool
|
||||||
|
if case .initialSetup = mode {
|
||||||
|
isInitialSetup = true
|
||||||
|
} else {
|
||||||
|
isInitialSetup = false
|
||||||
|
}
|
||||||
|
|
||||||
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
||||||
var isGroup = false
|
var isGroup = false
|
||||||
if case .group = peer.info {
|
if case .group = peer.info {
|
||||||
@ -721,17 +728,11 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch selectedType {
|
if case .revokeNames = mode {
|
||||||
case .publicChannel:
|
let count = Int32(publicChannelsToRevoke?.count ?? 0)
|
||||||
var displayAvailability = false
|
entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(premiumLimits.maxPublicLinksCount)").string, count, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount, isPremiumDisabled))
|
||||||
if peer.addressName == nil {
|
|
||||||
displayAvailability = publicChannelsToRevoke != nil && !(publicChannelsToRevoke!.isEmpty)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !"".isEmpty && displayAvailability {
|
|
||||||
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
||||||
// entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(20)").string, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount))
|
|
||||||
|
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for peer in publicChannelsToRevoke.sorted(by: { lhs, rhs in
|
for peer in publicChannelsToRevoke.sorted(by: { lhs, rhs in
|
||||||
var lhsDate: Int32 = 0
|
var lhsDate: Int32 = 0
|
||||||
@ -747,10 +748,10 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
entries.append(.existingLinkPeerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, ItemListPeerItemEditing(editable: true, editing: true, revealed: state.revealedRevokePeerId == peer.id), state.revokingPeerId == nil))
|
entries.append(.existingLinkPeerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, ItemListPeerItemEditing(editable: true, editing: true, revealed: state.revealedRevokePeerId == peer.id), state.revokingPeerId == nil))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_CreatePublicLinkHelp, true))
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
switch selectedType {
|
||||||
|
case .publicChannel:
|
||||||
entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Group_PublicLink_Placeholder, currentAddressName))
|
entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Group_PublicLink_Placeholder, currentAddressName))
|
||||||
if let status = state.addressNameValidationStatus {
|
if let status = state.addressNameValidationStatus {
|
||||||
let text: String
|
let text: String
|
||||||
@ -815,11 +816,10 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
entries.append(.privateLinkManage(presentationData.theme, presentationData.strings.InviteLink_Manage))
|
entries.append(.privateLinkManage(presentationData.theme, presentationData.strings.InviteLink_Manage))
|
||||||
entries.append(.privateLinkManageInfo(presentationData.theme, presentationData.strings.InviteLink_CreateInfo))
|
entries.append(.privateLinkManageInfo(presentationData.theme, presentationData.strings.InviteLink_CreateInfo))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case .privateChannel:
|
case .privateChannel:
|
||||||
let invite = (view.cachedData as? CachedChannelData)?.exportedInvitation
|
let invite = (view.cachedData as? CachedChannelData)?.exportedInvitation
|
||||||
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
||||||
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, mode != .initialSetup))
|
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, !isInitialSetup))
|
||||||
if isGroup {
|
if isGroup {
|
||||||
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePrivateLinkHelp))
|
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePrivateLinkHelp))
|
||||||
} else {
|
} else {
|
||||||
@ -855,13 +855,13 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
entries.append(.forwardingHeader(presentationData.theme, isGroup ? presentationData.strings.Group_Setup_ForwardingGroupTitle.uppercased() : presentationData.strings.Group_Setup_ForwardingChannelTitle.uppercased()))
|
entries.append(.forwardingHeader(presentationData.theme, isGroup ? presentationData.strings.Group_Setup_ForwardingGroupTitle.uppercased() : presentationData.strings.Group_Setup_ForwardingChannelTitle.uppercased()))
|
||||||
entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled))
|
entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled))
|
||||||
entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingChannelInfo) : (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled : presentationData.strings.Group_Setup_ForwardingChannelInfoDisabled)))
|
entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingChannelInfo) : (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled : presentationData.strings.Group_Setup_ForwardingChannelInfoDisabled)))
|
||||||
|
}
|
||||||
} else if let peer = view.peers[view.peerId] as? TelegramGroup {
|
} else if let peer = view.peers[view.peerId] as? TelegramGroup {
|
||||||
switch mode {
|
if case .revokeNames = mode {
|
||||||
case .revokeNames:
|
let count = Int32(publicChannelsToRevoke?.count ?? 0)
|
||||||
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(premiumLimits.maxPublicLinksCount)").string, count, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount, isPremiumDisabled))
|
||||||
// entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(20)").string, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount))
|
|
||||||
|
|
||||||
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesInfo, false))
|
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for peer in publicChannelsToRevoke.sorted(by: { lhs, rhs in
|
for peer in publicChannelsToRevoke.sorted(by: { lhs, rhs in
|
||||||
var lhsDate: Int32 = 0
|
var lhsDate: Int32 = 0
|
||||||
@ -878,10 +878,14 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch mode {
|
||||||
|
case .revokeNames:
|
||||||
|
break
|
||||||
case .privateLink:
|
case .privateLink:
|
||||||
let invite = (view.cachedData as? CachedGroupData)?.exportedInvitation
|
let invite = (view.cachedData as? CachedGroupData)?.exportedInvitation
|
||||||
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
||||||
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, mode != .initialSetup))
|
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, !isInitialSetup))
|
||||||
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_Help))
|
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_Help))
|
||||||
switch mode {
|
switch mode {
|
||||||
case .initialSetup, .revokeNames:
|
case .initialSetup, .revokeNames:
|
||||||
@ -922,7 +926,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
|
|
||||||
if displayAvailability {
|
if displayAvailability {
|
||||||
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
if let publicChannelsToRevoke = publicChannelsToRevoke {
|
||||||
// entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(20)").string, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount))
|
// entries.append(.linksLimitInfo(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesOrExtendInfo("\(20)").string, limits.maxPublicLinksCount, premiumLimits.maxPublicLinksCount))
|
||||||
|
|
||||||
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesInfo, false))
|
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesInfo, false))
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
@ -982,7 +986,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
case .privateChannel:
|
case .privateChannel:
|
||||||
let invite = (view.cachedData as? CachedGroupData)?.exportedInvitation
|
let invite = (view.cachedData as? CachedGroupData)?.exportedInvitation
|
||||||
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
entries.append(.privateLinkHeader(presentationData.theme, presentationData.strings.InviteLink_InviteLink.uppercased()))
|
||||||
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, mode != .initialSetup))
|
entries.append(.privateLink(presentationData.theme, invite, importers?.importers.prefix(3).compactMap { $0.peer.peer.flatMap(EnginePeer.init) } ?? [], importers?.count ?? 0, !isInitialSetup))
|
||||||
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePrivateLinkHelp))
|
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePrivateLinkHelp))
|
||||||
switch mode {
|
switch mode {
|
||||||
case .initialSetup, .revokeNames:
|
case .initialSetup, .revokeNames:
|
||||||
@ -1009,6 +1013,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled))
|
entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled))
|
||||||
entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled))
|
entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
@ -1079,16 +1084,24 @@ public enum ChannelVisibilityControllerMode {
|
|||||||
case initialSetup
|
case initialSetup
|
||||||
case generic
|
case generic
|
||||||
case privateLink
|
case privateLink
|
||||||
case revokeNames
|
case revokeNames([Peer])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func channelVisibilityController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: PeerId, mode: ChannelVisibilityControllerMode, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void, onDismissRemoveController: ViewController? = nil) -> ViewController {
|
public func channelVisibilityController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: PeerId, mode: ChannelVisibilityControllerMode, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void, onDismissRemoveController: ViewController? = nil, revokedPeerAddressName: ((PeerId) -> Void)? = nil) -> ViewController {
|
||||||
let statePromise = ValuePromise(ChannelVisibilityControllerState(), ignoreRepeated: true)
|
let statePromise = ValuePromise(ChannelVisibilityControllerState(), ignoreRepeated: true)
|
||||||
let stateValue = Atomic(value: ChannelVisibilityControllerState())
|
let stateValue = Atomic(value: ChannelVisibilityControllerState())
|
||||||
let updateState: ((ChannelVisibilityControllerState) -> ChannelVisibilityControllerState) -> Void = { f in
|
let updateState: ((ChannelVisibilityControllerState) -> ChannelVisibilityControllerState) -> Void = { f in
|
||||||
statePromise.set(stateValue.modify { f($0) })
|
statePromise.set(stateValue.modify { f($0) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let adminedPublicChannels = Promise<[Peer]?>()
|
||||||
|
if case let .revokeNames(peers) = mode {
|
||||||
|
adminedPublicChannels.set(.single(peers))
|
||||||
|
} else {
|
||||||
|
adminedPublicChannels.set(context.engine.peers.adminedPublicChannels(scope: .all)
|
||||||
|
|> map(Optional.init))
|
||||||
|
}
|
||||||
|
|
||||||
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
||||||
peersDisablingAddressNameAssignment.set(.single(nil) |> then(context.engine.peers.channelAddressNameAssignmentAvailability(peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
peersDisablingAddressNameAssignment.set(.single(nil) |> then(context.engine.peers.channelAddressNameAssignmentAvailability(peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
||||||
if case .addressNameLimitReached = result {
|
if case .addressNameLimitReached = result {
|
||||||
@ -1133,9 +1146,43 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
actionsDisposable.add(toggleRequestToJoinDisposable)
|
actionsDisposable.add(toggleRequestToJoinDisposable)
|
||||||
|
|
||||||
let arguments = ChannelVisibilityControllerArguments(context: context, updateCurrentType: { type in
|
let arguments = ChannelVisibilityControllerArguments(context: context, updateCurrentType: { type in
|
||||||
|
if type == .publicChannel {
|
||||||
|
let _ = combineLatest(
|
||||||
|
queue: Queue.mainQueue(),
|
||||||
|
adminedPublicChannels.get() |> filter { $0 != nil } |> take(1),
|
||||||
|
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)),
|
||||||
|
context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
|
||||||
|
)
|
||||||
|
).start(next: { peers, accountPeer, data in
|
||||||
|
let (limits, premiumLimits) = data
|
||||||
|
let isPremium = accountPeer?.isPremium ?? false
|
||||||
|
|
||||||
|
if let peers = peers {
|
||||||
|
let count = Int32(peers.count)
|
||||||
|
if count < limits.maxPublicLinksCount || (count < premiumLimits.maxPublicLinksCount && isPremium) {
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedSelectedType(type)
|
return state.withUpdatedSelectedType(type)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let controller = channelVisibilityController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, mode: .revokeNames(peers), upgradedToSupergroup: { _, _ in }, revokedPeerAddressName: { revokedPeerId in
|
||||||
|
let updatedPublicChannels = peers.filter { $0.id != revokedPeerId }
|
||||||
|
adminedPublicChannels.set(.single(updatedPublicChannels) |> then(
|
||||||
|
context.engine.peers.adminedPublicChannels(scope: .all) |> map(Optional.init))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
controller.navigationPresentation = .modal
|
||||||
|
pushControllerImpl?(controller)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
updateState { state in
|
||||||
|
return state.withUpdatedSelectedType(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
}, updatePublicLinkText: { currentText, text in
|
}, updatePublicLinkText: { currentText, text in
|
||||||
if text.isEmpty {
|
if text.isEmpty {
|
||||||
checkAddressNameDisposable.set(nil)
|
checkAddressNameDisposable.set(nil)
|
||||||
@ -1179,11 +1226,8 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
return state.withUpdatedRevokingPeerId(nil)
|
return state.withUpdatedRevokingPeerId(nil)
|
||||||
}
|
}
|
||||||
}, completed: {
|
}, completed: {
|
||||||
peersDisablingAddressNameAssignment.set(.single([]) |> delay(0.2, queue: Queue.mainQueue()) |> afterNext { _ in
|
revokedPeerAddressName?(peerId)
|
||||||
updateState { state in
|
dismissImpl?()
|
||||||
return state.withUpdatedRevokingPeerId(nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}))
|
}))
|
||||||
}, copyLink: { invite in
|
}, copyLink: { invite in
|
||||||
UIPasteboard.general.string = invite.link
|
UIPasteboard.general.string = invite.link
|
||||||
@ -1353,7 +1397,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
presentationData,
|
presentationData,
|
||||||
statePromise.get() |> deliverOnMainQueue,
|
statePromise.get() |> deliverOnMainQueue,
|
||||||
peerView,
|
peerView,
|
||||||
peersDisablingAddressNameAssignment.get() |> deliverOnMainQueue,
|
adminedPublicChannels.get(),
|
||||||
importersContext,
|
importersContext,
|
||||||
importersState.get(),
|
importersState.get(),
|
||||||
context.engine.data.get(
|
context.engine.data.get(
|
||||||
@ -1373,7 +1417,10 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
|
|
||||||
var rightNavigationButton: ItemListNavigationButton?
|
var rightNavigationButton: ItemListNavigationButton?
|
||||||
if case .revokeNames = mode {
|
if case .revokeNames = mode {
|
||||||
|
footerItem = IncreaseLimitFooterItem(theme: presentationData.theme, title: presentationData.strings.Premium_IncreaseLimit, colorful: true, action: {
|
||||||
|
let controller = PremiumIntroScreen(context: context, source: .publicLinks)
|
||||||
|
pushControllerImpl?(controller)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
if let peer = peer as? TelegramChannel {
|
if let peer = peer as? TelegramChannel {
|
||||||
var doneEnabled = true
|
var doneEnabled = true
|
||||||
@ -1400,7 +1447,14 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rightNavigationButton = ItemListNavigationButton(content: .text(mode == .initialSetup ? presentationData.strings.Common_Next : presentationData.strings.Common_Done), style: state.updatingAddressName ? .activity : .bold, enabled: doneEnabled, action: {
|
let isInitialSetup: Bool
|
||||||
|
if case .initialSetup = mode {
|
||||||
|
isInitialSetup = true
|
||||||
|
} else {
|
||||||
|
isInitialSetup = false
|
||||||
|
}
|
||||||
|
|
||||||
|
rightNavigationButton = ItemListNavigationButton(content: .text(isInitialSetup ? presentationData.strings.Common_Next : presentationData.strings.Common_Done), style: state.updatingAddressName ? .activity : .bold, enabled: doneEnabled, action: {
|
||||||
var updatedAddressNameValue: String?
|
var updatedAddressNameValue: String?
|
||||||
updateState { state in
|
updateState { state in
|
||||||
updatedAddressNameValue = updatedAddressName(mode: mode, state: state, peer: peer, cachedData: view.cachedData)
|
updatedAddressNameValue = updatedAddressName(mode: mode, state: state, peer: peer, cachedData: view.cachedData)
|
||||||
@ -1619,13 +1673,6 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
crossfade = hadNamesToRevoke != hasNamesToRevoke
|
crossfade = hadNamesToRevoke != hasNamesToRevoke
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasNamesToRevoke && selectedType == .publicChannel {
|
|
||||||
footerItem = IncreaseLimitFooterItem(theme: presentationData.theme, title: presentationData.strings.Premium_IncreaseLimit, colorful: true, action: {
|
|
||||||
let controller = PremiumIntroScreen(context: context, source: .publicLinks)
|
|
||||||
pushControllerImpl?(controller)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if let hadNamesToRevoke = hadNamesToRevoke {
|
if let hadNamesToRevoke = hadNamesToRevoke {
|
||||||
animateChanges = hadNamesToRevoke != hasNamesToRevoke
|
animateChanges = hadNamesToRevoke != hasNamesToRevoke
|
||||||
}
|
}
|
||||||
@ -1645,7 +1692,8 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
|||||||
title = presentationData.strings.Premium_LimitReached
|
title = presentationData.strings.Premium_LimitReached
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = channelVisibilityControllerEntries(presentationData: presentationData, mode: mode, view: view, publicChannelsToRevoke: publicChannelsToRevoke, importers: importers, state: state, limits: limits, premiumLimits: premiumLimits, isPremium: isPremium)
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
|
let entries = channelVisibilityControllerEntries(presentationData: presentationData, mode: mode, view: view, publicChannelsToRevoke: publicChannelsToRevoke, importers: importers, state: state, limits: limits, premiumLimits: premiumLimits, isPremium: isPremium, isPremiumDisabled: premiumConfiguration.isPremiumDisabled)
|
||||||
|
|
||||||
var focusItemTag: ItemListItemTag?
|
var focusItemTag: ItemListItemTag?
|
||||||
if entries.count > 1, let cachedChannelData = view.cachedData as? CachedChannelData, cachedChannelData.peerGeoLocation != nil {
|
if entries.count > 1, let cachedChannelData = view.cachedData as? CachedChannelData, cachedChannelData.peerGeoLocation != nil {
|
||||||
|
|||||||
@ -81,6 +81,9 @@ private let boldTextFont = Font.semibold(15.0)
|
|||||||
|
|
||||||
class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
||||||
private var hostView: ComponentHostView<Empty>?
|
private var hostView: ComponentHostView<Empty>?
|
||||||
|
|
||||||
|
private var params: (AnyComponent<Empty>, CGSize, ListViewItemNodeLayout, CGSize)?
|
||||||
|
|
||||||
private let titleNode: TextNode
|
private let titleNode: TextNode
|
||||||
private let textNode: TextNode
|
private let textNode: TextNode
|
||||||
|
|
||||||
@ -109,6 +112,19 @@ class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
|||||||
let hostView = ComponentHostView<Empty>()
|
let hostView = ComponentHostView<Empty>()
|
||||||
self.hostView = hostView
|
self.hostView = hostView
|
||||||
self.view.addSubview(hostView)
|
self.view.addSubview(hostView)
|
||||||
|
|
||||||
|
if let (component, containerSize, layout, textSize) = self.params {
|
||||||
|
let size = hostView.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: component,
|
||||||
|
environment: {},
|
||||||
|
containerSize: containerSize
|
||||||
|
)
|
||||||
|
hostView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - size.width) / 2.0), y: -30.0), size: size)
|
||||||
|
|
||||||
|
let textSpacing: CGFloat = -6.0
|
||||||
|
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - textSize.width) / 2.0), y: size.height + textSpacing), size: textSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func asyncLayout() -> (_ item: IncreaseLimitHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
func asyncLayout() -> (_ item: IncreaseLimitHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||||
@ -161,10 +177,7 @@ class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hostView = strongSelf.hostView {
|
let component = AnyComponent(PremiumLimitDisplayComponent(
|
||||||
let size = hostView.update(
|
|
||||||
transition: .immediate,
|
|
||||||
component: AnyComponent(PremiumLimitDisplayComponent(
|
|
||||||
inactiveColor: item.theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.5),
|
inactiveColor: item.theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.5),
|
||||||
activeColors: gradientColors,
|
activeColors: gradientColors,
|
||||||
inactiveTitle: item.strings.Premium_Free,
|
inactiveTitle: item.strings.Premium_Free,
|
||||||
@ -177,15 +190,23 @@ class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
|||||||
badgeText: "\(item.count)",
|
badgeText: "\(item.count)",
|
||||||
badgePosition: CGFloat(item.count) / CGFloat(item.premiumCount),
|
badgePosition: CGFloat(item.count) / CGFloat(item.premiumCount),
|
||||||
isPremiumDisabled: item.isPremiumDisabled
|
isPremiumDisabled: item.isPremiumDisabled
|
||||||
)),
|
))
|
||||||
environment: {},
|
let containerSize = CGSize(width: layout.size.width - params.leftInset - params.rightInset, height: 200.0)
|
||||||
containerSize: CGSize(width: layout.size.width - params.leftInset - params.rightInset, height: 200.0)
|
|
||||||
)
|
|
||||||
hostView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - size.width) / 2.0), y: -30.0), size: size)
|
|
||||||
|
|
||||||
let _ = textApply()
|
let _ = textApply()
|
||||||
|
|
||||||
|
if let hostView = strongSelf.hostView {
|
||||||
|
let size = hostView.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: component,
|
||||||
|
environment: {},
|
||||||
|
containerSize: containerSize
|
||||||
|
)
|
||||||
|
hostView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - size.width) / 2.0), y: -30.0), size: size)
|
||||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - textLayout.size.width) / 2.0), y: size.height + textSpacing), size: textLayout.size)
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - textLayout.size.width) / 2.0), y: size.height + textSpacing), size: textLayout.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf.params = (component, containerSize, layout, textLayout.size)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -807,7 +807,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.disposable = (context.engine.data.get(
|
self.disposable = (context.engine.data.subscribe(
|
||||||
TelegramEngine.EngineData.Item.Configuration.App(),
|
TelegramEngine.EngineData.Item.Configuration.App(),
|
||||||
TelegramEngine.EngineData.Item.Configuration.PremiumPromo()
|
TelegramEngine.EngineData.Item.Configuration.PremiumPromo()
|
||||||
)
|
)
|
||||||
@ -841,6 +841,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let _ = updatePremiumPromoConfigurationOnce(account: context.account).start()
|
||||||
|
|
||||||
let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers)
|
let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers)
|
||||||
self.stickersDisposable = (self.context.account.postbox.combinedView(keys: [stickersKey])
|
self.stickersDisposable = (self.context.account.postbox.combinedView(keys: [stickersKey])
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] views in
|
|> deliverOnMainQueue).start(next: { [weak self] views in
|
||||||
@ -1362,9 +1364,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
self.disposable = combineLatest(
|
self.disposable = combineLatest(
|
||||||
queue: Queue.mainQueue(),
|
queue: Queue.mainQueue(),
|
||||||
availableProducts,
|
availableProducts,
|
||||||
context.account.postbox.peerView(id: context.account.peerId)
|
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||||
|> map { view -> Bool in
|
|> map { peer -> Bool in
|
||||||
return view.peers[view.peerId]?.isPremium ?? false
|
return peer?.isPremium ?? false
|
||||||
},
|
},
|
||||||
otherPeerName
|
otherPeerName
|
||||||
).start(next: { [weak self] products, isPremium, otherPeerName in
|
).start(next: { [weak self] products, isPremium, otherPeerName in
|
||||||
@ -1418,6 +1420,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
}, completed: { [weak self] in
|
}, completed: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start()
|
||||||
strongSelf.isPremium = true
|
strongSelf.isPremium = true
|
||||||
strongSelf.updated(transition: .easeInOut(duration: 0.25))
|
strongSelf.updated(transition: .easeInOut(duration: 0.25))
|
||||||
strongSelf.completion()
|
strongSelf.completion()
|
||||||
|
|||||||
@ -49,7 +49,7 @@ final class ReactionsCarouselComponent: Component {
|
|||||||
public func update(component: ReactionsCarouselComponent, availableSize: CGSize, environment: Environment<DemoPageEnvironment>, transition: Transition) -> CGSize {
|
public func update(component: ReactionsCarouselComponent, availableSize: CGSize, environment: Environment<DemoPageEnvironment>, transition: Transition) -> CGSize {
|
||||||
let isDisplaying = environment[DemoPageEnvironment.self].isDisplaying
|
let isDisplaying = environment[DemoPageEnvironment.self].isDisplaying
|
||||||
|
|
||||||
if self.node == nil {
|
if self.node == nil && !component.reactions.isEmpty {
|
||||||
let node = ReactionCarouselNode(
|
let node = ReactionCarouselNode(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
|
|||||||
@ -45,7 +45,7 @@ final class StickersCarouselComponent: Component {
|
|||||||
public func update(component: StickersCarouselComponent, availableSize: CGSize, environment: Environment<DemoPageEnvironment>, transition: Transition) -> CGSize {
|
public func update(component: StickersCarouselComponent, availableSize: CGSize, environment: Environment<DemoPageEnvironment>, transition: Transition) -> CGSize {
|
||||||
let isDisplaying = environment[DemoPageEnvironment.self].isDisplaying
|
let isDisplaying = environment[DemoPageEnvironment.self].isDisplaying
|
||||||
|
|
||||||
if self.node == nil {
|
if self.node == nil && !component.stickers.isEmpty {
|
||||||
let node = StickersCarouselNode(
|
let node = StickersCarouselNode(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
stickers: component.stickers
|
stickers: component.stickers
|
||||||
|
|||||||
@ -6227,11 +6227,13 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.payments {
|
public extension Api.functions.payments {
|
||||||
static func assignAppStoreTransaction(transactionId: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func assignAppStoreTransaction(flags: Int32, transactionId: String, receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1654235439)
|
buffer.appendInt32(267129798)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeString(transactionId, buffer: buffer, boxed: false)
|
serializeString(transactionId, buffer: buffer, boxed: false)
|
||||||
return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("transactionId", String(describing: transactionId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
serializeBytes(receipt, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("transactionId", String(describing: transactionId)), ("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -6381,21 +6383,6 @@ public extension Api.functions.payments {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.payments {
|
|
||||||
static func restoreAppStoreReceipt(receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
|
||||||
let buffer = Buffer()
|
|
||||||
buffer.appendInt32(-2132923705)
|
|
||||||
serializeBytes(receipt, buffer: buffer, boxed: false)
|
|
||||||
return (FunctionDescription(name: "payments.restoreAppStoreReceipt", parameters: [("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
|
||||||
let reader = BufferReader(buffer)
|
|
||||||
var result: Api.Updates?
|
|
||||||
if let signature = reader.readInt32() {
|
|
||||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public extension Api.functions.payments {
|
public extension Api.functions.payments {
|
||||||
static func restorePlayMarketReceipt(receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func restorePlayMarketReceipt(receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
|||||||
@ -495,6 +495,8 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
let leftInset: CGFloat = 58.0 + params.leftInset
|
let leftInset: CGFloat = 58.0 + params.leftInset
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
var titleIconsWidth: CGFloat = 0.0
|
var titleIconsWidth: CGFloat = 0.0
|
||||||
var currentCredibilityIconImage: UIImage?
|
var currentCredibilityIconImage: UIImage?
|
||||||
var credibilityIconOffset: CGFloat = 0.0
|
var credibilityIconOffset: CGFloat = 0.0
|
||||||
@ -507,6 +509,9 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
} else if item.peer.isVerified {
|
} else if item.peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
credibilityIconOffset = 3.0
|
credibilityIconOffset = 3.0
|
||||||
|
} else if item.peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
|
credibilityIconOffset = 3.0
|
||||||
}
|
}
|
||||||
|
|
||||||
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
||||||
|
|||||||
@ -829,6 +829,8 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let verticalInset: CGFloat = 8.0
|
let verticalInset: CGFloat = 8.0
|
||||||
let verticalOffset: CGFloat = 0.0
|
let verticalOffset: CGFloat = 0.0
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
var titleIconsWidth: CGFloat = 0.0
|
var titleIconsWidth: CGFloat = 0.0
|
||||||
var currentCredibilityIconImage: UIImage?
|
var currentCredibilityIconImage: UIImage?
|
||||||
var credibilityIconOffset: CGFloat = 0.0
|
var credibilityIconOffset: CGFloat = 0.0
|
||||||
@ -841,6 +843,9 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
} else if item.peer.isVerified {
|
} else if item.peer.isVerified {
|
||||||
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||||
credibilityIconOffset = 3.0
|
credibilityIconOffset = 3.0
|
||||||
|
} else if item.peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
|
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
|
||||||
|
credibilityIconOffset = 3.0
|
||||||
}
|
}
|
||||||
|
|
||||||
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
||||||
|
|||||||
@ -8,26 +8,18 @@ public enum AssignAppStoreTransactionError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_assignAppStoreTransaction(account: Account, transactionId: String) -> Signal<Never, AssignAppStoreTransactionError> {
|
func _internal_assignAppStoreTransaction(account: Account, transactionId: String, receipt: Data, restore: Bool) -> Signal<Never, AssignAppStoreTransactionError> {
|
||||||
return account.network.request(Api.functions.payments.assignAppStoreTransaction(transactionId: transactionId))
|
var flags: Int32 = 0
|
||||||
|
if restore {
|
||||||
|
flags |= (1 << 0)
|
||||||
|
}
|
||||||
|
return account.network.request(Api.functions.payments.assignAppStoreTransaction(flags: flags, transactionId: transactionId, receipt: Buffer(data: receipt)))
|
||||||
|> mapError { _ -> AssignAppStoreTransactionError in
|
|> mapError { _ -> AssignAppStoreTransactionError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { updates -> Signal<Never, AssignAppStoreTransactionError> in
|
|> mapToSignal { updates -> Signal<Never, AssignAppStoreTransactionError> in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
|
return .complete()
|
||||||
return account.postbox.peerView(id: account.peerId)
|
|
||||||
|> castError(AssignAppStoreTransactionError.self)
|
|
||||||
|> take(until: { view in
|
|
||||||
if let peer = view.peers[view.peerId], peer.isPremium {
|
|
||||||
return SignalTakeAction(passthrough: false, complete: true)
|
|
||||||
} else {
|
|
||||||
return SignalTakeAction(passthrough: false, complete: false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|> mapToSignal { _ -> Signal<Never, AssignAppStoreTransactionError> in
|
|
||||||
return .never()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import Foundation
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import Postbox
|
import Postbox
|
||||||
|
|
||||||
@ -37,8 +38,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_clearBotPaymentInfo(network: self.account.network, info: info)
|
return _internal_clearBotPaymentInfo(network: self.account.network, info: info)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func assignAppStoreTransaction(transactionId: String) -> Signal<Never, AssignAppStoreTransactionError> {
|
public func assignAppStoreTransaction(transactionId: String, receipt: Data, restore: Bool) -> Signal<Never, AssignAppStoreTransactionError> {
|
||||||
return _internal_assignAppStoreTransaction(account: self.account, transactionId: transactionId)
|
return _internal_assignAppStoreTransaction(account: self.account, transactionId: transactionId, receipt: receipt, restore: restore)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func canPurchasePremium() -> Signal<Bool, NoError> {
|
public func canPurchasePremium() -> Signal<Bool, NoError> {
|
||||||
|
|||||||
@ -2300,6 +2300,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let themeUpdated = self.presentationData?.theme !== presentationData.theme
|
let themeUpdated = self.presentationData?.theme !== presentationData.theme
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
let credibilityIcon: CredibilityIcon
|
let credibilityIcon: CredibilityIcon
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
if peer.isFake {
|
if peer.isFake {
|
||||||
@ -2308,7 +2310,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
credibilityIcon = .scam
|
credibilityIcon = .scam
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
credibilityIcon = .verified
|
credibilityIcon = .verified
|
||||||
} else if peer.isPremium {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
credibilityIcon = .premium
|
credibilityIcon = .premium
|
||||||
} else {
|
} else {
|
||||||
credibilityIcon = .none
|
credibilityIcon = .none
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user