Add light context menu theme

This commit is contained in:
Ali 2023-10-24 18:39:41 +04:00
parent d7546f6751
commit 5452f275b4
15 changed files with 124 additions and 91 deletions

View File

@ -458,7 +458,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode {
self.highlightBackgroundNode.clipsToBounds = true self.highlightBackgroundNode.clipsToBounds = true
self.highlightBackgroundNode.cornerRadius = 14.0 self.highlightBackgroundNode.cornerRadius = 14.0
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: presentationData.theme.contextMenu.primaryColor.withAlphaComponent(0.15), knob: presentationData.theme.contextMenu.primaryColor, knobDiameter: 8.0), strings: presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { _ in let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: presentationData.theme.contextMenu.primaryColor.withAlphaComponent(0.15), knob: presentationData.theme.contextMenu.primaryColor, knobDiameter: 8.0, isDark: presentationData.theme.overallDarkAppearance), strings: presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { _ in
}, present: { _, _ in }, present: { _, _ in
}, rootNode: { [weak self] in }, rootNode: { [weak self] in
return self return self

View File

@ -17,22 +17,32 @@ private final class ContextMenuContainerMaskView: UIView {
public final class ContextMenuContainerNode: ASDisplayNode { public final class ContextMenuContainerNode: ASDisplayNode {
private var cachedMaskParams: CachedMaskParams? private var cachedMaskParams: CachedMaskParams?
private let maskView = ContextMenuContainerMaskView() private let maskView = ContextMenuContainerMaskView()
public let containerNode: ASDisplayNode
public var relativeArrowPosition: (CGFloat, Bool)? public var relativeArrowPosition: (CGFloat, Bool)?
private var effectView: UIVisualEffectView? private var effectView: UIVisualEffectView?
public init(blurred: Bool) { public init(isBlurred: Bool, isDark: Bool) {
self.containerNode = ASDisplayNode()
super.init() super.init()
if blurred { if isBlurred {
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark)) let effectView = UIVisualEffectView(effect: UIBlurEffect(style: isDark ? .dark : .light))
self.view.addSubview(effectView) self.containerNode.view.addSubview(effectView)
self.effectView = effectView self.effectView = effectView
} else { } else {
self.backgroundColor = UIColor(rgb: 0x8c8e8e) self.containerNode.backgroundColor = isDark ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0xF8F8F6)
} }
self.view.mask = self.maskView
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowRadius = 10.0
self.layer.shadowOpacity = 0.2
self.layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
self.containerNode.view.mask = self.maskView
self.addSubnode(self.containerNode)
} }
override public func didLoad() { override public func didLoad() {
@ -48,6 +58,8 @@ public final class ContextMenuContainerNode: ASDisplayNode {
} }
public func updateLayout(transition: ContainedViewLayoutTransition) { public func updateLayout(transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.containerNode, frame: self.bounds)
self.effectView?.frame = self.bounds self.effectView?.frame = self.bounds
let maskParams = CachedMaskParams(size: self.bounds.size, relativeArrowPosition: self.relativeArrowPosition?.0 ?? self.bounds.size.width / 2.0, arrowOnBottom: self.relativeArrowPosition?.1 ?? true) let maskParams = CachedMaskParams(size: self.bounds.size, relativeArrowPosition: self.relativeArrowPosition?.0 ?? self.bounds.size.width / 2.0, arrowOnBottom: self.relativeArrowPosition?.1 ?? true)
@ -87,6 +99,13 @@ public final class ContextMenuContainerNode: ASDisplayNode {
} }
layer.path = path.cgPath layer.path = path.cgPath
} }
if case let .animated(duration, curve) = transition, let previousPath = self.layer.shadowPath {
self.layer.shadowPath = path.cgPath
self.layer.animate(from: previousPath, to: path.cgPath, keyPath: "shadowPath", timingFunction: curve.timingFunction, duration: duration)
} else {
self.layer.shadowPath = path.cgPath
}
} }
} }
} }

