mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
e23c7f2e2b
commit
e348c620fa
@ -160,6 +160,12 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
}
|
||||
return true
|
||||
}
|
||||
if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer.description.contains("WKDeferringGesture") {
|
||||
return true
|
||||
}
|
||||
if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer.description.contains("UIWebTouchEventsGesture") {
|
||||
return true
|
||||
}
|
||||
if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UILongPressGestureRecognizer {
|
||||
return true
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ public class AttachmentController: ViewController {
|
||||
let panel: AttachmentPanel
|
||||
|
||||
fileprivate var currentType: AttachmentButtonType?
|
||||
private var currentControllers: [AttachmentContainable] = []
|
||||
fileprivate var currentControllers: [AttachmentContainable] = []
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
private var modalProgress: CGFloat = 0.0
|
||||
@ -402,7 +402,7 @@ public class AttachmentController: ViewController {
|
||||
if let current = current as? MinimizedContainerImpl {
|
||||
minimizedContainer = current
|
||||
} else if let context = self?.controller?.context {
|
||||
minimizedContainer = MinimizedContainerImpl(context: context, navigationController: navigationController)
|
||||
minimizedContainer = MinimizedContainerImpl(sharedContext: context.sharedContext)
|
||||
} else {
|
||||
minimizedContainer = nil
|
||||
}
|
||||
@ -954,7 +954,7 @@ public class AttachmentController: ViewController {
|
||||
if fromMenu && !hasButton, let inputContainerHeight = self.inputContainerHeight {
|
||||
panelHeight = inputContainerHeight
|
||||
}
|
||||
if hasPanel || hasButton || (fromMenu && isCompact) {
|
||||
if hasPanel || hasButton {
|
||||
containerInsets.bottom = panelHeight
|
||||
}
|
||||
|
||||
@ -1145,6 +1145,12 @@ public class AttachmentController: ViewController {
|
||||
return false
|
||||
}
|
||||
|
||||
public override var isMinimized: Bool {
|
||||
didSet {
|
||||
self.mainController.isMinimized = self.isMinimized
|
||||
}
|
||||
}
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
@ -1160,6 +1166,10 @@ public class AttachmentController: ViewController {
|
||||
self.node.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
|
||||
public var mainController: ViewController {
|
||||
return self.node.currentControllers.first!
|
||||
}
|
||||
|
||||
public final class InputPanelTransition {
|
||||
let inputNode: ASDisplayNode
|
||||
let accessoryPanelNode: ASDisplayNode?
|
||||
|
@ -2,6 +2,9 @@ import Foundation
|
||||
import AsyncDisplayKit
|
||||
|
||||
public protocol MinimizedContainer: ASDisplayNode {
|
||||
var navigationController: NavigationController? { get set }
|
||||
var controllers: [ViewController] { get }
|
||||
|
||||
var willMaximize: (() -> Void)? { get set }
|
||||
|
||||
func addController(_ viewController: ViewController, transition: ContainedViewLayoutTransition)
|
||||
|
@ -150,7 +150,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
private var rootModalFrame: NavigationModalFrame?
|
||||
private var modalContainers: [NavigationModalContainer] = []
|
||||
private var overlayContainers: [NavigationOverlayContainer] = []
|
||||
private var minimizedContainer: MinimizedContainer?
|
||||
open var minimizedContainer: MinimizedContainer? {
|
||||
didSet {
|
||||
self.minimizedContainer?.navigationController = self
|
||||
}
|
||||
}
|
||||
|
||||
private var globalOverlayContainers: [NavigationOverlayContainer] = []
|
||||
private var globalOverlayBelowKeyboardContainerParent: GlobalOverlayContainerParent?
|
||||
@ -826,6 +830,22 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
layout.additionalInsets.left = max(layout.intrinsicInsets.left, additionalSideInsets.left)
|
||||
layout.additionalInsets.right = max(layout.intrinsicInsets.right, additionalSideInsets.right)
|
||||
|
||||
var updatedSize = layout.size
|
||||
var updatedIntrinsicInsets = layout.intrinsicInsets
|
||||
if case .flat = navigationLayout.root, let minimizedContainer = self.minimizedContainer {
|
||||
if minimizedContainer.supernode !== self.displayNode {
|
||||
if let rootContainer = self.rootContainer, case let .flat(flatContainer) = rootContainer {
|
||||
self.displayNode.insertSubnode(minimizedContainer, aboveSubnode: flatContainer)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(minimizedContainer, at: 0)
|
||||
}
|
||||
}
|
||||
if (layout.inputHeight ?? 0.0).isZero {
|
||||
updatedSize.height -= minimizedContainer.collapsedHeight(layout: layout)
|
||||
updatedIntrinsicInsets.bottom = 0.0
|
||||
}
|
||||
}
|
||||
|
||||
switch navigationLayout.root {
|
||||
case let .flat(controllers):
|
||||
if let rootContainer = self.rootContainer {
|
||||
@ -839,12 +859,6 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
|
||||
var updatedSize = layout.size
|
||||
var updatedIntrinsicInsets = layout.intrinsicInsets
|
||||
if let minimizedContainer = self.minimizedContainer, (layout.inputHeight ?? 0.0).isZero {
|
||||
updatedSize.height -= minimizedContainer.collapsedHeight(layout: layout)
|
||||
updatedIntrinsicInsets.bottom = 0.0
|
||||
}
|
||||
let updatedLayout = layout.withUpdatedSize(updatedSize).withUpdatedIntrinsicInsets(updatedIntrinsicInsets)
|
||||
transition.updateFrame(node: flatContainer, frame: CGRect(origin: CGPoint(), size: updatedSize))
|
||||
flatContainer.update(layout: updatedLayout, canBeClosed: false, controllers: controllers, transition: transition)
|
||||
@ -904,8 +918,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
}
|
||||
self.rootContainer = .flat(flatContainer)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: .immediate)
|
||||
|
||||
let updatedLayout = layout.withUpdatedSize(updatedSize).withUpdatedIntrinsicInsets(updatedIntrinsicInsets)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: updatedSize)
|
||||
flatContainer.update(layout: updatedLayout, canBeClosed: false, controllers: controllers, transition: .immediate)
|
||||
}
|
||||
case let .split(masterControllers, detailControllers):
|
||||
if let rootContainer = self.rootContainer {
|
||||
@ -931,6 +947,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, detailsPlaceholderNode: self.detailsPlaceholderNode, transition: .immediate)
|
||||
flatContainer.statusBarStyleUpdated = nil
|
||||
flatContainer.removeFromSupernode()
|
||||
|
||||
if let minimizedContainer = self.minimizedContainer {
|
||||
minimizedContainer.removeFromSupernode()
|
||||
self.minimizedContainer = nil
|
||||
}
|
||||
case let .split(splitContainer):
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
@ -1554,17 +1575,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.isMaximizing = true
|
||||
self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
|
||||
|
||||
self.minimizedContainer?.removeFromSupernode()
|
||||
self.minimizedContainer = minimizedContainer
|
||||
|
||||
if let minimizedContainer {
|
||||
if let modalContainer = self.modalContainers.first {
|
||||
self.displayNode.insertSubnode(minimizedContainer, belowSubnode: modalContainer)
|
||||
} else {
|
||||
self.displayNode.addSubnode(minimizedContainer)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateContainersNonReentrant(transition: transition)
|
||||
}
|
||||
viewController.isMinimized = true
|
||||
|
@ -1195,7 +1195,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
var hintSeekable = false
|
||||
if let contentInfo = item.contentInfo, case let .message(message, _) = contentInfo {
|
||||
if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.id.namespace == Namespaces.Message.Local {
|
||||
if message.paidContent != nil {
|
||||
disablePictureInPicture = true
|
||||
} else if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.id.namespace == Namespaces.Message.Local {
|
||||
disablePictureInPicture = true
|
||||
} else {
|
||||
let throttledSignal = videoNode.status
|
||||
|
@ -49,6 +49,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
private let shadowNode: ASImageNode
|
||||
|
||||
private var controllerView: UIView?
|
||||
fileprivate var snapshotView: UIView?
|
||||
|
||||
var tapped: (() -> Void)?
|
||||
var highlighted: ((Bool) -> Void)?
|
||||
@ -97,13 +98,19 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
self.shadowNode.image = shadowImage
|
||||
|
||||
self.addSubnode(self.containerNode)
|
||||
if let snapshotView = self.item.controller.displayNode.view.snapshotView(afterScreenUpdates: false) {
|
||||
self.controllerView = snapshotView
|
||||
self.containerNode.view.addSubview(snapshotView)
|
||||
} else {
|
||||
self.controllerView = self.item.controller.displayNode.view
|
||||
self.containerNode.view.addSubview(self.item.controller.displayNode.view)
|
||||
self.controllerView = self.item.controller.displayNode.view
|
||||
self.containerNode.view.addSubview(self.item.controller.displayNode.view)
|
||||
|
||||
Queue.mainQueue().after(0.45) {
|
||||
if !self.isDismissed, let snapshotView = self.controllerView?.snapshotView(afterScreenUpdates: false) {
|
||||
self.snapshotView = snapshotView
|
||||
self.controllerView?.removeFromSuperview()
|
||||
self.controllerView = snapshotView
|
||||
self.containerNode.view.addSubview(snapshotView)
|
||||
self.requestLayout(transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
self.addSubnode(self.headerNode)
|
||||
self.addSubnode(self.dimCoverNode)
|
||||
self.addSubnode(self.shadowNode)
|
||||
@ -181,6 +188,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
}
|
||||
}
|
||||
|
||||
private func requestLayout(transition: ContainedViewLayoutTransition) {
|
||||
guard let (size, insets, isExpanded) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
self.updateLayout(size: size, insets: insets, isExpanded: isExpanded, transition: transition)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, insets: UIEdgeInsets, isExpanded: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, insets, isExpanded)
|
||||
|
||||
@ -203,7 +217,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
transition.updateFrame(node: self.headerNode, frame: headerFrame)
|
||||
transition.updateFrame(node: self.dimCoverNode, frame: CGRect(origin: .zero, size: size))
|
||||
|
||||
if let controllerView = self.controllerView {
|
||||
if let controllerView = self.snapshotView {
|
||||
let controllerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - controllerView.bounds.size.width) / 2.0), y: 0.0), size: controllerView.bounds.size)
|
||||
transition.updateFrame(view: controllerView, frame: controllerFrame)
|
||||
}
|
||||
@ -214,8 +228,8 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
}
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private weak var navigationController: NavigationController?
|
||||
private let sharedContext: SharedAccountContext
|
||||
public weak var navigationController: NavigationController?
|
||||
private var items: [Item] = []
|
||||
|
||||
private var presentationData: PresentationData
|
||||
@ -239,10 +253,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
private var isApplyingTransition = false
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
public init(context: AccountContext, navigationController: NavigationController) {
|
||||
self.context = context
|
||||
self.navigationController = navigationController
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
public var controllers: [ViewController] {
|
||||
return self.items.map { $0.controller }
|
||||
}
|
||||
|
||||
public init(sharedContext: SharedAccountContext) {
|
||||
self.sharedContext = sharedContext
|
||||
self.presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.bottomEdgeView = UIImageView()
|
||||
self.bottomEdgeView.contentMode = .scaleToFill
|
||||
@ -275,7 +292,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
self.view.addSubview(self.dimView)
|
||||
self.view.addSubview(self.scrollView)
|
||||
|
||||
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|
||||
self.presentationDataDisposable = (self.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] presentationData in
|
||||
guard let self else {
|
||||
return
|
||||
@ -488,6 +505,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return
|
||||
}
|
||||
self.requestUpdate(transition: .immediate)
|
||||
|
||||
if scrollView.contentOffset.y < -64.0 {
|
||||
self.isExpanded = false
|
||||
scrollView.panGestureRecognizer.isEnabled = false
|
||||
scrollView.panGestureRecognizer.isEnabled = true
|
||||
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
}
|
||||
|
||||
private func requestUpdate(transition: ContainedViewLayoutTransition, completion: @escaping (Transition) -> Void = { _ in }) {
|
||||
@ -773,6 +797,16 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
if self.currentTransition == currentTransition {
|
||||
self.currentTransition = nil
|
||||
}
|
||||
|
||||
if let snaphotView = itemNode.snapshotView {
|
||||
itemNode.item.controller.displayNode.view.addSubview(snaphotView)
|
||||
Queue.mainQueue().after(0.15, {
|
||||
snaphotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
||||
snaphotView.removeFromSuperview()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
completion(currentTransition)
|
||||
self.itemNodes[itemId] = nil
|
||||
itemNode.removeFromSupernode()
|
||||
|
@ -5296,6 +5296,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
guard let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
|
||||
if let navigationController = controller.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
||||
for controller in minimizedContainer.controllers {
|
||||
if let controller = controller as? AttachmentController, let mainController = controller.mainController as? WebAppController, mainController.botId == bot.peer.id && mainController.source == .settings {
|
||||
navigationController.maximizeViewController(controller, animated: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let presentationData = self.presentationData
|
||||
let proceed: (Bool) -> Void = { [weak self] installed in
|
||||
guard let self else {
|
||||
|
@ -178,6 +178,7 @@ final class SharedApplicationContext {
|
||||
let notificationManager: SharedNotificationManager
|
||||
let wakeupManager: SharedWakeupManager
|
||||
let overlayMediaController: ViewController & OverlayMediaController
|
||||
var minimizedContainer: MinimizedContainer?
|
||||
|
||||
init(sharedContext: SharedAccountContextImpl, notificationManager: SharedNotificationManager, wakeupManager: SharedWakeupManager) {
|
||||
self.sharedContext = sharedContext
|
||||
|
@ -168,6 +168,10 @@ final class AuthorizedApplicationContext {
|
||||
self.notificationController = NotificationContainerController(context: context)
|
||||
|
||||
self.rootController = TelegramRootController(context: context)
|
||||
self.rootController.minimizedContainer = self.sharedApplicationContext.minimizedContainer
|
||||
self.rootController.minimizedContainerUpdated = { [weak self] minimizedContainer in
|
||||
self?.sharedApplicationContext.minimizedContainer = minimizedContainer
|
||||
}
|
||||
|
||||
self.rootController.globalOverlayControllersUpdated = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
|
@ -0,0 +1,253 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import ChatPresentationInterfaceState
|
||||
import ChatControllerInteraction
|
||||
import WebUI
|
||||
import AttachmentUI
|
||||
import AccountContext
|
||||
import TelegramNotices
|
||||
import PresentationDataUtils
|
||||
|
||||
extension ChatControllerImpl {
|
||||
func openWebApp(buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource) {
|
||||
guard let peerId = self.chatLocation.peerId, let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
self.chatDisplayNode.dismissInput()
|
||||
|
||||
let botName: String
|
||||
let botAddress: String
|
||||
if case let .inline(bot) = source {
|
||||
botName = bot.compactDisplayTitle
|
||||
botAddress = bot.addressName ?? ""
|
||||
} else {
|
||||
botName = EnginePeer(peer).displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder)
|
||||
botAddress = peer.addressName ?? ""
|
||||
}
|
||||
|
||||
if source == .generic {
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if !$0.contains(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.append(.requestInProgress)
|
||||
return updatedContexts.sorted()
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let updateProgress = { [weak self] in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if let index = $0.firstIndex(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.remove(at: index)
|
||||
return updatedContexts
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let openWebView = {
|
||||
if source == .menu {
|
||||
self.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||
return state.updatedForceInputCommandsHidden(true)
|
||||
// return state.updatedShowWebView(true).updatedForceInputCommandsHidden(true)
|
||||
}
|
||||
|
||||
if let currentMenuWebAppController = self.currentMenuWebAppController {
|
||||
if currentMenuWebAppController.isMinimized {
|
||||
(currentMenuWebAppController.navigationController as? NavigationController)?.maximizeViewController(currentMenuWebAppController, animated: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if let navigationController = self.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
||||
for controller in minimizedContainer.controllers {
|
||||
if let controller = controller as? AttachmentController, let mainController = controller.mainController as? WebAppController, mainController.botId == peerId && mainController.source == .menu {
|
||||
navigationController.maximizeViewController(controller, animated: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let context = self.context
|
||||
let params = WebAppParameters(source: .menu, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: self.context, updatedPresentationData: self.updatedPresentationData, params: params, threadId: self.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, getInputContainerNode: { [weak self] in
|
||||
if let strongSelf = self, let layout = strongSelf.validLayout, case .compact = layout.metrics.widthClass {
|
||||
return (strongSelf.chatDisplayNode.getWindowInputAccessoryHeight(), strongSelf.chatDisplayNode.inputPanelContainerNode, {
|
||||
return strongSelf.chatDisplayNode.textInputPanelNode?.makeAttachmentMenuTransition(accessoryPanelNode: nil)
|
||||
})
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, willDismiss: { [weak self] in
|
||||
self?.interfaceInteraction?.updateShowWebView { _ in
|
||||
return false
|
||||
}
|
||||
}, didDismiss: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let isFocused = strongSelf.chatDisplayNode.textInputPanelNode?.isFocused ?? false
|
||||
strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.inputContextPanelContainer)
|
||||
if isFocused {
|
||||
strongSelf.chatDisplayNode.textInputPanelNode?.ensureFocused()
|
||||
}
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||
return state.updatedForceInputCommandsHidden(false)
|
||||
}
|
||||
}
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
self.push(controller)
|
||||
self.currentMenuWebAppController = controller
|
||||
} else if simple {
|
||||
var isInline = false
|
||||
var botId = peerId
|
||||
var botName = botName
|
||||
var botAddress = ""
|
||||
if case let .inline(bot) = source {
|
||||
isInline = true
|
||||
botId = bot.id
|
||||
botName = bot.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder)
|
||||
botAddress = bot.addressName ?? ""
|
||||
}
|
||||
|
||||
self.messageActionCallbackDisposable.set(((self.context.engine.messages.requestSimpleWebView(botId: botId, url: url, source: isInline ? .inline : .generic, themeParams: generateWebAppThemeParams(self.presentationData.theme))
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] url in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: isInline ? .inline : .simple, peerId: peerId, botId: botId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.messageActionCallbackDisposable.set(((self.context.engine.messages.requestWebView(peerId: peerId, botId: peerId, url: !url.isEmpty ? url : nil, payload: nil, themeParams: generateWebAppThemeParams(self.presentationData.theme), fromMenu: buttonText == "Menu", replyToMessageId: nil, threadId: self.chatLocation.threadId)
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
var botPeer = EnginePeer(peer)
|
||||
if case let .inline(bot) = source {
|
||||
botPeer = bot
|
||||
}
|
||||
let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: self.context.sharedContext.accountManager, peerId: botPeer.id)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if value {
|
||||
openWebView()
|
||||
} else {
|
||||
let controller = webAppLaunchConfirmationController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: botPeer, completion: { _ in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
openWebView()
|
||||
}, showMore: nil)
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -574,15 +574,7 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
controller.updateVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
if let currentMenuWebAppController = selfController.currentMenuWebAppController, !selfController.presentationInterfaceState.showWebView {
|
||||
selfController.currentMenuWebAppController = nil
|
||||
if let currentMenuWebAppController = currentMenuWebAppController as? AttachmentController {
|
||||
currentMenuWebAppController.ensureUnfocused = false
|
||||
}
|
||||
currentMenuWebAppController.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
|
||||
selfController.presentationInterfaceStatePromise.set(selfController.presentationInterfaceState)
|
||||
|
||||
if case .tag = selfController.chatDisplayNode.historyNode.tag {
|
||||
|
@ -3691,227 +3691,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
strongSelf.openResolved(result: .join(joinHash), sourceMessageId: nil)
|
||||
}, openWebView: { [weak self] buttonText, url, simple, source in
|
||||
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
|
||||
let botName: String
|
||||
let botAddress: String
|
||||
if case let .inline(bot) = source {
|
||||
botName = bot.compactDisplayTitle
|
||||
botAddress = bot.addressName ?? ""
|
||||
} else {
|
||||
botName = EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)
|
||||
botAddress = peer.addressName ?? ""
|
||||
}
|
||||
|
||||
if source == .generic {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if !$0.contains(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.append(.requestInProgress)
|
||||
return updatedContexts.sorted()
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let updateProgress = { [weak self] in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if let index = $0.firstIndex(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.remove(at: index)
|
||||
return updatedContexts
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let openWebView = {
|
||||
if source == .menu {
|
||||
strongSelf.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||
return state.updatedForceInputCommandsHidden(true)
|
||||
// return state.updatedShowWebView(true).updatedForceInputCommandsHidden(true)
|
||||
}
|
||||
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .menu, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, getInputContainerNode: { [weak self] in
|
||||
if let strongSelf = self, let layout = strongSelf.validLayout, case .compact = layout.metrics.widthClass {
|
||||
return (strongSelf.chatDisplayNode.getWindowInputAccessoryHeight(), strongSelf.chatDisplayNode.inputPanelContainerNode, {
|
||||
return strongSelf.chatDisplayNode.textInputPanelNode?.makeAttachmentMenuTransition(accessoryPanelNode: nil)
|
||||
})
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, willDismiss: { [weak self] in
|
||||
self?.interfaceInteraction?.updateShowWebView { _ in
|
||||
return false
|
||||
}
|
||||
}, didDismiss: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let isFocused = strongSelf.chatDisplayNode.textInputPanelNode?.isFocused ?? false
|
||||
strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.inputContextPanelContainer)
|
||||
if isFocused {
|
||||
strongSelf.chatDisplayNode.textInputPanelNode?.ensureFocused()
|
||||
}
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||
return state.updatedForceInputCommandsHidden(false)
|
||||
}
|
||||
}
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.push(controller)
|
||||
strongSelf.currentMenuWebAppController = controller
|
||||
} else if simple {
|
||||
var isInline = false
|
||||
var botId = peerId
|
||||
var botName = botName
|
||||
var botAddress = ""
|
||||
if case let .inline(bot) = source {
|
||||
isInline = true
|
||||
botId = bot.id
|
||||
botName = bot.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)
|
||||
botAddress = bot.addressName ?? ""
|
||||
}
|
||||
|
||||
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestSimpleWebView(botId: botId, url: url, source: isInline ? .inline : .generic, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme))
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] url in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: isInline ? .inline : .simple, peerId: peerId, botId: botId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestWebView(peerId: peerId, botId: peerId, url: !url.isEmpty ? url : nil, payload: nil, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), fromMenu: buttonText == "Menu", replyToMessageId: nil, threadId: strongSelf.chatLocation.threadId)
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false)
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
var botPeer = EnginePeer(peer)
|
||||
if case let .inline(bot) = source {
|
||||
botPeer = bot
|
||||
}
|
||||
let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: botPeer.id)
|
||||
|> deliverOnMainQueue).startStandalone(next: { value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if value {
|
||||
openWebView()
|
||||
} else {
|
||||
let controller = webAppLaunchConfirmationController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: botPeer, completion: { _ in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
openWebView()
|
||||
}, showMore: nil)
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
}
|
||||
})
|
||||
self.openWebApp(buttonText: buttonText, url: url, simple: simple, source: source)
|
||||
}, activateAdAction: { [weak self] messageId, progress in
|
||||
guard let self, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId), let adAttribute = message.adAttribute else {
|
||||
return
|
||||
|
@ -88,6 +88,15 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
|
||||
private var applicationInFocusDisposable: Disposable?
|
||||
private var storyUploadEventsDisposable: Disposable?
|
||||
|
||||
override public var minimizedContainer: MinimizedContainer? {
|
||||
didSet {
|
||||
self.minimizedContainer?.navigationController = self
|
||||
self.minimizedContainerUpdated(self.minimizedContainer)
|
||||
}
|
||||
}
|
||||
|
||||
public var minimizedContainerUpdated: (MinimizedContainer?) -> Void = { _ in }
|
||||
|
||||
public init(context: AccountContext) {
|
||||
self.context = context
|
||||
|
@ -1771,9 +1771,9 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
fileprivate let moreButtonNode: MoreButtonNode
|
||||
|
||||
private let context: AccountContext
|
||||
private let source: WebAppParameters.Source
|
||||
public let source: WebAppParameters.Source
|
||||
private let peerId: PeerId
|
||||
private let botId: PeerId
|
||||
public let botId: PeerId
|
||||
private let botName: String
|
||||
private let url: String?
|
||||
private let queryId: Int64?
|
||||
@ -2094,13 +2094,17 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
}
|
||||
|
||||
public func shouldDismissImmediately() -> Bool {
|
||||
if self.controllerNode.needDismissConfirmation {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
public override var isMinimized: Bool {
|
||||
didSet {
|
||||
if self.isMinimized != oldValue && self.isMinimized {
|
||||
self.controllerNode.webView?.hideScrollIndicators()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func shouldDismissImmediately() -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
final class WebAppPickerContext: AttachmentMediaPickerContext {
|
||||
@ -2182,7 +2186,6 @@ public func standaloneWebAppController(
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
// controller.getInputContainerNode = getInputContainerNode
|
||||
controller.requestController = { _, present in
|
||||
let webAppController = WebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, replyToMessageId: nil, threadId: threadId)
|
||||
webAppController.openUrl = openUrl
|
||||
|
@ -194,6 +194,22 @@ final class WebAppWebView: WKWebView {
|
||||
}
|
||||
}
|
||||
|
||||
func hideScrollIndicators() {
|
||||
var hiddenViews: [UIView] = []
|
||||
for view in self.scrollView.subviews.reversed() {
|
||||
let minSize = min(view.frame.width, view.frame.height)
|
||||
if minSize < 4.0 {
|
||||
view.isHidden = true
|
||||
hiddenViews.append(view)
|
||||
}
|
||||
}
|
||||
Queue.mainQueue().after(2.0) {
|
||||
for view in hiddenViews {
|
||||
view.isHidden = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendEvent(name: String, data: String?) {
|
||||
let script = "window.TelegramGameProxy.receiveEvent(\"\(name)\", \(data ?? "null"))"
|
||||
self.evaluateJavaScript(script, completionHandler: { _, _ in
|
||||
|
Loading…
x
Reference in New Issue
Block a user