mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Switch to new check node implementation
This commit is contained in:
parent
838f16781e
commit
249b684e64
@ -250,7 +250,7 @@ public class ChatListAdditionalCategoryItemNode: ItemListRevealOptionsItemNode {
|
||||
selectionNode = current
|
||||
updatedSelectionNode = selectionNode
|
||||
} else {
|
||||
selectionNode = CheckNode(strokeColor: item.presentationData.theme.list.itemCheckColors.strokeColor, fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, style: .plain)
|
||||
selectionNode = CheckNode(theme: CheckNodeTheme(theme: item.presentationData.theme, style: .plain))
|
||||
selectionNode.isUserInteractionEnabled = false
|
||||
updatedSelectionNode = selectionNode
|
||||
}
|
||||
@ -322,9 +322,9 @@ public class ChatListAdditionalCategoryItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.selectionNode = updatedSelectionNode
|
||||
strongSelf.addSubnode(updatedSelectionNode)
|
||||
}
|
||||
updatedSelectionNode.setIsChecked(isSelected, animated: animated)
|
||||
updatedSelectionNode.setSelected(isSelected, animated: animated)
|
||||
|
||||
updatedSelectionNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 32.0 - 12.0, y: floor((nodeLayout.contentSize.height - 32.0) / 2.0)), size: CGSize(width: 32.0, height: 32.0))
|
||||
updatedSelectionNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 22.0 - 17.0, y: floor((nodeLayout.contentSize.height - 22.0) / 2.0)), size: CGSize(width: 22.0, height: 22.0))
|
||||
} else if let selectionNode = strongSelf.selectionNode {
|
||||
selectionNode.removeFromSupernode()
|
||||
strongSelf.selectionNode = nil
|
||||
|
@ -10,6 +10,7 @@ swift_library(
|
||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||
"//submodules/Display:Display",
|
||||
"//submodules/LegacyComponents:LegacyComponents",
|
||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -1,82 +1,292 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
import Display
|
||||
import LegacyComponents
|
||||
import TelegramPresentationData
|
||||
|
||||
public enum CheckNodeStyle {
|
||||
case plain
|
||||
case overlay
|
||||
case navigation
|
||||
case compact
|
||||
}
|
||||
|
||||
public final class CheckNode: ASDisplayNode {
|
||||
private var strokeColor: UIColor
|
||||
private var fillColor: UIColor
|
||||
private var foregroundColor: UIColor
|
||||
private let checkStyle: CheckNodeStyle
|
||||
public struct CheckNodeTheme {
|
||||
public let backgroundColor: UIColor
|
||||
public let strokeColor: UIColor
|
||||
public let borderColor: UIColor
|
||||
public let overlayBorder: Bool
|
||||
public let hasInset: Bool
|
||||
public let hasShadow: Bool
|
||||
public let filledBorder: Bool
|
||||
public let borderWidth: CGFloat?
|
||||
|
||||
private var checkView: TGCheckButtonView?
|
||||
|
||||
public private(set) var isChecked: Bool = false
|
||||
|
||||
private weak var target: AnyObject?
|
||||
private var action: Selector?
|
||||
|
||||
public init(strokeColor: UIColor, fillColor: UIColor, foregroundColor: UIColor, style: CheckNodeStyle) {
|
||||
public init(backgroundColor: UIColor, strokeColor: UIColor, borderColor: UIColor, overlayBorder: Bool, hasInset: Bool, hasShadow: Bool, filledBorder: Bool = false, borderWidth: CGFloat? = nil) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.strokeColor = strokeColor
|
||||
self.fillColor = fillColor
|
||||
self.foregroundColor = foregroundColor
|
||||
self.checkStyle = style
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let style: TGCheckButtonStyle
|
||||
let checkSize: CGSize
|
||||
switch self.checkStyle {
|
||||
case .plain:
|
||||
style = TGCheckButtonStyleDefault
|
||||
checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
case .overlay:
|
||||
style = TGCheckButtonStyleMedia
|
||||
checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
case .navigation:
|
||||
style = TGCheckButtonStyleGallery
|
||||
checkSize = CGSize(width: 39.0, height: 39.0)
|
||||
case .compact:
|
||||
style = TGCheckButtonStyleCompact
|
||||
checkSize = CGSize(width: 30.0, height: 30.0)
|
||||
}
|
||||
let checkView = TGCheckButtonView(style: style, pallete: TGCheckButtonPallete(defaultBackgroundColor: self.fillColor, accentBackgroundColor: self.fillColor, defaultBorderColor: self.strokeColor, mediaBorderColor: self.strokeColor, chatBorderColor: self.strokeColor, check: self.foregroundColor, blueColor: self.fillColor, barBackgroundColor: self.fillColor))!
|
||||
checkView.setSelected(true, animated: false)
|
||||
checkView.layoutSubviews()
|
||||
checkView.setSelected(self.isChecked, animated: false)
|
||||
if let target = self.target, let action = self.action {
|
||||
checkView.addTarget(target, action: action, for: .touchUpInside)
|
||||
}
|
||||
self.checkView = checkView
|
||||
self.view.addSubview(checkView)
|
||||
|
||||
checkView.frame = CGRect(origin: CGPoint(), size: checkSize)
|
||||
}
|
||||
|
||||
public func setIsChecked(_ isChecked: Bool, animated: Bool) {
|
||||
if isChecked != self.isChecked {
|
||||
self.isChecked = isChecked
|
||||
self.checkView?.setSelected(isChecked, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
public func addTarget(target: AnyObject?, action: Selector) {
|
||||
self.target = target
|
||||
self.action = action
|
||||
if self.isNodeLoaded {
|
||||
self.checkView?.addTarget(target, action: action, for: .touchUpInside)
|
||||
}
|
||||
self.borderColor = borderColor
|
||||
self.overlayBorder = overlayBorder
|
||||
self.hasInset = hasInset
|
||||
self.hasShadow = hasShadow
|
||||
self.filledBorder = filledBorder
|
||||
self.borderWidth = borderWidth
|
||||
}
|
||||
}
|
||||
|
||||
public extension CheckNodeTheme {
|
||||
enum Style {
|
||||
case plain
|
||||
case overlay
|
||||
}
|
||||
|
||||
init(theme: PresentationTheme, style: Style, hasInset: Bool = false) {
|
||||
let borderColor: UIColor
|
||||
var hasInset = hasInset
|
||||
let overlayBorder: Bool
|
||||
let hasShadow: Bool
|
||||
switch style {
|
||||
case .plain:
|
||||
borderColor = theme.list.itemCheckColors.strokeColor
|
||||
overlayBorder = false
|
||||
hasShadow = false
|
||||
case .overlay:
|
||||
borderColor = UIColor(rgb: 0xffffff)
|
||||
hasInset = true
|
||||
overlayBorder = true
|
||||
hasShadow = true
|
||||
}
|
||||
|
||||
self.init(backgroundColor: theme.list.itemCheckColors.fillColor, strokeColor: theme.list.itemCheckColors.foregroundColor, borderColor: borderColor, overlayBorder: overlayBorder, hasInset: hasInset, hasShadow: hasShadow)
|
||||
}
|
||||
}
|
||||
|
||||
public enum CheckNodeContent {
|
||||
case check
|
||||
case counter(Int)
|
||||
}
|
||||
|
||||
private final class CheckNodeParameters: NSObject {
|
||||
let theme: CheckNodeTheme
|
||||
let content: CheckNodeContent
|
||||
let animationProgress: CGFloat
|
||||
let selected: Bool
|
||||
let animatingOut: Bool
|
||||
|
||||
init(theme: CheckNodeTheme, content: CheckNodeContent, animationProgress: CGFloat, selected: Bool, animatingOut: Bool) {
|
||||
self.theme = theme
|
||||
self.content = content
|
||||
self.animationProgress = animationProgress
|
||||
self.selected = selected
|
||||
self.animatingOut = animatingOut
|
||||
}
|
||||
}
|
||||
|
||||
public class CheckNode: ASDisplayNode {
|
||||
private var animatingOut = false
|
||||
private var animationProgress: CGFloat = 0.0
|
||||
public var theme: CheckNodeTheme {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public init(theme: CheckNodeTheme, content: CheckNodeContent = .check) {
|
||||
self.theme = theme
|
||||
self.content = content
|
||||
|
||||
super.init()
|
||||
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
public var content: CheckNodeContent {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public var selected = false
|
||||
public func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
guard self.selected != selected else {
|
||||
return
|
||||
}
|
||||
self.selected = selected
|
||||
|
||||
if animated {
|
||||
self.animatingOut = !selected
|
||||
|
||||
let animation = POPBasicAnimation()
|
||||
animation.property = (POPAnimatableProperty.property(withName: "progress", initializer: { property in
|
||||
property?.readBlock = { node, values in
|
||||
values?.pointee = (node as! CheckNode).animationProgress
|
||||
}
|
||||
property?.writeBlock = { node, values in
|
||||
(node as! CheckNode).animationProgress = values!.pointee
|
||||
(node as! CheckNode).setNeedsDisplay()
|
||||
}
|
||||
property?.threshold = 0.01
|
||||
}) as! POPAnimatableProperty)
|
||||
animation.fromValue = (selected ? 0.0 : 1.0) as NSNumber
|
||||
animation.toValue = (selected ? 1.0 : 0.0) as NSNumber
|
||||
animation.timingFunction = CAMediaTimingFunction(name: selected ? CAMediaTimingFunctionName.easeOut : CAMediaTimingFunctionName.easeIn)
|
||||
animation.duration = selected ? 0.21 : 0.15
|
||||
self.pop_add(animation, forKey: "progress")
|
||||
} else {
|
||||
self.pop_removeAllAnimations()
|
||||
self.animatingOut = false
|
||||
self.animationProgress = selected ? 1.0 : 0.0
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public func setHighlighted(_ highlighted: Bool, animated: Bool = false) {
|
||||
}
|
||||
|
||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
return CheckNodeParameters(theme: self.theme, content: self.content, animationProgress: self.animationProgress, selected: self.selected, animatingOut: self.animatingOut)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if !isRasterizing {
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(bounds)
|
||||
}
|
||||
|
||||
if let parameters = parameters as? CheckNodeParameters {
|
||||
let center = CGPoint(x: bounds.width / 2.0, y: bounds.width / 2.0)
|
||||
|
||||
var borderWidth: CGFloat = 1.0 + UIScreenPixel
|
||||
if parameters.theme.hasInset {
|
||||
borderWidth = 1.5
|
||||
}
|
||||
if let customBorderWidth = parameters.theme.borderWidth {
|
||||
borderWidth = customBorderWidth
|
||||
}
|
||||
|
||||
let checkWidth: CGFloat = 1.5
|
||||
|
||||
let inset: CGFloat = parameters.theme.hasInset ? 2.0 - UIScreenPixel : 0.0
|
||||
|
||||
let checkProgress = parameters.animatingOut ? 1.0 : parameters.animationProgress
|
||||
let fillProgress = parameters.animatingOut ? 1.0 : min(1.0, parameters.animationProgress * 1.35)
|
||||
|
||||
context.setStrokeColor(parameters.theme.borderColor.cgColor)
|
||||
context.setLineWidth(borderWidth)
|
||||
|
||||
let maybeScaleOut = {
|
||||
if parameters.animatingOut {
|
||||
context.translateBy(x: bounds.width / 2.0, y: bounds.height / 2.0)
|
||||
context.scaleBy(x: parameters.animationProgress, y: parameters.animationProgress)
|
||||
context.translateBy(x: -bounds.width / 2.0, y: -bounds.height / 2.0)
|
||||
|
||||
context.setAlpha(parameters.animationProgress)
|
||||
}
|
||||
}
|
||||
|
||||
let borderInset = borderWidth / 2.0 + inset
|
||||
let borderProgress: CGFloat = parameters.theme.filledBorder ? fillProgress : 1.0
|
||||
let borderFrame = bounds.insetBy(dx: borderInset, dy: borderInset)
|
||||
|
||||
if parameters.theme.filledBorder {
|
||||
maybeScaleOut()
|
||||
}
|
||||
|
||||
context.saveGState()
|
||||
if parameters.theme.hasShadow {
|
||||
context.setShadow(offset: CGSize(), blur: 2.5, color: UIColor(rgb: 0x000000, alpha: 0.22).cgColor)
|
||||
}
|
||||
|
||||
context.strokeEllipse(in: borderFrame.insetBy(dx: borderFrame.width * (1.0 - borderProgress), dy: borderFrame.height * (1.0 - borderProgress)))
|
||||
context.restoreGState()
|
||||
|
||||
if !parameters.theme.filledBorder {
|
||||
maybeScaleOut()
|
||||
}
|
||||
|
||||
context.setFillColor(parameters.theme.backgroundColor.cgColor)
|
||||
|
||||
let fillInset = parameters.theme.overlayBorder ? borderWidth + inset : inset
|
||||
let fillFrame = bounds.insetBy(dx: fillInset, dy: fillInset)
|
||||
context.fillEllipse(in: fillFrame.insetBy(dx: fillFrame.width * (1.0 - fillProgress), dy: fillFrame.height * (1.0 - fillProgress)))
|
||||
|
||||
let scale = (bounds.width - inset) / 18.0
|
||||
|
||||
let firstSegment: CGFloat = max(0.0, min(1.0, checkProgress * 3.0))
|
||||
let s = CGPoint(x: center.x - (4.0 - 0.3333) * scale, y: center.y + 0.5 * scale)
|
||||
let p1 = CGPoint(x: 2.5 * scale, y: 3.0 * scale)
|
||||
let p2 = CGPoint(x: 4.6667 * scale, y: -6.0 * scale)
|
||||
|
||||
if !firstSegment.isZero {
|
||||
if firstSegment < 1.0 {
|
||||
context.move(to: CGPoint(x: s.x + p1.x * firstSegment, y: s.y + p1.y * firstSegment))
|
||||
context.addLine(to: s)
|
||||
} else {
|
||||
let secondSegment = (checkProgress - 0.33) * 1.5
|
||||
context.move(to: CGPoint(x: s.x + p1.x + p2.x * secondSegment, y: s.y + p1.y + p2.y * secondSegment))
|
||||
context.addLine(to: CGPoint(x: s.x + p1.x, y: s.y + p1.y))
|
||||
context.addLine(to: s)
|
||||
}
|
||||
}
|
||||
|
||||
context.setStrokeColor(parameters.theme.strokeColor.cgColor)
|
||||
if parameters.theme.strokeColor == .clear {
|
||||
context.setBlendMode(.clear)
|
||||
}
|
||||
context.setLineWidth(checkWidth)
|
||||
context.setLineCap(.round)
|
||||
context.setLineJoin(.round)
|
||||
context.setMiterLimit(10.0)
|
||||
|
||||
context.strokePath()
|
||||
}
|
||||
}
|
||||
|
||||
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesBegan(touches, with: event)
|
||||
}
|
||||
|
||||
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesEnded(touches, with: event)
|
||||
}
|
||||
|
||||
override public func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
|
||||
super.touchesCancelled(touches, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
public class InteractiveCheckNode: CheckNode {
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
|
||||
public var valueChanged: ((Bool) -> Void)?
|
||||
|
||||
override public init(theme: CheckNodeTheme, content: CheckNodeContent = .check) {
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
super.init(theme: theme, content: content)
|
||||
|
||||
self.addSubnode(self.buttonNode)
|
||||
|
||||
self.buttonNode.addTarget(self, action: #selector(buttonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if highlighted {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .spring)
|
||||
transition.updateTransformScale(node: strongSelf, scale: 0.85)
|
||||
} else {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.5, curve: .spring)
|
||||
transition.updateTransformScale(node: strongSelf, scale: 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
self.setSelected(!self.selected, animated: true)
|
||||
self.valueChanged?(self.selected)
|
||||
}
|
||||
|
||||
public override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.buttonNode.frame = self.bounds
|
||||
}
|
||||
}
|
||||
|
@ -1,168 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import LegacyComponents
|
||||
|
||||
public struct CheckNodeTheme {
|
||||
public let backgroundColor: UIColor
|
||||
public let strokeColor: UIColor
|
||||
public let borderColor: UIColor
|
||||
public let hasShadow: Bool
|
||||
|
||||
public init(backgroundColor: UIColor, strokeColor: UIColor, borderColor: UIColor, hasShadow: Bool) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.strokeColor = strokeColor
|
||||
self.borderColor = borderColor
|
||||
self.hasShadow = hasShadow
|
||||
}
|
||||
}
|
||||
|
||||
public enum CheckNodeContent {
|
||||
case check
|
||||
case counter(Int)
|
||||
}
|
||||
|
||||
private final class CheckNodeParameters: NSObject {
|
||||
let theme: CheckNodeTheme
|
||||
let content: CheckNodeContent
|
||||
let animationProgress: CGFloat
|
||||
let selected: Bool
|
||||
|
||||
init(theme: CheckNodeTheme, content: CheckNodeContent, animationProgress: CGFloat, selected: Bool) {
|
||||
self.theme = theme
|
||||
self.content = content
|
||||
self.animationProgress = animationProgress
|
||||
self.selected = selected
|
||||
}
|
||||
}
|
||||
|
||||
public class ModernCheckNode: ASDisplayNode {
|
||||
private var animationProgress: CGFloat = 0.0
|
||||
public var theme: CheckNodeTheme {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public init(theme: CheckNodeTheme, content: CheckNodeContent = .check) {
|
||||
self.theme = theme
|
||||
self.content = content
|
||||
|
||||
super.init()
|
||||
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
public var content: CheckNodeContent {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public var selected = false
|
||||
public func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
guard self.selected != selected else {
|
||||
return
|
||||
}
|
||||
self.selected = selected
|
||||
|
||||
if selected && animated {
|
||||
let animation = POPBasicAnimation()
|
||||
animation.property = (POPAnimatableProperty.property(withName: "progress", initializer: { property in
|
||||
property?.readBlock = { node, values in
|
||||
values?.pointee = (node as! ModernCheckNode).animationProgress
|
||||
}
|
||||
property?.writeBlock = { node, values in
|
||||
(node as! ModernCheckNode).animationProgress = values!.pointee
|
||||
(node as! ModernCheckNode).setNeedsDisplay()
|
||||
}
|
||||
property?.threshold = 0.01
|
||||
}) as! POPAnimatableProperty)
|
||||
animation.fromValue = 0.0 as NSNumber
|
||||
animation.toValue = 1.0 as NSNumber
|
||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||
animation.duration = 0.21
|
||||
self.pop_add(animation, forKey: "progress")
|
||||
} else {
|
||||
self.pop_removeAllAnimations()
|
||||
self.animationProgress = selected ? 1.0 : 0.0
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public func setHighlighted(_ highlighted: Bool, animated: Bool = false) {
|
||||
}
|
||||
|
||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
return CheckNodeParameters(theme: self.theme, content: self.content, animationProgress: self.animationProgress, selected: self.selected)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if !isRasterizing {
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(bounds)
|
||||
}
|
||||
|
||||
if let parameters = parameters as? CheckNodeParameters {
|
||||
let progress = parameters.animationProgress
|
||||
let diameter = bounds.width
|
||||
let center = CGPoint(x: diameter / 2.0, y: diameter / 2.0)
|
||||
|
||||
var borderWidth: CGFloat = 1.5
|
||||
if UIScreenScale == 3.0 {
|
||||
borderWidth = 5.0 / 3.0
|
||||
}
|
||||
|
||||
context.setStrokeColor(parameters.theme.borderColor.cgColor)
|
||||
context.setLineWidth(borderWidth)
|
||||
context.strokeEllipse(in: bounds.insetBy(dx: borderWidth / 2.0, dy: borderWidth / 2.0))
|
||||
|
||||
context.setFillColor(parameters.theme.backgroundColor.cgColor)
|
||||
context.fillEllipse(in: bounds.insetBy(dx: (diameter - borderWidth) * (1.0 - parameters.animationProgress), dy: (diameter - borderWidth) * (1.0 - parameters.animationProgress)))
|
||||
|
||||
let firstSegment: CGFloat = max(0.0, min(1.0, progress * 3.0))
|
||||
let s = CGPoint(x: center.x - 4.0, y: center.y + UIScreenPixel)
|
||||
let p1 = CGPoint(x: 3.0, y: 3.0)
|
||||
let p2 = CGPoint(x: 5.0, y: -6.0)
|
||||
|
||||
if !firstSegment.isZero {
|
||||
if firstSegment < 1.0 {
|
||||
context.move(to: CGPoint(x: s.x + p1.x * firstSegment, y: s.y + p1.y * firstSegment))
|
||||
context.addLine(to: s)
|
||||
} else {
|
||||
let secondSegment = (progress - 0.33) * 1.5
|
||||
context.move(to: CGPoint(x: s.x + p1.x + p2.x * secondSegment, y: s.y + p1.y + p2.y * secondSegment))
|
||||
context.addLine(to: CGPoint(x: s.x + p1.x, y: s.y + p1.y))
|
||||
context.addLine(to: s)
|
||||
}
|
||||
}
|
||||
|
||||
context.setStrokeColor(parameters.theme.strokeColor.cgColor)
|
||||
if parameters.theme.strokeColor == .clear {
|
||||
context.setBlendMode(.clear)
|
||||
}
|
||||
context.setLineWidth(borderWidth)
|
||||
context.setLineCap(.round)
|
||||
context.setLineJoin(.round)
|
||||
context.setMiterLimit(10.0)
|
||||
|
||||
context.strokePath()
|
||||
}
|
||||
}
|
||||
|
||||
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesBegan(touches, with: event)
|
||||
}
|
||||
|
||||
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesEnded(touches, with: event)
|
||||
}
|
||||
|
||||
override public func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
|
||||
super.touchesCancelled(touches, with: event)
|
||||
}
|
||||
}
|
@ -97,7 +97,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
private let maskNode: ASImageNode
|
||||
|
||||
private var checkNode: CheckNode?
|
||||
private var checkNode: InteractiveCheckNode?
|
||||
|
||||
private let textClippingNode: ASDisplayNode
|
||||
private let textNode: EditableTextNode
|
||||
@ -162,10 +162,6 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
self.containerNode.addSubnode(self.textLimitNode)
|
||||
}
|
||||
|
||||
@objc private func checkNodePressed() {
|
||||
self.item?.toggleSelected()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
@ -360,16 +356,18 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
|
||||
strongSelf.textNode.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
let checkFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + 11.0, y: floor((layout.contentSize.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
let checkSize = CGSize(width: 22.0, height: 22.0)
|
||||
let checkFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + 16.0, y: floor((layout.contentSize.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
if let isSelected = item.isSelected {
|
||||
if let checkNode = strongSelf.checkNode {
|
||||
transition.updateFrame(node: checkNode, frame: checkFrame)
|
||||
checkNode.setIsChecked(isSelected, animated: true)
|
||||
checkNode.setSelected(isSelected, animated: true)
|
||||
} else {
|
||||
let checkNode = CheckNode(strokeColor: item.presentationData.theme.list.itemCheckColors.strokeColor, fillColor: item.presentationData.theme.list.itemSwitchColors.positiveColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, style: .plain)
|
||||
checkNode.addTarget(target: strongSelf, action: #selector(strongSelf.checkNodePressed))
|
||||
checkNode.setIsChecked(isSelected, animated: false)
|
||||
let checkNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: item.presentationData.theme.list.itemSwitchColors.positiveColor, strokeColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, borderColor: item.presentationData.theme.list.itemCheckColors.strokeColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||
checkNode.setSelected(isSelected, animated: false)
|
||||
checkNode.valueChanged = { [weak self] value in
|
||||
self?.item?.toggleSelected()
|
||||
}
|
||||
strongSelf.checkNode = checkNode
|
||||
strongSelf.containerNode.addSubnode(checkNode)
|
||||
checkNode.frame = checkFrame
|
||||
|
@ -535,7 +535,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
selectionNode = current
|
||||
updatedSelectionNode = selectionNode
|
||||
} else {
|
||||
selectionNode = CheckNode(strokeColor: item.presentationData.theme.list.itemCheckColors.strokeColor, fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, style: .plain)
|
||||
selectionNode = CheckNode(theme: CheckNodeTheme(theme: item.presentationData.theme, style: .plain))
|
||||
selectionNode.isUserInteractionEnabled = false
|
||||
updatedSelectionNode = selectionNode
|
||||
}
|
||||
@ -1004,9 +1004,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.selectionNode = updatedSelectionNode
|
||||
strongSelf.addSubnode(updatedSelectionNode)
|
||||
}
|
||||
updatedSelectionNode.setIsChecked(isSelected, animated: animated)
|
||||
updatedSelectionNode.setSelected(isSelected, animated: animated)
|
||||
|
||||
updatedSelectionNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 32.0 - 12.0, y: floor((nodeLayout.contentSize.height - 32.0) / 2.0)), size: CGSize(width: 32.0, height: 32.0))
|
||||
updatedSelectionNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 22.0 - 17.0, y: floor((nodeLayout.contentSize.height - 22.0) / 2.0)), size: CGSize(width: 22.0, height: 22.0))
|
||||
} else if let selectionNode = strongSelf.selectionNode {
|
||||
selectionNode.removeFromSupernode()
|
||||
strongSelf.selectionNode = nil
|
||||
|
@ -74,13 +74,14 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
||||
self.checkNode = ASImageNode()
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
self.checkNode.displaysAsynchronously = false
|
||||
self.checkNode.image = generateImage(CGSize(width: 14.0, height: 11.0), rotatedContext: { size, context in
|
||||
self.checkNode.image = generateImage(CGSize(width: 14.0, height: 12.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setStrokeColor(theme.controlAccentColor.cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
context.move(to: CGPoint(x: 12.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 4.16482734, y: 9.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: 5.81145833))
|
||||
context.setLineWidth(2.0 - UIScreenPixel)
|
||||
context.setLineCap(.round)
|
||||
context.move(to: CGPoint(x: 13.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 5.0, y: 11.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: 7.0))
|
||||
context.strokePath()
|
||||
})
|
||||
self.checkNode.isAccessibilityElement = false
|
||||
@ -146,8 +147,8 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
||||
|
||||
self.button.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
var titleOrigin: CGFloat = 44.0
|
||||
var checkOrigin: CGFloat = 22.0
|
||||
var titleOrigin: CGFloat = 50.0
|
||||
var checkOrigin: CGFloat = 27.0
|
||||
if let item = self.item, item.style == .alignRight {
|
||||
titleOrigin = 24.0
|
||||
checkOrigin = size.width - 22.0
|
||||
|
@ -15,11 +15,13 @@ public final class AlertControllerTheme: Equatable {
|
||||
public let primaryColor: UIColor
|
||||
public let secondaryColor: UIColor
|
||||
public let accentColor: UIColor
|
||||
public let contrastColor: UIColor
|
||||
public let destructiveColor: UIColor
|
||||
public let disabledColor: UIColor
|
||||
public let controlBorderColor: UIColor
|
||||
public let baseFontSize: CGFloat
|
||||
|
||||
public init(backgroundType: ActionSheetControllerThemeBackgroundType, backgroundColor: UIColor, separatorColor: UIColor, highlightedItemColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, accentColor: UIColor, destructiveColor: UIColor, disabledColor: UIColor, baseFontSize: CGFloat) {
|
||||
public init(backgroundType: ActionSheetControllerThemeBackgroundType, backgroundColor: UIColor, separatorColor: UIColor, highlightedItemColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, accentColor: UIColor, contrastColor: UIColor, destructiveColor: UIColor, disabledColor: UIColor, controlBorderColor: UIColor, baseFontSize: CGFloat) {
|
||||
self.backgroundType = backgroundType
|
||||
self.backgroundColor = backgroundColor
|
||||
self.separatorColor = separatorColor
|
||||
@ -27,8 +29,10 @@ public final class AlertControllerTheme: Equatable {
|
||||
self.primaryColor = primaryColor
|
||||
self.secondaryColor = secondaryColor
|
||||
self.accentColor = accentColor
|
||||
self.contrastColor = contrastColor
|
||||
self.destructiveColor = destructiveColor
|
||||
self.disabledColor = disabledColor
|
||||
self.controlBorderColor = controlBorderColor
|
||||
self.baseFontSize = baseFontSize
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,22 @@ import TelegramPresentationData
|
||||
import CheckNode
|
||||
|
||||
public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCustomDisplayNode {
|
||||
private var checkNode: CheckNode
|
||||
private var checkNode: InteractiveCheckNode
|
||||
private weak var target: AnyObject?
|
||||
private var action: Selector?
|
||||
|
||||
public init(theme: PresentationTheme) {
|
||||
self.checkNode = CheckNode(strokeColor: theme.list.itemCheckColors.strokeColor, fillColor: theme.list.itemCheckColors.fillColor, foregroundColor: theme.list.itemCheckColors.foregroundColor, style: .navigation)
|
||||
self.checkNode = InteractiveCheckNode(theme: CheckNodeTheme(theme: theme, style: .overlay))
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.checkNode)
|
||||
|
||||
self.checkNode.valueChanged = { [weak self] value in
|
||||
if let strongSelf = self, let target = strongSelf.target, let action = strongSelf.action {
|
||||
let _ = target.perform(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var isHighlightable: Bool {
|
||||
@ -21,15 +29,16 @@ public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCu
|
||||
}
|
||||
|
||||
public var isChecked: Bool {
|
||||
return self.checkNode.isChecked
|
||||
return self.checkNode.selected
|
||||
}
|
||||
|
||||
public func setIsChecked(_ isChecked: Bool, animated: Bool) {
|
||||
self.checkNode.setIsChecked(isChecked, animated: animated)
|
||||
self.checkNode.setSelected(isChecked, animated: animated)
|
||||
}
|
||||
|
||||
public func addTarget(target: AnyObject?, action: Selector) {
|
||||
self.checkNode.addTarget(target: target, action: action)
|
||||
self.target = target
|
||||
self.action = action
|
||||
}
|
||||
|
||||
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
@ -40,7 +49,7 @@ public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCu
|
||||
super.layout()
|
||||
|
||||
let size = self.bounds.size
|
||||
let checkSize = CGSize(width: 39.0, height: 39.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: floor((size.width - checkSize.width) / 2.0) + 11.0, y: floor((size.height - checkSize.height) / 2.0) + 3.0), size: checkSize)
|
||||
let checkSize = CGSize(width: 36.0, height: 36.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - checkSize.width) / 2.0) + 11.0, y: floorToScreenPixels((size.height - checkSize.height) / 2.0) + 3.0), size: checkSize)
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ public final class GridMessageSelectionNode: ASDisplayNode {
|
||||
|
||||
public init(theme: PresentationTheme, toggle: @escaping (Bool) -> Void) {
|
||||
self.toggle = toggle
|
||||
self.checkNode = CheckNode(strokeColor: theme.list.itemCheckColors.strokeColor, fillColor: theme.list.itemCheckColors.fillColor, foregroundColor: theme.list.itemCheckColors.foregroundColor, style: .overlay)
|
||||
self.checkNode = CheckNode(theme: CheckNodeTheme(theme: theme, style: .overlay, hasInset: true))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
@ -42,7 +42,7 @@ public final class GridMessageSelectionNode: ASDisplayNode {
|
||||
public func updateSelected(_ selected: Bool, animated: Bool) {
|
||||
if self.selected != selected {
|
||||
self.selected = selected
|
||||
self.checkNode.setIsChecked(selected, animated: animated)
|
||||
self.checkNode.setSelected(selected, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public final class GridMessageSelectionNode: ASDisplayNode {
|
||||
override public func layout() {
|
||||
super.layout()
|
||||
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: self.bounds.size.width - checkSize.width, y: 0.0), size: checkSize)
|
||||
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: self.bounds.size.width - checkSize.width - 2.0, y: 2.0), size: checkSize)
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public final class ItemListSelectableControlNode: ASDisplayNode {
|
||||
private let checkNode: CheckNode
|
||||
|
||||
public init(strokeColor: UIColor, fillColor: UIColor, foregroundColor: UIColor) {
|
||||
self.checkNode = CheckNode(strokeColor: strokeColor, fillColor: fillColor, foregroundColor: foregroundColor, style: .plain)
|
||||
self.checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: fillColor, strokeColor: foregroundColor, borderColor: strokeColor, overlayBorder: false, hasInset: true, hasShadow: false))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
@ -26,9 +26,9 @@ public final class ItemListSelectableControlNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
return (compact ? 38.0 : 45.0, { size, animated in
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
resultNode.checkNode.frame = CGRect(origin: CGPoint(x: compact ? 9 : 12.0, y: floor((size.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
resultNode.checkNode.setIsChecked(selected, animated: animated)
|
||||
let checkSize = CGSize(width: 26.0, height: 26.0)
|
||||
resultNode.checkNode.frame = CGRect(origin: CGPoint(x: compact ? 11.0 : 13.0, y: floorToScreenPixels((size.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
resultNode.checkNode.setSelected(selected, animated: animated)
|
||||
return resultNode
|
||||
})
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ swift_library(
|
||||
"//submodules/ContextUI:ContextUI",
|
||||
"//submodules/LocalizedPeerData:LocalizedPeerData",
|
||||
"//submodules/AccountContext:AccountContext",
|
||||
"//submodules/CheckNode:CheckNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -13,6 +13,7 @@ import LegacyComponents
|
||||
import ContextUI
|
||||
import LocalizedPeerData
|
||||
import AccountContext
|
||||
import CheckNode
|
||||
|
||||
private let avatarFont = avatarPlaceholderFont(size: 24.0)
|
||||
private let textFont = Font.regular(11.0)
|
||||
@ -71,7 +72,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
||||
private let avatarNodeContainer: ASDisplayNode
|
||||
private let avatarNode: AvatarNode
|
||||
private let onlineNode: PeerOnlineMarkerNode
|
||||
private var checkView: TGCheckButtonView?
|
||||
private var checkNode: CheckNode?
|
||||
private let textNode: ASTextNode
|
||||
|
||||
public var toggleSelection: (() -> Void)?
|
||||
@ -209,23 +210,20 @@ public final class SelectablePeerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
if selected {
|
||||
if self.checkView == nil {
|
||||
let checkView = TGCheckButtonView(style: TGCheckButtonStyleShare, pallete: TGCheckButtonPallete(defaultBackgroundColor: self.theme.checkBackgroundColor, accentBackgroundColor: self.theme.checkFillColor, defaultBorderColor: .clear, mediaBorderColor: .clear, chatBorderColor: .clear, check: self.theme.checkColor, blueColor: self.theme.checkFillColor, barBackgroundColor: self.theme.checkBackgroundColor))!
|
||||
|
||||
self.checkView = checkView
|
||||
checkView.isUserInteractionEnabled = false
|
||||
self.view.addSubview(checkView)
|
||||
if self.checkNode == nil {
|
||||
let checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: self.theme.checkFillColor, strokeColor: self.theme.checkColor, borderColor: self.theme.checkBackgroundColor, overlayBorder: true, hasInset: false, hasShadow: false, filledBorder: true, borderWidth: 2.0))
|
||||
self.checkNode = checkNode
|
||||
checkNode.isUserInteractionEnabled = false
|
||||
self.addSubnode(checkNode)
|
||||
|
||||
let avatarFrame = self.avatarNode.frame
|
||||
let checkSize = checkView.bounds.size
|
||||
checkView.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 14.0, y: avatarFrame.maxY - 22.0), size: checkSize)
|
||||
checkView.setSelected(true, animated: animated)
|
||||
let checkSize = CGSize(width: 24.0, height: 24.0)
|
||||
checkNode.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 10.0, y: avatarFrame.maxY - 18.0), size: checkSize)
|
||||
checkNode.setSelected(true, animated: animated)
|
||||
}
|
||||
} else if let checkView = self.checkView {
|
||||
self.checkView = nil
|
||||
checkView.setSelected(false, animated: animated, bump: false, completion: { [weak checkView] in
|
||||
checkView?.removeFromSuperview()
|
||||
})
|
||||
} else if let checkNode = self.checkNode {
|
||||
self.checkNode = nil
|
||||
checkNode.setSelected(false, animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,9 +255,9 @@ public final class SelectablePeerNode: ASDisplayNode {
|
||||
|
||||
self.onlineNode.frame = CGRect(origin: CGPoint(x: avatarContainerFrame.maxX - self.onlineNode.frame.width - 2.0, y: avatarContainerFrame.maxY - self.onlineNode.frame.height - 2.0), size: self.onlineNode.frame.size)
|
||||
|
||||
if let checkView = self.checkView {
|
||||
let checkSize = checkView.bounds.size
|
||||
checkView.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 14.0, y: avatarFrame.maxY - 22.0), size: checkSize)
|
||||
if let checkNode = self.checkNode {
|
||||
let checkSize = CGSize(width: 24.0, height: 24.0)
|
||||
checkNode.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 10.0, y: avatarFrame.maxY - 18.0), size: checkSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,11 +159,11 @@ private enum NotificationPeerExceptionEntry: ItemListNodeEntry {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! NotificationPeerExceptionArguments
|
||||
switch self {
|
||||
case let .remove(_, theme, strings):
|
||||
case let .remove(_, _, strings):
|
||||
return ItemListActionItem(presentationData: presentationData, title: strings.Notification_Exceptions_RemoveFromExceptions, kind: .generic, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.removeFromExceptions()
|
||||
})
|
||||
case let .switcher(_, theme, strings, mode, selected):
|
||||
case let .switcher(_, _, strings, mode, selected):
|
||||
let title: String
|
||||
switch mode {
|
||||
case .alwaysOn:
|
||||
@ -174,9 +174,9 @@ private enum NotificationPeerExceptionEntry: ItemListNodeEntry {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectMode(mode)
|
||||
})
|
||||
case let .switcherHeader(_, theme, text):
|
||||
case let .switcherHeader(_, _, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .displayPreviews(_, theme, strings, value, selected):
|
||||
case let .displayPreviews(_, _, strings, value, selected):
|
||||
let title: String
|
||||
switch value {
|
||||
case .alwaysOn:
|
||||
@ -187,21 +187,21 @@ private enum NotificationPeerExceptionEntry: ItemListNodeEntry {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectDisplayPreviews(value)
|
||||
})
|
||||
case let .displayPreviewsHeader(_, theme, text):
|
||||
case let .displayPreviewsHeader(_, _, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .soundModernHeader(_, theme, text):
|
||||
case let .soundModernHeader(_, _, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .soundClassicHeader(_, theme, text):
|
||||
case let .soundClassicHeader(_, _, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .none(_, _, theme, text, selected):
|
||||
case let .none(_, _, _, text, selected):
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
|
||||
arguments.selectSound(.none)
|
||||
})
|
||||
case let .default(_, _, theme, text, selected):
|
||||
case let .default(_, _, _, text, selected):
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectSound(.default)
|
||||
})
|
||||
case let .sound(_, _, theme, text, sound, selected):
|
||||
case let .sound(_, _, _, text, sound, selected):
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectSound(sound)
|
||||
})
|
||||
|
@ -13,7 +13,7 @@ enum WallpaperOptionButtonValue {
|
||||
|
||||
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let checkNode: ModernCheckNode
|
||||
private let checkNode: CheckNode
|
||||
private let colorNode: ASImageNode
|
||||
private let textNode: ASTextNode
|
||||
|
||||
@ -45,7 +45,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
self.backgroundNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.3)
|
||||
self.backgroundNode.cornerRadius = 14.0
|
||||
|
||||
self.checkNode = ModernCheckNode(theme: CheckNodeTheme(backgroundColor: .white, strokeColor: .clear, borderColor: .white, hasShadow: false))
|
||||
self.checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: .white, strokeColor: .clear, borderColor: .white, overlayBorder: false, hasInset: false, hasShadow: false, borderWidth: 1.5))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
self.colorNode = ASImageNode()
|
||||
|
@ -94,13 +94,13 @@ public extension ActionSheetController {
|
||||
public extension AlertControllerTheme {
|
||||
convenience init(presentationTheme: PresentationTheme, fontSize: PresentationFontSize) {
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, baseFontSize: fontSize.baseDisplaySize)
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, contrastColor: presentationTheme.list.itemCheckColors.foregroundColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, controlBorderColor: presentationTheme.list.itemCheckColors.strokeColor, baseFontSize: fontSize.baseDisplaySize)
|
||||
}
|
||||
|
||||
convenience init(presentationData: PresentationData) {
|
||||
let presentationTheme = presentationData.theme
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, baseFontSize: presentationData.listsFontSize.baseDisplaySize)
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, contrastColor: presentationData.theme.list.itemCheckColors.foregroundColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, controlBorderColor: presentationData.theme.list.itemCheckColors.strokeColor, baseFontSize: presentationData.listsFontSize.baseDisplaySize)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
|
||||
private let titleNode: ASTextNode
|
||||
private let textNode: ASTextNode
|
||||
private let authorizeCheckNode: CheckNode
|
||||
private let authorizeCheckNode: InteractiveCheckNode
|
||||
private let authorizeLabelNode: ASTextNode
|
||||
private let allowWriteCheckNode: CheckNode
|
||||
private let allowWriteCheckNode: InteractiveCheckNode
|
||||
private let allowWriteLabelNode: ASTextNode
|
||||
|
||||
private let actionNodesSeparator: ASDisplayNode
|
||||
@ -47,7 +47,7 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
|
||||
var authorize: Bool = true {
|
||||
didSet {
|
||||
self.authorizeCheckNode.setIsChecked(self.authorize, animated: true)
|
||||
self.authorizeCheckNode.setSelected(self.authorize, animated: true)
|
||||
self.allowWriteCheckNode.isUserInteractionEnabled = self.authorize
|
||||
self.allowWriteCheckNode.alpha = self.authorize ? 1.0 : 0.4
|
||||
self.allowWriteLabelNode.alpha = self.authorize ? 1.0 : 0.4
|
||||
@ -59,7 +59,7 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
|
||||
var allowWriteAccess: Bool = true {
|
||||
didSet {
|
||||
self.allowWriteCheckNode.setIsChecked(self.allowWriteAccess, animated: true)
|
||||
self.allowWriteCheckNode.setSelected(self.allowWriteAccess, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,14 +77,14 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
|
||||
self.authorizeCheckNode = CheckNode(strokeColor: theme.separatorColor, fillColor: theme.accentColor, foregroundColor: .white, style: .plain)
|
||||
self.authorizeCheckNode.setIsChecked(true, animated: false)
|
||||
self.authorizeCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||
self.authorizeCheckNode.setSelected(true, animated: false)
|
||||
self.authorizeLabelNode = ASTextNode()
|
||||
self.authorizeLabelNode.maximumNumberOfLines = 4
|
||||
self.authorizeLabelNode.isUserInteractionEnabled = true
|
||||
|
||||
self.allowWriteCheckNode = CheckNode(strokeColor: theme.separatorColor, fillColor: theme.accentColor, foregroundColor: .white, style: .plain)
|
||||
self.allowWriteCheckNode.setIsChecked(true, animated: false)
|
||||
self.allowWriteCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||
self.allowWriteCheckNode.setSelected(true, animated: false)
|
||||
self.allowWriteLabelNode = ASTextNode()
|
||||
self.allowWriteLabelNode.maximumNumberOfLines = 4
|
||||
self.allowWriteLabelNode.isUserInteractionEnabled = true
|
||||
@ -128,8 +128,16 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
self.addSubnode(separatorNode)
|
||||
}
|
||||
|
||||
self.authorizeCheckNode.addTarget(target: self, action: #selector(self.authorizePressed))
|
||||
self.allowWriteCheckNode.addTarget(target: self, action: #selector(self.allowWritePressed))
|
||||
self.authorizeCheckNode.valueChanged = { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.authorize = !strongSelf.authorize
|
||||
}
|
||||
}
|
||||
self.allowWriteCheckNode.valueChanged = { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.allowWriteAccess = !strongSelf.allowWriteAccess
|
||||
}
|
||||
}
|
||||
|
||||
self.updateTheme(theme)
|
||||
}
|
||||
@ -141,10 +149,6 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
self.allowWriteLabelNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.allowWriteTap(_:))))
|
||||
}
|
||||
|
||||
@objc private func authorizePressed() {
|
||||
self.authorize = !self.authorize
|
||||
}
|
||||
|
||||
@objc private func authorizeTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||
self.authorize = !self.authorize
|
||||
}
|
||||
@ -155,10 +159,6 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func allowWritePressed() {
|
||||
self.allowWriteAccess = !self.allowWriteAccess
|
||||
}
|
||||
|
||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.Conversation_OpenBotLinkTitle, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
@ -196,14 +196,14 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
|
||||
origin.y += textSize.height + 16.0
|
||||
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
let checkSize = CGSize(width: 22.0, height: 22.0)
|
||||
let condensedSize = CGSize(width: size.width - 76.0, height: size.height)
|
||||
|
||||
var entriesHeight: CGFloat = 0.0
|
||||
|
||||
let authorizeSize = self.authorizeLabelNode.measure(condensedSize)
|
||||
transition.updateFrame(node: self.authorizeLabelNode, frame: CGRect(origin: CGPoint(x: 46.0, y: origin.y), size: authorizeSize))
|
||||
transition.updateFrame(node: self.authorizeCheckNode, frame: CGRect(origin: CGPoint(x: 7.0, y: origin.y - 7.0), size: checkSize))
|
||||
transition.updateFrame(node: self.authorizeCheckNode, frame: CGRect(origin: CGPoint(x: 12.0, y: origin.y - 2.0), size: checkSize))
|
||||
origin.y += authorizeSize.height
|
||||
entriesHeight += authorizeSize.height
|
||||
|
||||
@ -213,7 +213,7 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
||||
|
||||
let allowWriteSize = self.allowWriteLabelNode.measure(condensedSize)
|
||||
transition.updateFrame(node: self.allowWriteLabelNode, frame: CGRect(origin: CGPoint(x: 46.0, y: origin.y), size: allowWriteSize))
|
||||
transition.updateFrame(node: self.allowWriteCheckNode, frame: CGRect(origin: CGPoint(x: 7.0, y: origin.y - 7.0), size: checkSize))
|
||||
transition.updateFrame(node: self.allowWriteCheckNode, frame: CGRect(origin: CGPoint(x: 12.0, y: origin.y - 2.0), size: checkSize))
|
||||
origin.y += allowWriteSize.height
|
||||
entriesHeight += allowWriteSize.height
|
||||
}
|
||||
|
@ -1128,7 +1128,7 @@ final class FileMessageSelectionNode: ASDisplayNode {
|
||||
public init(theme: PresentationTheme, incoming: Bool, noPreview: Bool, toggle: @escaping (Bool) -> Void) {
|
||||
self.noPreview = noPreview
|
||||
self.toggle = toggle
|
||||
self.checkNode = CheckNode(strokeColor: incoming ? theme.chat.message.incoming.mediaPlaceholderColor : theme.chat.message.outgoing.mediaPlaceholderColor, fillColor: theme.list.itemCheckColors.fillColor, foregroundColor: theme.list.itemCheckColors.foregroundColor, style: noPreview ? .compact : .overlay)
|
||||
self.checkNode = CheckNode(theme: noPreview ? CheckNodeTheme(backgroundColor: theme.list.itemCheckColors.fillColor, strokeColor: theme.list.itemCheckColors.foregroundColor, borderColor: incoming ? theme.chat.message.incoming.mediaPlaceholderColor : theme.chat.message.outgoing.mediaPlaceholderColor, overlayBorder: false, hasInset: false, hasShadow: false) : CheckNodeTheme(theme: theme, style: .overlay))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
@ -1157,7 +1157,7 @@ final class FileMessageSelectionNode: ASDisplayNode {
|
||||
public func updateSelected(_ selected: Bool, animated: Bool) {
|
||||
if self.selected != selected {
|
||||
self.selected = selected
|
||||
self.checkNode.setIsChecked(selected, animated: animated)
|
||||
self.checkNode.setSelected(selected, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1170,12 +1170,14 @@ final class FileMessageSelectionNode: ASDisplayNode {
|
||||
override public func layout() {
|
||||
super.layout()
|
||||
|
||||
let checkSize = CGSize(width: 30.0, height: 30.0)
|
||||
let checkSize: CGSize
|
||||
let checkOrigin: CGPoint
|
||||
if self.noPreview {
|
||||
checkOrigin = CGPoint(x: 23.0, y: 20.0)
|
||||
checkSize = CGSize(width: 20.0, height: 20.0)
|
||||
checkOrigin = CGPoint(x: 29.0, y: 26.0)
|
||||
} else {
|
||||
checkOrigin = CGPoint(x: 39.0, y: -5.0)
|
||||
checkSize = CGSize(width: 28.0, height: 28.0)
|
||||
checkOrigin = CGPoint(x: 41.0, y: -3.0)
|
||||
}
|
||||
self.checkNode.frame = CGRect(origin: checkOrigin, size: checkSize)
|
||||
}
|
||||
|
@ -14,21 +14,19 @@ final class ChatMessageSelectionNode: ASDisplayNode {
|
||||
init(wallpaper: TelegramWallpaper, theme: PresentationTheme, toggle: @escaping (Bool) -> Void) {
|
||||
self.toggle = toggle
|
||||
|
||||
let style: CheckNodeStyle
|
||||
let style: CheckNodeTheme.Style
|
||||
if wallpaper == theme.chat.defaultWallpaper, case .color = wallpaper {
|
||||
style = .plain
|
||||
} else {
|
||||
style = .overlay
|
||||
}
|
||||
|
||||
self.checkNode = CheckNode(strokeColor: theme.list.itemCheckColors.strokeColor, fillColor: theme.list.itemCheckColors.fillColor, foregroundColor: theme.list.itemCheckColors.foregroundColor, style: style)
|
||||
self.checkNode = CheckNode(theme: CheckNodeTheme(theme: theme, style: style, hasInset: true))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.checkNode)
|
||||
|
||||
//self.hitTestSlop = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -40,7 +38,7 @@ final class ChatMessageSelectionNode: ASDisplayNode {
|
||||
func updateSelected(_ selected: Bool, animated: Bool) {
|
||||
if self.selected != selected {
|
||||
self.selected = selected
|
||||
self.checkNode.setIsChecked(selected, animated: animated)
|
||||
self.checkNode.setSelected(selected, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +49,7 @@ final class ChatMessageSelectionNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, leftInset: CGFloat) {
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: 4.0 + leftInset, y: floor((size.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: 6.0 + leftInset, y: floor((size.height - checkSize.height) / 2.0)), size: checkSize)
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,6 @@ class WebSearchGalleryController: ViewController {
|
||||
if let checkNode = self.checkNode, let controllerInteraction = self.controllerInteraction, let centralItemNode = self.galleryNode.pager.centralItemNode() as? WebSearchVideoGalleryItemNode, let item = centralItemNode.item {
|
||||
let legacyItem = LegacyWebSearchItem(result: item.result)
|
||||
|
||||
checkNode.setIsChecked(!checkNode.isChecked, animated: true)
|
||||
controllerInteraction.selectionState?.setItem(legacyItem, selected: checkNode.isChecked)
|
||||
}
|
||||
}
|
||||
|
@ -210,17 +210,12 @@ final class WebSearchItemNode: GridItemNode {
|
||||
self.updateSelectionState(animated: false)
|
||||
}
|
||||
|
||||
@objc func toggleSelection() {
|
||||
if let checkNode = self.checkNode, let item = self.item {
|
||||
checkNode.setIsChecked(!checkNode.isChecked, animated: true)
|
||||
item.controllerInteraction.toggleSelection(item.result, checkNode.isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
func updateSelectionState(animated: Bool) {
|
||||
if self.checkNode == nil, let item = self.item, let _ = item.controllerInteraction.selectionState {
|
||||
let checkNode = CheckNode(strokeColor: item.theme.list.itemCheckColors.strokeColor, fillColor: item.theme.list.itemCheckColors.fillColor, foregroundColor: item.theme.list.itemCheckColors.foregroundColor, style: .overlay)
|
||||
checkNode.addTarget(target: self, action: #selector(self.toggleSelection))
|
||||
let checkNode = InteractiveCheckNode(theme: CheckNodeTheme(theme: item.theme, style: .overlay))
|
||||
checkNode.valueChanged = { value in
|
||||
item.controllerInteraction.toggleSelection(item.result, value)
|
||||
}
|
||||
self.addSubnode(checkNode)
|
||||
self.checkNode = checkNode
|
||||
self.setNeedsLayout()
|
||||
@ -229,7 +224,7 @@ final class WebSearchItemNode: GridItemNode {
|
||||
if let item = self.item {
|
||||
if let selectionState = item.controllerInteraction.selectionState {
|
||||
let selected = selectionState.isIdentifierSelected(item.result.id)
|
||||
self.checkNode?.setIsChecked(selected, animated: animated)
|
||||
self.checkNode?.setSelected(selected, animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,8 +256,8 @@ final class WebSearchItemNode: GridItemNode {
|
||||
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor))()
|
||||
}
|
||||
|
||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
||||
self.checkNode?.frame = CGRect(origin: CGPoint(x: imageFrame.width - checkSize.width, y: 0.0), size: checkSize)
|
||||
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||
self.checkNode?.frame = CGRect(origin: CGPoint(x: imageFrame.width - checkSize.width - 2.0, y: 2.0), size: checkSize)
|
||||
}
|
||||
|
||||
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user