mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
274 lines
12 KiB
Swift
274 lines
12 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import AsyncDisplayKit
|
|
import SwiftSignalKit
|
|
import TelegramPresentationData
|
|
import TelegramUIPreferences
|
|
import AppBundle
|
|
|
|
private func generateArrowImage(color: UIColor) -> UIImage? {
|
|
let smallRadius: CGFloat = 5.0
|
|
let largeRadius: CGFloat = 14.0
|
|
return generateImage(CGSize(width: smallRadius + largeRadius, height: smallRadius + largeRadius + 16.0), contextGenerator: { size, context in
|
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
if let image = generateTintedImage(image: UIImage(bundleImageName: "Instant View/SettingsArrow"), color: color), let cgImage = image.cgImage {
|
|
context.setFillColor(color.cgColor)
|
|
context.fill(CGRect(origin: CGPoint(x: 0.0, y: size.height - image.size.height - 16.0), size: CGSize(width: size.width, height: 16.0)))
|
|
context.draw(cgImage, in: CGRect(origin: CGPoint(x: size.width - image.size.width, y: size.height - image.size.height), size: image.size))
|
|
}
|
|
})
|
|
}
|
|
|
|
final class InstantPageSettingsNode: ASDisplayNode {
|
|
private var settings: InstantPagePresentationSettings
|
|
private var currentThemeType: (InstantPageThemeType, Bool)
|
|
private var theme: InstantPageSettingsItemTheme
|
|
|
|
private let applySettings: (InstantPagePresentationSettings) -> Void
|
|
private let openInSafari: () -> Void
|
|
|
|
private var sections: [[InstantPageSettingsItemNode]] = []
|
|
private let sansFamilyNode: InstantPageSettingsFontFamilyNode
|
|
private let serifFamilyNode: InstantPageSettingsFontFamilyNode
|
|
private let themeItemNode: InstantPageSettingsThemeItemNode
|
|
private let autoNightItemNode: InstantPageSettingsSwitchNode
|
|
private let openInItemNode: InstantPageSettingsButtonItemNode
|
|
|
|
private let arrowNode: ASImageNode
|
|
private let itemContainerNode: ASDisplayNode
|
|
|
|
init(strings: PresentationStrings, settings: InstantPagePresentationSettings, currentThemeType: (InstantPageThemeType, Bool), applySettings: @escaping (InstantPagePresentationSettings) -> Void, openInSafari: @escaping () -> Void) {
|
|
self.settings = settings
|
|
self.currentThemeType = currentThemeType
|
|
self.theme = InstantPageSettingsItemTheme.themeFor(currentThemeType.0)
|
|
|
|
self.applySettings = applySettings
|
|
self.openInSafari = openInSafari
|
|
|
|
self.arrowNode = ASImageNode()
|
|
self.arrowNode.displayWithoutProcessing = true
|
|
self.arrowNode.displaysAsynchronously = false
|
|
self.arrowNode.image = generateArrowImage(color: self.theme.itemBackgroundColor)
|
|
|
|
self.itemContainerNode = ASDisplayNode()
|
|
self.itemContainerNode.layer.masksToBounds = true
|
|
self.itemContainerNode.layer.cornerRadius = 16.0
|
|
self.itemContainerNode.backgroundColor = self.theme.listBackgroundColor
|
|
|
|
var updateSerifImpl: ((Bool) -> Void)?
|
|
var updateThemeTypeImpl: ((InstantPageThemeType) -> Void)?
|
|
var updateAutoNightImpl: ((Bool) -> Void)?
|
|
var openInSafariImpl: (() -> Void)?
|
|
|
|
self.sansFamilyNode = InstantPageSettingsFontFamilyNode(theme: self.theme, title: "San Francisco", family: nil, checked: !settings.forceSerif, tapped: {
|
|
updateSerifImpl?(false)
|
|
})
|
|
self.serifFamilyNode = InstantPageSettingsFontFamilyNode(theme: self.theme, title: "Georgia", family: "Georgia", checked: settings.forceSerif, tapped: {
|
|
updateSerifImpl?(true)
|
|
})
|
|
self.themeItemNode = InstantPageSettingsThemeItemNode(theme: theme, themeType: settings.themeType, update: { value in
|
|
updateThemeTypeImpl?(value)
|
|
})
|
|
self.autoNightItemNode = InstantPageSettingsSwitchNode(theme: theme, title: strings.InstantPage_AutoNightTheme, isOn: settings.autoNightMode, isEnabled: settings.themeType != .dark, toggled: { value in
|
|
updateAutoNightImpl?(value)
|
|
})
|
|
self.openInItemNode = InstantPageSettingsButtonItemNode(theme: theme, title: strings.Web_OpenExternal, tapped: {
|
|
openInSafariImpl?()
|
|
})
|
|
super.init()
|
|
|
|
self.addSubnode(self.arrowNode)
|
|
self.addSubnode(self.itemContainerNode)
|
|
|
|
self.sections = [
|
|
[
|
|
InstantPageSettingsBacklightItemNode(theme: self.theme)
|
|
],
|
|
[
|
|
InstantPageSettingsFontSizeItemNode(theme: self.theme, fontSizeVariant: Int(settings.fontSize.rawValue), updated: { [weak self] value in
|
|
if let strongSelf = self {
|
|
strongSelf.updateSettings {
|
|
let size: InstantPagePresentationFontSize = InstantPagePresentationFontSize(rawValue: Int32(value)) ?? .standard
|
|
return $0.withUpdatedFontSize(size)
|
|
}
|
|
}
|
|
}),
|
|
self.sansFamilyNode,
|
|
self.serifFamilyNode
|
|
],
|
|
[
|
|
self.themeItemNode,
|
|
self.autoNightItemNode
|
|
],
|
|
[
|
|
self.openInItemNode
|
|
]
|
|
]
|
|
|
|
for section in self.sections {
|
|
for item in section {
|
|
self.itemContainerNode.addSubnode(item)
|
|
}
|
|
}
|
|
|
|
updateSerifImpl = { [weak self] value in
|
|
if let strongSelf = self {
|
|
strongSelf.updateSettings {
|
|
return $0.withUpdatedForceSerif(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
updateThemeTypeImpl = { [weak self] value in
|
|
if let strongSelf = self {
|
|
let disableAutoNightMode = strongSelf.currentThemeType.1
|
|
strongSelf.updateSettings {
|
|
if disableAutoNightMode {
|
|
let currentTime: Int32 = 0
|
|
return $0.withUpdatedThemeType(value).withUpdatedIgnoreAutoNightModeUntil(currentTime)
|
|
} else {
|
|
return $0.withUpdatedThemeType(value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
updateAutoNightImpl = { [weak self] value in
|
|
if let strongSelf = self {
|
|
strongSelf.updateSettings {
|
|
return $0.withUpdatedAutoNightMode(value).withUpdatedIgnoreAutoNightModeUntil(0)
|
|
}
|
|
}
|
|
}
|
|
openInSafariImpl = { [weak self] in
|
|
if let strongSelf = self {
|
|
strongSelf.openInSafari()
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
|
let fixedWidth: CGFloat = 295.0
|
|
let sectionSpacing: CGFloat = 4.0
|
|
let sideInset: CGFloat = 11.0
|
|
let topInset: CGFloat = layout.insets(options: [.statusBar]).top + 44.0 + 6.0
|
|
|
|
var contentHeight: CGFloat = 0.0
|
|
var itemSizes: [[CGFloat]] = []
|
|
for sectionIndex in 0 ..< self.sections.count {
|
|
itemSizes.append([])
|
|
if sectionIndex != 0 {
|
|
contentHeight += sectionSpacing
|
|
}
|
|
for itemIndex in 0 ..< self.sections[sectionIndex].count {
|
|
let previousItem: InstantPageSettingsItemNodeStatus
|
|
var previousItemNode: InstantPageSettingsItemNode?
|
|
let nextItem: InstantPageSettingsItemNodeStatus
|
|
var nextItemNode: InstantPageSettingsItemNode?
|
|
if itemIndex == 0 {
|
|
if sectionIndex == 0 {
|
|
previousItem = .none
|
|
} else {
|
|
previousItem = .otherSection
|
|
}
|
|
} else {
|
|
previousItem = .sameSection
|
|
previousItemNode = self.sections[sectionIndex][itemIndex - 1]
|
|
}
|
|
if itemIndex == self.sections[sectionIndex].count - 1 {
|
|
if sectionIndex == self.sections.count - 1 {
|
|
nextItem = .none
|
|
} else {
|
|
nextItem = .otherSection
|
|
}
|
|
} else {
|
|
nextItem = .sameSection
|
|
nextItemNode = self.sections[sectionIndex][itemIndex + 1]
|
|
}
|
|
let itemHeight = self.sections[sectionIndex][itemIndex].updateLayout(width: fixedWidth, previousItem: (previousItem, previousItemNode), nextItem: (nextItem, nextItemNode))
|
|
itemSizes[sectionIndex].append(itemHeight)
|
|
contentHeight += itemHeight
|
|
}
|
|
}
|
|
|
|
if let image = self.arrowNode.image {
|
|
transition.updateFrame(node: self.arrowNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideInset - image.size.width, y: topInset - image.size.height + 16.0 + 8.0), size: image.size))
|
|
}
|
|
|
|
transition.updateFrame(node: self.itemContainerNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideInset - fixedWidth, y: topInset), size: CGSize(width: fixedWidth, height: contentHeight)))
|
|
var nextItemOffset: CGFloat = 0.0
|
|
for sectionIndex in 0 ..< self.sections.count {
|
|
if sectionIndex != 0 {
|
|
nextItemOffset += sectionSpacing
|
|
}
|
|
for itemIndex in 0 ..< self.sections[sectionIndex].count {
|
|
let itemHeight = itemSizes[sectionIndex][itemIndex]
|
|
transition.updateFrame(node: self.sections[sectionIndex][itemIndex], frame: CGRect(origin: CGPoint(x: 0.0, y: nextItemOffset), size: CGSize(width: fixedWidth, height: itemHeight)))
|
|
nextItemOffset += itemHeight
|
|
}
|
|
}
|
|
}
|
|
|
|
func animateIn() {
|
|
self.layer.allowsGroupOpacity = true
|
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { [weak self] _ in
|
|
self?.layer.allowsGroupOpacity = false
|
|
})
|
|
}
|
|
|
|
func animateOut(completion: @escaping () -> Void) {
|
|
self.layer.allowsGroupOpacity = true
|
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak self] _ in
|
|
self?.layer.allowsGroupOpacity = false
|
|
completion()
|
|
})
|
|
}
|
|
|
|
private func updateSettings(_ f: (InstantPagePresentationSettings) -> InstantPagePresentationSettings) {
|
|
let updated = f(self.settings)
|
|
if updated != self.settings {
|
|
self.settings = updated
|
|
|
|
self.applySettings(settings)
|
|
}
|
|
}
|
|
|
|
func updateSettingsAndCurrentThemeType(settings: InstantPagePresentationSettings, type: (InstantPageThemeType, Bool)) {
|
|
self.currentThemeType = type
|
|
|
|
self.sansFamilyNode.checked = !self.settings.forceSerif
|
|
self.serifFamilyNode.checked = self.settings.forceSerif
|
|
self.themeItemNode.themeType = self.settings.themeType
|
|
self.autoNightItemNode.isEnabled = self.settings.themeType != .dark
|
|
|
|
let theme = InstantPageSettingsItemTheme.themeFor(self.currentThemeType.0)
|
|
if theme != self.theme {
|
|
self.theme = theme
|
|
|
|
if let snapshotView = self.view.snapshotView(afterScreenUpdates: false) {
|
|
self.view.addSubview(snapshotView)
|
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
|
snapshotView?.removeFromSuperview()
|
|
})
|
|
}
|
|
|
|
self.arrowNode.image = generateArrowImage(color: self.theme.itemBackgroundColor)
|
|
self.itemContainerNode.backgroundColor = self.theme.listBackgroundColor
|
|
for section in self.sections {
|
|
for item in section {
|
|
item.updateTheme(self.theme)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
if self.itemContainerNode.frame.contains(point) {
|
|
return super.hitTest(point, with: event)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|