diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGCameraController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGCameraController.h index d680c7525c..d1e0b2fcc0 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGCameraController.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGCameraController.h @@ -45,6 +45,8 @@ typedef enum { @property (nonatomic, strong) id stickersContext; @property (nonatomic, assign) bool shortcut; +@property (nonatomic, assign) int64_t sendPaidMessageStars; + @property (nonatomic, strong) NSAttributedString *forcedCaption; @property (nonatomic, strong) NSString *recipientName; diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index 468e45bd69..c751629564 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -1446,6 +1446,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus if (editingContext == nil) { editingContext = [[TGMediaEditingContext alloc] init]; + editingContext.sendPaidMessageStars = self.sendPaidMessageStars; if (self.forcedCaption != nil) [editingContext setForcedCaption:self.forcedCaption]; _editingContext = editingContext; diff --git a/submodules/LegacyComponents/Sources/TGPhotoToolbarView.m b/submodules/LegacyComponents/Sources/TGPhotoToolbarView.m index d982cf6297..2069a92037 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoToolbarView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoToolbarView.m @@ -673,57 +673,71 @@ CGFloat offset = 8.0f; if (self.frame.size.width > self.frame.size.height) { - if (buttons.count == 1) - { - UIView *button = buttons.firstObject; - button.frame = CGRectMake(CGFloor(self.frame.size.width / 2 - button.frame.size.width / 2), offset, button.frame.size.width, button.frame.size.height); + _cancelButton.frame = CGRectMake(0, 0, 49, 49); + + CGFloat leftEdge = _cancelButton.frame.size.width; + CGFloat rightEdge = 0.0f; + + if (_starsDoneButton != nil) { + CGSize buttonSize = [_starsDoneButton updateCount:_sendPaidMessageStars]; + rightEdge = buttonSize.width + 2.0f; + [_starsDoneButton updateFrame:CGRectMake(self.frame.size.width - rightEdge, 2.0f, buttonSize.width, buttonSize.height)]; + } else { + rightEdge = _cancelButton.frame.size.width; } - else if (buttons.count == 2) - { + + CGFloat availableWidth = self.frame.size.width - leftEdge - rightEdge; + CGFloat startX = leftEdge; + CGFloat sideOffset = 5.0f; + + if (buttons.count == 1) { + UIView *button = buttons.firstObject; + CGFloat buttonX = startX + (availableWidth - button.frame.size.width) / 2; + button.frame = CGRectMake(buttonX, offset, button.frame.size.width, button.frame.size.height); + } + else if (buttons.count == 2) { UIView *leftButton = buttons.firstObject; UIView *rightButton = buttons.lastObject; - leftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 5 * 2 - 5 - leftButton.frame.size.width / 2), offset, leftButton.frame.size.width, leftButton.frame.size.height); - rightButton.frame = CGRectMake(CGCeil(self.frame.size.width - leftButton.frame.origin.x - rightButton.frame.size.width), offset, rightButton.frame.size.width, rightButton.frame.size.height); + CGFloat leftButtonX = startX + availableWidth / 3 - leftButton.frame.size.width / 2 - sideOffset; + CGFloat rightButtonX = startX + 2 * availableWidth / 3 - rightButton.frame.size.width / 2 + sideOffset; + + leftButton.frame = CGRectMake(leftButtonX, offset, leftButton.frame.size.width, leftButton.frame.size.height); + rightButton.frame = CGRectMake(rightButtonX, offset, rightButton.frame.size.width, rightButton.frame.size.height); } - else if (buttons.count == 3) - { + else if (buttons.count == 3) { UIView *leftButton = buttons.firstObject; UIView *centerButton = [buttons objectAtIndex:1]; UIView *rightButton = buttons.lastObject; - centerButton.frame = CGRectMake(CGFloor(self.frame.size.width / 2 - centerButton.frame.size.width / 2), offset, centerButton.frame.size.width, centerButton.frame.size.height); - - leftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 6 * 2 - 10 - leftButton.frame.size.width / 2), offset, leftButton.frame.size.width, leftButton.frame.size.height); + CGFloat leftButtonX = startX + availableWidth / 4 - leftButton.frame.size.width / 2 - sideOffset; + CGFloat centerButtonX = startX + availableWidth / 2 - centerButton.frame.size.width / 2; + CGFloat rightButtonX = startX + 3 * availableWidth / 4 - rightButton.frame.size.width / 2 + sideOffset; - rightButton.frame = CGRectMake(CGCeil(self.frame.size.width - leftButton.frame.origin.x - rightButton.frame.size.width), offset, rightButton.frame.size.width, rightButton.frame.size.height); + leftButton.frame = CGRectMake(leftButtonX, offset, leftButton.frame.size.width, leftButton.frame.size.height); + centerButton.frame = CGRectMake(centerButtonX, offset, centerButton.frame.size.width, centerButton.frame.size.height); + rightButton.frame = CGRectMake(rightButtonX, offset, rightButton.frame.size.width, rightButton.frame.size.height); } - else if (buttons.count == 4) - { + else if (buttons.count == 4) { UIView *leftButton = buttons.firstObject; UIView *centerLeftButton = [buttons objectAtIndex:1]; UIView *centerRightButton = [buttons objectAtIndex:2]; UIView *rightButton = buttons.lastObject; - leftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 8 * 2 - 3 - leftButton.frame.size.width / 2), offset, leftButton.frame.size.width, leftButton.frame.size.height); + CGFloat leftButtonX = startX + availableWidth / 5 - leftButton.frame.size.width / 2 - sideOffset; + CGFloat centerLeftButtonX = startX + 2 * availableWidth / 5 - centerLeftButton.frame.size.width / 2 - TGScreenPixelFloor(sideOffset / 2.0); + CGFloat centerRightButtonX = startX + 3 * availableWidth / 5 - centerRightButton.frame.size.width / 2 + TGScreenPixelFloor(sideOffset / 2.0); + CGFloat rightButtonX = startX + 4 * availableWidth / 5 - rightButton.frame.size.width / 2 + sideOffset; - centerLeftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 10 * 4 + 5 - centerLeftButton.frame.size.width / 2), offset, centerLeftButton.frame.size.width, centerLeftButton.frame.size.height); - - centerRightButton.frame = CGRectMake(CGCeil(self.frame.size.width - centerLeftButton.frame.origin.x - centerRightButton.frame.size.width), offset, centerRightButton.frame.size.width, centerRightButton.frame.size.height); - - rightButton.frame = CGRectMake(CGCeil(self.frame.size.width - leftButton.frame.origin.x - rightButton.frame.size.width), offset, rightButton.frame.size.width, rightButton.frame.size.height); + leftButton.frame = CGRectMake(leftButtonX, offset, leftButton.frame.size.width, leftButton.frame.size.height); + centerLeftButton.frame = CGRectMake(centerLeftButtonX, offset, centerLeftButton.frame.size.width, centerLeftButton.frame.size.height); + centerRightButton.frame = CGRectMake(centerRightButtonX, offset, centerRightButton.frame.size.width, centerRightButton.frame.size.height); + rightButton.frame = CGRectMake(rightButtonX, offset, rightButton.frame.size.width, rightButton.frame.size.height); } - _cancelButton.frame = CGRectMake(0, 0, 49, 49); CGFloat offset = 49.0f; if (_doneButton.frame.size.width > 49.0f) offset = 60.0f; - - if (_starsDoneButton != nil) { - CGSize buttonSize = [_starsDoneButton updateCount:_sendPaidMessageStars]; - [_starsDoneButton updateFrame:CGRectMake(self.frame.size.width - buttonSize.width - 2.0, 49.0f - offset + 2.0f, buttonSize.width, buttonSize.height)]; - } - _doneButton.frame = CGRectMake(self.frame.size.width - offset, 49.0f - offset, _doneButton.frame.size.width, _doneButton.frame.size.height); _infoLabel.frame = CGRectMake(49.0f + 10.0f, 0.0f, self.frame.size.width - (49.0f + 10.0f) * 2.0f, 49.0f); diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 6e797cb7ce..be1a0091b5 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -674,8 +674,8 @@ public final class ShareController: ViewController { if case let .messages(messages) = self.subject { messageCount = messages.count - } else if case let .image(images) = self.subject { - messageCount = images.count + } else if case .image = self.subject { + messageCount = 1 } else if case let .fromExternal(count, _) = self.subject { messageCount = count } diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift index c64b332a9c..5a40912d80 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift @@ -2153,7 +2153,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { }))) } - if isSaved { + if isSaved && interfaceState.sendPaidMessageStars == nil { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) }, action: { [weak self] _, f in @@ -2764,6 +2764,13 @@ public final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { })) } } else { + let sendPaidMessageStars: Signal + if let chatPeerId = strongSelf.chatPeerId { + sendPaidMessageStars = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.SendPaidMessageStars(id: chatPeerId)) + } else { + sendPaidMessageStars = .single(nil) + } + return combineLatest( context.engine.stickers.isStickerSaved(id: file.fileId), context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: accountPeerId)) |> map { peer -> Bool in @@ -2772,10 +2779,11 @@ public final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { hasPremium = true } return hasPremium - } + }, + sendPaidMessageStars ) |> deliverOnMainQueue - |> map { [weak itemLayer] isStarred, hasPremium -> (UIView, CGRect, PeekControllerContent)? in + |> map { [weak itemLayer] isStarred, hasPremium, sendPaidMessageStars -> (UIView, CGRect, PeekControllerContent)? in guard let strongSelf = self, let itemLayer = itemLayer else { return nil } @@ -2805,18 +2813,20 @@ public final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { }))) } - menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - if let strongSelf = self, let peekController = strongSelf.peekController { - if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = sendSticker(.standalone(media: file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) - } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = sendSticker(.standalone(media: file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + if sendPaidMessageStars == nil { + menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + if let strongSelf = self, let peekController = strongSelf.peekController { + if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { + let _ = sendSticker(.standalone(media: file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + let _ = sendSticker(.standalone(media: file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + } } - } - f(.default) - }))) + f(.default) + }))) + } } menuItems.append( diff --git a/submodules/TelegramUI/Components/LegacyCamera/Sources/LegacyCamera.swift b/submodules/TelegramUI/Components/LegacyCamera/Sources/LegacyCamera.swift index be2b344db3..eb76dd20d1 100644 --- a/submodules/TelegramUI/Components/LegacyCamera/Sources/LegacyCamera.swift +++ b/submodules/TelegramUI/Components/LegacyCamera/Sources/LegacyCamera.swift @@ -10,7 +10,7 @@ import ShareController import LegacyUI import LegacyMediaPickerUI -public func presentedLegacyCamera(context: AccountContext, peer: Peer?, chatLocation: ChatLocation, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, attachmentController: ViewController? = nil, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: NSAttributedString, hasSchedule: Bool, enablePhoto: Bool, enableVideo: Bool, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ChatSendMessageActionSheetController.SendParameters?) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, dismissedWithResult: @escaping () -> Void = {}, finishedTransitionIn: @escaping () -> Void = {}) { +public func presentedLegacyCamera(context: AccountContext, peer: Peer?, chatLocation: ChatLocation, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, attachmentController: ViewController? = nil, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: NSAttributedString, hasSchedule: Bool, enablePhoto: Bool, enableVideo: Bool, sendPaidMessageStars: Int64 = 0, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ChatSendMessageActionSheetController.SendParameters?) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, dismissedWithResult: @escaping () -> Void = {}, finishedTransitionIn: @escaping () -> Void = {}) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) @@ -35,6 +35,7 @@ public func presentedLegacyCamera(context: AccountContext, peer: Peer?, chatLoca } else { controller = TGCameraController(context: legacyController.context, saveEditedPhotos: saveCapturedPhotos && !isSecretChat, saveCapturedMedia: saveCapturedPhotos && !isSecretChat) } + controller.sendPaidMessageStars = sendPaidMessageStars controller.modalPresentationStyle = .fullScreen controller.inhibitMultipleCapture = editingMedia diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index 7140300641..1eb10582cc 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -429,15 +429,17 @@ final class StoryItemSetContainerSendMessage { }))) } - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.contextMenu.primaryColor) - }, action: { [weak self, weak view] _, a in - a(.default) - - guard let self, let view else { - return - } - self.presentScheduleTimePicker(view: view) - }))) + if component.slice.additionalPeerData.sendPaidMessageStars == nil { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.contextMenu.primaryColor) + }, action: { [weak self, weak view] _, a in + a(.default) + + guard let self, let view else { + return + } + self.presentScheduleTimePicker(view: view) + }))) + } let contextItems = ContextController.Items(content: .list(items)) diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerPaidMessage.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerPaidMessage.swift index 5aa4ed7a50..ae7516293a 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerPaidMessage.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerPaidMessage.swift @@ -28,9 +28,13 @@ extension ChatControllerImpl { guard let self, let starsContext = self.context.starsContext else { return } - if let dismissedAmount, dismissedAmount == sendPaidMessageStars.value, let currentState = starsContext.currentState, currentState.balance.value > totalAmount, count < 3 && totalAmount < 100 { - completion(true) - self.displayPaidMessageUndo(count: count, amount: sendPaidMessageStars) + if let dismissedAmount, dismissedAmount == sendPaidMessageStars.value, let currentState = starsContext.currentState, currentState.balance.value > totalAmount { + if count < 3 && totalAmount < 100 { + completion(false) + } else { + completion(true) + self.displayPaidMessageUndo(count: count, amount: sendPaidMessageStars) + } } else { var presentationData = self.presentationData if forceDark { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 700eba94c2..fda440a9a1 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -9288,12 +9288,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var attributes = attributes if let sendPaidMessageStars = self.presentationInterfaceState.sendPaidMessageStars { + var effectivePostpone = postpone for i in (0 ..< attributes.count).reversed() { - if attributes[i] is PaidStarsMessageAttribute { + if let paidStarsMessageAttribute = attributes[i] as? PaidStarsMessageAttribute { + effectivePostpone = effectivePostpone || paidStarsMessageAttribute.postponeSending attributes.remove(at: i) } } - attributes.append(PaidStarsMessageAttribute(stars: sendPaidMessageStars, postponeSending: postpone)) + attributes.append(PaidStarsMessageAttribute(stars: sendPaidMessageStars, postponeSending: effectivePostpone)) } if silentPosting || scheduleTime != nil { diff --git a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift index e36b0510f5..b856b26bbc 100644 --- a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift +++ b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift @@ -111,9 +111,11 @@ extension ChatControllerImpl { count += 1 } var totalAmount: StarsAmount = .zero + var chargingPeers: [EnginePeer] = [] for peer in peers { if let maybeAmount = sendPaidMessageStars[peer.id], let amount = maybeAmount { totalAmount = totalAmount + amount + chargingPeers.append(peer) } } @@ -320,7 +322,7 @@ extension ChatControllerImpl { context: nil, presentationData: strongSelf.presentationData, updatedPresentationData: nil, - peers: peers, + peers: chargingPeers, count: count, amount: totalAmount, totalAmount: totalAmount, diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift index 85bba67ea7..e5ba6f0de2 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift @@ -1834,7 +1834,7 @@ extension ChatControllerImpl { } let inputText = strongSelf.presentationInterfaceState.interfaceState.effectiveInputState.inputText - presentedLegacyCamera(context: strongSelf.context, peer: strongSelf.presentationInterfaceState.renderedPeer?.peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: nil, parentController: strongSelf, attachmentController: self?.attachmentController, editingMedia: false, saveCapturedPhotos: storeCapturedMedia, mediaGrouping: true, initialCaption: inputText, hasSchedule: hasSchedule, enablePhoto: enablePhoto, enableVideo: enableVideo, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime, parameters in + presentedLegacyCamera(context: strongSelf.context, peer: strongSelf.presentationInterfaceState.renderedPeer?.peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: nil, parentController: strongSelf, attachmentController: self?.attachmentController, editingMedia: false, saveCapturedPhotos: storeCapturedMedia, mediaGrouping: true, initialCaption: inputText, hasSchedule: hasSchedule, enablePhoto: enablePhoto, enableVideo: enableVideo, sendPaidMessageStars: strongSelf.presentationInterfaceState.sendPaidMessageStars?.value ?? 0, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime, parameters in if let strongSelf = self { strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil, parameters: parameters) if !inputText.string.isEmpty { diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index fd32edc50c..3719ff656f 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -40,6 +40,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie private var itemNodes: [MediaId: HorizontalStickerGridItemNode] = [:] private var validLayout: CGSize? + fileprivate weak var currentInterfaceState: ChatPresentationInterfaceState? private var ignoreScrolling: Bool = false private var animateInOnLayout: Bool = false @@ -123,18 +124,20 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie }))) } - menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - if let strongSelf = self, let peekController = strongSelf.peekController { - if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, animationNode.view, animationNode.bounds, nil, []) - } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, imageNode.view, imageNode.bounds, nil, []) + if strongSelf.currentInterfaceState?.sendPaidMessageStars == nil { + menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + if let strongSelf = self, let peekController = strongSelf.peekController { + if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, animationNode.view, animationNode.bounds, nil, []) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, imageNode.view, imageNode.bounds, nil, []) + } } - } - f(.default) - }))) + f(.default) + }))) + } menuItems.append( .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in @@ -604,6 +607,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode { override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) { self.validLayout = (size, leftInset) + self.stickersNode.currentInterfaceState = interfaceState transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size)) diff --git a/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift b/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift index da8e19073d..57c3f686f1 100644 --- a/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift +++ b/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift @@ -22,6 +22,7 @@ import ListSectionComponent import ListItemComponentAdaptor import TelegramStringFormatting import UndoUI +import ChatMessagePaymentAlertController private final class SheetContent: CombinedComponent { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -410,45 +411,100 @@ public final class WebAppMessagePreviewScreen: ViewControllerComponentContainer fatalError("init(coder:) has not been implemented") } - fileprivate func complete(peers: [EnginePeer]) { - for peer in peers { - let _ = self.context.engine.messages.enqueueOutgoingMessage( - to: peer.id, - replyTo: nil, - storyId: nil, - content: .preparedInlineMessage(self.preparedMessage) - ).start() - } + private func presentPaidMessageAlertIfNeeded(peers: [EnginePeer], requiresStars: [EnginePeer.Id: Int64], completion: @escaping () -> Void) { - let text: String - let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - if peers.count == 1, let peer = peers.first { - let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string - } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { - let firstPeerName = firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - let secondPeerName = secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string - } else if let peer = peers.first { - let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string - } else { - text = "" - } - - if let navigationController = self.navigationController as? NavigationController { - Queue.mainQueue().after(1.0) { - guard let lastController = navigationController.viewControllers.last as? ViewController else { + } + + fileprivate func complete(peers: [EnginePeer], controller: ViewController?) { + let _ = (self.context.engine.data.get( + EngineDataMap( + peers.map { TelegramEngine.EngineData.Item.Peer.SendPaidMessageStars.init(id: $0.id) } + ) + ) + |> deliverOnMainQueue).start(next: { [weak self] sendPaidMessageStars in + guard let self else { + return + } + var totalAmount: StarsAmount = .zero + var chargingPeers: [EnginePeer] = [] + for peer in peers { + if let maybeAmount = sendPaidMessageStars[peer.id], let amount = maybeAmount { + totalAmount = totalAmount + amount + chargingPeers.append(peer) + } + } + + let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } + let proceed = { [weak self] in + guard let self else { return } - lastController.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: false, text: text), elevatedLayout: false, position: .top, animateInAsReplacement: true, action: { action in - return false - }), in: .window(.root)) + + for peer in peers { + var starsAmount: StarsAmount? + if let maybeAmount = sendPaidMessageStars[peer.id], let amount = maybeAmount { + starsAmount = amount + } + let _ = self.context.engine.messages.enqueueOutgoingMessage( + to: peer.id, + replyTo: nil, + storyId: nil, + content: .preparedInlineMessage(self.preparedMessage), + sendPaidMessageStars: starsAmount + ).start() + } + + let text: String + if peers.count == 1, let peer = peers.first { + let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string + } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { + let firstPeerName = firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + let secondPeerName = secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string + } else if let peer = peers.first { + let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string + } else { + text = "" + } + + if let navigationController = self.navigationController as? NavigationController { + Queue.mainQueue().after(1.0) { + guard let lastController = navigationController.viewControllers.last as? ViewController else { + return + } + lastController.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: false, text: text), elevatedLayout: false, position: .top, animateInAsReplacement: true, action: { action in + return false + }), in: .window(.root)) + } + } + + self.completeWithResult(true) + self.dismiss() + controller?.dismiss() } - } - - self.completeWithResult(true) - self.dismiss() + + if totalAmount.value > 0 { + let controller = chatMessagePaymentAlertController( + context: nil, + presentationData: presentationData, + updatedPresentationData: nil, + peers: chargingPeers, + count: 1, + amount: totalAmount, + totalAmount: totalAmount, + hasCheck: false, + navigationController: self.navigationController as? NavigationController, + completion: { _ in + proceed() + } + ) + self.present(controller, in: .window(.root)) + } else { + proceed() + } + }) } private var completed = false @@ -468,8 +524,7 @@ public final class WebAppMessagePreviewScreen: ViewControllerComponentContainer guard let self else { return } - self.complete(peers: peers) - controller?.dismiss() + self.complete(peers: peers, controller: controller) } self.push(controller)