mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
204 lines
9.9 KiB
Swift
204 lines
9.9 KiB
Swift
import Foundation
|
|
import Display
|
|
import AsyncDisplayKit
|
|
import SwiftSignalKit
|
|
import TelegramCore
|
|
|
|
final class PermissionControllerNode: ASDisplayNode {
|
|
private let theme: AuthorizationTheme
|
|
private let strings: PresentationStrings
|
|
|
|
private let iconNode: ASImageNode
|
|
private let titleNode: ImmediateTextNode
|
|
private let textNode: ImmediateTextNode
|
|
private let buttonNode: SolidRoundedButtonNode
|
|
private let privacyPolicyNode: HighlightableButtonNode
|
|
private let nextNode: HighlightableButtonNode
|
|
|
|
private var layoutArguments: (ContainerViewLayout, CGFloat)?
|
|
|
|
private var title: String?
|
|
|
|
var allow: (() -> Void)?
|
|
var next: (() -> Void)? {
|
|
didSet {
|
|
self.nextNode.isHidden = self.next == nil
|
|
}
|
|
}
|
|
var openPrivacyPolicy: (() -> Void)?
|
|
var dismiss: (() -> Void)?
|
|
|
|
init(theme: AuthorizationTheme, strings: PresentationStrings) {
|
|
self.theme = theme
|
|
self.strings = strings
|
|
|
|
self.iconNode = ASImageNode()
|
|
self.iconNode.isLayerBacked = true
|
|
self.iconNode.displayWithoutProcessing = true
|
|
self.iconNode.displaysAsynchronously = false
|
|
|
|
self.titleNode = ImmediateTextNode()
|
|
self.titleNode.maximumNumberOfLines = 0
|
|
self.titleNode.textAlignment = .center
|
|
self.titleNode.isUserInteractionEnabled = false
|
|
self.titleNode.displaysAsynchronously = false
|
|
|
|
self.textNode = ImmediateTextNode()
|
|
self.textNode.textAlignment = .center
|
|
self.textNode.maximumNumberOfLines = 0
|
|
self.textNode.displaysAsynchronously = false
|
|
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.primaryColor)
|
|
let link = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.accentColor, additionalAttributes: [TelegramTextAttributes.URL: ""])
|
|
self.textNode.attributedText = parseMarkdownIntoAttributedString(strings.Login_TermsOfServiceLabel.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)
|
|
|
|
self.buttonNode = SolidRoundedButtonNode(theme: self.theme, height: 48.0, cornerRadius: 9.0)
|
|
|
|
self.privacyPolicyNode = HighlightableButtonNode()
|
|
self.privacyPolicyNode.setTitle("Privacy Policy", with: Font.regular(16.0), with: self.theme.accentColor, for: .normal)
|
|
|
|
self.nextNode = HighlightableButtonNode()
|
|
self.nextNode.setTitle("Skip", with: Font.regular(17.0), with: self.theme.accentColor, for: .normal)
|
|
self.nextNode.isHidden = true
|
|
|
|
super.init()
|
|
|
|
self.setViewBlock({
|
|
return UITracingLayerView()
|
|
})
|
|
|
|
self.backgroundColor = self.theme.backgroundColor
|
|
|
|
self.addSubnode(self.iconNode)
|
|
self.addSubnode(self.titleNode)
|
|
self.addSubnode(self.textNode)
|
|
self.addSubnode(self.buttonNode)
|
|
self.addSubnode(self.privacyPolicyNode)
|
|
self.addSubnode(self.nextNode)
|
|
|
|
self.buttonNode.pressed = { [weak self] in
|
|
self?.allow?()
|
|
}
|
|
|
|
self.privacyPolicyNode.addTarget(self, action: #selector(self.privacyPolicyPressed), forControlEvents: .touchUpInside)
|
|
self.nextNode.addTarget(self, action: #selector(self.nextPressed), forControlEvents: .touchUpInside)
|
|
}
|
|
|
|
func updateData(subject: DeviceAccessSubject, currentStatus: AccessType) {
|
|
var icon: UIImage?
|
|
var title = ""
|
|
var text = ""
|
|
var buttonTitle = ""
|
|
var hasPrivacyPolicy = false
|
|
|
|
switch subject {
|
|
case .contacts:
|
|
icon = UIImage(bundleImageName: "Settings/Permissions/Contacts")
|
|
title = "Sync Your Contacts"
|
|
text = "See who's on Telegram and switch seamlessly, without having to \"add\" to add your friends."
|
|
if currentStatus == .denied {
|
|
buttonTitle = "Allow in Settings"
|
|
} else {
|
|
buttonTitle = "Allow Access"
|
|
}
|
|
hasPrivacyPolicy = true
|
|
case .notifications:
|
|
icon = UIImage(bundleImageName: "Settings/Permissions/Notifications")
|
|
title = "Turn ON Notifications"
|
|
text = "Don't miss important messages from your friends and coworkers."
|
|
if currentStatus == .denied || currentStatus == .restricted {
|
|
buttonTitle = "Turn ON in Settings"
|
|
} else {
|
|
buttonTitle = "Turn Notifications ON"
|
|
}
|
|
case .cellularData:
|
|
icon = UIImage(bundleImageName: "Settings/Permissions/CellularData")
|
|
title = "Turn ON Mobile Data"
|
|
text = "Don't worry, Telegram keeps network usage to a minimum. You can further control this in Settings > Data and Storage."
|
|
buttonTitle = "Turn ON in Settings"
|
|
case .siri:
|
|
title = "Turn ON Siri"
|
|
text = "Use Siri to send messages and make calls."
|
|
if currentStatus == .denied {
|
|
buttonTitle = "Turn ON in Settings"
|
|
} else {
|
|
buttonTitle = "Turn Siri ON"
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
|
|
self.iconNode.image = icon
|
|
self.title = title
|
|
|
|
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: self.theme.primaryColor)
|
|
let link = MarkdownAttributeSet(font: Font.regular(16.0), textColor: self.theme.accentColor, additionalAttributes: [TelegramTextAttributes.URL: ""])
|
|
self.textNode.attributedText = parseMarkdownIntoAttributedString(text.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)
|
|
|
|
self.buttonNode.title = buttonTitle
|
|
|
|
self.privacyPolicyNode.isHidden = !hasPrivacyPolicy
|
|
|
|
if let (layout, navigationHeight) = self.layoutArguments {
|
|
self.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: .immediate)
|
|
}
|
|
}
|
|
|
|
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
|
self.layoutArguments = (layout, navigationBarHeight)
|
|
|
|
let insets = layout.insets(options: [.statusBar])
|
|
let fontSize: CGFloat
|
|
let sideInset: CGFloat
|
|
if layout.size.width > 330.0 {
|
|
fontSize = 22.0
|
|
sideInset = 38.0
|
|
} else {
|
|
fontSize = 18.0
|
|
sideInset = 20.0
|
|
}
|
|
|
|
let nextSize = self.nextNode.measure(layout.size)
|
|
transition.updateFrame(node: self.nextNode, frame: CGRect(x: layout.size.width - insets.right - nextSize.width - 16.0, y: insets.top + 10.0 + 60.0, width: nextSize.width, height: nextSize.height))
|
|
|
|
self.titleNode.attributedText = NSAttributedString(string: self.title ?? "", font: Font.semibold(fontSize), textColor: self.theme.primaryColor)
|
|
|
|
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
|
let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
|
let buttonHeight = self.buttonNode.updateLayout(width: layout.size.width, transition: transition)
|
|
|
|
var items: [AuthorizationLayoutItem] = []
|
|
if let icon = self.iconNode.image {
|
|
items.append(AuthorizationLayoutItem(node: self.iconNode, size: icon.size, spacingBefore: AuthorizationLayoutItemSpacing(weight: 122.0, maxValue: 122.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 15.0, maxValue: 15.0)))
|
|
}
|
|
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
|
|
items.append(AuthorizationLayoutItem(node: self.textNode, size: textSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 5.0, maxValue: 5.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 35.0, maxValue: 35.0)))
|
|
items.append(AuthorizationLayoutItem(node: self.buttonNode, size: CGSize(width: layout.size.width, height: buttonHeight), spacingBefore: AuthorizationLayoutItemSpacing(weight: 35.0, maxValue: 35.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 50.0)))
|
|
|
|
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false)
|
|
|
|
let privacyPolicySize = self.privacyPolicyNode.measure(layout.size)
|
|
transition.updateFrame(node: self.privacyPolicyNode, frame: CGRect(x: (layout.size.width - privacyPolicySize.width) / 2.0, y: self.buttonNode.frame.maxY + (layout.size.height - self.buttonNode.frame.maxY - insets.bottom - privacyPolicySize.height) / 2.0, width: privacyPolicySize.width, height: privacyPolicySize.height))
|
|
}
|
|
|
|
@objc func allowPressed() {
|
|
self.allow?()
|
|
}
|
|
|
|
@objc func privacyPolicyPressed() {
|
|
self.openPrivacyPolicy?()
|
|
}
|
|
|
|
@objc func nextPressed() {
|
|
self.next?()
|
|
}
|
|
|
|
func animateOut(completion: (() -> Void)? = nil) {
|
|
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, completion: { [weak self] _ in
|
|
if let strongSelf = self {
|
|
strongSelf.dismiss?()
|
|
}
|
|
completion?()
|
|
})
|
|
}
|
|
}
|