View File

@ -24,13 +24,15 @@ public struct ContextMenuControllerArguments {
public var hasHapticFeedback: Bool public var hasHapticFeedback: Bool
public var blurred: Bool public var blurred: Bool
public var skipCoordnateConversion: Bool public var skipCoordnateConversion: Bool
public var isDark: Bool
public init(actions: [ContextMenuAction], catchTapsOutside: Bool, hasHapticFeedback: Bool, blurred: Bool, skipCoordnateConversion: Bool) { public init(actions: [ContextMenuAction], catchTapsOutside: Bool, hasHapticFeedback: Bool, blurred: Bool, skipCoordnateConversion: Bool, isDark: Bool) {
self.actions = actions self.actions = actions
self.catchTapsOutside = catchTapsOutside self.catchTapsOutside = catchTapsOutside
self.hasHapticFeedback = hasHapticFeedback self.hasHapticFeedback = hasHapticFeedback
self.blurred = blurred self.blurred = blurred
self.skipCoordnateConversion = skipCoordnateConversion self.skipCoordnateConversion = skipCoordnateConversion
self.isDark = isDark
} }
} }
@ -40,7 +42,7 @@ public func setContextMenuControllerProvider(_ f: @escaping (ContextMenuControll
contextMenuControllerProvider = f contextMenuControllerProvider = f
} }
public func makeContextMenuController(actions: [ContextMenuAction], catchTapsOutside: Bool = false, hasHapticFeedback: Bool = false, blurred: Bool = false, skipCoordnateConversion: Bool = false) -> ContextMenuController { public func makeContextMenuController(actions: [ContextMenuAction], catchTapsOutside: Bool = false, hasHapticFeedback: Bool = false, blurred: Bool = false, isDark: Bool = true, skipCoordnateConversion: Bool = false) -> ContextMenuController {
guard let contextMenuControllerProvider = contextMenuControllerProvider else { guard let contextMenuControllerProvider = contextMenuControllerProvider else {
preconditionFailure() preconditionFailure()
} }
@ -49,6 +51,7 @@ public func makeContextMenuController(actions: [ContextMenuAction], catchTapsOut
catchTapsOutside: catchTapsOutside, catchTapsOutside: catchTapsOutside,
hasHapticFeedback: hasHapticFeedback, hasHapticFeedback: hasHapticFeedback,
blurred: blurred, blurred: blurred,
skipCoordnateConversion: skipCoordnateConversion skipCoordnateConversion: skipCoordnateConversion,
isDark: isDark
)) ))
} }

View File

@ -33,8 +33,8 @@ final class TooltipControllerNode: ASDisplayNode {
self.dismissByTapOutside = dismissByTapOutside self.dismissByTapOutside = dismissByTapOutside
self.dismissByTapOutsideSource = dismissByTapOutsideSource self.dismissByTapOutsideSource = dismissByTapOutsideSource
self.containerNode = ContextMenuContainerNode(blurred: false) self.containerNode = ContextMenuContainerNode(isBlurred: false, isDark: true)
self.containerNode.backgroundColor = UIColor(white: 0.0, alpha: 0.8) self.containerNode.containerNode.backgroundColor = UIColor(white: 0.0, alpha: 0.8)
self.imageNode = ASImageNode() self.imageNode = ASImageNode()
self.imageNode.image = content.image self.imageNode.image = content.image
@ -57,9 +57,9 @@ final class TooltipControllerNode: ASDisplayNode {
super.init() super.init()
self.containerNode.addSubnode(self.imageNode) self.containerNode.containerNode.addSubnode(self.imageNode)
self.containerNode.addSubnode(self.textNode) self.containerNode.containerNode.addSubnode(self.textNode)
self.contentNode.flatMap { self.containerNode.addSubnode($0) } self.contentNode.flatMap { self.containerNode.containerNode.addSubnode($0) }
self.addSubnode(self.containerNode) self.addSubnode(self.containerNode)
} }

