diff --git a/submodules/Display/Source/InteractiveTransitionGestureRecognizer.swift b/submodules/Display/Source/InteractiveTransitionGestureRecognizer.swift index 8b72c2f7a0..56120b515e 100644 --- a/submodules/Display/Source/InteractiveTransitionGestureRecognizer.swift +++ b/submodules/Display/Source/InteractiveTransitionGestureRecognizer.swift @@ -61,21 +61,16 @@ public enum InteractiveTransitionGestureRecognizerEdgeWidth { } public class InteractiveTransitionGestureRecognizer: UIPanGestureRecognizer { - private let staticEdgeWidth: InteractiveTransitionGestureRecognizerEdgeWidth + private let edgeWidth: InteractiveTransitionGestureRecognizerEdgeWidth private let allowedDirections: (CGPoint) -> InteractiveTransitionGestureRecognizerDirections - public var dynamicEdgeWidth: ((CGPoint) -> InteractiveTransitionGestureRecognizerEdgeWidth)? - private var currentEdgeWidth: InteractiveTransitionGestureRecognizerEdgeWidth - - private var ignoreOffset: CGPoint = CGPoint() private var validatedGesture = false private var firstLocation: CGPoint = CGPoint() private var currentAllowedDirections: InteractiveTransitionGestureRecognizerDirections = [] public init(target: Any?, action: Selector?, allowedDirections: @escaping (CGPoint) -> InteractiveTransitionGestureRecognizerDirections, edgeWidth: InteractiveTransitionGestureRecognizerEdgeWidth = .constant(16.0)) { self.allowedDirections = allowedDirections - self.staticEdgeWidth = edgeWidth - self.currentEdgeWidth = edgeWidth + self.edgeWidth = edgeWidth super.init(target: target, action: action) @@ -86,7 +81,6 @@ public class InteractiveTransitionGestureRecognizer: UIPanGestureRecognizer { override public func reset() { super.reset() - self.ignoreOffset = CGPoint() self.validatedGesture = false self.currentAllowedDirections = [] } @@ -105,10 +99,6 @@ public class InteractiveTransitionGestureRecognizer: UIPanGestureRecognizer { return } - if let dynamicEdgeWidth = self.dynamicEdgeWidth { - self.currentEdgeWidth = dynamicEdgeWidth(point) - } - super.touchesBegan(touches, with: event) self.firstLocation = point @@ -138,11 +128,6 @@ public class InteractiveTransitionGestureRecognizer: UIPanGestureRecognizer { } } - override public func translation(in view: UIView?) -> CGPoint { - let result = super.translation(in: view) - return result//.offsetBy(dx: self.ignoreOffset.x, dy: self.ignoreOffset.y) - } - override public func touchesMoved(_ touches: Set, with event: UIEvent) { let location = touches.first!.location(in: self.view) let translation = CGPoint(x: location.x - self.firstLocation.x, y: location.y - self.firstLocation.y) @@ -161,63 +146,41 @@ public class InteractiveTransitionGestureRecognizer: UIPanGestureRecognizer { if absTranslationX > 2.0 && absTranslationX > absTranslationY * 2.0 { self.state = .failed } else if absTranslationY > 2.0 && absTranslationX * 2.0 < absTranslationY { - self.ignoreOffset = CGPoint(x: -translation.x, y: -translation.y) self.validatedGesture = true } } } else { - let defaultEdgeWidth: CGFloat - switch self.staticEdgeWidth { + let edgeWidth: CGFloat + switch self.edgeWidth { case let .constant(value): - defaultEdgeWidth = value + edgeWidth = value case let .widthMultiplier(factor, minValue, maxValue): - defaultEdgeWidth = max(minValue, min(size.width * factor, maxValue)) - } - - let extendedEdgeWidth: CGFloat - switch self.currentEdgeWidth { - case let .constant(value): - extendedEdgeWidth = value - case let .widthMultiplier(factor, minValue, maxValue): - extendedEdgeWidth = max(minValue, min(size.width * factor, maxValue)) + edgeWidth = max(minValue, min(size.width * factor, maxValue)) } if !self.validatedGesture { - if self.firstLocation.x < extendedEdgeWidth && !self.currentAllowedDirections.contains(.rightEdge) { + if self.firstLocation.x < edgeWidth && !self.currentAllowedDirections.contains(.rightEdge) { self.state = .failed return } - if self.firstLocation.x > size.width - extendedEdgeWidth && !self.currentAllowedDirections.contains(.leftEdge) { + if self.firstLocation.x > size.width - edgeWidth && !self.currentAllowedDirections.contains(.leftEdge) { self.state = .failed return } - if self.currentAllowedDirections.contains(.rightEdge) && self.firstLocation.x < extendedEdgeWidth { - if absTranslationY > 2.0 && absTranslationY > absTranslationX * 2.0 { - self.state = .failed - } else if absTranslationX > 2.0 && absTranslationY * 2.0 < absTranslationX { - self.ignoreOffset = CGPoint(x: -translation.x, y: -translation.y) - self.validatedGesture = true - fireBegan = true - } - } else { - if self.currentAllowedDirections.contains(.rightEdge) && self.firstLocation.x < defaultEdgeWidth { - self.ignoreOffset = CGPoint(x: -translation.x, y: -translation.y) - self.validatedGesture = true - } else if self.currentAllowedDirections.contains(.leftEdge) && self.firstLocation.x > size.width - defaultEdgeWidth { - self.ignoreOffset = CGPoint(x: -translation.x, y: -translation.y) - self.validatedGesture = true - } else if !self.currentAllowedDirections.contains(.leftCenter) && translation.x < 0.0 { - self.state = .failed - } else if !self.currentAllowedDirections.contains(.rightCenter) && translation.x > 0.0 { - self.state = .failed - } else if absTranslationY > 2.0 && absTranslationY > absTranslationX * 2.0 { - self.state = .failed - } else if absTranslationX > 2.0 && absTranslationY * 2.0 < absTranslationX { - self.ignoreOffset = CGPoint(x: -translation.x, y: -translation.y) - self.validatedGesture = true - fireBegan = true - } + if self.currentAllowedDirections.contains(.rightEdge) && self.firstLocation.x < edgeWidth { + self.validatedGesture = true + } else if self.currentAllowedDirections.contains(.leftEdge) && self.firstLocation.x > size.width - edgeWidth { + self.validatedGesture = true + } else if !self.currentAllowedDirections.contains(.leftCenter) && translation.x < 0.0 { + self.state = .failed + } else if !self.currentAllowedDirections.contains(.rightCenter) && translation.x > 0.0 { + self.state = .failed + } else if absTranslationY > 2.0 && absTranslationY > absTranslationX * 2.0 { + self.state = .failed + } else if absTranslationX > 2.0 && absTranslationY * 2.0 < absTranslationX { + self.validatedGesture = true + fireBegan = true } } } diff --git a/submodules/Display/Source/Navigation/NavigationContainer.swift b/submodules/Display/Source/Navigation/NavigationContainer.swift index 2a9614ff24..516639626d 100644 --- a/submodules/Display/Source/Navigation/NavigationContainer.swift +++ b/submodules/Display/Source/Navigation/NavigationContainer.swift @@ -142,12 +142,12 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega } return .right }) - panRecognizer.dynamicEdgeWidth = { [weak self] _ in + /*panRecognizer.dynamicEdgeWidth = { [weak self] _ in guard let self, let controller = self.controllers.last, let value = controller.interactiveNavivationGestureEdgeWidth else { return .constant(16.0) } return value - } + }*/ if #available(iOS 13.4, *) { panRecognizer.allowedScrollTypesMask = .continuous } diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index c3da0743ba..b549d3d41e 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -172,7 +172,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 9cb991d7b9..ca37f1a9d8 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -436,7 +436,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 4490fc76cb..cdf27920f1 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -1048,7 +1048,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message5.id] = message5 sampleMessages.append(message5) @@ -1059,7 +1059,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message7) let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index d89f7d51a7..e7540c31c9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -599,7 +599,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message5.id] = message5 sampleMessages.append(message5) @@ -610,7 +610,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message7) let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index a20fecdc7e..a329a970dc 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -159,7 +159,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)) } diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 9603c2d28d..64cea4abac 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -590,6 +590,8 @@ extension StoreMessage { let isForumTopic = (innerFlags & (1 << 3)) != 0 var quote: EngineMessageReplyQuote? + let isQuote = (innerFlags & (1 << 9)) != 0 + if quoteText != nil || replyMedia != nil { quote = EngineMessageReplyQuote(text: quoteText ?? "", entities: messageTextEntitiesFromApiEntities(quoteEntities ?? []), media: textMediaAndExpirationTimerFromApiMedia(replyMedia, peerId).media) } @@ -601,9 +603,7 @@ extension StoreMessage { if isForumTopic { let threadIdValue = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToTopId) threadMessageId = threadIdValue - if replyPeerId == peerId { - threadId = makeMessageThreadId(threadIdValue) - } + threadId = makeMessageThreadId(threadIdValue) } } else { let threadIdValue = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToTopId) @@ -623,10 +623,10 @@ extension StoreMessage { threadId = makeMessageThreadId(threadIdValue) } } - attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote)) + attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote)) } if let replyHeader = replyHeader { - attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote)) + attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote)) } case let .messageReplyStoryHeader(userId, storyId): attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), id: storyId))) @@ -867,8 +867,9 @@ extension StoreMessage { if let replyTo = replyTo { var threadMessageId: MessageId? switch replyTo { - case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities): + case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities): var quote: EngineMessageReplyQuote? + let isQuote = (innerFlags & (1 << 9)) != 0 if quoteText != nil || replyMedia != nil { quote = EngineMessageReplyQuote(text: quoteText ?? "", entities: messageTextEntitiesFromApiEntities(quoteEntities ?? []), media: textMediaAndExpirationTimerFromApiMedia(replyMedia, peerId).media) } @@ -892,9 +893,9 @@ extension StoreMessage { default: break } - attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote)) + attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote)) } else if let replyHeader = replyHeader { - attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote)) + attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote)) } case let .messageReplyStoryHeader(userId, storyId): attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), id: storyId))) diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index 897da394fe..a2c3ed32dd 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -563,6 +563,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, if let replyToMessageId = replyToMessageId { var threadMessageId: MessageId? var quote = replyToMessageId.quote + let isQuote = quote != nil if let replyMessage = transaction.getMessage(replyToMessageId.messageId) { threadMessageId = replyMessage.effectiveReplyThreadMessageId if quote == nil, replyToMessageId.messageId.peerId != peerId { @@ -579,7 +580,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, quote = EngineMessageReplyQuote(text: replyMessage.text, entities: messageTextEntitiesInRange(entities: replyMessage.textEntitiesAttribute?.entities ?? [], range: NSRange(location: 0, length: nsText.length), onlyQuoteable: true), media: replyMedia) } } - attributes.append(ReplyMessageAttribute(messageId: replyToMessageId.messageId, threadMessageId: threadMessageId, quote: quote)) + attributes.append(ReplyMessageAttribute(messageId: replyToMessageId.messageId, threadMessageId: threadMessageId, quote: quote, isQuote: isQuote)) } if let replyToStoryId = replyToStoryId { attributes.append(ReplyStoryAttribute(storyId: replyToStoryId)) diff --git a/submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift index bfc7e28cbe..7e8f5e7440 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift @@ -164,7 +164,7 @@ public func standaloneSendEnqueueMessages( } if let replyToMessageId = message.replyToMessageId { - attributes.append(ReplyMessageAttribute(messageId: replyToMessageId, threadMessageId: nil, quote: nil)) + attributes.append(ReplyMessageAttribute(messageId: replyToMessageId, threadMessageId: nil, quote: nil, isQuote: false)) } if let forwardOptions = message.forwardOptions { attributes.append(ForwardOptionsMessageAttribute(hideNames: forwardOptions.hideNames, hideCaptions: forwardOptions.hideCaptions)) diff --git a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift index f49fff8893..3c3bd5ae1a 100644 --- a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift +++ b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift @@ -793,7 +793,9 @@ public final class PendingMessageManager { if peerId != replyAttribute.messageId.peerId { replyPeerId = replyAttribute.messageId.peerId } - replyQuote = replyAttribute.quote + if replyAttribute.isQuote { + replyQuote = replyAttribute.quote + } } else if let attribute = attribute as? ReplyStoryAttribute { replyToStoryId = attribute.storyId } else if let _ = attribute as? ForwardSourceInfoAttribute { @@ -1160,7 +1162,9 @@ public final class PendingMessageManager { if peer.id != replyAttribute.messageId.peerId { replyPeerId = replyAttribute.messageId.peerId } - replyQuote = replyAttribute.quote + if replyAttribute.isQuote { + replyQuote = replyAttribute.quote + } } else if let attribute = attribute as? ReplyStoryAttribute { replyToStoryId = attribute.storyId } else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute { diff --git a/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift b/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift index f110c457ca..7724ed9162 100644 --- a/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift +++ b/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift @@ -881,7 +881,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32 } if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) { - attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)) + attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)) } var entitiesAttribute: TextEntitiesMessageAttribute? @@ -1113,7 +1113,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32 } if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) { - attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)) + attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)) } var entitiesAttribute: TextEntitiesMessageAttribute? @@ -1392,7 +1392,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32 } if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) { - attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)) + attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)) } var entitiesAttribute: TextEntitiesMessageAttribute? @@ -1593,7 +1593,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32 } if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) { - attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)) + attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)) } var entitiesAttribute: TextEntitiesMessageAttribute? diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReplyMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReplyMessageAttribute.swift index 5f7bcb3c03..b5918615dd 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReplyMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReplyMessageAttribute.swift @@ -6,15 +6,17 @@ public class ReplyMessageAttribute: MessageAttribute { public let messageId: MessageId public let threadMessageId: MessageId? public let quote: EngineMessageReplyQuote? + public let isQuote: Bool public var associatedMessageIds: [MessageId] { return [self.messageId] } - public init(messageId: MessageId, threadMessageId: MessageId?, quote: EngineMessageReplyQuote?) { + public init(messageId: MessageId, threadMessageId: MessageId?, quote: EngineMessageReplyQuote?, isQuote: Bool) { self.messageId = messageId self.threadMessageId = threadMessageId self.quote = quote + self.isQuote = isQuote } required public init(decoder: PostboxDecoder) { @@ -28,6 +30,7 @@ public class ReplyMessageAttribute: MessageAttribute { } self.quote = decoder.decodeCodable(EngineMessageReplyQuote.self, forKey: "qu") + self.isQuote = decoder.decodeBoolForKey("iq", orElse: self.quote != nil) } public func encode(_ encoder: PostboxEncoder) { @@ -44,6 +47,7 @@ public class ReplyMessageAttribute: MessageAttribute { } else { encoder.encodeNil(forKey: "qu") } + encoder.encodeBool(self.isQuote, forKey: "iq") } } @@ -51,6 +55,7 @@ public class QuotedReplyMessageAttribute: MessageAttribute { public let peerId: PeerId? public let authorName: String? public let quote: EngineMessageReplyQuote? + public let isQuote: Bool public var associatedMessageIds: [MessageId] { return [] @@ -64,16 +69,18 @@ public class QuotedReplyMessageAttribute: MessageAttribute { } } - public init(peerId: PeerId?, authorName: String?, quote: EngineMessageReplyQuote?) { + public init(peerId: PeerId?, authorName: String?, quote: EngineMessageReplyQuote?, isQuote: Bool) { self.peerId = peerId self.authorName = authorName self.quote = quote + self.isQuote = isQuote } required public init(decoder: PostboxDecoder) { self.peerId = decoder.decodeOptionalInt64ForKey("p").flatMap(PeerId.init) self.authorName = decoder.decodeOptionalStringForKey("a") self.quote = decoder.decodeCodable(EngineMessageReplyQuote.self, forKey: "qu") + self.isQuote = decoder.decodeBoolForKey("iq", orElse: true) } public func encode(_ encoder: PostboxEncoder) { @@ -94,14 +101,16 @@ public class QuotedReplyMessageAttribute: MessageAttribute { } else { encoder.encodeNil(forKey: "qu") } + + encoder.encodeBool(self.isQuote, forKey: "iq") } } extension QuotedReplyMessageAttribute { - convenience init(apiHeader: Api.MessageFwdHeader, quote: EngineMessageReplyQuote?) { + convenience init(apiHeader: Api.MessageFwdHeader, quote: EngineMessageReplyQuote?, isQuote: Bool) { switch apiHeader { case let .messageFwdHeader(_, fromId, fromName, _, _, _, _, _, _): - self.init(peerId: fromId?.peerId, authorName: fromName, quote: quote) + self.init(peerId: fromId?.peerId, authorName: fromName, quote: quote, isQuote: isQuote) } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/PublicHeaders/ChatInputTextViewImpl/ChatInputTextViewImpl.h b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/PublicHeaders/ChatInputTextViewImpl/ChatInputTextViewImpl.h index fc04921265..528c45c33f 100755 --- a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/PublicHeaders/ChatInputTextViewImpl/ChatInputTextViewImpl.h +++ b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/PublicHeaders/ChatInputTextViewImpl/ChatInputTextViewImpl.h @@ -19,6 +19,7 @@ @property (nonatomic, copy) bool (^ _Nullable shouldRespondToAction)(SEL _Nullable); @property (nonatomic, copy) bool (^ _Nullable shouldReturn)(); @property (nonatomic, copy) void (^ _Nullable backspaceWhileEmpty)(); +@property (nonatomic, copy) void (^ _Nullable dropAutocorrectioniOS16)(); - (instancetype _Nonnull)initWithFrame:(CGRect)frame textContainer:(NSTextContainer * _Nullable)textContainer disableTiling:(bool)disableTiling; diff --git a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/Sources/ChatInputTextViewImpl.m b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/Sources/ChatInputTextViewImpl.m index a92c35160a..8e96504a12 100755 --- a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/Sources/ChatInputTextViewImpl.m +++ b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/ChatInputTextViewImpl/Sources/ChatInputTextViewImpl.m @@ -12,6 +12,12 @@ @end +@interface ChatInputTextViewImpl () { + UIGestureRecognizer *_tapRecognizer; +} + +@end + @implementation ChatInputTextViewImpl - (instancetype _Nonnull)initWithFrame:(CGRect)frame textContainer:(NSTextContainer * _Nullable)textContainer disableTiling:(bool)disableTiling { @@ -26,10 +32,40 @@ #pragma clang diagnostic pop } } + + if (@available(iOS 17.0, *)) { + } else { + _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(workaroundTapGesture:)]; + _tapRecognizer.cancelsTouchesInView = false; + _tapRecognizer.delaysTouchesBegan = false; + _tapRecognizer.delaysTouchesEnded = false; + _tapRecognizer.delegate = self; + [self addGestureRecognizer:_tapRecognizer]; + } } return self; } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return true; +} + +- (void)workaroundTapGesture:(UITapGestureRecognizer *)recognizer { + if (recognizer.state == UIGestureRecognizerStateEnded) { + static Class promptClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + promptClass = NSClassFromString([[NSString alloc] initWithFormat:@"%@AutocorrectInlinePrompt", @"UI"]); + }); + UIView *result = [self hitTest:[recognizer locationInView:self] withEvent:nil]; + if (result != nil && [result class] == promptClass) { + if (_dropAutocorrectioniOS16) { + _dropAutocorrectioniOS16(); + } + } + } +} + - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (_shouldRespondToAction) { diff --git a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/Sources/ChatInputTextNode.swift b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/Sources/ChatInputTextNode.swift index 5ad648a733..9c659bd795 100644 --- a/submodules/TelegramUI/Components/Chat/ChatInputTextNode/Sources/ChatInputTextNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatInputTextNode/Sources/ChatInputTextNode.swift @@ -32,7 +32,6 @@ open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate { } private var selectionChangedForEditedText: Bool = false - private var isPreservingSelection: Bool = false public var textView: ChatInputTextView { return self.view as! ChatInputTextView @@ -81,20 +80,7 @@ open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate { get { return self.textView.attributedText } set(value) { - if self.textView.attributedText != value { - let selectedRange = self.textView.selectedRange; - let preserveSelectedRange = selectedRange.location != self.textView.textStorage.length - - self.textView.attributedText = value ?? NSAttributedString() - - if preserveSelectedRange { - self.isPreservingSelection = true - self.textView.selectedRange = selectedRange - self.isPreservingSelection = false - } - - self.textView.updateTextContainerInset() - } + self.textView.attributedText = value } } @@ -164,7 +150,7 @@ open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate { } @objc public func textViewDidChangeSelection(_ textView: UITextView) { - if self.isPreservingSelection { + if self.textView.isPreservingSelection { return } @@ -187,6 +173,9 @@ open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate { guard let delegate = self.delegate else { return true } + if self.textView.isPreservingText { + return false + } return delegate.chatInputTextNode(shouldChangeTextIn: range, replacementText: text) } @@ -306,6 +295,30 @@ public final class ChatInputTextView: ChatInputTextViewImpl, NSLayoutManagerDele } } + override public var attributedText: NSAttributedString? { + get { + return super.attributedText + } set(value) { + if self.attributedText != value { + let selectedRange = self.selectedRange + let preserveSelectedRange = selectedRange.location != self.textStorage.length + + super.attributedText = value ?? NSAttributedString() + + if preserveSelectedRange { + self.isPreservingSelection = true + self.selectedRange = selectedRange + self.isPreservingSelection = false + } + + self.updateTextContainerInset() + } + } + } + + fileprivate var isPreservingSelection: Bool = false + fileprivate var isPreservingText: Bool = false + public weak var customDelegate: ChatInputTextNodeDelegate? public var theme: Theme? { @@ -391,6 +404,27 @@ public final class ChatInputTextView: ChatInputTextViewImpl, NSLayoutManagerDele self.customTextStorage.delegate = self self.measurementTextStorage.delegate = self + self.dropAutocorrectioniOS16 = { [weak self] in + guard let self else { + return + } + + self.isPreservingSelection = true + self.isPreservingText = true + + let rangeCopy = self.selectedRange + var fakeRange = rangeCopy + if fakeRange.location != 0 { + fakeRange.location -= 1 + } + self.unmarkText() + self.selectedRange = fakeRange + self.selectedRange = rangeCopy + + self.isPreservingSelection = false + self.isPreservingText = false + } + self.shouldCopy = { [weak self] in guard let self else { return true @@ -542,7 +576,7 @@ public final class ChatInputTextView: ChatInputTextViewImpl, NSLayoutManagerDele if self.measurementTextStorage != self.attributedText || self.measurementTextContainer.size != measureSize || self.measurementTextContainer.rightInset != rightInset { self.measurementTextContainer.rightInset = rightInset - self.measurementTextStorage.setAttributedString(self.attributedText) + self.measurementTextStorage.setAttributedString(self.attributedText ?? NSAttributedString()) self.measurementTextContainer.size = measureSize self.measurementLayoutManager.invalidateLayout(forCharacterRange: NSRange(location: 0, length: self.measurementTextStorage.length), actualCharacterRange: nil) self.measurementLayoutManager.ensureLayout(for: self.measurementTextContainer) @@ -772,6 +806,7 @@ private final class QuoteBackgroundView: UIView { self.backgroundView.update( size: size, + isTransparent: false, primaryColor: theme.foreground, secondaryColor: theme.lineStyle != .solid ? .clear : nil, thirdColor: theme.lineStyle == .tripleDashed ? .clear : nil, diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift index 2633d227df..f75ac88511 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -114,8 +114,8 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { private var threadInfoNode: ChatMessageThreadInfoNode? private var replyInfoNode: ChatMessageReplyInfoNode? private var replyBackgroundContent: WallpaperBubbleBackgroundNode? - private var replyBackgroundNode: NavigationBackgroundNode? private var forwardInfoNode: ChatMessageForwardInfoNode? + private var forwardBackgroundContent: WallpaperBubbleBackgroundNode? private var actionButtonsNode: ChatMessageActionButtonsNode? private var reactionButtonsNode: ChatMessageReactionButtonsNode? @@ -305,7 +305,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let item = self.item { let _ = item replyRecognizer.allowBothDirections = false//!item.context.sharedContext.immediateExperimentalUISettings.unidirectionalSwipeToReply - self.view.disablesInteractiveTransitionGestureRecognizer = true + self.view.disablesInteractiveTransitionGestureRecognizer = false } replyRecognizer.shouldBegin = { [weak self] in if let strongSelf = self, let item = strongSelf.item { @@ -1058,7 +1058,6 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { var viaBotApply: (TextNodeLayout, () -> TextNode)? var threadInfoApply: (CGSize, (Bool) -> ChatMessageThreadInfoNode)? var replyInfoApply: (CGSize, (CGSize, Bool, ListViewItemUpdateAnimation) -> ChatMessageReplyInfoNode)? - var needsReplyBackground = false var replyMarkup: ReplyMarkupMessageAttribute? var availableContentWidth = min(200.0, max(60.0, params.width - params.leftInset - params.rightInset - max(imageSize.width, 160.0) - 20.0 - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left)) @@ -1080,7 +1079,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { var replyMessage: Message? var replyForward: QuotedReplyMessageAttribute? - var replyQuote: EngineMessageReplyQuote? + var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyStory: StoryId? for attribute in item.message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { @@ -1107,7 +1106,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } else { replyMessage = item.message.associatedMessages[replyAttribute.messageId] } - replyQuote = replyAttribute.quote + replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) } } else if let quoteReplyAttribute = attribute as? QuotedReplyMessageAttribute { replyForward = quoteReplyAttribute } else if let attribute = attribute as? ReplyStoryAttribute { @@ -1216,10 +1215,16 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { forwardInfoSizeApply = makeForwardInfoLayout(item.context, item.presentationData, item.presentationData.strings, .standalone, forwardSource, forwardAuthorSignature, forwardPsaType, nil, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude)) } - if replyInfoApply != nil || viaBotApply != nil || forwardInfoSizeApply != nil { + var needsReplyBackground = false + if replyInfoApply != nil { needsReplyBackground = true } + var needsForwardBackground = false + if viaBotApply != nil || forwardInfoSizeApply != nil { + needsForwardBackground = true + } + var maxContentWidth = imageSize.width var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { @@ -1272,6 +1277,53 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { layoutSize.height += 4.0 + reactionButtonsSizeAndApply.0.height } + var headersOffset: CGFloat = 0.0 + if let (threadInfoSize, _) = threadInfoApply { + headersOffset += threadInfoSize.height + 10.0 + } + + var viaBotFrame: CGRect? + if let (viaBotLayout, _) = viaBotApply { + viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 15.0) : (params.width - params.rightInset - viaBotLayout.size.width - layoutConstants.bubble.edgeInset - 14.0)), y: headersOffset + 8.0), size: viaBotLayout.size) + } + + var replyInfoFrame: CGRect? + if let (replyInfoSize, _) = replyInfoApply { + var viaBotSize = CGSize() + if let viaBotFrame = viaBotFrame { + viaBotSize = viaBotFrame.size + } + let replyInfoFrameValue = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - max(replyInfoSize.width, viaBotSize.width) - layoutConstants.bubble.edgeInset - 10.0)), y: headersOffset + 8.0 + viaBotSize.height), size: replyInfoSize) + replyInfoFrame = replyInfoFrameValue + if let viaBotFrameValue = viaBotFrame { + if replyInfoFrameValue.minX < replyInfoFrameValue.minX { + viaBotFrame = viaBotFrameValue.offsetBy(dx: replyInfoFrameValue.minX - viaBotFrameValue.minX, dy: 0.0) + } + } + } + + var replyBackgroundFrame: CGRect? + if let replyInfoFrame = replyInfoFrame { + var viaBotSize = CGSize() + if let viaBotFrame = viaBotFrame { + viaBotSize = viaBotFrame.size + } + + replyBackgroundFrame = CGRect(origin: CGPoint(x: replyInfoFrame.minX - 4.0, y: headersOffset + replyInfoFrame.minY - viaBotSize.height - 2.0), size: CGSize(width: max(replyInfoFrame.size.width, viaBotSize.width) + 8.0, height: replyInfoFrame.size.height + viaBotSize.height + 5.0)) + } + let _ = replyBackgroundFrame + + /*if let replyBackgroundFrameValue = replyBackgroundFrame { + if replyBackgroundFrameValue.insetBy(dx: -2.0, dy: -2.0).intersects(baseShareButtonFrame) { + let offset: CGFloat = 25.0 + + layoutSize.height += offset + updatedImageFrame.origin.y += offset + dateAndStatusFrame.origin.y += offset + baseShareButtonFrame.origin.y += offset + } + }*/ + func finishLayout(_ animation: ListViewItemUpdateAnimation, _ apply: ListViewItemApply, _ synchronousLoads: Bool) { if let strongSelf = weakSelf.value { strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature) @@ -1391,34 +1443,31 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { dateAndStatusApply(animation) if needsReplyBackground { - if let replyBackgroundNode = strongSelf.replyBackgroundNode { - replyBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate) - } else { - let replyBackgroundNode = NavigationBackgroundNode(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)) - strongSelf.replyBackgroundNode = replyBackgroundNode - strongSelf.contextSourceNode.contentNode.addSubnode(replyBackgroundNode) + if strongSelf.replyBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + backgroundContent.clipsToBounds = true + strongSelf.replyBackgroundContent = backgroundContent + strongSelf.contextSourceNode.contentNode.insertSubnode(backgroundContent, at: 0) } - - if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true { - if strongSelf.replyBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { - backgroundContent.clipsToBounds = true - strongSelf.replyBackgroundContent = backgroundContent - strongSelf.insertSubnode(backgroundContent, at: 0) - } - } else { - strongSelf.replyBackgroundContent?.removeFromSupernode() - strongSelf.replyBackgroundContent = nil - } - } else if let replyBackgroundNode = strongSelf.replyBackgroundNode { - strongSelf.replyBackgroundNode = nil - replyBackgroundNode.removeFromSupernode() - + } else { if let replyBackgroundContent = strongSelf.replyBackgroundContent { replyBackgroundContent.removeFromSupernode() strongSelf.replyBackgroundContent = nil } } + if needsForwardBackground { + if strongSelf.forwardBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + backgroundContent.clipsToBounds = true + strongSelf.forwardBackgroundContent = backgroundContent + strongSelf.contextSourceNode.contentNode.insertSubnode(backgroundContent, at: 0) + } + } else { + if let forwardBackgroundContent = strongSelf.forwardBackgroundContent { + forwardBackgroundContent.removeFromSupernode() + strongSelf.forwardBackgroundContent = nil + } + } + var headersOffset: CGFloat = 0.0 if let (threadInfoSize, threadInfoApply) = threadInfoApply { let threadInfoNode = threadInfoApply(synchronousLoads) @@ -1446,16 +1495,24 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { messageInfoSize = CGSize(width: max(messageInfoSize.width, replyInfoSize.width), height: 0.0) } + var forwardAreaFrame: CGRect? if let (viaBotLayout, viaBotApply) = viaBotApply, forwardInfoSizeApply == nil { let viaBotNode = viaBotApply() if strongSelf.viaBotNode == nil { strongSelf.viaBotNode = viaBotNode strongSelf.contextSourceNode.contentNode.addSubnode(viaBotNode) } - let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0), size: viaBotLayout.size) + let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0 - 5.0)), y: headersOffset + 8.0), size: viaBotLayout.size) + viaBotNode.frame = viaBotFrame messageInfoSize = CGSize(width: messageInfoSize.width, height: viaBotLayout.size.height) + + if let forwardAreaFrameValue = forwardAreaFrame { + forwardAreaFrame = forwardAreaFrameValue.union(viaBotFrame) + } else { + forwardAreaFrame = viaBotFrame + } } else if let viaBotNode = strongSelf.viaBotNode { viaBotNode.removeFromSupernode() strongSelf.viaBotNode = nil @@ -1471,10 +1528,16 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { forwardInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } } - let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize) + let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0 - 5.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize) forwardInfoNode.frame = forwardInfoFrame - messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height - 1.0) + messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height + 8.0) + + if let forwardAreaFrameValue = forwardAreaFrame { + forwardAreaFrame = forwardAreaFrameValue.union(forwardInfoFrame) + } else { + forwardAreaFrame = forwardInfoFrame + } } else if let forwardInfoNode = strongSelf.forwardInfoNode { if animation.isAnimated { if let forwardInfoNode = strongSelf.forwardInfoNode { @@ -1489,9 +1552,18 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } + var forwardBackgroundFrame: CGRect? + if let forwardAreaFrame { + forwardBackgroundFrame = forwardAreaFrame.insetBy(dx: -6.0, dy: -3.0) + } + var replyBackgroundFrame: CGRect? if let (replyInfoSize, replyInfoApply) = replyInfoApply { - let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize) + if headersOffset != 0.0 { + headersOffset += 6.0 + } + + let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - replyInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize) replyBackgroundFrame = replyInfoFrame let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation) @@ -1507,24 +1579,25 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode = nil } - if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame { - replyBackgroundNode.frame = replyBackgroundFrame - - let cornerRadius = 4.0 - replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate) - - if let backgroundContent = strongSelf.replyBackgroundContent { - replyBackgroundNode.isHidden = true - backgroundContent.cornerRadius = cornerRadius - backgroundContent.frame = replyBackgroundNode.frame - if let (rect, containerSize) = strongSelf.absoluteRect { - var backgroundFrame = backgroundContent.frame - backgroundFrame.origin.x += rect.minX - backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) - } - } else { - replyBackgroundNode.isHidden = false + if let backgroundContent = strongSelf.replyBackgroundContent, let replyBackgroundFrame { + backgroundContent.cornerRadius = 4.0 + backgroundContent.frame = replyBackgroundFrame + if let (rect, containerSize) = strongSelf.absoluteRect { + var backgroundFrame = backgroundContent.frame + backgroundFrame.origin.x += rect.minX + backgroundFrame.origin.y += rect.minY + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) + } + } + + if let backgroundContent = strongSelf.forwardBackgroundContent, let forwardBackgroundFrame { + backgroundContent.cornerRadius = 4.0 + backgroundContent.frame = forwardBackgroundFrame + if let (rect, containerSize) = strongSelf.absoluteRect { + var backgroundFrame = backgroundContent.frame + backgroundFrame.origin.x += rect.minX + backgroundFrame.origin.y += rect.minY + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } @@ -1533,7 +1606,8 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode?.alpha = panelsAlpha strongSelf.viaBotNode?.alpha = panelsAlpha strongSelf.forwardInfoNode?.alpha = panelsAlpha - strongSelf.replyBackgroundNode?.alpha = panelsAlpha + strongSelf.replyBackgroundContent?.alpha = panelsAlpha + strongSelf.forwardBackgroundContent?.alpha = panelsAlpha if isFailed { let deliveryFailedNode: ChatMessageDeliveryFailedNode @@ -1969,7 +2043,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { for attribute in item.message.attributes { if let attribute = attribute as? ReplyMessageAttribute { return .optionalAction({ - item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text)) + item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil)) }) } else if let attribute = attribute as? ReplyStoryAttribute { return .optionalAction({ @@ -2445,8 +2519,11 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let forwardInfoNode = self.forwardInfoNode { transition.updateAlpha(node: forwardInfoNode, alpha: panelsAlpha) } - if let replyBackgroundNode = self.replyBackgroundNode { - transition.updateAlpha(node: replyBackgroundNode, alpha: panelsAlpha) + if let replyBackgroundContent = self.replyBackgroundContent { + transition.updateAlpha(node: replyBackgroundContent, alpha: panelsAlpha) + } + if let forwardBackgroundContent = self.forwardBackgroundContent { + transition.updateAlpha(node: forwardBackgroundContent, alpha: panelsAlpha) } if let selectionState = item.controllerInteraction.selectionState { @@ -2814,9 +2891,13 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { relativeTargetRect: sourceReplyPanel.relativeTargetRect ) let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: mappedPanel, localRect: localRect, transition: transition) - if let replyBackgroundNode = self.replyBackgroundNode { - transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset) - replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + if let replyBackgroundContent = self.replyBackgroundContent { + transition.animatePositionAdditive(layer: replyBackgroundContent.layer, offset: offset) + replyBackgroundContent.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + if let forwardBackgroundContent = self.forwardBackgroundContent { + transition.animatePositionAdditive(layer: forwardBackgroundContent.layer, offset: offset) + forwardBackgroundContent.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift index d3c49d26c7..67455efa73 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift @@ -869,13 +869,13 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { if let current = self.backgroundView { backgroundView = current animation.animator.updateFrame(layer: backgroundView.layer, frame: backgroundFrame, completion: nil) - backgroundView.update(size: backgroundFrame.size, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: animation) + backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: animation) } else { backgroundView = MessageInlineBlockBackgroundView() self.backgroundView = backgroundView backgroundView.frame = backgroundFrame self.transformContainer.view.insertSubview(backgroundView, at: 0) - backgroundView.update(size: backgroundFrame.size, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: .None) + backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: .None) } } else { if let backgroundView = self.backgroundView { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index e93526f73e..8179f13be0 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -1615,7 +1615,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI var inlineBotNameString: String? var replyMessage: Message? var replyForward: QuotedReplyMessageAttribute? - var replyQuote: EngineMessageReplyQuote? + var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyStory: StoryId? var replyMarkup: ReplyMarkupMessageAttribute? var authorNameColor: UIColor? @@ -1632,7 +1632,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI } else { replyMessage = firstMessage.associatedMessages[attribute.messageId] } - replyQuote = attribute.quote + replyQuote = attribute.quote.flatMap { ($0, attribute.isQuote) } } else if let attribute = attribute as? QuotedReplyMessageAttribute { replyForward = attribute } else if let attribute = attribute as? ReplyStoryAttribute { @@ -4047,7 +4047,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI if let replyInfoNode = self.replyInfoNode { progress = replyInfoNode.makeProgress() } - item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text, progress: progress)) + item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil, progress: progress)) }, contextMenuOnLongPress: true)) } else if let attribute = attribute as? ReplyStoryAttribute { return .action(InternalBubbleTapAction.Action({ diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift index ec0267c3b3..92dc14d03c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift @@ -456,7 +456,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco var replyMessage: Message? var replyForward: QuotedReplyMessageAttribute? - var replyQuote: EngineMessageReplyQuote? + var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyStory: StoryId? for attribute in item.message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { @@ -499,7 +499,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco } else { replyMessage = item.message.associatedMessages[replyAttribute.messageId] } - replyQuote = replyAttribute.quote + replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) } } else if let attribute = attribute as? QuotedReplyMessageAttribute { replyForward = attribute } else if let attribute = attribute as? ReplyStoryAttribute { @@ -963,7 +963,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco for attribute in item.message.attributes { if let attribute = attribute as? ReplyMessageAttribute { return .optionalAction({ - item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text)) + item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil)) }) } else if let attribute = attribute as? QuotedReplyMessageAttribute { return .action(InternalBubbleTapAction.Action { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveInstantVideoNode/Sources/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveInstantVideoNode/Sources/ChatMessageInteractiveInstantVideoNode.swift index 7215cdba22..d8dfd8c06a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveInstantVideoNode/Sources/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveInstantVideoNode/Sources/ChatMessageInteractiveInstantVideoNode.swift @@ -331,7 +331,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { if !ignoreHeaders { var replyMessage: Message? var replyForward: QuotedReplyMessageAttribute? - var replyQuote: EngineMessageReplyQuote? + var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyStory: StoryId? for attribute in item.message.attributes { @@ -361,7 +361,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } else { replyMessage = item.message.associatedMessages[replyAttribute.messageId] } - replyQuote = replyAttribute.quote + replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) } } else if let attribute = attribute as? QuotedReplyMessageAttribute { replyForward = attribute } else if let attribute = attribute as? ReplyStoryAttribute { @@ -1291,7 +1291,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { if let item = self.item { for attribute in item.message.attributes { if let attribute = attribute as? ReplyMessageAttribute { - item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text)) + item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil)) return } else if let attribute = attribute as? ReplyStoryAttribute { item.controllerInteraction.navigateToStory(item.message, attribute.storyId) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift index 1645b42d4d..64d8b54e47 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift @@ -80,7 +80,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { public let type: ChatMessageReplyInfoType public let message: Message? public let replyForward: QuotedReplyMessageAttribute? - public let quote: EngineMessageReplyQuote? + public let quote: (quote: EngineMessageReplyQuote, isQuote: Bool)? public let story: StoryId? public let parentMessage: Message public let constrainedSize: CGSize @@ -95,7 +95,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { type: ChatMessageReplyInfoType, message: Message?, replyForward: QuotedReplyMessageAttribute?, - quote: EngineMessageReplyQuote?, + quote: (quote: EngineMessageReplyQuote, isQuote: Bool)?, story: StoryId?, parentMessage: Message, constrainedSize: CGSize, @@ -410,7 +410,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { var text: String var messageEntities: [MessageTextEntity] - if let quote = arguments.quote, !quote.text.isEmpty { + if let quote = arguments.quote?.quote, !quote.text.isEmpty { text = quote.text messageEntities = quote.entities } else { @@ -547,7 +547,15 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { var adjustedConstrainedTextSize = contrainedTextSize var textCutout: TextNodeCutout? var textCutoutWidth: CGFloat = 0.0 - if arguments.quote != nil || arguments.replyForward?.quote != nil { + + var isQuote = false + if let quote = arguments.quote, quote.isQuote { + isQuote = true + } else if let replyForward = arguments.replyForward, replyForward.quote != nil, replyForward.isQuote { + isQuote = true + } + + if isQuote { additionalTitleWidth += 10.0 maxTitleNumberOfLines = 2 maxTextNumberOfLines = 5 @@ -761,8 +769,13 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { )] as? TelegramMediaFile ) } + var isTransparent: Bool = false + if case .standalone = arguments.type { + isTransparent = true + } node.backgroundView.update( size: backgroundFrame.size, + isTransparent: isTransparent, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, @@ -770,7 +783,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { animation: animation ) - if arguments.quote != nil || arguments.replyForward?.quote != nil { + if isQuote { let quoteIconView: UIImageView if let current = node.quoteIconView { quoteIconView = current diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift index 168cd19a7f..9e077fedce 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift @@ -56,8 +56,8 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { private var threadInfoNode: ChatMessageThreadInfoNode? private var replyInfoNode: ChatMessageReplyInfoNode? private var replyBackgroundContent: WallpaperBubbleBackgroundNode? - private var replyBackgroundNode: NavigationBackgroundNode? private var forwardInfoNode: ChatMessageForwardInfoNode? + private var forwardBackgroundContent: WallpaperBubbleBackgroundNode? private var actionButtonsNode: ChatMessageActionButtonsNode? private var reactionButtonsNode: ChatMessageReactionButtonsNode? @@ -350,6 +350,14 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { replyBackgroundContent.update(rect: rect, within: containerSize, transition: .immediate) } + + if let forwardBackgroundContent = self.forwardBackgroundContent { + var forwardBackgroundContentFrame = forwardBackgroundContent.frame + forwardBackgroundContentFrame.origin.x += rect.minX + forwardBackgroundContentFrame.origin.y += rect.minY + + forwardBackgroundContent.update(rect: rect, within: containerSize, transition: .immediate) + } } } @@ -651,7 +659,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { var replyMessage: Message? var replyForward: QuotedReplyMessageAttribute? - var replyQuote: EngineMessageReplyQuote? + var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyStory: StoryId? for attribute in item.message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { @@ -679,7 +687,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } else { replyMessage = item.message.associatedMessages[replyAttribute.messageId] } - replyQuote = replyAttribute.quote + replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) } } else if let attribute = attribute as? QuotedReplyMessageAttribute { replyForward = attribute } else if let attribute = attribute as? ReplyStoryAttribute { @@ -784,10 +792,15 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } var needsReplyBackground = false - if replyInfoApply != nil || viaBotApply != nil || forwardInfoSizeApply != nil { + if replyInfoApply != nil { needsReplyBackground = true } + var needsForwardBackground = false + if viaBotApply != nil || forwardInfoSizeApply != nil { + needsForwardBackground = true + } + var maxContentWidth = imageSize.width var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { @@ -971,34 +984,31 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } if needsReplyBackground { - if let replyBackgroundNode = strongSelf.replyBackgroundNode { - replyBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate) - } else { - let replyBackgroundNode = NavigationBackgroundNode(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)) - strongSelf.replyBackgroundNode = replyBackgroundNode - strongSelf.contextSourceNode.contentNode.addSubnode(replyBackgroundNode) + if strongSelf.replyBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + backgroundContent.clipsToBounds = true + strongSelf.replyBackgroundContent = backgroundContent + strongSelf.contextSourceNode.contentNode.insertSubnode(backgroundContent, at: 0) } - - if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true { - if strongSelf.replyBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { - backgroundContent.clipsToBounds = true - strongSelf.replyBackgroundContent = backgroundContent - strongSelf.insertSubnode(backgroundContent, at: 0) - } - } else { - strongSelf.replyBackgroundContent?.removeFromSupernode() - strongSelf.replyBackgroundContent = nil - } - } else if let replyBackgroundNode = strongSelf.replyBackgroundNode { - replyBackgroundNode.removeFromSupernode() - strongSelf.replyBackgroundNode = nil - + } else { if let replyBackgroundContent = strongSelf.replyBackgroundContent { replyBackgroundContent.removeFromSupernode() strongSelf.replyBackgroundContent = nil } } + if needsForwardBackground { + if strongSelf.forwardBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + backgroundContent.clipsToBounds = true + strongSelf.forwardBackgroundContent = backgroundContent + strongSelf.contextSourceNode.contentNode.insertSubnode(backgroundContent, at: 0) + } + } else { + if let forwardBackgroundContent = strongSelf.forwardBackgroundContent { + forwardBackgroundContent.removeFromSupernode() + strongSelf.forwardBackgroundContent = nil + } + } + var headersOffset: CGFloat = 0.0 if let (threadInfoSize, threadInfoApply) = threadInfoApply { let threadInfoNode = threadInfoApply(synchronousLoads) @@ -1026,16 +1036,24 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { messageInfoSize = CGSize(width: max(messageInfoSize.width, replyInfoSize.width), height: 0.0) } + var forwardAreaFrame: CGRect? if let (viaBotLayout, viaBotApply) = viaBotApply, forwardInfoSizeApply == nil { let viaBotNode = viaBotApply() if strongSelf.viaBotNode == nil { strongSelf.viaBotNode = viaBotNode strongSelf.contextSourceNode.contentNode.addSubnode(viaBotNode) } - let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0), size: viaBotLayout.size) + let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0 - 5.0)), y: headersOffset + 8.0), size: viaBotLayout.size) + viaBotNode.frame = viaBotFrame messageInfoSize = CGSize(width: messageInfoSize.width, height: viaBotLayout.size.height) + + if let forwardAreaFrameValue = forwardAreaFrame { + forwardAreaFrame = forwardAreaFrameValue.union(viaBotFrame) + } else { + forwardAreaFrame = viaBotFrame + } } else if let viaBotNode = strongSelf.viaBotNode { viaBotNode.removeFromSupernode() strongSelf.viaBotNode = nil @@ -1051,10 +1069,16 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { forwardInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } } - let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize) + let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0 - 5.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize) forwardInfoNode.frame = forwardInfoFrame - messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height - 1.0) + messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height + 8.0) + + if let forwardAreaFrameValue = forwardAreaFrame { + forwardAreaFrame = forwardAreaFrameValue.union(forwardInfoFrame) + } else { + forwardAreaFrame = forwardInfoFrame + } } else if let forwardInfoNode = strongSelf.forwardInfoNode { if animation.isAnimated { if let forwardInfoNode = strongSelf.forwardInfoNode { @@ -1069,9 +1093,18 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } } + var forwardBackgroundFrame: CGRect? + if let forwardAreaFrame { + forwardBackgroundFrame = forwardAreaFrame.insetBy(dx: -6.0, dy: -3.0) + } + var replyBackgroundFrame: CGRect? if let (replyInfoSize, replyInfoApply) = replyInfoApply { - let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize) + if headersOffset != 0.0 { + headersOffset += 6.0 + } + + let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - replyInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize) replyBackgroundFrame = replyInfoFrame let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation) @@ -1087,24 +1120,25 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode = nil } - if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame { - replyBackgroundNode.frame = replyBackgroundFrame - - let cornerRadius = 4.0 - replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate) - - if let backgroundContent = strongSelf.replyBackgroundContent { - replyBackgroundNode.isHidden = true - backgroundContent.cornerRadius = cornerRadius - backgroundContent.frame = replyBackgroundNode.frame - if let (rect, containerSize) = strongSelf.absoluteRect { - var backgroundFrame = backgroundContent.frame - backgroundFrame.origin.x += rect.minX - backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) - } - } else { - replyBackgroundNode.isHidden = false + if let backgroundContent = strongSelf.replyBackgroundContent, let replyBackgroundFrame { + backgroundContent.cornerRadius = 4.0 + backgroundContent.frame = replyBackgroundFrame + if let (rect, containerSize) = strongSelf.absoluteRect { + var backgroundFrame = backgroundContent.frame + backgroundFrame.origin.x += rect.minX + backgroundFrame.origin.y += rect.minY + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) + } + } + + if let backgroundContent = strongSelf.forwardBackgroundContent, let forwardBackgroundFrame { + backgroundContent.cornerRadius = 4.0 + backgroundContent.frame = forwardBackgroundFrame + if let (rect, containerSize) = strongSelf.absoluteRect { + var backgroundFrame = backgroundContent.frame + backgroundFrame.origin.x += rect.minX + backgroundFrame.origin.y += rect.minY + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } @@ -1113,7 +1147,8 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode?.alpha = panelsAlpha strongSelf.viaBotNode?.alpha = panelsAlpha strongSelf.forwardInfoNode?.alpha = panelsAlpha - strongSelf.replyBackgroundNode?.alpha = panelsAlpha + strongSelf.replyBackgroundContent?.alpha = panelsAlpha + strongSelf.forwardBackgroundContent?.alpha = panelsAlpha if isFailed { let deliveryFailedNode: ChatMessageDeliveryFailedNode @@ -1336,7 +1371,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { for attribute in item.message.attributes { if let attribute = attribute as? ReplyMessageAttribute { return .optionalAction({ - item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text)) + item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil)) }) } else if let attribute = attribute as? ReplyStoryAttribute { return .optionalAction({ @@ -1591,8 +1626,11 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { if let forwardInfoNode = self.forwardInfoNode { transition.updateAlpha(node: forwardInfoNode, alpha: panelsAlpha) } - if let replyBackgroundNode = self.replyBackgroundNode { - transition.updateAlpha(node: replyBackgroundNode, alpha: panelsAlpha) + if let replyBackgroundContent = self.replyBackgroundContent { + transition.updateAlpha(node: replyBackgroundContent, alpha: panelsAlpha) + } + if let forwardBackgroundContent = self.forwardBackgroundContent { + transition.updateAlpha(node: forwardBackgroundContent, alpha: panelsAlpha) } if let selectionState = item.controllerInteraction.selectionState { @@ -1635,10 +1673,10 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { let alpha: CGFloat = 0.0 let previousAlpha = replyInfoNode.alpha replyInfoNode.alpha = alpha - self.replyBackgroundNode?.alpha = alpha + self.replyBackgroundContent?.alpha = alpha if animated { replyInfoNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) - self.replyBackgroundNode?.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) + self.replyBackgroundContent?.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) } } } else { @@ -1664,10 +1702,10 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { let alpha: CGFloat = 1.0 let previousAlpha = replyInfoNode.alpha replyInfoNode.alpha = alpha - self.replyBackgroundNode?.alpha = alpha + self.replyBackgroundContent?.alpha = alpha if animated { replyInfoNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) - self.replyBackgroundNode?.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) + self.replyBackgroundContent?.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.3) } } } @@ -1957,9 +1995,13 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { ) let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: mappedPanel, localRect: localRect, transition: transition) - if let replyBackgroundNode = self.replyBackgroundNode { - transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset) - replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + if let replyBackgroundContent = self.replyBackgroundContent { + transition.animatePositionAdditive(layer: replyBackgroundContent.layer, offset: offset) + replyBackgroundContent.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + if let forwardBackgroundContent = self.forwardBackgroundContent { + transition.animatePositionAdditive(layer: forwardBackgroundContent.layer, offset: offset) + forwardBackgroundContent.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) } } } diff --git a/submodules/TelegramUI/Components/Chat/MessageInlineBlockBackgroundView/Sources/MessageInlineBlockBackgroundView.swift b/submodules/TelegramUI/Components/Chat/MessageInlineBlockBackgroundView/Sources/MessageInlineBlockBackgroundView.swift index 0f91d1ceb5..8b0ed49bf0 100644 --- a/submodules/TelegramUI/Components/Chat/MessageInlineBlockBackgroundView/Sources/MessageInlineBlockBackgroundView.swift +++ b/submodules/TelegramUI/Components/Chat/MessageInlineBlockBackgroundView/Sources/MessageInlineBlockBackgroundView.swift @@ -28,7 +28,7 @@ private func addRoundedRectPath(context: CGContext, rect: CGRect, radius: CGFloa context.restoreGState() } -private func generateBackgroundTemplateImage(addStripe: Bool) -> UIImage { +private func generateBackgroundTemplateImage(addStripe: Bool, isTransparent: Bool) -> UIImage { return generateImage(CGSize(width: radius * 2.0 + 4.0, height: radius * 2.0 + 8.0), rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) @@ -36,7 +36,9 @@ private func generateBackgroundTemplateImage(addStripe: Bool) -> UIImage { context.clip() context.setFillColor(UIColor.white.withMultipliedAlpha(0.1).cgColor) - context.fill(CGRect(origin: CGPoint(), size: size)) + if !isTransparent { + context.fill(CGRect(origin: CGPoint(), size: size)) + } if addStripe { context.setFillColor(UIColor.white.withMultipliedAlpha(0.2).cgColor) @@ -69,11 +71,19 @@ private func generateProgressTemplateImage() -> UIImage { } private let backgroundSolidTemplateImage: UIImage = { - return generateBackgroundTemplateImage(addStripe: true) + return generateBackgroundTemplateImage(addStripe: true, isTransparent: false) }() private let backgroundDashTemplateImage: UIImage = { - return generateBackgroundTemplateImage(addStripe: false) + return generateBackgroundTemplateImage(addStripe: false, isTransparent: false) +}() + +private let transparentBackgroundSolidTemplateImage: UIImage = { + return generateBackgroundTemplateImage(addStripe: true, isTransparent: true) +}() + +private let transparentBackgroundDashTemplateImage: UIImage = { + return generateBackgroundTemplateImage(addStripe: false, isTransparent: true) }() private func generateDashBackgroundTemplateImage() -> UIImage { @@ -436,6 +446,7 @@ public final class MessageInlineBlockBackgroundView: UIView { private struct Params: Equatable { var size: CGSize + var isTransparent: Bool var primaryColor: UIColor var secondaryColor: UIColor? var thirdColor: UIColor? @@ -444,6 +455,7 @@ public final class MessageInlineBlockBackgroundView: UIView { init( size: CGSize, + isTransparent: Bool, primaryColor: UIColor, secondaryColor: UIColor?, thirdColor: UIColor?, @@ -451,6 +463,7 @@ public final class MessageInlineBlockBackgroundView: UIView { displayProgress: Bool ) { self.size = size + self.isTransparent = isTransparent self.primaryColor = primaryColor self.secondaryColor = secondaryColor self.thirdColor = thirdColor @@ -467,6 +480,7 @@ public final class MessageInlineBlockBackgroundView: UIView { if let params = self.params { self.update( size: params.size, + isTransparent: params.isTransparent, primaryColor: params.primaryColor, secondaryColor: params.secondaryColor, thirdColor: params.thirdColor, @@ -577,6 +591,7 @@ public final class MessageInlineBlockBackgroundView: UIView { public func update( size: CGSize, + isTransparent: Bool, primaryColor: UIColor, secondaryColor: UIColor?, thirdColor: UIColor?, @@ -585,6 +600,7 @@ public final class MessageInlineBlockBackgroundView: UIView { ) { let params = Params( size: size, + isTransparent: isTransparent, primaryColor: primaryColor, secondaryColor: secondaryColor, thirdColor: thirdColor, @@ -602,10 +618,18 @@ public final class MessageInlineBlockBackgroundView: UIView { patternContentLayer.layerTintColor = primaryColor.cgColor } - if params.secondaryColor != nil { - self.backgroundView.image = backgroundDashTemplateImage + if params.isTransparent { + if params.secondaryColor != nil { + self.backgroundView.image = transparentBackgroundDashTemplateImage + } else { + self.backgroundView.image = transparentBackgroundSolidTemplateImage + } } else { - self.backgroundView.image = backgroundSolidTemplateImage + if params.secondaryColor != nil { + self.backgroundView.image = backgroundDashTemplateImage + } else { + self.backgroundView.image = backgroundSolidTemplateImage + } } self.backgroundView.tintColor = params.primaryColor } @@ -711,7 +735,7 @@ public final class MessageInlineBlockBackgroundView: UIView { let itemSize = CGSize(width: placement.size / 3.0, height: placement.size / 3.0) patternContentLayer.frame = CGRect(origin: CGPoint(x: size.width - placement.position.x / 3.0 - itemSize.width * 0.5, y: placement.position.y / 3.0 - itemSize.height * 0.5), size: itemSize) - var alphaFraction = abs(placement.position.x) / 500.0 + var alphaFraction = abs(placement.position.x) / min(500.0, size.width) alphaFraction = min(1.0, max(0.0, alphaFraction)) patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction) diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift index 8cc1b6b1ff..a2fd9c8995 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift @@ -196,7 +196,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 98e76e0d18..1881b8a122 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -774,7 +774,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .pinnedMessageUpdated: for attribute in message.attributes { if let attribute = attribute as? ReplyMessageAttribute { - strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text))) + strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil))) break } } @@ -783,7 +783,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .gameScore: for attribute in message.attributes { if let attribute = attribute as? ReplyMessageAttribute { - strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text))) + strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote?.text : nil))) break } } @@ -17034,7 +17034,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil) })) + var quote: String? + if case let .id(_, params) = messageLocation { + quote = params.quote + } + + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: ChatControllerSubject.MessageHighlight(quote: quote), timecode: nil) })) } }) completion?() diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index dff4f1438f..70225da376 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -566,7 +566,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { mappedQuote = EngineMessageReplyQuote(text: quote, entities: [], media: nil) } - attributes.append(ReplyMessageAttribute(messageId: replyMessage.id, threadMessageId: nil, quote: mappedQuote)) + attributes.append(ReplyMessageAttribute(messageId: replyMessage.id, threadMessageId: nil, quote: mappedQuote, isQuote: mappedQuote != nil)) } let message = Message( diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 2ce05e2c0d..7daebc0a99 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -2849,8 +2849,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch var hasTracking = false var hasTrackingView = false - if textInputNode.selectedRange.length == 0 && textInputNode.selectedRange.location > 0 { - let selectedSubstring = textInputNode.textView.attributedText.attributedSubstring(from: NSRange(location: 0, length: textInputNode.selectedRange.location)) + if textInputNode.selectedRange.length == 0, textInputNode.selectedRange.location > 0, let attributedText = textInputNode.textView.attributedText { + let selectedSubstring = attributedText.attributedSubstring(from: NSRange(location: 0, length: textInputNode.selectedRange.location)) if let lastCharacter = selectedSubstring.string.last, String(lastCharacter).isSingleEmoji { let queryLength = (String(lastCharacter) as NSString).length if selectedSubstring.attribute(ChatTextInputAttributes.customEmoji, at: selectedSubstring.length - queryLength, effectiveRange: nil) == nil {