diff --git a/submodules/BrowserUI/Sources/BrowserScreen.swift b/submodules/BrowserUI/Sources/BrowserScreen.swift index a6f0f5ef72..70fd9ebdc3 100644 --- a/submodules/BrowserUI/Sources/BrowserScreen.swift +++ b/submodules/BrowserUI/Sources/BrowserScreen.swift @@ -18,6 +18,7 @@ import MinimizedContainer import InstantPageUI import NavigationStackComponent import LottieComponent +import WebKit private let settingsTag = GenericComponentViewTag() @@ -489,13 +490,13 @@ public class BrowserScreen: ViewController, MinimizableController { case expand } - fileprivate final class Node: ViewControllerTracingNode { + final class Node: ViewControllerTracingNode { private weak var controller: BrowserScreen? private let context: AccountContext private let contentContainerView = UIView() fileprivate let contentNavigationContainer = ComponentView() - fileprivate var content: [BrowserContent] = [] + private(set) var content: [BrowserContent] = [] fileprivate var contentState: BrowserContentState? private var contentStateDisposable = MetaDisposable() @@ -785,13 +786,14 @@ public class BrowserScreen: ViewController, MinimizableController { let browserContent: BrowserContent switch content { case let .webPage(url): - let webContent = BrowserWebContent(context: self.context, presentationData: self.presentationData, url: url) + let webContent = BrowserWebContent(context: self.context, presentationData: self.presentationData, url: url, preferredConfiguration: self.controller?.preferredConfiguration) webContent.cancelInteractiveTransitionGestures = { [weak self] in if let self, let view = self.controller?.view { cancelInteractiveTransitionGestures(view: view) } } browserContent = webContent + self.controller?.preferredConfiguration = nil case let .instantPage(webPage, anchor, sourceLocation): let instantPageContent = BrowserInstantPageContent(context: self.context, presentationData: self.presentationData, webPage: webPage, anchor: anchor, url: webPage.content.url ?? "", sourceLocation: sourceLocation) instantPageContent.openPeer = { [weak self] peer in @@ -846,7 +848,9 @@ public class BrowserScreen: ViewController, MinimizableController { return } if controller.isMinimized { - + if let navigationController = controller.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer { + minimizedContainer.removeController(controller) + } } else { controller.dismiss() } @@ -1373,7 +1377,7 @@ public class BrowserScreen: ViewController, MinimizableController { private let context: AccountContext private let subject: Subject - + private var preferredConfiguration: WKWebViewConfiguration? private var openPreviousOnClose = false private var validLayout: ContainerViewLayout? @@ -1390,7 +1394,7 @@ public class BrowserScreen: ViewController, MinimizableController { // "application/vnd.openxmlformats-officedocument.presentationml.presentation" ] - public init(context: AccountContext, subject: Subject, openPreviousOnClose: Bool = false) { + public init(context: AccountContext, subject: Subject, preferredConfiguration: WKWebViewConfiguration? = nil, openPreviousOnClose: Bool = false) { var subject = subject if case let .webPage(url) = subject, let parsedUrl = URL(string: url) { if parsedUrl.host?.hasSuffix(".ton") == true { @@ -1403,6 +1407,7 @@ public class BrowserScreen: ViewController, MinimizableController { } self.context = context self.subject = subject + self.preferredConfiguration = preferredConfiguration self.openPreviousOnClose = openPreviousOnClose super.init(navigationBarPresentationData: nil) @@ -1420,7 +1425,7 @@ public class BrowserScreen: ViewController, MinimizableController { preconditionFailure() } - private var node: Node { + var node: Node { return self.displayNode as! Node } diff --git a/submodules/BrowserUI/Sources/BrowserWebContent.swift b/submodules/BrowserUI/Sources/BrowserWebContent.swift index 3886d877d0..de137be650 100644 --- a/submodules/BrowserUI/Sources/BrowserWebContent.swift +++ b/submodules/BrowserUI/Sources/BrowserWebContent.swift @@ -203,40 +203,46 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU private var tempFile: TempBoxFile? - init(context: AccountContext, presentationData: PresentationData, url: String) { + init(context: AccountContext, presentationData: PresentationData, url: String, preferredConfiguration: WKWebViewConfiguration? = nil) { self.context = context self.uuid = UUID() self.presentationData = presentationData - let configuration = WKWebViewConfiguration() - - var proxyServerHost = "magic.org" - if let data = context.currentAppConfiguration.with({ $0 }).data, let hostValue = data["ton_proxy_address"] as? String { - proxyServerHost = hostValue - } - configuration.setURLSchemeHandler(TonSchemeHandler(proxyServerHost: proxyServerHost), forURLScheme: "tonsite") - configuration.allowsInlineMediaPlayback = true - if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { - configuration.mediaTypesRequiringUserActionForPlayback = [] - } else { - configuration.mediaPlaybackRequiresUserAction = false - } - - let contentController = WKUserContentController() - let videoScript = WKUserScript(source: videoSource, injectionTime: .atDocumentStart, forMainFrameOnly: false) - contentController.addUserScript(videoScript) - let touchScript = WKUserScript(source: setupTouchObservers, injectionTime: .atDocumentStart, forMainFrameOnly: false) - contentController.addUserScript(touchScript) - configuration.userContentController = contentController - configuration.applicationNameForUserAgent = computedUserAgent() - var handleScriptMessageImpl: ((WKScriptMessage) -> Void)? - let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: false) - contentController.addUserScript(eventProxyScript) - contentController.add(WeakScriptMessageHandler { message in - handleScriptMessageImpl?(message) - }, name: "performAction") + let configuration: WKWebViewConfiguration + if let preferredConfiguration { + configuration = preferredConfiguration + } else { + configuration = WKWebViewConfiguration() + var proxyServerHost = "magic.org" + if let data = context.currentAppConfiguration.with({ $0 }).data, let hostValue = data["ton_proxy_address"] as? String { + proxyServerHost = hostValue + } + configuration.setURLSchemeHandler(TonSchemeHandler(proxyServerHost: proxyServerHost), forURLScheme: "tonsite") + configuration.allowsInlineMediaPlayback = true + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + configuration.mediaTypesRequiringUserActionForPlayback = [] + } else { + configuration.mediaPlaybackRequiresUserAction = false + } + + let contentController = WKUserContentController() + let videoScript = WKUserScript(source: videoSource, injectionTime: .atDocumentStart, forMainFrameOnly: false) + contentController.addUserScript(videoScript) + let touchScript = WKUserScript(source: setupTouchObservers, injectionTime: .atDocumentStart, forMainFrameOnly: false) + contentController.addUserScript(touchScript) + + let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: false) + contentController.addUserScript(eventProxyScript) + contentController.add(WeakScriptMessageHandler { message in + handleScriptMessageImpl?(message) + }, name: "performAction") + + configuration.userContentController = contentController + configuration.applicationNameForUserAgent = computedUserAgent() + } + self.webView = WebView(frame: CGRect(), configuration: configuration) self.webView.allowsLinkPreview = true @@ -786,7 +792,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.minimize() self.openAppUrl(url) } else { - self.open(url: url, new: true) + return self.open(url: url, configuration: configuration, new: true) } } } @@ -927,17 +933,19 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU self.present(alertController, nil) } - private func open(url: String, new: Bool) { + @discardableResult private func open(url: String, configuration: WKWebViewConfiguration? = nil, new: Bool) -> WKWebView? { let subject: BrowserScreen.Subject = .webPage(url: url) if new, let navigationController = self.getNavigationController() { navigationController._keepModalDismissProgress = true self.minimize() - let controller = BrowserScreen(context: self.context, subject: subject, openPreviousOnClose: true) + let controller = BrowserScreen(context: self.context, subject: subject, preferredConfiguration: configuration, openPreviousOnClose: true) navigationController._keepModalDismissProgress = true navigationController.pushViewController(controller) + return (controller.node.content.last as? BrowserWebContent)?.webView } else { self.pushContent(subject) } + return nil } private func share(url: String) { diff --git a/submodules/Display/Source/Navigation/MinimizedContainer.swift b/submodules/Display/Source/Navigation/MinimizedContainer.swift index 58201ab9bd..3642a85063 100644 --- a/submodules/Display/Source/Navigation/MinimizedContainer.swift +++ b/submodules/Display/Source/Navigation/MinimizedContainer.swift @@ -12,6 +12,7 @@ public protocol MinimizedContainer: ASDisplayNode { var statusBarStyleUpdated: (() -> Void)? { get set } func addController(_ viewController: MinimizableController, topEdgeOffset: CGFloat?, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void, transition: ContainedViewLayoutTransition) + func removeController(_ viewController: MinimizableController) func maximizeController(_ viewController: MinimizableController, animated: Bool, completion: @escaping (Bool) -> Void) func collapse() func dismissAll(completion: @escaping () -> Void) diff --git a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedContainer.swift b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedContainer.swift index 7597459eef..800eff84f3 100644 --- a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedContainer.swift +++ b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedContainer.swift @@ -558,6 +558,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll self.requestUpdate(transition: transition) } + public func removeController(_ viewController: MinimizableController) { + guard let item = self.items.first(where: { $0.controller === viewController }) else { + return + } + + self.items.removeAll(where: { $0.id == item.id }) + self.requestUpdate(transition: .animated(duration: 0.25, curve: .easeInOut)) + } + private enum Transition: Equatable { case minimize(itemId: AnyHashable) case maximize(itemId: AnyHashable) diff --git a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift index 0944758d99..43e0faa569 100644 --- a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift +++ b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift @@ -73,7 +73,7 @@ final class MinimizedHeaderNode: ASDisplayNode { guard let self else { return } - let titles = titles.compactMap { $0 } + let titles = titles.compactMap { $0 }.filter { !$0.isEmpty } if titles.count == 1, let title = titles.first { self.title = title } else if let title = titles.last {