View File

@ -426,7 +426,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
) )
self.textNode.visibility = true self.textNode.visibility = true
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: defaultDarkPresentationTheme.list.itemAccentColor.withMultipliedAlpha(0.5), knob: defaultDarkPresentationTheme.list.itemAccentColor), strings: presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: defaultDarkPresentationTheme.list.itemAccentColor.withMultipliedAlpha(0.5), knob: defaultDarkPresentationTheme.list.itemAccentColor, isDark: true), strings: presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in
guard let self else { guard let self else {
return return
} }

View File

@ -103,8 +103,8 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode {
self.containerNode = ASDisplayNode() self.containerNode = ASDisplayNode()
self.containerNode.subnodeTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0) self.containerNode.subnodeTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
self.tooltipContainerNode = ContextMenuContainerNode(blurred: false) self.tooltipContainerNode = ContextMenuContainerNode(isBlurred: false, isDark: true)
self.tooltipContainerNode.backgroundColor = UIColor(white: 0.0, alpha: 0.8) self.tooltipContainerNode.containerNode.backgroundColor = UIColor(white: 0.0, alpha: 0.8)
self.textNode = ImmediateTextNode() self.textNode = ImmediateTextNode()
self.textNode.isUserInteractionEnabled = false self.textNode.isUserInteractionEnabled = false
@ -119,7 +119,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode {
self.addSubnode(self.containerNode) self.addSubnode(self.containerNode)
self.tooltipContainerNode.addSubnode(self.textNode) self.tooltipContainerNode.containerNode.addSubnode(self.textNode)
self.addSubnode(self.tooltipContainerNode) self.addSubnode(self.tooltipContainerNode)
} }

View File

