diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift index 6166e8bbcf..f6c9f86578 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift @@ -342,6 +342,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { rawString = "❌ You rejected the message with the comment:" } else { rawString = "❌ You rejected the message." + smallFont = true } case .lowBalance: rawString = "⚠️ **Transaction failed** because the user didn't have enough Stars." @@ -354,6 +355,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { rawString = "❌ **\(channelName)** rejected your message with the comment:" } else { rawString = "❌ **\(channelName)** rejected your message." + smallFont = true } case .lowBalance: rawString = "⚠️ **Transaction failed** because you didn't have enough Stars." diff --git a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift index 9689a9daaf..3fcde05e7c 100644 --- a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift @@ -547,9 +547,9 @@ private final class SheetContent: CombinedComponent { switch mode { case .sender: if let amount = state.amount { - buttonString = "Set # \(presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator))" + buttonString = "Offer # \(presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator))" } else { - buttonString = "Set # Free" + buttonString = "Offer for Free" } case .admin: buttonString = "Update Terms" diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c50c8d7f5f..175f765e96 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -2358,27 +2358,54 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = strongSelf.context.engine.messages.monoforumPerformSuggestedPostAction(id: message.id, action: .approve(timestamp: timestamp)).startStandalone() } case 2: - var entities: [MessageTextEntity] = [] - for attribute in message.attributes { - if let attribute = attribute as? TextEntitiesMessageAttribute { - entities = attribute.entities - break - } - } - let inputText = chatInputStateStringWithAppliedEntities(message.text, entities: entities) - strongSelf.updateChatPresentationInterfaceState(interactive: true, { state in - var state = state - state = state.updatedInterfaceState { interfaceState in + var entities: [MessageTextEntity] = [] + for attribute in message.attributes { + if let attribute = attribute as? TextEntitiesMessageAttribute { + entities = attribute.entities + break + } + } + var inputTextMaxLength: Int32 = 4096 + var webpageUrl: String? + for media in message.media { + if media is TelegramMediaImage || media is TelegramMediaFile { + inputTextMaxLength = strongSelf.context.userLimits.maxCaptionLength + } else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { + webpageUrl = content.url + } + } + + let inputText = chatInputStateStringWithAppliedEntities(message.text, entities: entities) + var disableUrlPreviews: [String] = [] + if webpageUrl == nil { + disableUrlPreviews = detectUrls(inputText) + } + + var updated = state.updatedInterfaceState { interfaceState in + return interfaceState.withUpdatedEditMessage(ChatEditMessageState(messageId: messageId, inputState: ChatTextInputState(inputText: inputText), disableUrlPreviews: disableUrlPreviews, inputTextMaxLength: inputTextMaxLength, mediaCaptionIsAbove: nil)) + } + + let (updatedState, updatedPreviewQueryState) = updatedChatEditInterfaceMessageState(context: strongSelf.context, state: updated, message: message) + updated = updatedState + strongSelf.editingUrlPreviewQueryState?.1.dispose() + strongSelf.editingUrlPreviewQueryState = updatedPreviewQueryState + + updated = updated.updatedInputMode({ _ in + return .text + }) + updated = updated.updatedShowCommands(false) + updated = updated.updatedInterfaceState { interfaceState in var interfaceState = interfaceState + interfaceState = interfaceState.withUpdatedPostSuggestionState(ChatInterfaceState.PostSuggestionState( editingOriginalMessageId: message.id, price: attribute.amount, timestamp: attribute.timestamp - )).withUpdatedComposeInputState(ChatTextInputState(inputText: inputText)) + )) return interfaceState } - return state + return updated }) default: break @@ -7421,7 +7448,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } return state }) - self.interfaceInteraction?.editMessage() + if self.presentationInterfaceState.interfaceState.postSuggestionState == nil { + self.interfaceInteraction?.editMessage() + } } } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index aa70977665..4287a59f0e 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1719,7 +1719,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { if let postSuggestionState = state.postSuggestionState { state = state.withUpdatedPostSuggestionState(nil) if postSuggestionState.editingOriginalMessageId != nil { - state = state.withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) + state = state.withUpdatedEditMessage(nil) } } return state @@ -4476,7 +4476,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { effectivePresentationInterfaceState = effectivePresentationInterfaceState.updatedInterfaceState { $0.withUpdatedEffectiveInputState(textInputPanelNode.inputTextState) } } - if let _ = effectivePresentationInterfaceState.interfaceState.editMessage { + if let _ = effectivePresentationInterfaceState.interfaceState.editMessage, effectivePresentationInterfaceState.interfaceState.postSuggestionState == nil { self.interfaceInteraction?.editMessage() } else { var isScheduledMessages = false @@ -4493,7 +4493,13 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { var messages: [EnqueueMessage] = [] - let effectiveInputText = expandedInputStateAttributedString(effectivePresentationInterfaceState.interfaceState.composeInputState.inputText) + let effectiveInputText: NSAttributedString + + if effectivePresentationInterfaceState.interfaceState.editMessage != nil && effectivePresentationInterfaceState.interfaceState.postSuggestionState != nil { + effectiveInputText = expandedInputStateAttributedString(effectivePresentationInterfaceState.interfaceState.effectiveInputState.inputText) + } else { + effectiveInputText = expandedInputStateAttributedString(effectivePresentationInterfaceState.interfaceState.composeInputState.inputText) + } let peerSpecificEmojiPack = (self.controller?.contentData?.state.peerView?.cachedData as? CachedChannelData)?.emojiPack @@ -4609,6 +4615,30 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } else { let inputText = convertMarkdownToAttributes(effectiveInputText) + var mediaReference: AnyMediaReference? + var webpage: TelegramMediaWebpage? + if let urlPreview = self.chatPresentationInterfaceState.urlPreview { + if self.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreviews.contains(urlPreview.url) { + } else { + webpage = urlPreview.webPage + } + } + mediaReference = webpage.flatMap(AnyMediaReference.standalone) + + if let postSuggestionState = effectivePresentationInterfaceState.interfaceState.postSuggestionState, let editingOriginalMessageId = postSuggestionState.editingOriginalMessageId { + if let editMessageState = effectivePresentationInterfaceState.editMessageState, let mediaReferenceValue = editMessageState.mediaReference { + mediaReference = mediaReferenceValue + } else { + if let message = self.historyNode.messageInCurrentHistoryView(editingOriginalMessageId) { + for media in message.media { + if media is TelegramMediaFile || media is TelegramMediaImage { + mediaReference = .message(message: MessageReference(message), media: media) + } + } + } + } + } + for text in breakChatInputText(trimChatInputText(inputText)) { if text.length != 0 { var attributes: [MessageAttribute] = [] @@ -4622,12 +4652,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var webpage: TelegramMediaWebpage? if let urlPreview = self.chatPresentationInterfaceState.urlPreview { if self.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreviews.contains(urlPreview.url) { attributes.append(OutgoingContentInfoMessageAttribute(flags: [.disableLinkPreviews])) } else { - webpage = urlPreview.webPage attributes.append(WebpagePreviewMessageAttribute(leadingPreview: !urlPreview.positionBelowText, forceLargeMedia: urlPreview.largeMedia, isManuallyAdded: true, isSafe: false)) } } @@ -4647,9 +4675,15 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { bubbleUpEmojiOrStickersets.removeAll() } - messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) + messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) + mediaReference = nil } } + + if let mediaReferenceValue = mediaReference { + mediaReference = nil + messages.append(.message(text: "", attributes: [], inlineStickers: inlineStickers, mediaReference: mediaReferenceValue, threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) + } var forwardingToSameChat = false if case let .peer(id) = self.chatPresentationInterfaceState.chatLocation, id.namespace == Namespaces.Peer.CloudUser, id != self.context.account.peerId, let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds, forwardMessageIds.count == 1 { @@ -4723,7 +4757,21 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { strongSelf.ignoreUpdateHeight = true textInputPanelNode.text = "" - strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedPostSuggestionState(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeDisableUrlPreviews([]) }) + strongSelf.requestUpdateChatInterfaceState(.immediate, true, { state in + var state = state + state = state.withUpdatedReplyMessageSubject(nil) + state = state.withUpdatedSendMessageEffect(nil) + + if state.postSuggestionState != nil { + state = state.withUpdatedPostSuggestionState(nil) + state = state.withUpdatedEditMessage(nil) + } + + state = state.withUpdatedForwardMessageIds(nil) + state = state.withUpdatedForwardOptionsState(nil) + state = state.withUpdatedComposeDisableUrlPreviews([]) + return state + }) strongSelf.ignoreUpdateHeight = false } }, usedCorrelationId) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift index 177b5133b0..a86c11bb33 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift @@ -28,7 +28,7 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS break } - if let editMessage = chatPresentationInterfaceState.interfaceState.editMessage { + if let editMessage = chatPresentationInterfaceState.interfaceState.editMessage, chatPresentationInterfaceState.interfaceState.postSuggestionState == nil { if let editingUrlPreview = chatPresentationInterfaceState.editingUrlPreview, !editMessage.disableUrlPreviews.contains(editingUrlPreview.url) { if let previewPanelNode = currentPanel as? WebpagePreviewAccessoryPanelNode { previewPanelNode.interfaceInteraction = interfaceInteraction diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 3b9f217e90..f110d755c1 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -564,6 +564,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch let attachmentButton: HighlightableButtonNode let attachmentButtonDisabledNode: HighlightableButtonNode + + + let searchLayoutClearButton: HighlightableButton private let searchLayoutClearImageNode: ASImageNode private var searchActivityIndicator: ActivityIndicator?