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
|
selectionNode = current
|
||||||
updatedSelectionNode = selectionNode
|
updatedSelectionNode = selectionNode
|
||||||
} else {
|
} 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
|
selectionNode.isUserInteractionEnabled = false
|
||||||
updatedSelectionNode = selectionNode
|
updatedSelectionNode = selectionNode
|
||||||
}
|
}
|
||||||
@ -322,9 +322,9 @@ public class ChatListAdditionalCategoryItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.selectionNode = updatedSelectionNode
|
strongSelf.selectionNode = updatedSelectionNode
|
||||||
strongSelf.addSubnode(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 {
|
} else if let selectionNode = strongSelf.selectionNode {
|
||||||
selectionNode.removeFromSupernode()
|
selectionNode.removeFromSupernode()
|
||||||
strongSelf.selectionNode = nil
|
strongSelf.selectionNode = nil
|
||||||
|
@ -10,6 +10,7 @@ swift_library(
|
|||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
"//submodules/Display:Display",
|
"//submodules/Display:Display",
|
||||||
"//submodules/LegacyComponents:LegacyComponents",
|
"//submodules/LegacyComponents:LegacyComponents",
|
||||||
|
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -1,82 +1,292 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
|
import Display
|
||||||
import LegacyComponents
|
import LegacyComponents
|
||||||
|
import TelegramPresentationData
|
||||||
|
|
||||||
public enum 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?
|
||||||
|
|
||||||
|
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.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 plain
|
||||||
case overlay
|
case overlay
|
||||||
case navigation
|
}
|
||||||
case compact
|
|
||||||
|
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 final class CheckNode: ASDisplayNode {
|
public enum CheckNodeContent {
|
||||||
private var strokeColor: UIColor
|
case check
|
||||||
private var fillColor: UIColor
|
case counter(Int)
|
||||||
private var foregroundColor: UIColor
|
}
|
||||||
private let checkStyle: CheckNodeStyle
|
|
||||||
|
|
||||||
private var checkView: TGCheckButtonView?
|
private final class CheckNodeParameters: NSObject {
|
||||||
|
let theme: CheckNodeTheme
|
||||||
|
let content: CheckNodeContent
|
||||||
|
let animationProgress: CGFloat
|
||||||
|
let selected: Bool
|
||||||
|
let animatingOut: Bool
|
||||||
|
|
||||||
public private(set) var isChecked: Bool = false
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private weak var target: AnyObject?
|
public class CheckNode: ASDisplayNode {
|
||||||
private var action: Selector?
|
private var animatingOut = false
|
||||||
|
private var animationProgress: CGFloat = 0.0
|
||||||
|
public var theme: CheckNodeTheme {
|
||||||
|
didSet {
|
||||||
|
self.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public init(strokeColor: UIColor, fillColor: UIColor, foregroundColor: UIColor, style: CheckNodeStyle) {
|
public init(theme: CheckNodeTheme, content: CheckNodeContent = .check) {
|
||||||
self.strokeColor = strokeColor
|
self.theme = theme
|
||||||
self.fillColor = fillColor
|
self.content = content
|
||||||
self.foregroundColor = foregroundColor
|
|
||||||
self.checkStyle = style
|
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
self.isOpaque = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func didLoad() {
|
public var content: CheckNodeContent {
|
||||||
super.didLoad()
|
didSet {
|
||||||
|
self.setNeedsDisplay()
|
||||||
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) {
|
public var selected = false
|
||||||
self.target = target
|
public func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||||
self.action = action
|
guard self.selected != selected else {
|
||||||
if self.isNodeLoaded {
|
return
|
||||||
self.checkView?.addTarget(target, action: action, for: .touchUpInside)
|
|
||||||
}
|
}
|
||||||
|
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 bottomStripeNode: ASDisplayNode
|
||||||
private let maskNode: ASImageNode
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
private var checkNode: CheckNode?
|
private var checkNode: InteractiveCheckNode?
|
||||||
|
|
||||||
private let textClippingNode: ASDisplayNode
|
private let textClippingNode: ASDisplayNode
|
||||||
private let textNode: EditableTextNode
|
private let textNode: EditableTextNode
|
||||||
@ -162,10 +162,6 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
|||||||
self.containerNode.addSubnode(self.textLimitNode)
|
self.containerNode.addSubnode(self.textLimitNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func checkNodePressed() {
|
|
||||||
self.item?.toggleSelected()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
@ -360,16 +356,18 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
|||||||
|
|
||||||
strongSelf.textNode.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
strongSelf.textNode.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||||
|
|
||||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
let checkSize = CGSize(width: 22.0, height: 22.0)
|
||||||
let checkFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + 11.0, y: floor((layout.contentSize.height - checkSize.height) / 2.0)), size: checkSize)
|
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 isSelected = item.isSelected {
|
||||||
if let checkNode = strongSelf.checkNode {
|
if let checkNode = strongSelf.checkNode {
|
||||||
transition.updateFrame(node: checkNode, frame: checkFrame)
|
transition.updateFrame(node: checkNode, frame: checkFrame)
|
||||||
checkNode.setIsChecked(isSelected, animated: true)
|
checkNode.setSelected(isSelected, animated: true)
|
||||||
} else {
|
} 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)
|
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.addTarget(target: strongSelf, action: #selector(strongSelf.checkNodePressed))
|
checkNode.setSelected(isSelected, animated: false)
|
||||||
checkNode.setIsChecked(isSelected, animated: false)
|
checkNode.valueChanged = { [weak self] value in
|
||||||
|
self?.item?.toggleSelected()
|
||||||
|
}
|
||||||
strongSelf.checkNode = checkNode
|
strongSelf.checkNode = checkNode
|
||||||
strongSelf.containerNode.addSubnode(checkNode)
|
strongSelf.containerNode.addSubnode(checkNode)
|
||||||
checkNode.frame = checkFrame
|
checkNode.frame = checkFrame
|
||||||
|
@ -535,7 +535,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
selectionNode = current
|
selectionNode = current
|
||||||
updatedSelectionNode = selectionNode
|
updatedSelectionNode = selectionNode
|
||||||
} else {
|
} 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
|
selectionNode.isUserInteractionEnabled = false
|
||||||
updatedSelectionNode = selectionNode
|
updatedSelectionNode = selectionNode
|
||||||
}
|
}
|
||||||
@ -1004,9 +1004,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.selectionNode = updatedSelectionNode
|
strongSelf.selectionNode = updatedSelectionNode
|
||||||
strongSelf.addSubnode(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 {
|
} else if let selectionNode = strongSelf.selectionNode {
|
||||||
selectionNode.removeFromSupernode()
|
selectionNode.removeFromSupernode()
|
||||||
strongSelf.selectionNode = nil
|
strongSelf.selectionNode = nil
|
||||||
|
@ -74,13 +74,14 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
|||||||
self.checkNode = ASImageNode()
|
self.checkNode = ASImageNode()
|
||||||
self.checkNode.isUserInteractionEnabled = false
|
self.checkNode.isUserInteractionEnabled = false
|
||||||
self.checkNode.displaysAsynchronously = 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.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
context.setStrokeColor(theme.controlAccentColor.cgColor)
|
context.setStrokeColor(theme.controlAccentColor.cgColor)
|
||||||
context.setLineWidth(2.0)
|
context.setLineWidth(2.0 - UIScreenPixel)
|
||||||
context.move(to: CGPoint(x: 12.0, y: 1.0))
|
context.setLineCap(.round)
|
||||||
context.addLine(to: CGPoint(x: 4.16482734, y: 9.0))
|
context.move(to: CGPoint(x: 13.0, y: 1.0))
|
||||||
context.addLine(to: CGPoint(x: 1.0, y: 5.81145833))
|
context.addLine(to: CGPoint(x: 5.0, y: 11.0))
|
||||||
|
context.addLine(to: CGPoint(x: 1.0, y: 7.0))
|
||||||
context.strokePath()
|
context.strokePath()
|
||||||
})
|
})
|
||||||
self.checkNode.isAccessibilityElement = false
|
self.checkNode.isAccessibilityElement = false
|
||||||
@ -146,8 +147,8 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
|||||||
|
|
||||||
self.button.frame = CGRect(origin: CGPoint(), size: size)
|
self.button.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
|
||||||
var titleOrigin: CGFloat = 44.0
|
var titleOrigin: CGFloat = 50.0
|
||||||
var checkOrigin: CGFloat = 22.0
|
var checkOrigin: CGFloat = 27.0
|
||||||
if let item = self.item, item.style == .alignRight {
|
if let item = self.item, item.style == .alignRight {
|
||||||
titleOrigin = 24.0
|
titleOrigin = 24.0
|
||||||
checkOrigin = size.width - 22.0
|
checkOrigin = size.width - 22.0
|
||||||
|
@ -15,11 +15,13 @@ public final class AlertControllerTheme: Equatable {
|
|||||||
public let primaryColor: UIColor
|
public let primaryColor: UIColor
|
||||||
public let secondaryColor: UIColor
|
public let secondaryColor: UIColor
|
||||||
public let accentColor: UIColor
|
public let accentColor: UIColor
|
||||||
|
public let contrastColor: UIColor
|
||||||
public let destructiveColor: UIColor
|
public let destructiveColor: UIColor
|
||||||
public let disabledColor: UIColor
|
public let disabledColor: UIColor
|
||||||
|
public let controlBorderColor: UIColor
|
||||||
public let baseFontSize: CGFloat
|
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.backgroundType = backgroundType
|
||||||
self.backgroundColor = backgroundColor
|
self.backgroundColor = backgroundColor
|
||||||
self.separatorColor = separatorColor
|
self.separatorColor = separatorColor
|
||||||
@ -27,8 +29,10 @@ public final class AlertControllerTheme: Equatable {
|
|||||||
self.primaryColor = primaryColor
|
self.primaryColor = primaryColor
|
||||||
self.secondaryColor = secondaryColor
|
self.secondaryColor = secondaryColor
|
||||||
self.accentColor = accentColor
|
self.accentColor = accentColor
|
||||||
|
self.contrastColor = contrastColor
|
||||||
self.destructiveColor = destructiveColor
|
self.destructiveColor = destructiveColor
|
||||||
self.disabledColor = disabledColor
|
self.disabledColor = disabledColor
|
||||||
|
self.controlBorderColor = controlBorderColor
|
||||||
self.baseFontSize = baseFontSize
|
self.baseFontSize = baseFontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,22 @@ import TelegramPresentationData
|
|||||||
import CheckNode
|
import CheckNode
|
||||||
|
|
||||||
public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCustomDisplayNode {
|
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) {
|
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()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.checkNode)
|
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 {
|
public var isHighlightable: Bool {
|
||||||
@ -21,15 +29,16 @@ public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCu
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var isChecked: Bool {
|
public var isChecked: Bool {
|
||||||
return self.checkNode.isChecked
|
return self.checkNode.selected
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setIsChecked(_ isChecked: Bool, animated: Bool) {
|
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) {
|
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 {
|
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||||
@ -40,7 +49,7 @@ public final class GalleryNavigationCheckNode: ASDisplayNode, NavigationButtonCu
|
|||||||
super.layout()
|
super.layout()
|
||||||
|
|
||||||
let size = self.bounds.size
|
let size = self.bounds.size
|
||||||
let checkSize = CGSize(width: 39.0, height: 39.0)
|
let checkSize = CGSize(width: 36.0, height: 36.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)
|
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) {
|
public init(theme: PresentationTheme, toggle: @escaping (Bool) -> Void) {
|
||||||
self.toggle = toggle
|
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
|
self.checkNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -42,7 +42,7 @@ public final class GridMessageSelectionNode: ASDisplayNode {
|
|||||||
public func updateSelected(_ selected: Bool, animated: Bool) {
|
public func updateSelected(_ selected: Bool, animated: Bool) {
|
||||||
if self.selected != selected {
|
if self.selected != selected {
|
||||||
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() {
|
override public func layout() {
|
||||||
super.layout()
|
super.layout()
|
||||||
|
|
||||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||||
self.checkNode.frame = CGRect(origin: CGPoint(x: self.bounds.size.width - checkSize.width, y: 0.0), size: checkSize)
|
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
|
private let checkNode: CheckNode
|
||||||
|
|
||||||
public init(strokeColor: UIColor, fillColor: UIColor, foregroundColor: UIColor) {
|
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
|
self.checkNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -26,9 +26,9 @@ public final class ItemListSelectableControlNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (compact ? 38.0 : 45.0, { size, animated in
|
return (compact ? 38.0 : 45.0, { size, animated in
|
||||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
let checkSize = CGSize(width: 26.0, height: 26.0)
|
||||||
resultNode.checkNode.frame = CGRect(origin: CGPoint(x: compact ? 9 : 12.0, y: floor((size.height - checkSize.height) / 2.0)), size: checkSize)
|
resultNode.checkNode.frame = CGRect(origin: CGPoint(x: compact ? 11.0 : 13.0, y: floorToScreenPixels((size.height - checkSize.height) / 2.0)), size: checkSize)
|
||||||
resultNode.checkNode.setIsChecked(selected, animated: animated)
|
resultNode.checkNode.setSelected(selected, animated: animated)
|
||||||
return resultNode
|
return resultNode
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ swift_library(
|
|||||||
"//submodules/ContextUI:ContextUI",
|
"//submodules/ContextUI:ContextUI",
|
||||||
"//submodules/LocalizedPeerData:LocalizedPeerData",
|
"//submodules/LocalizedPeerData:LocalizedPeerData",
|
||||||
"//submodules/AccountContext:AccountContext",
|
"//submodules/AccountContext:AccountContext",
|
||||||
|
"//submodules/CheckNode:CheckNode",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -13,6 +13,7 @@ import LegacyComponents
|
|||||||
import ContextUI
|
import ContextUI
|
||||||
import LocalizedPeerData
|
import LocalizedPeerData
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import CheckNode
|
||||||
|
|
||||||
private let avatarFont = avatarPlaceholderFont(size: 24.0)
|
private let avatarFont = avatarPlaceholderFont(size: 24.0)
|
||||||
private let textFont = Font.regular(11.0)
|
private let textFont = Font.regular(11.0)
|
||||||
@ -71,7 +72,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||||||
private let avatarNodeContainer: ASDisplayNode
|
private let avatarNodeContainer: ASDisplayNode
|
||||||
private let avatarNode: AvatarNode
|
private let avatarNode: AvatarNode
|
||||||
private let onlineNode: PeerOnlineMarkerNode
|
private let onlineNode: PeerOnlineMarkerNode
|
||||||
private var checkView: TGCheckButtonView?
|
private var checkNode: CheckNode?
|
||||||
private let textNode: ASTextNode
|
private let textNode: ASTextNode
|
||||||
|
|
||||||
public var toggleSelection: (() -> Void)?
|
public var toggleSelection: (() -> Void)?
|
||||||
@ -209,23 +210,20 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
if self.checkView == nil {
|
if self.checkNode == 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))!
|
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
|
||||||
self.checkView = checkView
|
checkNode.isUserInteractionEnabled = false
|
||||||
checkView.isUserInteractionEnabled = false
|
self.addSubnode(checkNode)
|
||||||
self.view.addSubview(checkView)
|
|
||||||
|
|
||||||
let avatarFrame = self.avatarNode.frame
|
let avatarFrame = self.avatarNode.frame
|
||||||
let checkSize = checkView.bounds.size
|
let checkSize = CGSize(width: 24.0, height: 24.0)
|
||||||
checkView.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 14.0, y: avatarFrame.maxY - 22.0), size: checkSize)
|
checkNode.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 10.0, y: avatarFrame.maxY - 18.0), size: checkSize)
|
||||||
checkView.setSelected(true, animated: animated)
|
checkNode.setSelected(true, animated: animated)
|
||||||
}
|
}
|
||||||
} else if let checkView = self.checkView {
|
} else if let checkNode = self.checkNode {
|
||||||
self.checkView = nil
|
self.checkNode = nil
|
||||||
checkView.setSelected(false, animated: animated, bump: false, completion: { [weak checkView] in
|
checkNode.setSelected(false, animated: animated)
|
||||||
checkView?.removeFromSuperview()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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)
|
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 {
|
if let checkNode = self.checkNode {
|
||||||
let checkSize = checkView.bounds.size
|
let checkSize = CGSize(width: 24.0, height: 24.0)
|
||||||
checkView.frame = CGRect(origin: CGPoint(x: avatarFrame.maxX - 14.0, y: avatarFrame.maxY - 22.0), size: checkSize)
|
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 {
|
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||||
let arguments = arguments as! NotificationPeerExceptionArguments
|
let arguments = arguments as! NotificationPeerExceptionArguments
|
||||||
switch self {
|
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: {
|
return ItemListActionItem(presentationData: presentationData, title: strings.Notification_Exceptions_RemoveFromExceptions, kind: .generic, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||||
arguments.removeFromExceptions()
|
arguments.removeFromExceptions()
|
||||||
})
|
})
|
||||||
case let .switcher(_, theme, strings, mode, selected):
|
case let .switcher(_, _, strings, mode, selected):
|
||||||
let title: String
|
let title: String
|
||||||
switch mode {
|
switch mode {
|
||||||
case .alwaysOn:
|
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: {
|
return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||||
arguments.selectMode(mode)
|
arguments.selectMode(mode)
|
||||||
})
|
})
|
||||||
case let .switcherHeader(_, theme, text):
|
case let .switcherHeader(_, _, text):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
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
|
let title: String
|
||||||
switch value {
|
switch value {
|
||||||
case .alwaysOn:
|
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: {
|
return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||||
arguments.selectDisplayPreviews(value)
|
arguments.selectDisplayPreviews(value)
|
||||||
})
|
})
|
||||||
case let .displayPreviewsHeader(_, theme, text):
|
case let .displayPreviewsHeader(_, _, text):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
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)
|
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)
|
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: {
|
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
|
||||||
arguments.selectSound(.none)
|
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: {
|
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||||
arguments.selectSound(.default)
|
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: {
|
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||||
arguments.selectSound(sound)
|
arguments.selectSound(sound)
|
||||||
})
|
})
|
||||||
|
@ -13,7 +13,7 @@ enum WallpaperOptionButtonValue {
|
|||||||
|
|
||||||
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||||
private let backgroundNode: ASDisplayNode
|
private let backgroundNode: ASDisplayNode
|
||||||
private let checkNode: ModernCheckNode
|
private let checkNode: CheckNode
|
||||||
private let colorNode: ASImageNode
|
private let colorNode: ASImageNode
|
||||||
private let textNode: ASTextNode
|
private let textNode: ASTextNode
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
|||||||
self.backgroundNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.3)
|
self.backgroundNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.3)
|
||||||
self.backgroundNode.cornerRadius = 14.0
|
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.checkNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.colorNode = ASImageNode()
|
self.colorNode = ASImageNode()
|
||||||
|
@ -94,13 +94,13 @@ public extension ActionSheetController {
|
|||||||
public extension AlertControllerTheme {
|
public extension AlertControllerTheme {
|
||||||
convenience init(presentationTheme: PresentationTheme, fontSize: PresentationFontSize) {
|
convenience init(presentationTheme: PresentationTheme, fontSize: PresentationFontSize) {
|
||||||
let actionSheet = presentationTheme.actionSheet
|
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) {
|
convenience init(presentationData: PresentationData) {
|
||||||
let presentationTheme = presentationData.theme
|
let presentationTheme = presentationData.theme
|
||||||
let actionSheet = presentationTheme.actionSheet
|
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 titleNode: ASTextNode
|
||||||
private let textNode: ASTextNode
|
private let textNode: ASTextNode
|
||||||
private let authorizeCheckNode: CheckNode
|
private let authorizeCheckNode: InteractiveCheckNode
|
||||||
private let authorizeLabelNode: ASTextNode
|
private let authorizeLabelNode: ASTextNode
|
||||||
private let allowWriteCheckNode: CheckNode
|
private let allowWriteCheckNode: InteractiveCheckNode
|
||||||
private let allowWriteLabelNode: ASTextNode
|
private let allowWriteLabelNode: ASTextNode
|
||||||
|
|
||||||
private let actionNodesSeparator: ASDisplayNode
|
private let actionNodesSeparator: ASDisplayNode
|
||||||
@ -47,7 +47,7 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
|||||||
|
|
||||||
var authorize: Bool = true {
|
var authorize: Bool = true {
|
||||||
didSet {
|
didSet {
|
||||||
self.authorizeCheckNode.setIsChecked(self.authorize, animated: true)
|
self.authorizeCheckNode.setSelected(self.authorize, animated: true)
|
||||||
self.allowWriteCheckNode.isUserInteractionEnabled = self.authorize
|
self.allowWriteCheckNode.isUserInteractionEnabled = self.authorize
|
||||||
self.allowWriteCheckNode.alpha = self.authorize ? 1.0 : 0.4
|
self.allowWriteCheckNode.alpha = self.authorize ? 1.0 : 0.4
|
||||||
self.allowWriteLabelNode.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 {
|
var allowWriteAccess: Bool = true {
|
||||||
didSet {
|
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 = ASTextNode()
|
||||||
self.textNode.maximumNumberOfLines = 0
|
self.textNode.maximumNumberOfLines = 0
|
||||||
|
|
||||||
self.authorizeCheckNode = CheckNode(strokeColor: theme.separatorColor, fillColor: theme.accentColor, foregroundColor: .white, style: .plain)
|
self.authorizeCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||||
self.authorizeCheckNode.setIsChecked(true, animated: false)
|
self.authorizeCheckNode.setSelected(true, animated: false)
|
||||||
self.authorizeLabelNode = ASTextNode()
|
self.authorizeLabelNode = ASTextNode()
|
||||||
self.authorizeLabelNode.maximumNumberOfLines = 4
|
self.authorizeLabelNode.maximumNumberOfLines = 4
|
||||||
self.authorizeLabelNode.isUserInteractionEnabled = true
|
self.authorizeLabelNode.isUserInteractionEnabled = true
|
||||||
|
|
||||||
self.allowWriteCheckNode = CheckNode(strokeColor: theme.separatorColor, fillColor: theme.accentColor, foregroundColor: .white, style: .plain)
|
self.allowWriteCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||||
self.allowWriteCheckNode.setIsChecked(true, animated: false)
|
self.allowWriteCheckNode.setSelected(true, animated: false)
|
||||||
self.allowWriteLabelNode = ASTextNode()
|
self.allowWriteLabelNode = ASTextNode()
|
||||||
self.allowWriteLabelNode.maximumNumberOfLines = 4
|
self.allowWriteLabelNode.maximumNumberOfLines = 4
|
||||||
self.allowWriteLabelNode.isUserInteractionEnabled = true
|
self.allowWriteLabelNode.isUserInteractionEnabled = true
|
||||||
@ -128,8 +128,16 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
|||||||
self.addSubnode(separatorNode)
|
self.addSubnode(separatorNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.authorizeCheckNode.addTarget(target: self, action: #selector(self.authorizePressed))
|
self.authorizeCheckNode.valueChanged = { [weak self] value in
|
||||||
self.allowWriteCheckNode.addTarget(target: self, action: #selector(self.allowWritePressed))
|
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)
|
self.updateTheme(theme)
|
||||||
}
|
}
|
||||||
@ -141,10 +149,6 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
|||||||
self.allowWriteLabelNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.allowWriteTap(_:))))
|
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) {
|
@objc private func authorizeTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||||
self.authorize = !self.authorize
|
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) {
|
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||||
self.titleNode.attributedText = NSAttributedString(string: strings.Conversation_OpenBotLinkTitle, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
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))
|
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
|
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)
|
let condensedSize = CGSize(width: size.width - 76.0, height: size.height)
|
||||||
|
|
||||||
var entriesHeight: CGFloat = 0.0
|
var entriesHeight: CGFloat = 0.0
|
||||||
|
|
||||||
let authorizeSize = self.authorizeLabelNode.measure(condensedSize)
|
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.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
|
origin.y += authorizeSize.height
|
||||||
entriesHeight += authorizeSize.height
|
entriesHeight += authorizeSize.height
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ private final class ChatMessageActionUrlAuthAlertContentNode: AlertContentNode {
|
|||||||
|
|
||||||
let allowWriteSize = self.allowWriteLabelNode.measure(condensedSize)
|
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.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
|
origin.y += allowWriteSize.height
|
||||||
entriesHeight += 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) {
|
public init(theme: PresentationTheme, incoming: Bool, noPreview: Bool, toggle: @escaping (Bool) -> Void) {
|
||||||
self.noPreview = noPreview
|
self.noPreview = noPreview
|
||||||
self.toggle = toggle
|
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
|
self.checkNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -1157,7 +1157,7 @@ final class FileMessageSelectionNode: ASDisplayNode {
|
|||||||
public func updateSelected(_ selected: Bool, animated: Bool) {
|
public func updateSelected(_ selected: Bool, animated: Bool) {
|
||||||
if self.selected != selected {
|
if self.selected != selected {
|
||||||
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() {
|
override public func layout() {
|
||||||
super.layout()
|
super.layout()
|
||||||
|
|
||||||
let checkSize = CGSize(width: 30.0, height: 30.0)
|
let checkSize: CGSize
|
||||||
let checkOrigin: CGPoint
|
let checkOrigin: CGPoint
|
||||||
if self.noPreview {
|
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 {
|
} 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)
|
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) {
|
init(wallpaper: TelegramWallpaper, theme: PresentationTheme, toggle: @escaping (Bool) -> Void) {
|
||||||
self.toggle = toggle
|
self.toggle = toggle
|
||||||
|
|
||||||
let style: CheckNodeStyle
|
let style: CheckNodeTheme.Style
|
||||||
if wallpaper == theme.chat.defaultWallpaper, case .color = wallpaper {
|
if wallpaper == theme.chat.defaultWallpaper, case .color = wallpaper {
|
||||||
style = .plain
|
style = .plain
|
||||||
} else {
|
} else {
|
||||||
style = .overlay
|
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
|
self.checkNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.checkNode)
|
self.addSubnode(self.checkNode)
|
||||||
|
|
||||||
//self.hitTestSlop = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
@ -40,7 +38,7 @@ final class ChatMessageSelectionNode: ASDisplayNode {
|
|||||||
func updateSelected(_ selected: Bool, animated: Bool) {
|
func updateSelected(_ selected: Bool, animated: Bool) {
|
||||||
if self.selected != selected {
|
if self.selected != selected {
|
||||||
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) {
|
func updateLayout(size: CGSize, leftInset: CGFloat) {
|
||||||
let checkSize = CGSize(width: 32.0, height: 32.0)
|
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||||
self.checkNode.frame = CGRect(origin: CGPoint(x: 4.0 + leftInset, y: floor((size.height - checkSize.height) / 2.0)), size: checkSize)
|
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 {
|
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)
|
let legacyItem = LegacyWebSearchItem(result: item.result)
|
||||||
|
|
||||||
checkNode.setIsChecked(!checkNode.isChecked, animated: true)
|
|
||||||
controllerInteraction.selectionState?.setItem(legacyItem, selected: checkNode.isChecked)
|
controllerInteraction.selectionState?.setItem(legacyItem, selected: checkNode.isChecked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,17 +210,12 @@ final class WebSearchItemNode: GridItemNode {
|
|||||||
self.updateSelectionState(animated: false)
|
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) {
|
func updateSelectionState(animated: Bool) {
|
||||||
if self.checkNode == nil, let item = self.item, let _ = item.controllerInteraction.selectionState {
|
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)
|
let checkNode = InteractiveCheckNode(theme: CheckNodeTheme(theme: item.theme, style: .overlay))
|
||||||
checkNode.addTarget(target: self, action: #selector(self.toggleSelection))
|
checkNode.valueChanged = { value in
|
||||||
|
item.controllerInteraction.toggleSelection(item.result, value)
|
||||||
|
}
|
||||||
self.addSubnode(checkNode)
|
self.addSubnode(checkNode)
|
||||||
self.checkNode = checkNode
|
self.checkNode = checkNode
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
@ -229,7 +224,7 @@ final class WebSearchItemNode: GridItemNode {
|
|||||||
if let item = self.item {
|
if let item = self.item {
|
||||||
if let selectionState = item.controllerInteraction.selectionState {
|
if let selectionState = item.controllerInteraction.selectionState {
|
||||||
let selected = selectionState.isIdentifierSelected(item.result.id)
|
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))()
|
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)
|
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||||
self.checkNode?.frame = CGRect(origin: CGPoint(x: imageFrame.width - checkSize.width, y: 0.0), size: checkSize)
|
self.checkNode?.frame = CGRect(origin: CGPoint(x: imageFrame.width - checkSize.width - 2.0, y: 2.0), size: checkSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user