@ -3486,23 +3486,28 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
}) })
strongSelf.setAnimationForKey("contentNode\(contentNodeIndex)Frame", animation: animation) strongSelf.setAnimationForKey("contentNode\(contentNodeIndex)Frame", animation: animation)
} else { } else {
if let animateTextAndWebpagePositionSwap, let contentNode = contentNode as? ChatMessageTextBubbleContentNode, let snapshotLayer = contentNode.layer.snapshotContentTree() { var useExpensiveSnapshot = false
let clippingLayer = SimpleLayer() if case .messageOptions = item.associatedData.subject {
clippingLayer.masksToBounds = true useExpensiveSnapshot = true
clippingLayer.frame = contentNode.frame }
if let animateTextAndWebpagePositionSwap, let contentNode = contentNode as? ChatMessageTextBubbleContentNode, let snapshotView = useExpensiveSnapshot ? contentNode.view.snapshotView(afterScreenUpdates: false) : contentNode.layer.snapshotContentTreeAsView() {
let clippingView = UIView()
clippingView.clipsToBounds = true
clippingView.frame = contentNode.frame
clippingLayer.addSublayer(snapshotLayer) clippingView.addSubview(snapshotView)
snapshotLayer.frame = CGRect(origin: CGPoint(), size: contentNode.bounds.size) snapshotView.frame = CGRect(origin: CGPoint(), size: contentNode.bounds.size)
contentNode.layer.superlayer?.insertSublayer(clippingLayer, below: contentNode.layer) contentNode.view.superview?.insertSubview(clippingView, belowSubview: contentNode.view)
animation.animator.updateAlpha(layer: clippingLayer, alpha: 0.0, completion: { [weak clippingLayer] _ in animation.animator.updateAlpha(layer: clippingView.layer, alpha: 0.0, completion: { [weak clippingView] _ in
clippingLayer?.removeFromSuperlayer() clippingView?.removeFromSuperview()
}) })
let positionOffset: CGFloat = animateTextAndWebpagePositionSwap ? -1.0 : 1.0 let positionOffset: CGFloat = animateTextAndWebpagePositionSwap ? -1.0 : 1.0
animation.animator.updatePosition(layer: snapshotLayer, position: CGPoint(x: snapshotLayer.position.x, y: snapshotLayer.position.y + positionOffset * contentNode.frame.height), completion: nil) animation.animator.updatePosition(layer: snapshotView.layer, position: CGPoint(x: snapshotView.center.x, y: snapshotView.center.y + positionOffset * contentNode.frame.height), completion: nil)
contentNode.frame = contentNodeFrame contentNode.frame = contentNodeFrame

View File

@ -1796,7 +1796,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
knobColor = item.presentationData.theme.theme.chat.message.outgoing.textSelectionKnobColor knobColor = item.presentationData.theme.theme.chat.message.outgoing.textSelectionKnobColor
} }
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor), strings: item.presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor, isDark: item.presentationData.theme.theme.overallDarkAppearance), strings: item.presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in
self?.updateIsTextSelectionActive?(value) self?.updateIsTextSelectionActive?(value)
}, present: { [weak self] c, a in }, present: { [weak self] c, a in
self?.arguments?.controllerInteraction.presentGlobalOverlayController(c, a) self?.arguments?.controllerInteraction.presentGlobalOverlayController(c, a)

View File

@ -1104,7 +1104,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
knobColor = item.presentationData.theme.theme.chat.message.outgoing.textSelectionKnobColor knobColor = item.presentationData.theme.theme.chat.message.outgoing.textSelectionKnobColor
} }
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor), strings: item.presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { [weak self] value in let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor, isDark: item.presentationData.theme.theme.overallDarkAppearance), strings: item.presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { [weak self] value in
self?.updateIsTextSelectionActive?(value) self?.updateIsTextSelectionActive?(value)
}, present: { [weak self] c, a in }, present: { [weak self] c, a in
guard let self, let item = self.item else { guard let self, let item = self.item else {

View File

@ -607,14 +607,14 @@ public final class MessageInlineBlockBackgroundView: UIView {
} }
let placements: [Placement] = [ let placements: [Placement] = [
Placement(CGPoint(x: 176.0, y: 13.0), 38.0), Placement(CGPoint(x: 180.0, y: 13.0), 38.0),
Placement(CGPoint(x: 51.0, y: 45.0), 58.0), Placement(CGPoint(x: 55.0, y: 47.0), 58.0),
Placement(CGPoint(x: 349.0, y: 36.0), 58.0), Placement(CGPoint(x: 364.0, y: 26.0), 58.0),
Placement(CGPoint(x: 132.0, y: 64.0), 46.0), Placement(CGPoint(x: 133.0, y: 74.0), 46.0),
Placement(CGPoint(x: 241.0, y: 64.0), 54.0), Placement(CGPoint(x: 262.0, y: 67.0), 54.0),
Placement(CGPoint(x: 68.0, y: 121.0), 44.0), Placement(CGPoint(x: 62.0, y: 125.0), 44.0),
Placement(CGPoint(x: 178.0, y: 122.0), 47.0), Placement(CGPoint(x: 171.0, y: 135.0), 47.0),
Placement(CGPoint(x: 315.0, y: 122.0), 47.0), Placement(CGPoint(x: 320.0, y: 124.0), 47.0),
] ]
for placement in placements { for placement in placements {
@ -631,7 +631,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
let itemSize = CGSize(width: placement.size / 3.0, height: placement.size / 3.0) 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) 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) / 400.0 var alphaFraction = abs(placement.position.x) / 500.0
alphaFraction = min(1.0, max(0.0, alphaFraction)) alphaFraction = min(1.0, max(0.0, alphaFraction))
patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction) patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction)

View File

