mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Web app improvements
This commit is contained in:
parent
ee86f431d7
commit
1a93f976a7
@ -64,6 +64,8 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
private var panGestureRecognizer: UIPanGestureRecognizer?
|
private var panGestureRecognizer: UIPanGestureRecognizer?
|
||||||
|
|
||||||
var isPanningUpdated: (Bool) -> Void = { _ in }
|
var isPanningUpdated: (Bool) -> Void = { _ in }
|
||||||
|
var isExpandedUpdated: (Bool) -> Void = { _ in }
|
||||||
|
var onExpandAnimationCompleted: () -> Void = {}
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
self.wrappingNode = ASDisplayNode()
|
self.wrappingNode = ASDisplayNode()
|
||||||
@ -150,6 +152,11 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
return self.panGestureArguments != nil
|
return self.panGestureArguments != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isAnimating = false
|
||||||
|
var isPanning: Bool {
|
||||||
|
return self.panGestureArguments != nil || self.isAnimating
|
||||||
|
}
|
||||||
|
|
||||||
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
|
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
|
||||||
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
|
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
|
||||||
guard let (layout, controllers, coveredByModalTransition) = self.validLayout else {
|
guard let (layout, controllers, coveredByModalTransition) = self.validLayout else {
|
||||||
@ -159,6 +166,14 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
let isLandscape = layout.orientation == .landscape
|
let isLandscape = layout.orientation == .landscape
|
||||||
let edgeTopInset = isLandscape ? 0.0 : attachmentDefaultTopInset(layout: layout)
|
let edgeTopInset = isLandscape ? 0.0 : attachmentDefaultTopInset(layout: layout)
|
||||||
|
|
||||||
|
let completion = {
|
||||||
|
self.isAnimating = false
|
||||||
|
guard self.panGestureArguments == nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isPanningUpdated(false)
|
||||||
|
}
|
||||||
|
|
||||||
switch recognizer.state {
|
switch recognizer.state {
|
||||||
case .began:
|
case .began:
|
||||||
let point = recognizer.location(in: self.view)
|
let point = recognizer.location(in: self.view)
|
||||||
@ -262,13 +277,6 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
let offset = currentTopInset + panOffset
|
let offset = currentTopInset + panOffset
|
||||||
let topInset: CGFloat = edgeTopInset
|
let topInset: CGFloat = edgeTopInset
|
||||||
|
|
||||||
let completion = {
|
|
||||||
guard self.panGestureArguments == nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.isPanningUpdated(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
var dismissing = false
|
var dismissing = false
|
||||||
if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) {
|
if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) {
|
||||||
self.interactivelyDismissed?()
|
self.interactivelyDismissed?()
|
||||||
@ -285,15 +293,14 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
let distance = topInset - offset
|
let distance = topInset - offset
|
||||||
let initialVelocity: CGFloat = distance.isZero ? 0.0 : abs(velocity.y / distance)
|
let initialVelocity: CGFloat = distance.isZero ? 0.0 : abs(velocity.y / distance)
|
||||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: transition)
|
|
||||||
|
|
||||||
Queue.mainQueue().after(0.5, completion)
|
self.isAnimating = true
|
||||||
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: transition, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
|
|
||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut))
|
self.isAnimating = true
|
||||||
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut), completion: completion)
|
||||||
Queue.mainQueue().after(0.35, completion)
|
|
||||||
}
|
}
|
||||||
} else if (velocity.y < -300.0 || offset < topInset / 2.0) {
|
} else if (velocity.y < -300.0 || offset < topInset / 2.0) {
|
||||||
if velocity.y > -2200.0 && velocity.y < -300.0, let listNode = listNode {
|
if velocity.y > -2200.0 && velocity.y < -300.0, let listNode = listNode {
|
||||||
@ -302,13 +309,11 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset)
|
|
||||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
|
|
||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: transition)
|
let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset)
|
||||||
|
self.isAnimating = true
|
||||||
Queue.mainQueue().after(0.5, completion)
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity)), completion: completion)
|
||||||
} else {
|
} else {
|
||||||
if let listNode = listNode {
|
if let listNode = listNode {
|
||||||
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
||||||
@ -319,9 +324,8 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut))
|
self.isAnimating = true
|
||||||
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut), completion: completion)
|
||||||
Queue.mainQueue().after(0.35, completion)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dismissing {
|
if !dismissing {
|
||||||
@ -334,7 +338,8 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
case .cancelled:
|
case .cancelled:
|
||||||
self.panGestureArguments = nil
|
self.panGestureArguments = nil
|
||||||
|
|
||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut))
|
self.isAnimating = true
|
||||||
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut), completion: completion)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -362,7 +367,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: transition)
|
self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(layout: ContainerViewLayout, controllers: [AttachmentContainable], coveredByModalTransition: CGFloat, transition: ContainedViewLayoutTransition) {
|
func update(layout: ContainerViewLayout, controllers: [AttachmentContainable], coveredByModalTransition: CGFloat, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void = {}) {
|
||||||
if self.isDismissed {
|
if self.isDismissed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -391,7 +396,9 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
} else {
|
} else {
|
||||||
topInset = effectiveExpanded ? 0.0 : edgeTopInset
|
topInset = effectiveExpanded ? 0.0 : edgeTopInset
|
||||||
}
|
}
|
||||||
transition.updateFrame(node: self.wrappingNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: layout.size))
|
transition.updateFrame(node: self.wrappingNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: layout.size), completion: { _ in
|
||||||
|
completion()
|
||||||
|
})
|
||||||
|
|
||||||
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / defaultTopInset)
|
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / defaultTopInset)
|
||||||
self.updateModalProgress?(modalProgress, transition)
|
self.updateModalProgress?(modalProgress, transition)
|
||||||
|
|||||||
@ -75,6 +75,7 @@ public protocol AttachmentContainable: ViewController {
|
|||||||
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void { get set }
|
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void { get set }
|
||||||
var cancelPanGesture: () -> Void { get set }
|
var cancelPanGesture: () -> Void { get set }
|
||||||
var isContainerPanning: () -> Bool { get set }
|
var isContainerPanning: () -> Bool { get set }
|
||||||
|
var isContainerExpanded: () -> Bool { get set }
|
||||||
|
|
||||||
func isContainerPanningUpdated(_ panning: Bool)
|
func isContainerPanningUpdated(_ panning: Bool)
|
||||||
|
|
||||||
@ -472,7 +473,15 @@ public class AttachmentController: ViewController {
|
|||||||
|
|
||||||
controller.isContainerPanning = { [weak self] in
|
controller.isContainerPanning = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
return strongSelf.container.isTracking
|
return strongSelf.container.isPanning
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.isContainerExpanded = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
return strongSelf.container.isExpanded
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -522,6 +522,7 @@ private class CreatePollControllerImpl: ItemListController, AttachmentContainabl
|
|||||||
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
public var cancelPanGesture: () -> Void = { }
|
public var cancelPanGesture: () -> Void = { }
|
||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createPollController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peer: EnginePeer, isQuiz: Bool? = nil, completion: @escaping (ComposedPoll) -> Void) -> AttachmentContainable {
|
public func createPollController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peer: EnginePeer, isQuiz: Bool? = nil, completion: @escaping (ComposedPoll) -> Void) -> AttachmentContainable {
|
||||||
|
|||||||
@ -410,6 +410,7 @@ open class LegacyController: ViewController, PresentableController, AttachmentCo
|
|||||||
open var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
open var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
open var cancelPanGesture: () -> Void = { }
|
open var cancelPanGesture: () -> Void = { }
|
||||||
open var isContainerPanning: () -> Bool = { return false }
|
open var isContainerPanning: () -> Bool = { return false }
|
||||||
|
open var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
public init(presentation: LegacyControllerPresentation, theme: PresentationTheme? = nil, strings: PresentationStrings? = nil, initialLayout: ContainerViewLayout? = nil) {
|
public init(presentation: LegacyControllerPresentation, theme: PresentationTheme? = nil, strings: PresentationStrings? = nil, initialLayout: ContainerViewLayout? = nil) {
|
||||||
self.sizeClass.set(SSignal.single(UIUserInterfaceSizeClass.compact.rawValue as NSNumber))
|
self.sizeClass.set(SSignal.single(UIUserInterfaceSizeClass.compact.rawValue as NSNumber))
|
||||||
|
|||||||
@ -76,6 +76,7 @@ public final class LocationPickerController: ViewController, AttachmentContainab
|
|||||||
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
public var cancelPanGesture: () -> Void = { }
|
public var cancelPanGesture: () -> Void = { }
|
||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: LocationPickerMode, completion: @escaping (TelegramMediaMap, String?) -> Void) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: LocationPickerMode, completion: @escaping (TelegramMediaMap, String?) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|||||||
@ -134,6 +134,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
public var cancelPanGesture: () -> Void = { }
|
public var cancelPanGesture: () -> Void = { }
|
||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
var dismissAll: () -> Void = { }
|
var dismissAll: () -> Void = { }
|
||||||
|
|
||||||
|
|||||||
@ -169,6 +169,7 @@ private class AttachmentFileControllerImpl: ItemListController, AttachmentContai
|
|||||||
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
public var cancelPanGesture: () -> Void = { }
|
public var cancelPanGesture: () -> Void = { }
|
||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
var delayDisappear = false
|
var delayDisappear = false
|
||||||
|
|
||||||
|
|||||||
@ -80,6 +80,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
|||||||
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
var cancelPanGesture: () -> Void = { }
|
var cancelPanGesture: () -> Void = { }
|
||||||
var isContainerPanning: () -> Bool = { return false }
|
var isContainerPanning: () -> Bool = { return false }
|
||||||
|
var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
init(_ params: ContactSelectionControllerParams) {
|
init(_ params: ContactSelectionControllerParams) {
|
||||||
self.context = params.context
|
self.context = params.context
|
||||||
|
|||||||
@ -75,6 +75,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
|
||||||
public var cancelPanGesture: () -> Void = { }
|
public var cancelPanGesture: () -> Void = { }
|
||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, UIScrollViewDelegate {
|
fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, UIScrollViewDelegate {
|
||||||
private weak var controller: WebAppController?
|
private weak var controller: WebAppController?
|
||||||
@ -348,6 +349,12 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func isContainerPanningUpdated(_ isPanning: Bool) {
|
||||||
|
if let (layout, navigationBarHeight) = self.validLayout {
|
||||||
|
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let previousLayout = self.validLayout?.0
|
let previousLayout = self.validLayout?.0
|
||||||
@ -373,7 +380,9 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
transition.updateFrame(view: webView, frame: frame)
|
transition.updateFrame(view: webView, frame: frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
webView.updateFrame(frame: viewportFrame, transition: transition)
|
if let controller = self.controller {
|
||||||
|
webView.updateMetrics(height: viewportFrame.height, isExpanded: controller.isContainerExpanded(), isStable: !controller.isContainerPanning(), transition: transition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let placeholderNode = self.placeholderNode {
|
if let placeholderNode = self.placeholderNode {
|
||||||
@ -665,6 +674,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.updateTabBarAlpha(1.0, .immediate)
|
self.updateTabBarAlpha(1.0, .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isContainerPanningUpdated(_ isPanning: Bool) {
|
||||||
|
self.controllerNode.isContainerPanningUpdated(isPanning)
|
||||||
|
}
|
||||||
|
|
||||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||||
super.containerLayoutUpdated(layout, transition: transition)
|
super.containerLayoutUpdated(layout, transition: transition)
|
||||||
|
|
||||||
|
|||||||
@ -126,8 +126,9 @@ final class WebAppWebView: WKWebView {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFrame(frame: CGRect, transition: ContainedViewLayoutTransition) {
|
func updateMetrics(height: CGFloat, isExpanded: Bool, isStable: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
self.sendEvent(name: "viewport_changed", data: "{height:\(frame.height)}")
|
let data = "{height:\(height), is_expanded:\(isExpanded ? "true" : "false"), is_stable_state:\(isStable ? "true" : "false")}"
|
||||||
|
self.sendEvent(name: "viewport_changed", data: data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private(set) var didTouchOnce = false
|
private(set) var didTouchOnce = false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user