mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
Various improvements
This commit is contained in:
@@ -27,161 +27,10 @@ import LocalAuth
|
||||
import OpenInExternalAppUI
|
||||
import ShareController
|
||||
import UndoUI
|
||||
import AvatarNode
|
||||
|
||||
private let durgerKingBotIds: [Int64] = [5104055776, 2200339955]
|
||||
|
||||
public class WebAppCancelButtonNode: ASDisplayNode {
|
||||
public enum State {
|
||||
case cancel
|
||||
case back
|
||||
}
|
||||
|
||||
public let buttonNode: HighlightTrackingButtonNode
|
||||
private let arrowNode: ASImageNode
|
||||
private let labelNode: ImmediateTextNode
|
||||
|
||||
public var state: State = .cancel
|
||||
|
||||
private var color: UIColor?
|
||||
|
||||
private var _theme: PresentationTheme
|
||||
public var theme: PresentationTheme {
|
||||
get {
|
||||
return self._theme
|
||||
}
|
||||
set {
|
||||
self._theme = newValue
|
||||
self.setState(self.state, animated: false, animateScale: false, force: true)
|
||||
}
|
||||
}
|
||||
private let strings: PresentationStrings
|
||||
|
||||
private weak var colorSnapshotView: UIView?
|
||||
|
||||
public func updateColor(_ color: UIColor?, transition: ContainedViewLayoutTransition) {
|
||||
let previousColor = self.color
|
||||
self.color = color
|
||||
|
||||
if case let .animated(duration, curve) = transition, previousColor != color, !self.animatingStateChange {
|
||||
if let snapshotView = self.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.bounds
|
||||
self.view.addSubview(snapshotView)
|
||||
self.colorSnapshotView = snapshotView
|
||||
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, timingFunction: curve.timingFunction, removeOnCompletion: false, completion: { _ in
|
||||
snapshotView.removeFromSuperview()
|
||||
})
|
||||
self.arrowNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: curve.timingFunction)
|
||||
self.labelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: curve.timingFunction)
|
||||
}
|
||||
}
|
||||
self.setState(self.state, animated: false, animateScale: false, force: true)
|
||||
}
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self._theme = theme
|
||||
self.strings = strings
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
self.arrowNode = ASImageNode()
|
||||
self.arrowNode.displaysAsynchronously = false
|
||||
|
||||
self.labelNode = ImmediateTextNode()
|
||||
self.labelNode.displaysAsynchronously = false
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.buttonNode)
|
||||
self.buttonNode.addSubnode(self.arrowNode)
|
||||
self.buttonNode.addSubnode(self.labelNode)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if highlighted {
|
||||
strongSelf.arrowNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.arrowNode.alpha = 0.4
|
||||
strongSelf.labelNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.labelNode.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.arrowNode.alpha = 1.0
|
||||
strongSelf.arrowNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
strongSelf.labelNode.alpha = 1.0
|
||||
strongSelf.labelNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
|
||||
self.setState(.cancel, animated: false, force: true)
|
||||
}
|
||||
|
||||
public func setTheme(_ theme: PresentationTheme, animated: Bool) {
|
||||
self._theme = theme
|
||||
var animated = animated
|
||||
if self.animatingStateChange {
|
||||
animated = false
|
||||
}
|
||||
self.setState(self.state, animated: animated, animateScale: false, force: true)
|
||||
}
|
||||
|
||||
private var animatingStateChange = false
|
||||
public func setState(_ state: State, animated: Bool, animateScale: Bool = true, force: Bool = false) {
|
||||
guard self.state != state || force else {
|
||||
return
|
||||
}
|
||||
self.state = state
|
||||
|
||||
if let colorSnapshotView = self.colorSnapshotView {
|
||||
self.colorSnapshotView = nil
|
||||
colorSnapshotView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if animated, let snapshotView = self.buttonNode.view.snapshotContentTree() {
|
||||
self.animatingStateChange = true
|
||||
snapshotView.layer.sublayerTransform = self.buttonNode.subnodeTransform
|
||||
self.view.addSubview(snapshotView)
|
||||
|
||||
let duration: Double = animateScale ? 0.25 : 0.3
|
||||
if animateScale {
|
||||
snapshotView.layer.animateScale(from: 1.0, to: 0.001, duration: 0.25, removeOnCompletion: false)
|
||||
}
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
self.animatingStateChange = false
|
||||
})
|
||||
|
||||
if animateScale {
|
||||
self.buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.25)
|
||||
}
|
||||
self.buttonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||
}
|
||||
|
||||
let color = self.color ?? self.theme.rootController.navigationBar.accentTextColor
|
||||
|
||||
self.arrowNode.isHidden = state == .cancel
|
||||
self.labelNode.attributedText = NSAttributedString(string: state == .cancel ? self.strings.Common_Close : self.strings.Common_Back, font: Font.regular(17.0), textColor: color)
|
||||
|
||||
let labelSize = self.labelNode.updateLayout(CGSize(width: 120.0, height: 56.0))
|
||||
|
||||
self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: labelSize.width, height: self.buttonNode.frame.height))
|
||||
self.arrowNode.image = NavigationBarTheme.generateBackArrowImage(color: color)
|
||||
if let image = self.arrowNode.image {
|
||||
self.arrowNode.frame = CGRect(origin: self.arrowNode.frame.origin, size: image.size)
|
||||
}
|
||||
self.labelNode.frame = CGRect(origin: self.labelNode.frame.origin, size: labelSize)
|
||||
self.buttonNode.subnodeTransform = CATransform3DMakeTranslation(state == .back ? 11.0 : 0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: self.buttonNode.frame.width, height: constrainedSize.height))
|
||||
self.arrowNode.frame = CGRect(origin: CGPoint(x: -19.0, y: floorToScreenPixels((constrainedSize.height - self.arrowNode.frame.size.height) / 2.0)), size: self.arrowNode.frame.size)
|
||||
self.labelNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((constrainedSize.height - self.labelNode.frame.size.height) / 2.0)), size: self.labelNode.frame.size)
|
||||
|
||||
return CGSize(width: 70.0, height: 56.0)
|
||||
}
|
||||
}
|
||||
|
||||
public struct WebAppParameters {
|
||||
public enum Source {
|
||||
case generic
|
||||
@@ -299,12 +148,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
private var queryId: Int64?
|
||||
fileprivate let canMinimize = true
|
||||
|
||||
private var placeholderDisposable: Disposable?
|
||||
private var iconDisposable: Disposable?
|
||||
private var placeholderDisposable = MetaDisposable()
|
||||
private var keepAliveDisposable: Disposable?
|
||||
|
||||
private var paymentDisposable: Disposable?
|
||||
|
||||
private var iconDisposable: Disposable?
|
||||
fileprivate var icon: UIImage?
|
||||
|
||||
private var lastExpansionTimestamp: Double?
|
||||
|
||||
private var didTransitionIn = false
|
||||
@@ -395,7 +245,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
}
|
||||
|
||||
self.placeholderDisposable = (placeholder
|
||||
self.placeholderDisposable.set((placeholder
|
||||
|> deliverOnMainQueue).start(next: { [weak self] fileReferenceAndIsPlaceholder in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@@ -413,7 +263,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
if let fileReference = fileReference {
|
||||
let _ = freeMediaFileInteractiveFetched(account: strongSelf.context.account, userLocation: .other, fileReference: fileReference).start()
|
||||
}
|
||||
strongSelf.iconDisposable = (svgIconImageFile(account: strongSelf.context.account, fileReference: fileReference, stickToTop: isPlaceholder)
|
||||
strongSelf.placeholderDisposable.set((svgIconImageFile(account: strongSelf.context.account, fileReference: fileReference, stickToTop: isPlaceholder)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] transform in
|
||||
if let strongSelf = self {
|
||||
let imageSize: CGSize
|
||||
@@ -433,13 +283,27 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
strongSelf.placeholderNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
})
|
||||
}))
|
||||
}))
|
||||
|
||||
self.iconDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: controller.botId))
|
||||
|> mapToSignal { peer -> Signal<UIImage?, NoError> in
|
||||
guard let peer else {
|
||||
return .complete()
|
||||
}
|
||||
return peerAvatarCompleteImage(account: context.account, peer: peer, size: CGSize(width: 32.0, height: 32.0), round: false)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] icon in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.icon = icon
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.placeholderDisposable?.dispose()
|
||||
self.iconDisposable?.dispose()
|
||||
self.placeholderDisposable.dispose()
|
||||
self.keepAliveDisposable?.dispose()
|
||||
self.paymentDisposable?.dispose()
|
||||
|
||||
@@ -2240,6 +2104,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
fileprivate var canMinimize: Bool {
|
||||
return self.controllerNode.canMinimize
|
||||
}
|
||||
|
||||
public var minimizedIcon: UIImage? {
|
||||
return self.controllerNode.icon
|
||||
}
|
||||
}
|
||||
|
||||
final class WebAppPickerContext: AttachmentMediaPickerContext {
|
||||
|
||||
Reference in New Issue
Block a user