mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
186 lines
7.2 KiB
Swift
186 lines
7.2 KiB
Swift
import Foundation
|
|
import Display
|
|
import AsyncDisplayKit
|
|
import UIKit
|
|
import SwiftSignalKit
|
|
import TelegramCore
|
|
|
|
final class ThemeAccentColorActionSheet: ActionSheetController {
|
|
private var presentationDisposable: Disposable?
|
|
|
|
private let _ready = Promise<Bool>()
|
|
override var ready: Promise<Bool> {
|
|
return self._ready
|
|
}
|
|
|
|
init(context: AccountContext, currentValue: Int32, applyValue: @escaping (Int32) -> Void) {
|
|
let presentationData = context.currentPresentationData.with { $0 }
|
|
let theme = presentationData.theme
|
|
let strings = presentationData.strings
|
|
|
|
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
|
|
|
self.presentationDisposable = (context.presentationData
|
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
|
if let strongSelf = self {
|
|
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
|
}
|
|
})
|
|
|
|
self._ready.set(.single(true))
|
|
|
|
var items: [ActionSheetItem] = []
|
|
items.append(ThemeAccentColorActionSheetItem(strings: strings, currentValue: currentValue, valueChanged: { [weak self] value in
|
|
self?.dismissAnimated()
|
|
applyValue(value)
|
|
}))
|
|
|
|
self.setItemGroups([
|
|
ActionSheetItemGroup(items: items),
|
|
ActionSheetItemGroup(items: [
|
|
ActionSheetButtonItem(title: strings.Common_Cancel, action: { [weak self] in
|
|
self?.dismissAnimated()
|
|
}),
|
|
])
|
|
])
|
|
}
|
|
|
|
required init(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
deinit {
|
|
self.presentationDisposable?.dispose()
|
|
}
|
|
}
|
|
|
|
private final class ThemeAccentColorActionSheetItem: ActionSheetItem {
|
|
let strings: PresentationStrings
|
|
|
|
let currentValue: Int32
|
|
let valueChanged: (Int32) -> Void
|
|
|
|
init(strings: PresentationStrings, currentValue: Int32, valueChanged: @escaping (Int32) -> Void) {
|
|
self.strings = strings
|
|
self.currentValue = currentValue
|
|
self.valueChanged = valueChanged
|
|
}
|
|
|
|
func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode {
|
|
return ThemeAccentColorActionSheetItemNode(theme: theme, strings: self.strings, currentValue: self.currentValue, valueChanged: self.valueChanged)
|
|
}
|
|
|
|
func updateNode(_ node: ActionSheetItemNode) {
|
|
}
|
|
}
|
|
|
|
private final class ThemeAccentColorActionSheetItemNode: ActionSheetItemNode {
|
|
private let theme: ActionSheetControllerTheme
|
|
private let strings: PresentationStrings
|
|
|
|
private let titleNode: ImmediateTextNode
|
|
|
|
private let valueChanged: (Int32) -> Void
|
|
private let items: [Int32]
|
|
private let itemNodes: [ASImageNode]
|
|
|
|
init(theme: ActionSheetControllerTheme, strings: PresentationStrings, currentValue: Int32, valueChanged: @escaping (Int32) -> Void) {
|
|
self.theme = theme
|
|
self.strings = strings
|
|
self.valueChanged = valueChanged
|
|
|
|
self.titleNode = ImmediateTextNode()
|
|
self.titleNode.displaysAsynchronously = false
|
|
self.titleNode.isLayerBacked = true
|
|
self.titleNode.attributedText = NSAttributedString(string: strings.Appearance_PickAccentColor, font: Font.medium(18.0), textColor: theme.primaryTextColor)
|
|
|
|
self.items = [
|
|
0xf83b4c, // red
|
|
0xff7519, // orange
|
|
0xeba239, // yellow
|
|
0x29b327, // green
|
|
0x00c2ed, // light blue
|
|
0x007ee5, // blue
|
|
0x7748ff, // purple
|
|
0xff5da2
|
|
]
|
|
self.itemNodes = self.items.map { color in
|
|
let imageNode = ASImageNode()
|
|
imageNode.displaysAsynchronously = false
|
|
imageNode.displayWithoutProcessing = true
|
|
|
|
imageNode.image = generateImage(CGSize(width: 60.0, height: 60.0), rotatedContext: { size, context in
|
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
context.draw(generateFilledCircleImage(diameter: size.width, color: UIColor(rgb: UInt32(bitPattern: color)))!.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
|
if color == currentValue {
|
|
context.scaleBy(x: 0.333, y: 0.333)
|
|
context.translateBy(x: 62.0, y: 72.0)
|
|
context.setLineWidth(10.0)
|
|
context.setLineCap(.round)
|
|
context.setStrokeColor(UIColor.white.cgColor)
|
|
|
|
let _ = try? drawSvgPath(context, path: "M0,23.173913 L16.699191,39.765981 C17.390617,40.452972 18.503246,40.464805 19.209127,39.792676 L61,0 S ")
|
|
}
|
|
})
|
|
return imageNode
|
|
}
|
|
|
|
super.init(theme: theme)
|
|
|
|
self.addSubnode(self.titleNode)
|
|
|
|
for itemNode in self.itemNodes {
|
|
itemNode.isUserInteractionEnabled = true
|
|
self.addSubnode(itemNode)
|
|
itemNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
|
}
|
|
}
|
|
|
|
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
|
if case .ended = recognizer.state {
|
|
for i in 0 ..< self.itemNodes.count {
|
|
if self.itemNodes[i].view == recognizer.view {
|
|
self.valueChanged(self.items[i])
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
|
let topInset: CGFloat = 12.0
|
|
let maximumItemSpacing: CGFloat = 18.0
|
|
let sideInset: CGFloat = 10.0
|
|
let columnCount: CGFloat = 4.0
|
|
let rowCount: CGFloat = 2.0
|
|
let itemSide: CGFloat = 60.0
|
|
|
|
let itemsWidth = itemSide * columnCount
|
|
let remainingWidth = constrainedSize.width - itemsWidth - sideInset * 2.0
|
|
let proposedSpacing = floor(remainingWidth / (columnCount - 1.0))
|
|
let itemSpacing = min(proposedSpacing, maximumItemSpacing)
|
|
|
|
let titleSpacing: CGFloat = itemSpacing
|
|
let bottomInset: CGFloat = itemSpacing
|
|
|
|
let titleSize = self.titleNode.updateLayout(constrainedSize)
|
|
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - titleSize.width) / 2.0), y: topInset), size: titleSize)
|
|
|
|
let itemsWidthWithSpacing = itemSpacing * (columnCount - 1.0) + itemSide * columnCount
|
|
let itemsLeftOrigin = floor((constrainedSize.width - itemsWidthWithSpacing) / 2.0)
|
|
|
|
for i in 0 ..< self.itemNodes.count {
|
|
let row = CGFloat(i / 4)
|
|
let column = CGFloat(i % 4)
|
|
self.itemNodes[i].frame = CGRect(origin: CGPoint(x: itemsLeftOrigin + column * (itemSide + itemSpacing), y: topInset + titleSize.height + titleSpacing + row * (itemSide + itemSpacing)), size: CGSize(width: itemSide, height: itemSide))
|
|
}
|
|
|
|
return CGSize(width: constrainedSize.width, height: topInset + titleSize.height + titleSpacing + rowCount * itemSide + (rowCount - 1.0) * itemSpacing + bottomInset)
|
|
}
|
|
|
|
override func layout() {
|
|
super.layout()
|
|
}
|
|
}
|
|
|