@ -16,14 +16,14 @@ final private class ContextMenuActionButton: HighlightTrackingButton {
final class ContextMenuActionNode: ASDisplayNode { final class ContextMenuActionNode: ASDisplayNode {
private let textNode: ImmediateTextNode? private let textNode: ImmediateTextNode?
private var textSize: CGSize? private var textSize: CGSize?
private let iconNode: ASImageNode? private let iconView: UIImageView?
private let action: () -> Void private let action: () -> Void
private let button: ContextMenuActionButton private let button: ContextMenuActionButton
private let actionArea: AccessibilityAreaNode private let actionArea: AccessibilityAreaNode
var dismiss: (() -> Void)? var dismiss: (() -> Void)?
init(action: ContextMenuAction, blurred: Bool) { init(action: ContextMenuAction, blurred: Bool, isDark: Bool) {
self.actionArea = AccessibilityAreaNode() self.actionArea = AccessibilityAreaNode()
self.actionArea.accessibilityTraits = .button self.actionArea.accessibilityTraits = .button
@ -34,30 +34,30 @@ final class ContextMenuActionNode: ASDisplayNode {
let textNode = ImmediateTextNode() let textNode = ImmediateTextNode()
textNode.isUserInteractionEnabled = false textNode.isUserInteractionEnabled = false
textNode.displaysAsynchronously = false textNode.displaysAsynchronously = false
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: UIColor.white) textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: isDark ? .white : .black)
textNode.isAccessibilityElement = false textNode.isAccessibilityElement = false
self.textNode = textNode self.textNode = textNode
self.iconNode = nil self.iconView = nil
case let .textWithIcon(title, icon): case let .textWithIcon(title, icon):
let textNode = ImmediateTextNode() let textNode = ImmediateTextNode()
textNode.isUserInteractionEnabled = false textNode.isUserInteractionEnabled = false
textNode.displaysAsynchronously = false textNode.displaysAsynchronously = false
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: UIColor.white) textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black)
textNode.isAccessibilityElement = false textNode.isAccessibilityElement = false
let iconNode = ASImageNode() let iconView = UIImageView()
iconNode.displaysAsynchronously = false iconView.tintColor = isDark ? .white : .black
iconNode.image = icon iconView.image = icon
self.textNode = textNode self.textNode = textNode
self.iconNode = iconNode self.iconView = iconView
case let .icon(image): case let .icon(image):
let iconNode = ASImageNode() let iconView = UIImageView()
iconNode.displaysAsynchronously = false iconView.tintColor = isDark ? .white : .black
iconNode.image = image iconView.image = image
self.iconNode = iconNode self.iconView = iconView
self.textNode = nil self.textNode = nil
} }
self.action = action.action self.action = action.action
@ -68,21 +68,25 @@ final class ContextMenuActionNode: ASDisplayNode {
super.init() super.init()
if !blurred { if !blurred {
self.backgroundColor = UIColor(rgb: 0x2f2f2f) self.backgroundColor = isDark ? UIColor(rgb: 0x2f2f2f) : nil
} }
if let textNode = self.textNode { if let textNode = self.textNode {
self.addSubnode(textNode) self.addSubnode(textNode)
} }
if let iconNode = self.iconNode { if let iconView = self.iconView {
self.addSubnode(iconNode) self.view.addSubview(iconView)
} }
self.button.highligthedChanged = { [weak self] highlighted in self.button.highligthedChanged = { [weak self] highlighted in
if blurred { if isDark {
self?.backgroundColor = highlighted ? UIColor(rgb: 0xffffff, alpha: 0.5) : .clear if blurred {
self?.backgroundColor = highlighted ? UIColor(rgb: 0xffffff, alpha: 0.5) : .clear
} else {
self?.backgroundColor = highlighted ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0x2f2f2f)
}
} else { } else {
self?.backgroundColor = highlighted ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0x2f2f2f) self?.backgroundColor = highlighted ? UIColor(rgb: 0xDCE3DC) : .clear
} }
} }
self.view.addSubview(self.button) self.view.addSubview(self.button)
@ -116,7 +120,7 @@ final class ContextMenuActionNode: ASDisplayNode {
var totalWidth = 0.0 var totalWidth = 0.0
totalWidth += textSize.width totalWidth += textSize.width
if let image = self.iconNode?.image { if let image = self.iconView?.image {
if totalWidth > 0.0 { if totalWidth > 0.0 {
totalWidth += 11.0 totalWidth += 11.0
} }
@ -127,7 +131,7 @@ final class ContextMenuActionNode: ASDisplayNode {
} }
return CGSize(width: totalWidth, height: 54.0) return CGSize(width: totalWidth, height: 54.0)
} else if let iconNode = self.iconNode, let image = iconNode.image { } else if let iconView = self.iconView, let image = iconView.image {
return CGSize(width: image.size.width + 36.0, height: 54.0) return CGSize(width: image.size.width + 36.0, height: 54.0)
} else { } else {
return CGSize(width: 36.0, height: 54.0) return CGSize(width: 36.0, height: 54.0)
@ -144,7 +148,7 @@ final class ContextMenuActionNode: ASDisplayNode {
if let textSize = self.textSize { if let textSize = self.textSize {
totalWidth += textSize.width totalWidth += textSize.width
} }
if let image = self.iconNode?.image { if let image = self.iconView?.image {
if totalWidth > 0.0 { if totalWidth > 0.0 {
totalWidth += 11.0 totalWidth += 11.0
} }
@ -154,9 +158,9 @@ final class ContextMenuActionNode: ASDisplayNode {
if let textNode = self.textNode, let textSize = self.textSize { if let textNode = self.textNode, let textSize = self.textSize {
textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - textSize.height) / 2.0)), size: textSize) textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - textSize.height) / 2.0)), size: textSize)
} }
if let iconNode = self.iconNode, let image = iconNode.image { if let iconView = self.iconView, let image = iconView.image {
let iconSize = image.size let iconSize = image.size
iconNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0) + totalWidth - iconSize.width, y: floorToScreenPixels((self.bounds.size.height - iconSize.height) / 2.0)), size: iconSize) iconView.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0) + totalWidth - iconSize.width, y: floorToScreenPixels((self.bounds.size.height - iconSize.height) / 2.0)), size: iconSize)
} }
} }
} }

