diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 3cc0905202..745f6064bd 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -11289,3 +11289,5 @@ Sorry for the inconvenience."; "GroupBoost.BoostToUnrestrict.Times_any" = "**%@** times"; "GroupBoost.BoostToUnrestrict" = "Boost the group %1$@ to remove messaging restrictions. Your boosts will help **%2$@** to unlock new features."; + +"Story.InputPlaceholderReplyInGroup" = "Comment Story..."; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 76d13f8575..f7d0186a4f 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -959,7 +959,7 @@ public protocol SharedAccountContext: AnyObject { func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, action: @escaping () -> Void) -> ViewController func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController - func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource) -> ViewController + func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (() -> Void)?) -> ViewController func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 40c8dda432..3eafa32fae 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1683,7 +1683,7 @@ public final class ChatListNode: ListView { guard let self else { return } - let controller = self.context.sharedContext.makePremiumGiftController(context: self.context, source: .chatList) + let controller = self.context.sharedContext.makePremiumGiftController(context: self.context, source: .chatList, completion: nil) self.push?(controller) }, openActiveSessions: { [weak self] in guard let self else { diff --git a/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift index bef4d74052..e721f4eb2f 100644 --- a/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift @@ -2209,6 +2209,13 @@ public class PremiumBoostLevelsScreen: ViewController { let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot]) |> deliverOnMainQueue).startStandalone(completed: { [weak self] in self?.updatedState.set(context.engine.peers.getChannelBoostStatus(peerId: peerId) + |> beforeNext { [weak self] status in + if let self, let status { + Queue.mainQueue().async { + self.controller?.boostStatusUpdated(status) + } + } + } |> map { status in if let status { return InternalBoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: Int32(status.boosts + 1)) @@ -2353,7 +2360,7 @@ public class PremiumBoostLevelsScreen: ViewController { controller?.dismiss(animated: true, completion: nil) Queue.mainQueue().after(0.4) { - let giftController = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost) + let giftController = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost, completion: nil) navigationController.pushViewController(giftController, animated: true) } } @@ -2424,6 +2431,7 @@ public class PremiumBoostLevelsScreen: ViewController { private var currentLayout: ContainerViewLayout? + public var boostStatusUpdated: (ChannelBoostStatus) -> Void = { _ in } public var disposed: () -> Void = {} public init( @@ -2493,7 +2501,7 @@ public class PremiumBoostLevelsScreen: ViewController { override open func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - + self.node.updateIsVisible(isVisible: false) } diff --git a/submodules/PremiumUI/Sources/PremiumBoostScreen.swift b/submodules/PremiumUI/Sources/PremiumBoostScreen.swift index 8cffe20868..00a0a4caa5 100644 --- a/submodules/PremiumUI/Sources/PremiumBoostScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumBoostScreen.swift @@ -239,7 +239,7 @@ public func PremiumBoostScreen( dismissImpl?() Queue.mainQueue().after(0.4) { - let controller = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost) + let controller = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost, completion: nil) pushController(controller) } }), diff --git a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift index 453fdbc7ed..973e4d3fb4 100644 --- a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift +++ b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift @@ -880,7 +880,7 @@ public class ReplaceBoostScreen: ViewController { } let navigationController = self.navigationController self.dismiss(animated: true, completion: { - let giftController = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost) + let giftController = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost, completion: nil) navigationController?.pushViewController(giftController, animated: true) }) } diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index 62637353f2..50350b227f 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -1046,7 +1046,7 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p return entries } -public func channelStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, section: ChannelStatsSection = .stats, boostStatus: ChannelBoostStatus? = nil) -> ViewController { +public func channelStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, section: ChannelStatsSection = .stats, boostStatus: ChannelBoostStatus? = nil, boostStatusUpdated: ((ChannelBoostStatus) -> Void)? = nil) -> ViewController { let statePromise = ValuePromise(ChannelStatsControllerState(section: section, boostersExpanded: false, moreBoostersDisplayed: 0, giftsSelected: false), ignoreRepeated: true) let stateValue = Atomic(value: ChannelStatsControllerState(section: section, boostersExpanded: false, moreBoostersDisplayed: 0, giftsSelected: false)) let updateState: ((ChannelStatsControllerState) -> ChannelStatsControllerState) -> Void = { f in @@ -1087,12 +1087,16 @@ public func channelStatsController(context: AccountContext, updatedPresentationD }) dataPromise.set(.single(nil) |> then(dataSignal)) - let boostData: Signal - if let boostStatus { - boostData = .single(boostStatus) - } else { - boostData = .single(nil) |> then(context.engine.peers.getChannelBoostStatus(peerId: peerId)) - } + let boostDataPromise = Promise() + boostDataPromise.set(.single(boostStatus) |> then(context.engine.peers.getChannelBoostStatus(peerId: peerId))) + + actionsDisposable.add((boostDataPromise.get() + |> deliverOnMainQueue).start(next: { boostStatus in + if let boostStatus, let boostStatusUpdated { + boostStatusUpdated(boostStatus) + } + })) + let boostsContext = ChannelBoostersContext(account: context.account, peerId: peerId, gift: false) let giftsContext = ChannelBoostersContext(account: context.account, peerId: peerId, gift: true) @@ -1253,7 +1257,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD dataPromise.get(), messagesPromise.get(), storiesPromise.get(), - boostData, + boostDataPromise.get(), boostsContext.state, giftsContext.state, longLoadingSignal @@ -1508,6 +1512,8 @@ public func channelStatsController(context: AccountContext, updatedPresentationD guard let boostStatus, let myBoostStatus else { return } + boostDataPromise.set(.single(boostStatus)) + let boostController = PremiumBoostLevelsScreen( context: context, peerId: peerId, @@ -1515,6 +1521,9 @@ public func channelStatsController(context: AccountContext, updatedPresentationD status: boostStatus, myBoostStatus: myBoostStatus ) + boostController.boostStatusUpdated = { boostStatus in + boostDataPromise.set(.single(boostStatus)) + } controller?.push(boostController) }) } diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift index a907c8376c..1b55c9e79c 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift @@ -390,7 +390,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { } return true } - + public var useExternalSearchContainer: Bool = false private var gifContext: GifContext? { @@ -2133,6 +2133,12 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { strongSelf.interaction?.presentGlobalOverlayController(contextController, nil) }) } + + public func scrollToGroupEmoji() { + if let pagerView = self.entityKeyboardView.componentView as? EntityKeyboardComponent.View { + pagerView.scrollToItemGroup(contentId: "emoji", groupId: "peerSpecific", subgroupId: nil) + } + } } private final class ContextControllerContentSourceImpl: ContextControllerContentSource { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 311b8a32b9..37578d14a1 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -6957,7 +6957,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } if channel.flags.contains(.isCreator) || (channel.adminRights?.rights.contains(.canInviteUsers) == true) { - let boostsController = channelStatsController(context: self.context, updatedPresentationData: controller.updatedPresentationData, peerId: self.peerId, section: .boosts, boostStatus: self.boostStatus) + let boostsController = channelStatsController(context: self.context, updatedPresentationData: controller.updatedPresentationData, peerId: self.peerId, section: .boosts, boostStatus: self.boostStatus, boostStatusUpdated: { [weak self] boostStatus in + if let self { + self.boostStatus = boostStatus + } + }) controller.push(boostsController) } else { let _ = combineLatest( @@ -8814,7 +8818,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro let controller = self.context.sharedContext.makePremiumIntroController(context: self.context, source: .settings, forceDark: false, dismissed: nil) self.controller?.push(controller) case .premiumGift: - let controller = self.context.sharedContext.makePremiumGiftController(context: self.context, source: .settings) + let controller = self.context.sharedContext.makePremiumGiftController(context: self.context, source: .settings, completion: nil) self.controller?.push(controller) case .stickers: if let settings = self.data?.globalSettings { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 5519a74203..2925b233eb 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -450,6 +450,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var mediaRestrictedTooltipControllerMode = true weak var checksTooltipController: TooltipController? weak var copyProtectionTooltipController: TooltipController? + weak var emojiPackTooltipController: TooltipScreen? var currentMessageTooltipScreens: [(TooltipScreen, ListViewItemNode)] = [] @@ -15757,6 +15758,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } ) self.present(tooltipScreen, in: .current) + self.emojiPackTooltipController = tooltipScreen let _ = ApplicationSpecificNotice.incrementGroupEmojiPackSuggestion(accountManager: self.context.sharedContext.accountManager, peerId: peerId).startStandalone() }) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index c4bcdfce2a..e81b8dfbc0 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -3705,6 +3705,17 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { strongSelf.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) }) + + if let emojiPackTooltipController = strongSelf.controller?.emojiPackTooltipController { + strongSelf.controller?.emojiPackTooltipController = nil + emojiPackTooltipController.dismiss() + + Queue.mainQueue().after(0.1) { + if let inputNode = strongSelf.inputNode as? ChatEntityKeyboardInputNode { + inputNode.scrollToGroupEmoji() + } + } + } }) } } diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 8cb1dbeab5..2a5d09ecf7 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -587,7 +587,7 @@ func openResolvedUrlImpl( } case let .premiumMultiGift(reference): dismissInput() - let controller = context.sharedContext.makePremiumGiftController(context: context, source: .deeplink(reference)) + let controller = context.sharedContext.makePremiumGiftController(context: context, source: .deeplink(reference), completion: nil) if let navigationController = navigationController { navigationController.pushViewController(controller, animated: true) } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 38cf692079..7cc369c123 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2049,7 +2049,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, forceDark: forceDark, cancel: cancel, action: action) } - public func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource) -> ViewController { + public func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (() -> Void)?) -> ViewController { let options = Promise<[PremiumGiftCodeOption]>() options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil)) @@ -2101,6 +2101,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { pushImpl?(c) }, completion: { filterImpl?() + completion?() }) pushImpl = { [weak giftController] c in giftController?.push(c) @@ -2108,7 +2109,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { filterImpl = { [weak giftController] in if let navigationController = giftController?.navigationController as? NavigationController { var controllers = navigationController.viewControllers - controllers = controllers.filter { !($0 is ContactMultiselectionController) } + controllers = controllers.filter { !($0 is ContactMultiselectionController) && !($0 is PremiumGiftScreen) } navigationController.setViewControllers(controllers, animated: true) } }