From 0b448bf68fd7ae92526bb6ca8ac6b0e2d20a366b Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 13 May 2025 13:41:41 +0400 Subject: [PATCH] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 13 +++ .../Sources/ContactListNode.swift | 2 +- .../TelegramEngine/Payments/StarGifts.swift | 91 ++++++++++++++----- .../Payments/TelegramEnginePayments.swift | 4 +- .../Sources/GiftStoreScreen.swift | 4 +- .../Sources/GiftViewScreen.swift | 82 +++++++++++------ .../Sources/PeerInfoScreen.swift | 11 ++- .../Sources/PeerInfoGiftsPaneNode.swift | 4 +- .../Sources/ChatbotSetupScreen.swift | 86 ++++++++++++++++-- .../Sources/ChatTranslationPanelNode.swift | 13 ++- 10 files changed, 243 insertions(+), 67 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e4cd94bb7e..209c1b82ee 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -14320,3 +14320,16 @@ Sorry for the inconvenience."; "Story.Editor.TooltipSelection_1" = "Tap here to view your %@ story"; "Story.Editor.TooltipSelection_any" = "Tap here to view your %@ stories"; + +"Gift.Buy.ErrorUnknown" = "An error occurred. Please try again."; +"Gift.Buy.ErrorPriceChanged.Title" = "Warning"; +"Gift.Buy.ErrorPriceChanged.Text" = "The price has increased from **%1$@** to **%2$@**. Buy the gift anyway?"; +"Gift.Buy.ErrorPriceChanged.Text.Stars_1" = "%@ Star"; +"Gift.Buy.ErrorPriceChanged.Text.Stars_any" = "%@ Stars"; + +"ChatbotSetup.Gift.Warning.Title" = "Warning"; +"ChatbotSetup.Gift.Warning.CombinedText" = "The bot **%@** will be able to **manage your gifts and stars**, including giving them away to other users."; +"ChatbotSetup.Gift.Warning.GiftsText" = "The bot **%@** will be able to **manage your gifts**, including giving them away to other users."; +"ChatbotSetup.Gift.Warning.StarsText" = "The bot **%@** will be able to **transfer your stars**."; +"ChatbotSetup.Gift.Warning.UsernameText" = "The bot **%@** will be able to **edit your username**, which will make your current username available for others to claim."; +"ChatbotSetup.Gift.Warning.Proceed" = "Proceed"; diff --git a/submodules/ContactListUI/Sources/ContactListNode.swift b/submodules/ContactListUI/Sources/ContactListNode.swift index ee236408c6..22d59abf0e 100644 --- a/submodules/ContactListUI/Sources/ContactListNode.swift +++ b/submodules/ContactListUI/Sources/ContactListNode.swift @@ -1841,7 +1841,7 @@ public final class ContactListNode: ASDisplayNode { } var isEmpty = false - if (authorizationStatus == .notDetermined || authorizationStatus == .denied) && peers.isEmpty { + if (authorizationStatus == .notDetermined || authorizationStatus == .denied) && peers.isEmpty && topPeers.isEmpty { isEmpty = true } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index e7ca7d8f5c..d266de078e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -854,6 +854,7 @@ public enum TransferStarGiftError { public enum BuyStarGiftError { case generic + case priceChanged(Int64) } public enum UpdateStarGiftPriceError { @@ -865,7 +866,7 @@ public enum UpgradeStarGiftError { case generic } -func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id) -> Signal { +func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal { let source: BotPaymentInvoiceSource = .starGiftResale(slug: slug, toPeerId: peerId) return _internal_fetchBotPaymentForm(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, source: source, themeParams: nil) |> map(Optional.init) @@ -874,6 +875,9 @@ func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id } |> mapToSignal { paymentForm in if let paymentForm { + if let paymentPrice = paymentForm.invoice.prices.first?.amount, let price, paymentPrice > price { + return .fail(.priceChanged(paymentPrice)) + } return _internal_sendStarsPaymentForm(account: account, formId: paymentForm.id, source: source) |> mapError { _ -> BuyStarGiftError in return .generic @@ -1473,26 +1477,53 @@ private final class ProfileGiftsContextImpl { return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId) } - func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { - if let count = self.count { - self.count = max(0, count - 1) + func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal { + var listingPrice: Int64? + if let gift = self.gifts.first(where: { gift in + if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { + return true + } + return false + }), case let .unique(uniqueGift) = gift.gift { + listingPrice = uniqueGift.resellStars } - self.gifts.removeAll(where: { gift in - if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { - return true - } - return false - }) - self.filteredGifts.removeAll(where: { gift in - if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { - return true - } - return false - }) - - self.pushState() - return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId) + if listingPrice == nil { + if let gift = self.filteredGifts.first(where: { gift in + if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { + return true + } + return false + }), case let .unique(uniqueGift) = gift.gift { + listingPrice = uniqueGift.resellStars + } + } + + return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price ?? listingPrice) + |> afterCompleted { [weak self] in + guard let self else { + return + } + self.queue.async { + if let count = self.count { + self.count = max(0, count - 1) + } + self.gifts.removeAll(where: { gift in + if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { + return true + } + return false + }) + self.filteredGifts.removeAll(where: { gift in + if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug { + return true + } + return false + }) + + self.pushState() + } + } } func removeStarGift(gift: TelegramCore.StarGift) { @@ -1975,11 +2006,11 @@ public final class ProfileGiftsContext { } } - public func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { + public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64? = nil) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in - disposable.set(impl.buyStarGift(slug: slug, peerId: peerId).start(error: { error in + disposable.set(impl.buyStarGift(slug: slug, peerId: peerId, price: price).start(error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() @@ -2606,8 +2637,18 @@ private final class ResaleGiftsContextImpl { self.loadMore() } - func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { - return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId) + func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal { + var listingPrice: Int64? + if let gift = self.gifts.first(where: { gift in + if case let .unique(uniqueGift) = gift, uniqueGift.slug == slug { + return true + } + return false + }), case let .unique(uniqueGift) = gift { + listingPrice = uniqueGift.resellStars + } + + return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price ?? listingPrice) |> afterCompleted { [weak self] in guard let self else { return @@ -2754,11 +2795,11 @@ public final class ResaleGiftsContext { } } - public func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { + public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64? = nil) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in - disposable.set(impl.buyStarGift(slug: slug, peerId: peerId).start(error: { error in + disposable.set(impl.buyStarGift(slug: slug, peerId: peerId, price: price).start(error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index 2fcf1f873a..000eb53c58 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -125,8 +125,8 @@ public extension TelegramEngine { return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId) } - public func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { - return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId) + public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal { + return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price) } public func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal { diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift index 4ca433b12f..c960a11524 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift @@ -270,8 +270,8 @@ final class GiftStoreScreenComponent: Component { subject: .uniqueGift(uniqueGift, state.peerId), allSubjects: allSubjects, index: index, - buyGift: { slug, peerId in - return self.state?.starGiftsContext.buyStarGift(slug: slug, peerId: peerId) ?? .complete() + buyGift: { slug, peerId, price in + return self.state?.starGiftsContext.buyStarGift(slug: slug, peerId: peerId, price: price) ?? .complete() }, updateResellStars: { price in return self.state?.starGiftsContext.updateStarGiftResellPrice(slug: uniqueGift.slug, price: price) ?? .complete() diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index c07308affd..f783f08939 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -1145,7 +1145,7 @@ private final class GiftViewSheetContent: CombinedComponent { } } - func commitBuy(skipConfirmation: Bool = false) { + func commitBuy(acceptedPrice: Int64? = nil, skipConfirmation: Bool = false) { guard let resellStars = self.subject.arguments?.resellStars, let starsContext = self.context.starsContext, let starsState = starsContext.currentState, case let .unique(uniqueGift) = self.subject.arguments?.gift else { return } @@ -1157,7 +1157,7 @@ private final class GiftViewSheetContent: CombinedComponent { let recipientPeerId = self.recipientPeerId ?? self.context.account.peerId let action = { - let proceed: (Int64) -> Void = { formId in + let proceed: () -> Void = { guard let controller = self.getController() as? GiftViewScreen else { return } @@ -1165,38 +1165,66 @@ private final class GiftViewSheetContent: CombinedComponent { self.inProgress = true self.updated() - let buyGiftImpl: ((String, EnginePeer.Id) -> Signal) + let buyGiftImpl: ((String, EnginePeer.Id, Int64?) -> Signal) if let buyGift = controller.buyGift { - buyGiftImpl = { slug, peerId in - return buyGift(slug, peerId) + buyGiftImpl = { slug, peerId, price in + return buyGift(slug, peerId, price) |> afterCompleted { context.starsContext?.load(force: true) } } } else { - buyGiftImpl = { slug, peerId in - return self.context.engine.payments.buyStarGift(slug: slug, peerId: peerId) + buyGiftImpl = { slug, peerId, price in + return self.context.engine.payments.buyStarGift(slug: slug, peerId: peerId, price: price) |> afterCompleted { context.starsContext?.load(force: true) } } } - self.buyDisposable = (buyGiftImpl(uniqueGift.slug, recipientPeerId) - |> deliverOnMainQueue).start(error: { [weak self] error in - guard let self, let controller = self.getController() else { - return - } - - self.inProgress = false - self.updated() - - let errorText = presentationData.strings.Gift_Send_ErrorUnknown - - let alertController = textAlertController(context: context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})], parseMarkdown: true) - controller.present(alertController, in: .window(.root)) - }, completed: { [weak self, weak starsContext] in - guard let self, let controller = self.getController() as? GiftViewScreen else { + self.buyDisposable = (buyGiftImpl(uniqueGift.slug, recipientPeerId, acceptedPrice ?? resellStars) + |> deliverOnMainQueue).start( + error: { [weak self] error in + guard let self, let controller = self.getController() else { + return + } + + self.inProgress = false + self.updated() + + switch error { + case let .priceChanged(newPrice): + let errorTitle = presentationData.strings.Gift_Buy_ErrorPriceChanged_Title + let originalPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(resellStars)) + let newPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(newPrice)) + let errorText = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text(originalPriceString, newPriceString).string + + let alertController = textAlertController( + context: context, + title: errorTitle, + text: errorText, + actions: [ + TextAlertAction(type: .defaultAction, title: presentationData.strings.Gift_Buy_Confirm_BuyFor(Int32(newPrice)), action: { [weak self] in + guard let self else { + return + } + self.commitBuy(acceptedPrice: newPrice, skipConfirmation: true) + }), + TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { + }) + ], + actionLayout: .vertical, + parseMarkdown: true + ) + controller.present(alertController, in: .window(.root)) + default: + let alertController = textAlertController(context: context, title: nil, text: presentationData.strings.Gift_Buy_ErrorUnknown, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})], parseMarkdown: true) + controller.present(alertController, in: .window(.root)) + } + }, + completed: { [weak self, weak starsContext] in + guard let self, + let controller = self.getController() as? GiftViewScreen else { return } self.inProgress = false @@ -1303,7 +1331,7 @@ private final class GiftViewSheetContent: CombinedComponent { self.commitBuy(skipConfirmation: true) } else { - proceed(buyForm.id) + proceed() } }); }) @@ -1312,7 +1340,7 @@ private final class GiftViewSheetContent: CombinedComponent { controller.push(purchaseController) }) } else { - proceed(buyForm.id) + proceed() } } } @@ -1321,7 +1349,7 @@ private final class GiftViewSheetContent: CombinedComponent { action() } else { let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: recipientPeerId)) - |> deliverOnMainQueue).start(next: { [weak self] peer in + |> deliverOnMainQueue).start(next: { [weak self] peer in guard let self, let peer else { return } @@ -3565,7 +3593,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { fileprivate let convertToStars: (() -> Void)? fileprivate let transferGift: ((Bool, EnginePeer.Id) -> Signal)? fileprivate let upgradeGift: ((Int64?, Bool) -> Signal)? - fileprivate let buyGift: ((String, EnginePeer.Id) -> Signal)? + fileprivate let buyGift: ((String, EnginePeer.Id, Int64?) -> Signal)? fileprivate let updateResellStars: ((Int64?) -> Signal)? fileprivate let togglePinnedToTop: ((Bool) -> Bool)? fileprivate let shareStory: ((StarGift.UniqueGift) -> Void)? @@ -3582,7 +3610,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { convertToStars: (() -> Void)? = nil, transferGift: ((Bool, EnginePeer.Id) -> Signal)? = nil, upgradeGift: ((Int64?, Bool) -> Signal)? = nil, - buyGift: ((String, EnginePeer.Id) -> Signal)? = nil, + buyGift: ((String, EnginePeer.Id, Int64?) -> Signal)? = nil, updateResellStars: ((Int64?) -> Signal)? = nil, togglePinnedToTop: ((Bool) -> Bool)? = nil, shareStory: ((StarGift.UniqueGift) -> Void)? = nil diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 41264e9ff6..07f27337fb 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -2851,6 +2851,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro private var hiddenMediaDisposable: Disposable? private let hiddenAvatarRepresentationDisposable = MetaDisposable() + private var autoTranslateDisposable: Disposable? + private var resolvePeerByNameDisposable: MetaDisposable? private let navigationActionDisposable = MetaDisposable() private let enqueueMediaMessageDisposable = MetaDisposable() @@ -5113,6 +5115,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.joinChannelDisposable.dispose() self.boostStatusDisposable?.dispose() self.personalChannelsDisposable?.dispose() + self.autoTranslateDisposable?.dispose() } override func didLoad() { @@ -9183,7 +9186,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } private func displayAutoTranslateLocked() { - let _ = combineLatest( + guard self.autoTranslateDisposable == nil else { + return + } + self.autoTranslateDisposable = combineLatest( queue: Queue.mainQueue(), context.engine.peers.getChannelBoostStatus(peerId: self.peerId), context.engine.peers.getMyBoostStatus() @@ -9197,6 +9203,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } }) controller.push(boostController) + + self.autoTranslateDisposable?.dispose() + self.autoTranslateDisposable = nil }) } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index 51dd286db5..8fe02c1c2b 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -604,11 +604,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } return self.profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) }, - buyGift: { [weak self] slug, peerId in + buyGift: { [weak self] slug, peerId, price in guard let self else { return .never() } - return self.profileGifts.buyStarGift(slug: slug, peerId: peerId) + return self.profileGifts.buyStarGift(slug: slug, peerId: peerId, price: price) }, updateResellStars: { [weak self] price in guard let self, let reference = product.reference else { diff --git a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift index 52368d0e33..f4caaa6672 100644 --- a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift @@ -174,6 +174,8 @@ final class ChatbotSetupScreenComponent: Component { private var permissions: [Permission] = [] private var botRights: TelegramBusinessBotRights = [] + private var temporaryEnabledPermissions = Set() + override init(frame: CGRect) { self.scrollView = ScrollView() self.scrollView.showsVerticalScrollIndicator = true @@ -505,6 +507,44 @@ final class ChatbotSetupScreenComponent: Component { } } + private func presentStarGiftsWarningIfNeeded(_ key: TelegramBusinessBotRights, completion: @escaping (Bool) -> Void) -> Bool { + guard let component = self.component, let environment = self.environment, let botResolutionState = self.botResolutionState, case let .found(peer, _) = botResolutionState.state, let controller = environment.controller() else { + return false + } + + if !key.contains(.transferAndUpgradeGifts) && !key.contains(.transferStars) && !key.contains(.editUsername) { + completion(true) + return false + } else { + let botUsername = "@\(peer.addressName ?? "")" + let text: String + if key.contains(.editUsername) { + text = environment.strings.ChatbotSetup_Gift_Warning_UsernameText(botUsername).string + } else if key == .transferAndUpgradeGifts { + text = environment.strings.ChatbotSetup_Gift_Warning_GiftsText(botUsername).string + } else if key == .transferStars { + text = environment.strings.ChatbotSetup_Gift_Warning_StarsText(botUsername).string + } else { + text = environment.strings.ChatbotSetup_Gift_Warning_CombinedText(botUsername).string + } + let alertController = textAlertController(context: component.context, title: environment.strings.ChatbotSetup_Gift_Warning_Title, text: text, actions: [ + TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: { + completion(false) + }), + TextAlertAction(type: .defaultAction, title: environment.strings.ChatbotSetup_Gift_Warning_Proceed, action: { + completion(true) + }) + ], parseMarkdown: true) + alertController.dismissed = { byOutsideTap in + if byOutsideTap { + completion(false) + } + } + controller.present(alertController, in: .window(.root)) + return true + } + } + func update(component: ChatbotSetupScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: ComponentTransition) -> CGSize { self.isUpdating = true defer { @@ -741,7 +781,7 @@ final class ChatbotSetupScreenComponent: Component { if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.isBusiness) { botResolutionState.state = .found(peer: peer, isInstalled: true) self.botResolutionState = botResolutionState - self.botRights = .All + self.botRights = [.reply, .readMessages, .deleteSentMessages, .deleteReceivedMessages] self.state?.updated(transition: .spring(duration: 0.3)) } else { self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.ChatbotSetup_ErrorBotNotBusinessCapable, actions: [ @@ -1074,6 +1114,10 @@ final class ChatbotSetupScreenComponent: Component { selectedCount += 1 } } + if self.temporaryEnabledPermissions.contains(permission.id) { + value = true + } + titleItems.append( AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( @@ -1101,11 +1145,33 @@ final class ChatbotSetupScreenComponent: Component { return } if let subpermissions = permission.subpermissions { - for subpermission in subpermissions { - if subpermission.enabled { - if let key = subpermission.key { + if value { + var combinedKey: TelegramBusinessBotRights = [] + for subpermission in subpermissions { + if subpermission.enabled, let key = subpermission.key { + combinedKey.insert(key) + } + } + self.temporaryEnabledPermissions.insert(permission.id) + + let presentedWarning = self.presentStarGiftsWarningIfNeeded(combinedKey, completion: { [weak self] value in + guard let self else { + return + } + if value { + self.botRights.insert(combinedKey) + } + self.temporaryEnabledPermissions.remove(permission.id) + self.state?.updated(transition: .spring(duration: 0.4)) + }) + + if !presentedWarning { + self.state?.updated(transition: .spring(duration: 0.4)) + } + } else { + for subpermission in subpermissions { + if subpermission.enabled, let key = subpermission.key { if value { - self.botRights.insert(key) } else { self.botRights.remove(key) } @@ -1170,7 +1236,15 @@ final class ChatbotSetupScreenComponent: Component { } if let key = subpermission.key { if !value { - self.botRights.insert(key) + let _ = self.presentStarGiftsWarningIfNeeded(key, completion: { [weak self] value in + guard let self else { + return + } + if value { + self.botRights.insert(key) + } + self.state?.updated(transition: .spring(duration: 0.4)) + }) } else { self.botRights.remove(key) } diff --git a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift index ae413aabd2..add15899cf 100644 --- a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift @@ -178,7 +178,18 @@ final class ChatTranslationPanelNode: ASDisplayNode { } @objc private func closePressed() { - let _ = ApplicationSpecificNotice.incrementTranslationSuggestion(accountManager: self.context.sharedContext.accountManager, count: -100, timestamp: Int32(Date().timeIntervalSince1970) + 60 * 60 * 24 * 7).startStandalone() + let isPremium = self.chatInterfaceState?.isPremium ?? false + + var translationAvailable = isPremium + if let channel = self.chatInterfaceState?.renderedPeer?.chatMainPeer as? TelegramChannel, channel.flags.contains(.autoTranslateEnabled) { + translationAvailable = true + } + + if translationAvailable { + self.interfaceInteraction?.hideTranslationPanel() + } else if !isPremium { + let _ = ApplicationSpecificNotice.incrementTranslationSuggestion(accountManager: self.context.sharedContext.accountManager, count: -100, timestamp: Int32(Date().timeIntervalSince1970) + 60 * 60 * 24 * 7).startStandalone() + } } @objc private func buttonPressed() {