View File

@ -19,6 +19,7 @@ public final class ContextMenuControllerImpl: ViewController, KeyShortcutRespond
private let hasHapticFeedback: Bool private let hasHapticFeedback: Bool
private let blurred: Bool private let blurred: Bool
private let skipCoordnateConversion: Bool private let skipCoordnateConversion: Bool
private let isDark: Bool
private var layout: ContainerViewLayout? private var layout: ContainerViewLayout?
@ -33,6 +34,7 @@ public final class ContextMenuControllerImpl: ViewController, KeyShortcutRespond
self.hasHapticFeedback = arguments.hasHapticFeedback self.hasHapticFeedback = arguments.hasHapticFeedback
self.blurred = arguments.blurred self.blurred = arguments.blurred
self.skipCoordnateConversion = arguments.skipCoordnateConversion self.skipCoordnateConversion = arguments.skipCoordnateConversion
self.isDark = arguments.isDark
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
@ -54,7 +56,7 @@ public final class ContextMenuControllerImpl: ViewController, KeyShortcutRespond
return false return false
} }
return dismissOnTap(view, point) return dismissOnTap(view, point)
}, catchTapsOutside: self.catchTapsOutside, hasHapticFeedback: self.hasHapticFeedback, blurred: self.blurred) }, catchTapsOutside: self.catchTapsOutside, hasHapticFeedback: self.hasHapticFeedback, blurred: self.blurred, isDark: self.isDark)
self.displayNodeDidLoad() self.displayNodeDidLoad()
} }

View File

