diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f55b0b7fea..becb070a68 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -12668,3 +12668,5 @@ Sorry for the inconvenience."; "WebApp.PrivacyPolicy" = "Privacy Policy"; "Conversation.OpenProfile" = "OPEN PROFILE"; + +"Stars.Intro.GiftStars" = "Gift Stars to Friends"; diff --git a/submodules/AccountContext/Sources/Premium.swift b/submodules/AccountContext/Sources/Premium.swift index 821887ec3f..52ee4ce8d4 100644 --- a/submodules/AccountContext/Sources/Premium.swift +++ b/submodules/AccountContext/Sources/Premium.swift @@ -139,6 +139,7 @@ public struct PremiumConfiguration { showPremiumGiftInAttachMenu: false, showPremiumGiftInTextField: false, giveawayGiftsPurchaseAvailable: false, + starsGiftsPurchaseAvailable: false, boostsPerGiftCount: 3, audioTransciptionTrialMaxDuration: 300, audioTransciptionTrialCount: 2, @@ -165,6 +166,7 @@ public struct PremiumConfiguration { public let showPremiumGiftInAttachMenu: Bool public let showPremiumGiftInTextField: Bool public let giveawayGiftsPurchaseAvailable: Bool + public let starsGiftsPurchaseAvailable: Bool public let boostsPerGiftCount: Int32 public let audioTransciptionTrialMaxDuration: Int32 public let audioTransciptionTrialCount: Int32 @@ -190,6 +192,7 @@ public struct PremiumConfiguration { showPremiumGiftInAttachMenu: Bool, showPremiumGiftInTextField: Bool, giveawayGiftsPurchaseAvailable: Bool, + starsGiftsPurchaseAvailable: Bool, boostsPerGiftCount: Int32, audioTransciptionTrialMaxDuration: Int32, audioTransciptionTrialCount: Int32, @@ -214,6 +217,7 @@ public struct PremiumConfiguration { self.showPremiumGiftInAttachMenu = showPremiumGiftInAttachMenu self.showPremiumGiftInTextField = showPremiumGiftInTextField self.giveawayGiftsPurchaseAvailable = giveawayGiftsPurchaseAvailable + self.starsGiftsPurchaseAvailable = starsGiftsPurchaseAvailable self.boostsPerGiftCount = boostsPerGiftCount self.audioTransciptionTrialMaxDuration = audioTransciptionTrialMaxDuration self.audioTransciptionTrialCount = audioTransciptionTrialCount @@ -246,6 +250,7 @@ public struct PremiumConfiguration { showPremiumGiftInAttachMenu: data["premium_gift_attach_menu_icon"] as? Bool ?? defaultValue.showPremiumGiftInAttachMenu, showPremiumGiftInTextField: data["premium_gift_text_field_icon"] as? Bool ?? defaultValue.showPremiumGiftInTextField, giveawayGiftsPurchaseAvailable: data["giveaway_gifts_purchase_available"] as? Bool ?? defaultValue.giveawayGiftsPurchaseAvailable, + starsGiftsPurchaseAvailable: data["stars_gifts_enabled"] as? Bool ?? defaultValue.starsGiftsPurchaseAvailable, boostsPerGiftCount: get(data["boosts_per_sent_gift"]) ?? defaultValue.boostsPerGiftCount, audioTransciptionTrialMaxDuration: get(data["transcribe_audio_trial_duration_max"]) ?? defaultValue.audioTransciptionTrialMaxDuration, audioTransciptionTrialCount: get(data["transcribe_audio_trial_weekly_number"]) ?? defaultValue.audioTransciptionTrialCount, diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 74c34c1c0b..4c6c5e094d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -2076,32 +2076,60 @@ public extension TelegramEngine.EngineData.Item { } } -public struct BotMenu: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { -public typealias Result = Optional - -fileprivate var id: EnginePeer.Id -public var mapKey: EnginePeer.Id { -return self.id -} - -public init(id: EnginePeer.Id) { -self.id = id -} - -var key: PostboxViewKey { -return .cachedPeerData(peerId: self.id) -} - -func extract(view: PostboxView) -> Result { -guard let view = view as? CachedPeerDataView else { -preconditionFailure() -} -if let cachedData = view.cachedPeerData as? CachedUserData { -return cachedData.botInfo?.menuButton -} else { -return nil -} -} -} + public struct BotMenu: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = Optional + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + var key: PostboxViewKey { + return .cachedPeerData(peerId: self.id) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedPeerDataView else { + preconditionFailure() + } + if let cachedData = view.cachedPeerData as? CachedUserData { + return cachedData.botInfo?.menuButton + } else { + return nil + } + } + } + + public struct BotCommands: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = Optional<[BotCommand]> + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + var key: PostboxViewKey { + return .cachedPeerData(peerId: self.id) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedPeerDataView else { + preconditionFailure() + } + if let cachedData = view.cachedPeerData as? CachedUserData { + return cachedData.botInfo?.commands + } else { + return nil + } + } + } } } diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift index 04df414332..e6329ee119 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift @@ -538,7 +538,7 @@ final class StarsTransactionsScreenComponent: Component { component.buy() }, buyAds: nil, - additionalAction: AnyComponent( + additionalAction: premiumConfiguration.starsGiftsPurchaseAvailable ? AnyComponent( Button( content: AnyComponent( HStack([ @@ -548,7 +548,7 @@ final class StarsTransactionsScreenComponent: Component { ), AnyComponentWithIdentity( id: "label", - component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Gift Stars to Friends", font: Font.regular(17.0), textColor: environment.theme.list.itemAccentColor)))) + component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_GiftStars, font: Font.regular(17.0), textColor: environment.theme.list.itemAccentColor)))) ) ], spacing: 6.0) @@ -557,7 +557,7 @@ final class StarsTransactionsScreenComponent: Component { component.gift() } ) - ) + ) : nil ) ))] )), diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/Contents.json new file mode 100644 index 0000000000..638a59cc88 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "privacy.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/privacy.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/privacy.pdf new file mode 100644 index 0000000000..e6d3dcbb39 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Privacy.imageset/privacy.pdf differ diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index f6ecc633db..9b32c4a186 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1987,7 +1987,12 @@ public final class WebAppController: ViewController, AttachmentContainable { @objc private func morePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) { let context = self.context - let presentationData = self.presentationData + var presentationData = self.presentationData + if !presentationData.theme.overallDarkAppearance, let headerColor = self.controllerNode.headerColor { + if headerColor.lightness < 0.5 { + presentationData = presentationData.withUpdated(theme: defaultDarkPresentationTheme) + } + } let peerId = self.peerId let botId = self.botId @@ -1998,10 +2003,11 @@ public final class WebAppController: ViewController, AttachmentContainable { let items = combineLatest(queue: Queue.mainQueue(), context.engine.messages.attachMenuBots(), - context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.botId)) + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.botId)), + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.BotCommands(id: self.botId)) ) |> take(1) - |> map { [weak self] attachMenuBots, botPeer -> ContextController.Items in + |> map { [weak self] attachMenuBots, botPeer, botCommands -> ContextController.Items in var items: [ContextMenuItem] = [] let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) }) @@ -2068,15 +2074,7 @@ public final class WebAppController: ViewController, AttachmentContainable { self?.controllerNode.webView?.reload() }))) - -// items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_PrivacyPolicy, icon: { theme in -// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reload"), color: theme.contextMenu.primaryColor) -// }, action: { [weak self] c, _ in -// c?.dismiss(completion: nil) -// -// self?.controllerNode.webView?.reload() -// }))) - + items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_TermsOfUse, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in @@ -2096,6 +2094,28 @@ public final class WebAppController: ViewController, AttachmentContainable { }) }))) + if let botCommands { + for command in botCommands { + if command.text == "privacy" { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_PrivacyPolicy, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Privacy"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] c, _ in + c?.dismiss(completion: nil) + + guard let self else { + return + } + let _ = enqueueMessages(account: self.context.account, peerId: self.botId, messages: [.message(text: "/privacy", attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).startStandalone() + + if let botPeer, let navigationController = self.getNavigationController() { + (self.parentController() as? AttachmentController)?.minimizeIfNeeded() + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(botPeer))) + } + }))) + } + } + } + if let _ = attachMenuBot, [.attachMenu, .settings, .generic].contains(source) { items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_RemoveBot, textColor: .destructive, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) @@ -2117,7 +2137,7 @@ public final class WebAppController: ViewController, AttachmentContainable { return ContextController.Items(content: .list(items)) } - let contextController = ContextController(presentationData: self.presentationData, source: .reference(WebAppContextReferenceContentSource(controller: self, sourceNode: node)), items: items, gesture: gesture) + let contextController = ContextController(presentationData: presentationData, source: .reference(WebAppContextReferenceContentSource(controller: self, sourceNode: node)), items: items, gesture: gesture) self.presentInGlobalOverlay(contextController) }