From 0d93bf0b71f08ec2eb2f354bb8348bf7156affd5 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Sat, 27 Jul 2019 20:07:08 +0100 Subject: [PATCH] Proof of concept --- .../Display/Display/GenerateImage.swift | 2 +- submodules/Display/Display/ListView.swift | 47 ++++++-------- .../Display/Display/ListViewItemNode.swift | 8 +++ .../ChatControllerBackgroundNode.swift | 2 + .../ChatMessageBubbleBackdrop.swift | 56 +++++++++++++++++ .../TelegramUI/ChatMessageBubbleImages.swift | 61 +++++++++++++------ .../ChatMessageBubbleItemNode.swift | 35 +++++++---- .../PresentationThemeEssentialGraphics.swift | 48 +++++++-------- .../project.pbxproj | 4 ++ 9 files changed, 182 insertions(+), 81 deletions(-) create mode 100644 submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift diff --git a/submodules/Display/Display/GenerateImage.swift b/submodules/Display/Display/GenerateImage.swift index ae6baba564..99eb870956 100644 --- a/submodules/Display/Display/GenerateImage.swift +++ b/submodules/Display/Display/GenerateImage.swift @@ -1,7 +1,7 @@ import Foundation import UIKit -private let deviceColorSpace: CGColorSpace = { +public let deviceColorSpace: CGColorSpace = { if #available(iOSApplicationExtension 9.3, *) { if let colorSpace = CGColorSpace(name: CGColorSpace.displayP3) { return colorSpace diff --git a/submodules/Display/Display/ListView.swift b/submodules/Display/Display/ListView.swift index 3fa834e803..d94cd83817 100644 --- a/submodules/Display/Display/ListView.swift +++ b/submodules/Display/Display/ListView.swift @@ -677,8 +677,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } for itemNode in self.itemNodes { - let position = itemNode.position - itemNode.position = CGPoint(x: position.x, y: position.y - deltaY) + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: -deltaY), within: self.visibleSize) if self.dynamicBounceEnabled && itemNode.wantsScrollDynamics { useScrollDynamics = true @@ -908,7 +907,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for itemNode in self.itemNodes { var frame = itemNode.frame frame.origin.y += offset - itemNode.frame = frame + itemNode.updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = itemNode.accessoryItemNode { itemNode.layoutAccessoryItemNode(accessoryItemNode, leftInset: self.insets.left, rightInset: self.insets.right) } @@ -1890,7 +1889,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture node.contentSize = layout.contentSize node.insets = layout.insets node.apparentHeight = animated ? 0.0 : layout.size.height - node.frame = nodeFrame + node.updateFrame(nodeFrame, within: self.visibleSize) if let accessoryItemNode = node.accessoryItemNode { node.layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -1905,14 +1904,13 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture if nextNode.index == nil && nextNode.subnodes == nil || nextNode.subnodes!.isEmpty { let nextHeight = nextNode.apparentHeight if abs(nextHeight - previousApparentHeight) < CGFloat.ulpOfOne { - if let animation = nextNode.animationForKey("apparentHeight") { + if let _ = nextNode.animationForKey("apparentHeight") { node.apparentHeight = previousApparentHeight offsetHeight = 0.0 - var offsetPosition = nextNode.position - offsetPosition.y += nextHeight - nextNode.position = offsetPosition + nextNode.updateFrame(nextNode.frame.offsetBy(dx: 0.0, dy: nextHeight), within: self.visibleSize) + nextNode.apparentHeight = 0.0 nextNode.removeApparentHeightAnimation() @@ -2015,7 +2013,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture while i >= 0 { var frame = self.itemNodes[i].frame frame.origin.y -= offsetHeight - self.itemNodes[i].frame = frame + self.itemNodes[i].updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = self.itemNodes[i].accessoryItemNode { self.itemNodes[i].layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2026,7 +2024,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture while i < self.itemNodes.count { var frame = self.itemNodes[i].frame frame.origin.y += offsetHeight - self.itemNodes[i].frame = frame + self.itemNodes[i].updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = self.itemNodes[i].accessoryItemNode { self.itemNodes[i].layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2253,7 +2251,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for i in index + 1 ..< self.itemNodes.count { var frame = self.itemNodes[i].frame frame.origin.y -= height - self.itemNodes[i].frame = frame + self.itemNodes[i].updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = self.itemNodes[i].accessoryItemNode { self.itemNodes[i].layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2264,7 +2262,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for i in (0 ..< index).reversed() { var frame = self.itemNodes[i].frame frame.origin.y += height - self.itemNodes[i].frame = frame + self.itemNodes[i].updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = self.itemNodes[i].accessoryItemNode { self.itemNodes[i].layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2350,7 +2348,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture if offset != 0.0 { var frame = itemNode.frame frame.origin.y += offset - itemNode.frame = frame + itemNode.updateFrame(frame, within: self.visibleSize) } index += 1 @@ -2419,7 +2417,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for itemNode in self.itemNodes { var frame = itemNode.frame frame.origin.y += offset - itemNode.frame = frame + itemNode.updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = itemNode.accessoryItemNode { itemNode.layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2439,7 +2437,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for itemNode in self.itemNodes { var frame = itemNode.frame frame.origin.y += offset - itemNode.frame = frame + itemNode.updateFrame(frame, within: self.visibleSize) if let accessoryItemNode = itemNode.accessoryItemNode { itemNode.layoutAccessoryItemNode(accessoryItemNode, leftInset: listInsets.left, rightInset: listInsets.right) } @@ -2487,8 +2485,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture self.visibleSize = updateSizeAndInsets.size for itemNode in self.itemNodes { - let position = itemNode.position - itemNode.position = CGPoint(x: position.x, y: position.y + offsetFix) + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offsetFix), within: self.visibleSize) } let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets, isExperimentalSnapToScrollToItem: isExperimentalSnapToScrollToItem) @@ -2497,8 +2494,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture offsetFix += snappedTopInset for itemNode in self.itemNodes { - let position = itemNode.position - itemNode.position = CGPoint(x: position.x, y: position.y + snappedTopInset) + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize) } } @@ -2608,8 +2604,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture if !snappedTopInset.isZero && previousApparentFrames.isEmpty { for itemNode in self.itemNodes { - let position = itemNode.position - itemNode.position = CGPoint(x: position.x, y: position.y + snappedTopInset) + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: snappedTopInset), within: self.visibleSize) } } @@ -2653,7 +2648,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for (previousNode, previousFrame) in previousApparentFrames { if previousNode.supernode == nil { temporaryPreviousNodes.append(previousNode) - previousNode.frame = previousFrame + previousNode.updateFrame(previousFrame, within: self.visibleSize) if previousUpperBound == nil || previousUpperBound! > previousFrame.minY { previousUpperBound = previousFrame.minY } @@ -2671,7 +2666,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for (previousNode, previousFrame) in previousApparentFrames { if previousNode.supernode == nil { temporaryPreviousNodes.append(previousNode) - previousNode.frame = previousFrame + previousNode.updateFrame(previousFrame, within: self.visibleSize) if previousUpperBound == nil || previousUpperBound! > previousFrame.minY { previousUpperBound = previousFrame.minY } @@ -2719,7 +2714,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture if let offset = offset, !offset.isZero { let lowestNodeToInsertBelow = self.lowestNodeToInsertBelow() for itemNode in temporaryPreviousNodes { - itemNode.frame = itemNode.frame.offsetBy(dx: 0.0, dy: offset) + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offset), within: self.visibleSize) if let lowestNodeToInsertBelow = lowestNodeToInsertBelow { self.insertSubnode(itemNode, belowSubnode: lowestNodeToInsertBelow) } else if let verticalScrollIndicator = self.verticalScrollIndicator { @@ -3547,9 +3542,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture for itemNode in self.itemNodes { let offset = offsetRanges.offsetForIndex(index) if offset != 0.0 { - var position = itemNode.position - position.y += offset - itemNode.position = position + itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: offset), within: self.visibleSize) } index += 1 diff --git a/submodules/Display/Display/ListViewItemNode.swift b/submodules/Display/Display/ListViewItemNode.swift index 898047167a..c12a81168f 100644 --- a/submodules/Display/Display/ListViewItemNode.swift +++ b/submodules/Display/Display/ListViewItemNode.swift @@ -549,4 +549,12 @@ open class ListViewItemNode: ASDisplayNode { override open func accessibilityElementDidBecomeFocused() { (self.supernode as? ListView)?.ensureItemNodeVisible(self, animated: false, overflow: 22.0) } + + func updateFrame(_ frame: CGRect, within containerSize: CGSize) { + self.frame = frame + self.updateAbsoluteRect(frame, within: containerSize) + } + + open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + } } diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerBackgroundNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerBackgroundNode.swift index a177fafcac..aea76c3698 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerBackgroundNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerBackgroundNode.swift @@ -53,12 +53,14 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: Media var image: UIImage? let _ = mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in if data.complete { + print("background image: \(data.path)") image = UIImage(contentsOfFile: data.path)?.precomposed() } }) backgroundImage = image } if backgroundImage == nil, let path = mediaBox.completedResourcePath(file.file.resource) { + print("background image: \(path)") backgroundImage = UIImage(contentsOfFile: path)?.precomposed() } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift new file mode 100644 index 0000000000..69e07fe8d2 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift @@ -0,0 +1,56 @@ +import Foundation +import AsyncDisplayKit +import Display +import Postbox + +private let backgroundContentImage = generateImage(CGSize(width: 1.0, height: 1000.0), rotatedContext: { size, context in + var locations: [CGFloat] = [0.0, 1.0] + let colors = [UIColor(rgb: 0x018CFE).cgColor, UIColor(rgb: 0x0A51A1).cgColor] as NSArray + + let colorSpace = deviceColorSpace + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) +}) + +private let backgroundContentIncomingImage = generateImage(CGSize(width: 1.0, height: 1000.0), rotatedContext: { size, context in + var locations: [CGFloat] = [0.0, 1.0] + let colors = [UIColor(rgb: 0x39393C).cgColor, UIColor(rgb: 0x222224).cgColor] as NSArray + + let colorSpace = deviceColorSpace + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) +}) + +private let blurredImage = UIImage(contentsOfFile: "/Users/peter/Library/Developer/CoreSimulator/Devices/5D789082-637B-493D-8CD3-32E59577B64D/data/Containers/Shared/AppGroup/AA2C1D1D-BD42-4662-8003-A4DDC118839F/telegram-data/account-8200745692227124259/postbox/media/telegram-cloud-document-1-5033031402610753634")?.precomposed() + +final class ChatMessageBubbleBackdrop: ASDisplayNode { + private let backgroundContent: ASDisplayNode + + private var currentType: Bool? + + override init() { + self.backgroundContent = ASDisplayNode() + + super.init() + + self.clipsToBounds = true + + self.addSubnode(self.backgroundContent) + } + + func setType(incoming: Bool, theme: ChatPresentationThemeData, mediaBox: MediaBox) { + if self.currentType != incoming { + self.currentType = incoming + + //self.backgroundContent.contents = blurredImage?.cgImage + + self.backgroundContent.contents = incoming ? backgroundContentIncomingImage?.cgImage : backgroundContentImage?.cgImage + } + } + + func update(rect: CGRect, within containerSize: CGSize) { + self.backgroundContent.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize) + } +} diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleImages.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleImages.swift index dc128a9fba..2f04369ec2 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleImages.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleImages.swift @@ -1,6 +1,8 @@ import Foundation import UIKit import Display +import TelegramPresentationData +import TelegramCore enum MessageBubbleImageNeighbors { case none @@ -24,11 +26,19 @@ func messageSingleBubbleLikeImage(fillColor: UIColor, strokeColor: UIColor) -> U })!.stretchableImage(withLeftCapWidth: Int(diameter / 2.0), topCapHeight: Int(diameter / 2.0)) } -func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors) -> UIImage { +func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors, theme: PresentationThemeChat, wallpaper: TelegramWallpaper) -> UIImage { let diameter: CGFloat = 36.0 let corner: CGFloat = 7.0 return generateImage(CGSize(width: 42.0, height: diameter), contextGenerator: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) + var drawWithClearColor = false + + if case let .color(color) = wallpaper { + drawWithClearColor = true + context.setFillColor(UIColor(rgb: UInt32(color)).cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + } else { + context.clear(CGRect(origin: CGPoint(), size: size)) + } let additionalOffset: CGFloat switch neighbors { @@ -44,40 +54,57 @@ func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor: UIColor let lineWidth: CGFloat = 1.0 - context.setFillColor(fillColor.cgColor) - context.setLineWidth(lineWidth) - context.setStrokeColor(strokeColor.cgColor) + if drawWithClearColor { + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + } else { + context.setFillColor(fillColor.cgColor) + context.setLineWidth(lineWidth) + context.setStrokeColor(strokeColor.cgColor) + } switch neighbors { case .none: - let _ = try? drawSvgPath(context, path: "M6,17.5 C6,7.83289181 13.8350169,0 23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41102995e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.strokePath() + if !drawWithClearColor { + let _ = try? drawSvgPath(context, path: "M6,17.5 C6,7.83289181 13.8350169,0 23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41102995e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") + context.strokePath() + } let _ = try? drawSvgPath(context, path: "M6,17.5 C6,7.83289181 13.8350169,0 23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41102995e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") context.fillPath() case .side: - context.strokeEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 35.0, height: 35.0))) - context.strokePath() + if !drawWithClearColor { + context.strokeEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 35.0, height: 35.0))) + context.strokePath() + } context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 35.0, height: 35.0))) case let .top(side): if side { - let _ = try? drawSvgPath(context, path: "M17.5,0 L17.5,0 C27.1649831,-1.7754286e-15 35,7.83501688 35,17.5 L35,29 C35,32.3137085 32.3137085,35 29,35 L6,35 C2.6862915,35 4.05812251e-16,32.3137085 0,29 L0,17.5 C-1.18361906e-15,7.83501688 7.83501688,1.7754286e-15 17.5,0 ") - context.strokePath() + if !drawWithClearColor { + let _ = try? drawSvgPath(context, path: "M17.5,0 L17.5,0 C27.1649831,-1.7754286e-15 35,7.83501688 35,17.5 L35,29 C35,32.3137085 32.3137085,35 29,35 L6,35 C2.6862915,35 4.05812251e-16,32.3137085 0,29 L0,17.5 C-1.18361906e-15,7.83501688 7.83501688,1.7754286e-15 17.5,0 ") + context.strokePath() + } let _ = try? drawSvgPath(context, path: "M17.5,0 L17.5,0 C27.1649831,-1.7754286e-15 35,7.83501688 35,17.5 L35,29 C35,32.3137085 32.3137085,35 29,35 L6,35 C2.6862915,35 4.05812251e-16,32.3137085 0,29 L0,17.5 C-1.18361906e-15,7.83501688 7.83501688,1.7754286e-15 17.5,0 ") context.fillPath() } else { - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L17.5,0 C7.83501688,0 0,7.83289181 0,17.5 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.strokePath() + if !drawWithClearColor { + let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L17.5,0 C7.83501688,0 0,7.83289181 0,17.5 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") + context.strokePath() + } let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L17.5,0 C7.83501688,0 0,7.83289181 0,17.5 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") context.fillPath() } case .bottom: - let _ = try? drawSvgPath(context, path: "M6,17.5 L6,5.99681848 C6,2.6882755 8.68486709,0 11.9968185,0 L23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41103066e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.strokePath() + if !drawWithClearColor { + let _ = try? drawSvgPath(context, path: "M6,17.5 L6,5.99681848 C6,2.6882755 8.68486709,0 11.9968185,0 L23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41103066e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") + context.strokePath() + } let _ = try? drawSvgPath(context, path: "M6,17.5 L6,5.99681848 C6,2.6882755 8.68486709,0 11.9968185,0 L23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41103066e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") context.fillPath() case .both: - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L5.99681848,0 C2.68486709,0 0,2.6882755 0,5.99681848 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.strokePath() + if !drawWithClearColor { + let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L5.99681848,0 C2.68486709,0 0,2.6882755 0,5.99681848 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") + context.strokePath() + } let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L5.99681848,0 C2.68486709,0 0,2.6882755 0,5.99681848 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") context.fillPath() } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index fe9fabddb0..b0a2b94344 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -128,6 +128,7 @@ private enum ContentNodeOperation { } class ChatMessageBubbleItemNode: ChatMessageItemView { + private let backgroundWallpaperNode: ChatMessageBubbleBackdrop private let backgroundNode: ChatMessageBackground private var transitionClippingNode: ASDisplayNode? @@ -171,11 +172,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { } required init() { + self.backgroundWallpaperNode = ChatMessageBubbleBackdrop() + self.backgroundNode = ChatMessageBackground() self.messageAccessibilityArea = AccessibilityAreaNode() super.init(layerBacked: false) + self.addSubnode(self.backgroundWallpaperNode) self.addSubnode(self.backgroundNode) self.addSubnode(self.messageAccessibilityArea) @@ -215,17 +219,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { override func animateAdded(_ currentTimestamp: Double, duration: Double) { super.animateAdded(currentTimestamp, duration: duration) - self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - - self.nameNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.adminBadgeNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.credibilityIconNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.forwardInfoNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.replyInfoNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - - for contentNode in self.contentNodes { - contentNode.animateAdded(currentTimestamp, duration: duration) - } + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } override func didLoad() { @@ -1370,6 +1364,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { backgroundType = .incoming(mergeType) } strongSelf.backgroundNode.setType(type: backgroundType, highlighted: strongSelf.highlightedState, graphics: graphics, transition: transition) + strongSelf.backgroundWallpaperNode.setType(incoming: incoming, theme: item.presentationData.theme, mediaBox: item.context.account.postbox.mediaBox) strongSelf.backgroundType = backgroundType @@ -1628,6 +1623,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { strongSelf.backgroundFrameTransition = nil } strongSelf.backgroundNode.frame = backgroundFrame + strongSelf.backgroundWallpaperNode.frame = backgroundFrame + if let (rect, size) = strongSelf.absoluteRect { + strongSelf.updateAbsoluteRect(rect, within: size) + } strongSelf.messageAccessibilityArea.frame = backgroundFrame if let shareButtonNode = strongSelf.shareButtonNode { shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - 30.0), size: CGSize(width: 29.0, height: 29.0)) @@ -1774,6 +1773,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { if let backgroundFrameTransition = self.backgroundFrameTransition { let backgroundFrame = CGRect.interpolator()(backgroundFrameTransition.0, backgroundFrameTransition.1, progress) as! CGRect self.backgroundNode.frame = backgroundFrame + self.backgroundWallpaperNode.frame = backgroundFrame + if let (rect, size) = self.absoluteRect { + self.updateAbsoluteRect(rect, within: size) + } self.messageAccessibilityArea.frame = backgroundFrame if let shareButtonNode = self.shareButtonNode { @@ -2115,7 +2118,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { if !self.backgroundNode.frame.contains(point) { if self.actionButtonsNode == nil || !self.actionButtonsNode!.frame.contains(point) { - //return nil } } @@ -2189,6 +2191,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { } self.backgroundNode.isHidden = hasHiddenBackground + self.backgroundWallpaperNode.isHidden = hasHiddenBackground } override func updateAutomaticMediaDownloadSettings() { @@ -2437,4 +2440,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { break } } + + private var absoluteRect: (CGRect, CGSize)? + + override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + self.absoluteRect = (rect, containerSize) + let mappedRect = CGRect(origin: CGPoint(x: rect.minX + self.backgroundWallpaperNode.frame.minX, y: containerSize.height - rect.maxY + self.backgroundWallpaperNode.frame.minY), size: rect.size) + self.backgroundWallpaperNode.update(rect: mappedRect, within: containerSize) + } } diff --git a/submodules/TelegramUI/TelegramUI/PresentationThemeEssentialGraphics.swift b/submodules/TelegramUI/TelegramUI/PresentationThemeEssentialGraphics.swift index ea5bd20001..d38be39677 100644 --- a/submodules/TelegramUI/TelegramUI/PresentationThemeEssentialGraphics.swift +++ b/submodules/TelegramUI/TelegramUI/PresentationThemeEssentialGraphics.swift @@ -131,32 +131,32 @@ public final class PrincipalThemeEssentialGraphics { let incoming: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.incoming.bubble.withoutWallpaper : theme.message.incoming.bubble.withWallpaper let outgoing: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.outgoing.bubble.withoutWallpaper : theme.message.outgoing.bubble.withWallpaper - self.chatMessageBackgroundIncomingImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none) - self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none) - self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false)) - self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false)) - self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true)) - self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true)) - self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom) - self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom) - self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both) - self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both) + self.chatMessageBackgroundIncomingImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper) - self.chatMessageBackgroundOutgoingImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none) - self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none) - self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false)) - self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false)) - self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true)) - self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true)) - self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom) - self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom) - self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both) - self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both) + self.chatMessageBackgroundOutgoingImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper) - self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side) - self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side) - self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side) - self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side) + self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper) + self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper) self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor)! self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor)! diff --git a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj index 8a4c511a03..d306ee29c2 100644 --- a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj @@ -1225,6 +1225,7 @@ D0FA08C020483F9600DD23FC /* ExtractVideoData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA08BF20483F9600DD23FC /* ExtractVideoData.swift */; }; D0FA08C8204982DC00DD23FC /* ChatTextInputActionButtonsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA08C7204982DC00DD23FC /* ChatTextInputActionButtonsNode.swift */; }; D0FA08CA2049BEAC00DD23FC /* ChatEmptyNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA08C92049BEAC00DD23FC /* ChatEmptyNode.swift */; }; + D0FAB13E22EBC25300D8BED2 /* ChatMessageBubbleBackdrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FAB13D22EBC25300D8BED2 /* ChatMessageBubbleBackdrop.swift */; }; D0FB87B21F7C4C19004DE005 /* FetchMediaUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FB87B11F7C4C19004DE005 /* FetchMediaUtils.swift */; }; D0FBE84F2273395C00B33B52 /* ChatListArchiveInfoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FBE84E2273395C00B33B52 /* ChatListArchiveInfoItem.swift */; }; D0FC194D201F82A000FEDBB2 /* OpenResolvedUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FC194C201F82A000FEDBB2 /* OpenResolvedUrl.swift */; }; @@ -2488,6 +2489,7 @@ D0FA0AC41E77431A005BB9B7 /* InstalledStickerPacksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstalledStickerPacksController.swift; sourceTree = ""; }; D0FA34FE1EA5834C00E56FFA /* ItemListControllerSegmentedTitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemListControllerSegmentedTitleView.swift; sourceTree = ""; }; D0FA35001EA6127000E56FFA /* StorageUsageController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageUsageController.swift; sourceTree = ""; }; + D0FAB13D22EBC25300D8BED2 /* ChatMessageBubbleBackdrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMessageBubbleBackdrop.swift; sourceTree = ""; }; D0FB87B11F7C4C19004DE005 /* FetchMediaUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchMediaUtils.swift; sourceTree = ""; }; D0FBE84E2273395C00B33B52 /* ChatListArchiveInfoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListArchiveInfoItem.swift; sourceTree = ""; }; D0FC194C201F82A000FEDBB2 /* OpenResolvedUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenResolvedUrl.swift; sourceTree = ""; }; @@ -4782,6 +4784,7 @@ D0AB262821C307D7008F6685 /* ChatMessagePollBubbleContentNode.swift */, 099529AF21D2123E00805E13 /* ChatMessageUnsupportedBubbleContentNode.swift */, D0439B5A228EC4A00067E026 /* ChatMessagePhoneNumberRequestContentNode.swift */, + D0FAB13D22EBC25300D8BED2 /* ChatMessageBubbleBackdrop.swift */, ); name = Items; sourceTree = ""; @@ -6333,6 +6336,7 @@ D0EC6E741EB9F58900EBF1C3 /* ThemeGridController.swift in Sources */, D0EC6E751EB9F58900EBF1C3 /* ThemeGridControllerNode.swift in Sources */, D0EC6E761EB9F58900EBF1C3 /* SettingsController.swift in Sources */, + D0FAB13E22EBC25300D8BED2 /* ChatMessageBubbleBackdrop.swift in Sources */, D0EC6E771EB9F58900EBF1C3 /* NotificationsAndSounds.swift in Sources */, D0EC6E781EB9F58900EBF1C3 /* NotificationSoundSelection.swift in Sources */, D056CD741FF2996B00880D28 /* ExternalMusicAlbumArtResources.swift in Sources */,