Swiftgram/TelegramUI/PermissionControllerNode.swift

224 lines
9.4 KiB
Swift

import Foundation
import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
enum PermissionStateKind: Int32 {
case contacts
case notifications
case siri
case cellularData
}
private enum PermissionRequestStatus {
case requestable
case denied
}
private enum PermissionNotificationsRequestStatus {
case requestable
case denied
case unreachable
}
private enum PermissionState: Equatable {
case contacts(status: PermissionRequestStatus)
case notifications(status: PermissionNotificationsRequestStatus)
case siri(status: PermissionRequestStatus)
case cellularData
var kind: PermissionStateKind {
switch self {
case .contacts:
return .contacts
case .notifications:
return .notifications
case .siri:
return .siri
case .cellularData:
return .cellularData
}
}
}
private struct PermissionControllerDataState: Equatable {
var state: PermissionState?
}
private struct PermissionControllerLayoutState: Equatable {
let layout: ContainerViewLayout
let navigationHeight: CGFloat
}
private struct PermissionControllerInnerState: Equatable {
var layout: PermissionControllerLayoutState?
var data: PermissionControllerDataState
}
private struct PermissionControllerState: Equatable {
var layout: PermissionControllerLayoutState
var data: PermissionControllerDataState
}
extension PermissionControllerState {
init?(_ state: PermissionControllerInnerState) {
guard let layout = state.layout else {
return nil
}
self.init(layout: layout, data: state.data)
}
}
final class PermissionControllerNode: ASDisplayNode {
private let account: Account
private var presentationData: PresentationData
private var innerState: PermissionControllerInnerState
private var contentNode: PermissionContentNode?
var allow: (() -> Void)?
var openPrivacyPolicy: (() -> Void)?
var dismiss: (() -> Void)?
init(account: Account) {
self.account = account
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
self.innerState = PermissionControllerInnerState(layout: nil, data: PermissionControllerDataState(state: nil))
super.init()
self.setViewBlock({
return UITracingLayerView()
})
self.applyPresentationData()
}
func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData
self.applyPresentationData()
}
private func applyPresentationData() {
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor }
func animateIn(completion: (() -> Void)? = nil) {
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
}
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: { _ in
completion?()
})
}
private func updateState(_ f: (PermissionControllerInnerState) -> PermissionControllerInnerState, transition: ContainedViewLayoutTransition) {
let updatedState = f(self.innerState)
if updatedState != self.innerState {
self.innerState = updatedState
if let state = PermissionControllerState(updatedState) {
self.transition(state: state, transition: transition)
}
}
}
private func transition(state: PermissionControllerState, transition: ContainedViewLayoutTransition) {
// let insets = state.layout.layout.insets(options: [.statusBar])
// let contentFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: state.layout.layout.size.width, height: state.layout.layout.size.height))
//
// if state.data.state?.kind != self.contentNode?.kind {
// if let dataState = state.data.state {
// let icon: UIImage?
// let title: String
// let text: String
// let buttonTitle: String
// let hasPrivacyPolicy: Bool
//
// switch dataState {
// case let .contacts(status):
// icon = UIImage(bundleImageName: "Settings/Permissions/Contacts")
// title = self.presentationData.strings.Permissions_ContactsTitle
// text = self.presentationData.strings.Permissions_ContactsText
// if status == .denied {
// buttonTitle = self.presentationData.strings.Permissions_ContactsAllowInSettings
// } else {
// buttonTitle = self.presentationData.strings.Permissions_ContactsAllow
// }
// hasPrivacyPolicy = true
// case let .notifications(status):
// icon = UIImage(bundleImageName: "Settings/Permissions/Notifications")
// title = self.presentationData.strings.Permissions_NotificationsTitle
// text = self.presentationData.strings.Permissions_NotificationsText
// if status == .denied {
// buttonTitle = self.presentationData.strings.Permissions_NotificationsAllowInSettings
// } else {
// buttonTitle = self.presentationData.strings.Permissions_NotificationsAllow
// }
// hasPrivacyPolicy = false
// case let .siri(status):
// icon = UIImage(bundleImageName: "Settings/Permissions/CellularData")
// title = self.presentationData.strings.Permissions_SiriTitle
// text = self.presentationData.strings.Permissions_SiriText
// if status == .denied {
// buttonTitle = self.presentationData.strings.Permissions_SiriAllowInSettings
// } else {
// buttonTitle = self.presentationData.strings.Permissions_SiriAllow
// }
// hasPrivacyPolicy = false
// case .cellularData:
// icon = UIImage(bundleImageName: "Settings/Permissions/CellularData")
// title = self.presentationData.strings.Permissions_CellularDataTitle
// text = self.presentationData.strings.Permissions_CellularDataText
// buttonTitle = self.presentationData.strings.Permissions_CellularDataAllowInSettings
// hasPrivacyPolicy = false
// }
//
// let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: dataState.kind, icon: icon, title: title, text: text, buttonTitle: buttonTitle, buttonAction: {}, openPrivacyPolicy: hasPrivacyPolicy ? self.openPrivacyPolicy : nil)
// self.insertSubnode(contentNode, at: 0)
// contentNode.updateLayout(size: contentFrame.size, insets: insets, transition: .immediate)
// contentNode.frame = contentFrame
// if let currentContentNode = self.contentNode {
// transition.updatePosition(node: currentContentNode, position: CGPoint(x: -contentFrame.size.width / 2.0, y: contentFrame.midY), completion: { [weak currentContentNode] _ in
// currentContentNode?.removeFromSupernode()
// })
// transition.animateHorizontalOffsetAdditive(node: contentNode, offset: -contentFrame.width)
// } else if transition.isAnimated {
// contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
// }
// self.contentNode = contentNode
// } else if let currentContentNode = self.contentNode {
// transition.updateAlpha(node: currentContentNode, alpha: 0.0, completion: { [weak currentContentNode] _ in
// currentContentNode?.removeFromSupernode()
// })
// self.contentNode = nil
// }
// } else if let contentNode = self.contentNode {
// transition.updateFrame(node: contentNode, frame: contentFrame)
// contentNode.updateLayout(size: contentFrame.size, insets: insets, transition: transition)
// }
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
self.updateState({ state in
var state = state
state.layout = PermissionControllerLayoutState(layout: layout, navigationHeight: navigationBarHeight)
return state
}, transition: transition)
}
func activateNextAction() {
}
@objc func allowPressed() {
self.allow?()
}
@objc func privacyPolicyPressed() {
self.openPrivacyPolicy?()
}
}