@ -5,15 +5,6 @@ import AppBundle
import AsyncDisplayKit import AsyncDisplayKit
import Display import Display
private func generateShadowImage() -> UIImage? {
return generateImage(CGSize(width: 30.0, height: 1.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setShadow(offset: CGSize(), blur: 10.0, color: UIColor(white: 0.18, alpha: 1.0).cgColor)
context.setFillColor(UIColor(white: 0.18, alpha: 1.0).cgColor)
context.fill(CGRect(origin: CGPoint(x: -15.0, y: 0.0), size: CGSize(width: 30.0, height: 1.0)))
})
}
private final class ArrowNode: HighlightTrackingButtonNode { private final class ArrowNode: HighlightTrackingButtonNode {
private let isLeft: Bool private let isLeft: Bool
@ -21,7 +12,7 @@ private final class ArrowNode: HighlightTrackingButtonNode {
private let separatorLayer: SimpleLayer private let separatorLayer: SimpleLayer
var action: (() -> Void)? var action: (() -> Void)?
init(isLeft: Bool) { init(isLeft: Bool, isDark: Bool) {
self.isLeft = isLeft self.isLeft = isLeft
self.iconView = UIImageView() self.iconView = UIImageView()
@ -39,12 +30,15 @@ private final class ArrowNode: HighlightTrackingButtonNode {
self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
self.backgroundColor = UIColor(rgb: 0x2f2f2f)
self.highligthedChanged = { [weak self] highlighted in self.highligthedChanged = { [weak self] highlighted in
guard let self else { guard let self else {
return return
} }
self.backgroundColor = highlighted ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0x2f2f2f) if isDark {
self.backgroundColor = highlighted ? UIColor(rgb: 0x8c8e8e) : nil
} else {
self.backgroundColor = highlighted ? UIColor(rgb: 0xDCE3DC) : nil
}
} }
} }
@ -70,6 +64,8 @@ private final class ArrowNode: HighlightTrackingButtonNode {
} }
final class ContextMenuNode: ASDisplayNode { final class ContextMenuNode: ASDisplayNode {
private let isDark: Bool
private let actions: [ContextMenuAction] private let actions: [ContextMenuAction]
private let dismiss: () -> Void private let dismiss: () -> Void
private let dismissOnTap: (UIView, CGPoint) -> Bool private let dismissOnTap: (UIView, CGPoint) -> Bool
@ -96,22 +92,24 @@ final class ContextMenuNode: ASDisplayNode {
private let feedback: HapticFeedback? private let feedback: HapticFeedback?
init(actions: [ContextMenuAction], dismiss: @escaping () -> Void, dismissOnTap: @escaping (UIView, CGPoint) -> Bool, catchTapsOutside: Bool, hasHapticFeedback: Bool, blurred: Bool = false) { init(actions: [ContextMenuAction], dismiss: @escaping () -> Void, dismissOnTap: @escaping (UIView, CGPoint) -> Bool, catchTapsOutside: Bool, hasHapticFeedback: Bool, blurred: Bool = false, isDark: Bool = true) {
self.isDark = isDark
self.actions = actions self.actions = actions
self.dismiss = dismiss self.dismiss = dismiss
self.dismissOnTap = dismissOnTap self.dismissOnTap = dismissOnTap
self.catchTapsOutside = catchTapsOutside self.catchTapsOutside = catchTapsOutside
self.containerNode = ContextMenuContainerNode(blurred: blurred) self.containerNode = ContextMenuContainerNode(isBlurred: blurred, isDark: isDark)
self.contentNode = ASDisplayNode() self.contentNode = ASDisplayNode()
self.contentNode.clipsToBounds = true self.contentNode.clipsToBounds = true
self.actionNodes = actions.map { action in self.actionNodes = actions.map { action in
return ContextMenuActionNode(action: action, blurred: blurred) return ContextMenuActionNode(action: action, blurred: blurred, isDark: isDark)
} }
self.pageLeftNode = ArrowNode(isLeft: true) self.pageLeftNode = ArrowNode(isLeft: true, isDark: isDark)
self.pageRightNode = ArrowNode(isLeft: false) self.pageRightNode = ArrowNode(isLeft: false, isDark: isDark)
if hasHapticFeedback { if hasHapticFeedback {
self.feedback = HapticFeedback() self.feedback = HapticFeedback()
@ -122,7 +120,7 @@ final class ContextMenuNode: ASDisplayNode {
super.init() super.init()
self.containerNode.addSubnode(self.contentNode) self.containerNode.containerNode.addSubnode(self.contentNode)
self.addSubnode(self.containerNode) self.addSubnode(self.containerNode)
let dismissNode = { let dismissNode = {
@ -133,8 +131,8 @@ final class ContextMenuNode: ASDisplayNode {
self.contentNode.addSubnode(actionNode) self.contentNode.addSubnode(actionNode)
} }
self.containerNode.addSubnode(self.pageLeftNode) self.containerNode.containerNode.addSubnode(self.pageLeftNode)
self.containerNode.addSubnode(self.pageRightNode) self.containerNode.containerNode.addSubnode(self.pageRightNode)
let navigatePage: (Bool) -> Void = { [weak self] isLeft in let navigatePage: (Bool) -> Void = { [weak self] isLeft in
guard let self else { guard let self else {
@ -173,12 +171,12 @@ final class ContextMenuNode: ASDisplayNode {
var offsetX: CGFloat var offsetX: CGFloat
} }
let separatorColor = UIColor(rgb: 0x8c8e8e) let separatorColor = self.isDark ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0xDCE3DC)
let height: CGFloat = 54.0 let height: CGFloat = 54.0
let pageLeftSize = self.pageLeftNode.update(color: .white, separatorColor: separatorColor, height: height) let pageLeftSize = self.pageLeftNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
let pageRightSize = self.pageRightNode.update(color: .white, separatorColor: separatorColor, height: height) let pageRightSize = self.pageRightNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
let maxPageWidth = layout.size.width - 20.0 - pageLeftSize.width - pageRightSize.width let maxPageWidth = layout.size.width - 20.0 - pageLeftSize.width - pageRightSize.width
var absoluteActionOffsetX: CGFloat = 0.0 var absoluteActionOffsetX: CGFloat = 0.0

View File

@ -729,7 +729,7 @@ final class StoryContentCaptionComponent: Component {
self.textSelectionKnobContainer.addSubview(textSelectionKnobSurface) self.textSelectionKnobContainer.addSubview(textSelectionKnobSurface)
} }
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: component.theme.list.itemAccentColor), strings: component.strings, textNode: textNode, updateIsActive: { [weak self] value in let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: component.theme.list.itemAccentColor, isDark: true), strings: component.strings, textNode: textNode, updateIsActive: { [weak self] value in
guard let self else { guard let self else {
return return
} }

View File

@ -61,11 +61,13 @@ public final class TextSelectionTheme {
public let selection: UIColor public let selection: UIColor
public let knob: UIColor public let knob: UIColor
public let knobDiameter: CGFloat public let knobDiameter: CGFloat
public let isDark: Bool
public init(selection: UIColor, knob: UIColor, knobDiameter: CGFloat = 12.0) { public init(selection: UIColor, knob: UIColor, knobDiameter: CGFloat = 12.0, isDark: Bool) {
self.selection = selection self.selection = selection
self.knob = knob self.knob = knob
self.knobDiameter = knobDiameter self.knobDiameter = knobDiameter
self.isDark = isDark
} }
} }
@ -755,7 +757,7 @@ public final class TextSelectionNode: ASDisplayNode {
self.contextMenu?.dismiss() self.contextMenu?.dismiss()
let contextMenu = makeContextMenuController(actions: actions, catchTapsOutside: false, hasHapticFeedback: false, skipCoordnateConversion: self.menuSkipCoordnateConversion) let contextMenu = makeContextMenuController(actions: actions, catchTapsOutside: false, hasHapticFeedback: false, isDark: self.theme.isDark, skipCoordnateConversion: self.menuSkipCoordnateConversion)
contextMenu.dismissOnTap = { [weak self] view, point in contextMenu.dismissOnTap = { [weak self] view, point in
guard let self else { guard let self else {
return true return true