diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index eb54cd350d..31acafe4dd 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -1011,14 +1011,15 @@ final class GiftOptionsScreenComponent: Component { } } -public final class GiftOptionsScreen: ViewControllerComponentContainer, GiftOptionsScreenProtocol { +open class GiftOptionsScreen: ViewControllerComponentContainer, GiftOptionsScreenProtocol { private let context: AccountContext public init( context: AccountContext, starsContext: StarsContext, peerId: EnginePeer.Id, - premiumOptions: [CachedPremiumGiftOption] + premiumOptions: [CachedPremiumGiftOption], + completion: @escaping () -> Void = {} ) { self.context = context diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift index 805b8aaf6c..e1f56350a5 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift @@ -341,7 +341,7 @@ final class GiftSetupScreenComponent: Component { autocapitalizationType: .none, autocorrectionType: .no, returnKeyType: .done, - characterLimit: 70, + characterLimit: 255, displayCharacterLimit: true, emptyLineHandling: .notAllowed, updated: { _ in diff --git a/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/BUILD b/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/BUILD index 154b99fe70..69caa55031 100644 --- a/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/BUILD +++ b/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/BUILD @@ -17,7 +17,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit", "//submodules/AccountContext", "//submodules/AttachmentUI", - "//submodules/PremiumUI", + "//submodules/TelegramUI/Components/Gifts/GiftOptionsScreen", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/Sources/PremiumGiftAttachmentScreen.swift b/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/Sources/PremiumGiftAttachmentScreen.swift index 520c5d79da..bada8afbba 100644 --- a/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/Sources/PremiumGiftAttachmentScreen.swift +++ b/submodules/TelegramUI/Components/PremiumGiftAttachmentScreen/Sources/PremiumGiftAttachmentScreen.swift @@ -5,15 +5,17 @@ import AsyncDisplayKit import ComponentFlow import SwiftSignalKit import AccountContext -import PremiumUI import AttachmentUI +import GiftOptionsScreen -public class PremiumGiftAttachmentScreen: PremiumGiftScreen, AttachmentContainable { +public class PremiumGiftAttachmentScreen: GiftOptionsScreen, AttachmentContainable { public var requestAttachmentMenuExpansion: () -> Void = {} public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in } public var parentController: () -> ViewController? = { return nil } + public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in } + public var updateTabBarVisibility: (Bool, ContainedViewLayoutTransition) -> Void = { _, _ in } public var cancelPanGesture: () -> Void = { } public var isContainerPanning: () -> Bool = { return false } public var isContainerExpanded: () -> Bool = { return false } @@ -25,17 +27,16 @@ public class PremiumGiftAttachmentScreen: PremiumGiftScreen, AttachmentContainab } private final class PremiumGiftContext: AttachmentMediaPickerContext { - private weak var controller: PremiumGiftScreen? + private weak var controller: GiftOptionsScreen? public var mainButtonState: Signal { - return self.controller?.mainButtonStatePromise.get() ?? .single(nil) + return .single(nil) } - init(controller: PremiumGiftScreen) { + init(controller: GiftOptionsScreen) { self.controller = controller } func mainButtonAction() { - self.controller?.mainButtonPressed() } } diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift index e3ba2c90f7..37d82d35fd 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift @@ -588,19 +588,17 @@ extension ChatControllerImpl { strongSelf.controllerNavigationDisposable.set(nil) } case .gift: - if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer { + if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let starsContext = context.starsContext { let premiumGiftOptions = strongSelf.presentationInterfaceState.premiumGiftOptions if !premiumGiftOptions.isEmpty { - let controller = PremiumGiftAttachmentScreen(context: context, peerIds: [peer.id], options: premiumGiftOptions, source: .attachMenu, pushController: { [weak self] c in - if let strongSelf = self { - strongSelf.push(c) - } - }, completion: { [weak self] in - if let strongSelf = self { - strongSelf.hintPlayNextOutgoingGift() - strongSelf.attachmentController?.dismiss(animated: true) + let controller = PremiumGiftAttachmentScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumGiftOptions, completion: { [weak self] in + guard let self else { + return } + self.hintPlayNextOutgoingGift() + self.attachmentController?.dismiss(animated: true) }) + completion(controller, controller.mediaPickerContext) strongSelf.controllerNavigationDisposable.set(nil) diff --git a/submodules/TelegramUI/Sources/ContactSelectionController.swift b/submodules/TelegramUI/Sources/ContactSelectionController.swift index cabf9baa3e..fdd0d2397d 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionController.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionController.swift @@ -14,6 +14,7 @@ import AttachmentUI import SearchBarNode import ChatSendAudioMessageContextPreview import ChatSendMessageActionUI +import ContextUI class ContactSelectionControllerImpl: ViewController, ContactSelectionController, PresentableController, AttachmentContainable { private let context: AccountContext @@ -42,6 +43,9 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController private let multipleSelection: Bool private let requirePhoneNumbers: Bool + private let openProfile: ((EnginePeer) -> Void)? + private let sendMessage: ((EnginePeer) -> Void)? + private var _ready = Promise() override var ready: Promise { return self._ready @@ -105,6 +109,9 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController self.multipleSelection = params.multipleSelection self.requirePhoneNumbers = params.requirePhoneNumbers + self.openProfile = params.openProfile + self.sendMessage = params.sendMessage + self.presentationData = params.updatedPresentationData?.initial ?? params.context.sharedContext.currentPresentationData.with { $0 } super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) @@ -219,15 +226,15 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController } self.contactsNode.requestOpenPeerFromSearch = { [weak self] peer in - self?.openPeer(peer: peer, action: .generic) + self?.openPeer(peer: peer, action: .generic, node: nil, gesture: nil) } self.contactsNode.contactListNode.activateSearch = { [weak self] in self?.activateSearch() } - self.contactsNode.contactListNode.openPeer = { [weak self] peer, action, _, _ in - self?.openPeer(peer: peer, action: action) + self.contactsNode.contactListNode.openPeer = { [weak self] peer, action, node, gesture in + self?.openPeer(peer: peer, action: action, node: node, gesture: gesture) } self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in @@ -357,7 +364,40 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController } } - private func openPeer(peer: ContactListPeer, action: ContactListAction) { + private func openPeer(peer: ContactListPeer, action: ContactListAction, node: ASDisplayNode?, gesture: ContextGesture?) { + if case .more = action { + guard case let .peer(peer, _, _) = peer, let node = node as? ContextReferenceContentNode else { + return + } + + let presentationData = self.presentationData + + var items: [ContextMenuItem] = [] + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Premium_Gift_ContactSelection_SendMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MessageBubble"), color: theme.contextMenu.primaryColor) + }, iconPosition: .left, action: { [weak self] _, a in + a(.default) + + if let self { + self.sendMessage?(EnginePeer(peer)) + } + }))) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Premium_Gift_ContactSelection_OpenProfile, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/User"), color: theme.contextMenu.primaryColor) + }, iconPosition: .left, action: { [weak self] _, a in + a(.default) + + if let self { + self.openProfile?(EnginePeer(peer)) + } + }))) + + let contextController = ContextController(presentationData: presentationData, source: .reference(ContactContextReferenceContentSource(controller: self, sourceNode: node)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + self.present(contextController, in: .window(.root)) + return + } + self.contactsNode.contactListNode.listNode.clearHighlightAnimated(true) self.confirmationDisposable.set((self.confirmation(peer) |> deliverOnMainQueue).startStrict(next: { [weak self] value in if let strongSelf = self { @@ -477,3 +517,17 @@ final class ContactsPickerContext: AttachmentMediaPickerContext { func mainButtonAction() { } } + +private final class ContactContextReferenceContentSource: ContextReferenceContentSource { + private let controller: ViewController + private let sourceNode: ContextReferenceContentNode + + init(controller: ViewController, sourceNode: ContextReferenceContentNode) { + self.controller = controller + self.sourceNode = sourceNode + } + + func transitionInfo() -> ContextControllerReferenceViewInfo? { + return ContextControllerReferenceViewInfo(referenceView: self.sourceNode.view, contentAreaInScreenSpace: UIScreen.main.bounds) + } +} diff --git a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift index 685113732e..ba488f43c1 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift @@ -41,6 +41,7 @@ final class ContactSelectionControllerNode: ASDisplayNode { var requestMultipleAction: ((_ silent: Bool, _ scheduleTime: Int32?, _ parameters: ChatSendMessageActionSheetController.SendParameters?) -> Void)? var dismiss: (() -> Void)? var cancelSearch: (() -> Void)? + var openPeerMore: ((ContactListPeer, ASDisplayNode?, ContextGesture?) -> Void)? var presentationData: PresentationData { didSet { diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 2baa737ced..bbdf81e5d1 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2277,17 +2277,17 @@ public final class SharedAccountContextImpl: SharedAccountContext { let presentationData = context.sharedContext.currentPresentationData.with { $0 } var presentBirthdayPickerImpl: (() -> Void)? - var starsMode: ContactSelectionControllerMode = .generic + var mode: ContactSelectionControllerMode = .generic var currentBirthdays: [EnginePeer.Id: TelegramBirthday]? if case let .chatList(birthdays) = source, let birthdays, !birthdays.isEmpty { - starsMode = .starsGifting(birthdays: birthdays, hasActions: true) + mode = .starsGifting(birthdays: birthdays, hasActions: true) currentBirthdays = birthdays } else if case let .settings(birthdays) = source, let birthdays, !birthdays.isEmpty { - starsMode = .starsGifting(birthdays: birthdays, hasActions: true) + mode = .starsGifting(birthdays: birthdays, hasActions: true) currentBirthdays = birthdays } else { - starsMode = .starsGifting(birthdays: nil, hasActions: true) + mode = .starsGifting(birthdays: nil, hasActions: true) } let contactOptions: Signal<[ContactListAdditionalOption], NoError> @@ -2320,7 +2320,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil)) let controller = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams( context: context, - mode: starsMode, + mode: mode, autoDismiss: false, title: { strings in return "Gift Premium or Stars" }, options: contactOptions, @@ -2331,7 +2331,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { sendMessageImpl?(peer) } )) - let _ = combineLatest(queue: Queue.mainQueue(), contactsController.result, options.get()) + let _ = combineLatest(queue: Queue.mainQueue(), controller.result, options.get()) .startStandalone(next: { [weak controller] result, options in if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext { let premiumOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) } @@ -2339,8 +2339,6 @@ public final class SharedAccountContextImpl: SharedAccountContext { giftController.navigationPresentation = .modal controller?.push(giftController) -// completion?([peer.id]) - if case .chatList = source, let _ = currentBirthdays { let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone() }