From aec940a39ecbf5b0c5615b0607fb0132dca5d223 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 10 Apr 2022 13:29:22 +0400 Subject: [PATCH] Web app improvements --- .../TelegramUI/Sources/ChatController.swift | 5 +-- .../TelegramUI/Sources/OpenResolvedUrl.swift | 5 +-- .../Sources/WebAppAlertContentNode.swift | 41 +++++++++++-------- .../WebUI/Sources/WebAppController.swift | 17 ++++---- submodules/WebUI/Sources/WebAppWebView.swift | 13 ++++-- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f2004f17af..217ae1eb25 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10694,10 +10694,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = (context.engine.messages.getAttachMenuBot(botId: botId) |> deliverOnMainQueue).start(next: { bot in let peer = EnginePeer(bot.peer) - guard let icon = bot.icons[.default] else { - return - } - let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: { + let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), icons: bot.icons, completion: { let _ = (context.engine.messages.addBotToAttachMenu(botId: botId) |> deliverOnMainQueue).start(error: { _ in diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 6233a05c5b..54a506cb7d 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -558,10 +558,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur let _ = (context.engine.messages.getAttachMenuBot(botId: peerId) |> deliverOnMainQueue).start(next: { bot in let peer = EnginePeer(bot.peer) - guard let icon = bot.icons[.default] else { - return - } - let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: { + let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), icons: bot.icons, completion: { let _ = (context.engine.messages.addBotToAttachMenu(botId: peerId) |> deliverOnMainQueue).start(error: { _ in presentError(presentationData.strings.WebApp_AddToAttachmentUnavailableError) diff --git a/submodules/WebUI/Sources/WebAppAlertContentNode.swift b/submodules/WebUI/Sources/WebAppAlertContentNode.swift index 7f9cddf3c2..652904f5ae 100644 --- a/submodules/WebUI/Sources/WebAppAlertContentNode.swift +++ b/submodules/WebUI/Sources/WebAppAlertContentNode.swift @@ -14,7 +14,7 @@ import PhotoResources private final class WebAppAlertContentNode: AlertContentNode { private let strings: PresentationStrings private let peerName: String - private let peerIcon: TelegramMediaFile + private let peerIcon: TelegramMediaFile? private let textNode: ASTextNode private let appIconNode: ASImageNode @@ -32,10 +32,17 @@ private final class WebAppAlertContentNode: AlertContentNode { return self.isUserInteractionEnabled } - init(account: Account, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, peerName: String, peerIcon: TelegramMediaFile, actions: [TextAlertAction]) { + init(account: Account, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, peerName: String, icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile], actions: [TextAlertAction]) { self.strings = strings self.peerName = peerName - self.peerIcon = peerIcon + + if let icon = icons[.iOSStatic] { + self.peerIcon = icon + } else if let icon = icons[.default] { + self.peerIcon = icon + } else { + self.peerIcon = nil + } self.textNode = ASTextNode() self.textNode.maximumNumberOfLines = 0 @@ -83,17 +90,19 @@ private final class WebAppAlertContentNode: AlertContentNode { self.updateTheme(theme) - let _ = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: peerIcon)).start() - self.iconDisposable = (svgIconImageFile(account: account, fileReference: .standalone(media: peerIcon)) - |> deliverOnMainQueue).start(next: { [weak self] transform in - if let strongSelf = self { - let availableSize = CGSize(width: 48.0, height: 48.0) - let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: availableSize, boundingSize: availableSize, intrinsicInsets: UIEdgeInsets()) - let drawingContext = transform(arguments) - let image = drawingContext?.generateImage()?.withRenderingMode(.alwaysTemplate) - strongSelf.appIconNode.image = generateTintedImage(image: image, color: theme.accentColor, backgroundColor: nil) - } - }) + if let peerIcon = self.peerIcon { + let _ = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: peerIcon)).start() + self.iconDisposable = (svgIconImageFile(account: account, fileReference: .standalone(media: peerIcon)) + |> deliverOnMainQueue).start(next: { [weak self] transform in + if let strongSelf = self { + let availableSize = CGSize(width: 48.0, height: 48.0) + let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: availableSize, boundingSize: availableSize, intrinsicInsets: UIEdgeInsets()) + let drawingContext = transform(arguments) + let image = drawingContext?.generateImage()?.withRenderingMode(.alwaysTemplate) + strongSelf.appIconNode.image = generateTintedImage(image: image, color: theme.accentColor, backgroundColor: nil) + } + }) + } } deinit { @@ -230,7 +239,7 @@ private final class WebAppAlertContentNode: AlertContentNode { } } -public func addWebAppToAttachmentController(context: AccountContext, peerName: String, peerIcon: TelegramMediaFile, completion: @escaping () -> Void) -> AlertController { +public func addWebAppToAttachmentController(context: AccountContext, peerName: String, icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile], completion: @escaping () -> Void) -> AlertController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let theme = presentationData.theme let strings = presentationData.strings @@ -245,7 +254,7 @@ public func addWebAppToAttachmentController(context: AccountContext, peerName: S completion() })] - contentNode = WebAppAlertContentNode(account: context.account, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, peerName: peerName, peerIcon: peerIcon, actions: actions) + contentNode = WebAppAlertContentNode(account: context.account, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, peerName: peerName, icons: icons, actions: actions) let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode!) dismissImpl = { [weak controller] animated in diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 19bbc99b22..36fd7c33be 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -119,6 +119,12 @@ public final class WebAppController: ViewController, AttachmentContainable { webView.handleScriptMessage = { [weak self] message in self?.handleScriptMessage(message) } + webView.onFirstTouch = { [weak self] in + if let strongSelf = self, let delayedScriptMessage = strongSelf.delayedScriptMessage { + strongSelf.delayedScriptMessage = nil + strongSelf.handleScriptMessage(delayedScriptMessage) + } + } self.webView = webView let placeholderNode = ShimmerEffectNode() @@ -315,11 +321,7 @@ public final class WebAppController: ViewController, AttachmentContainable { placeholderNode?.removeFromSupernode() }) } - - Queue.mainQueue().after(1.0, { - webView.handleTap() - }) - + if let (layout, navigationBarHeight) = self.validLayout { self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) } @@ -406,7 +408,8 @@ public final class WebAppController: ViewController, AttachmentContainable { self.loadingProgressPromise.set(.single(CGFloat(webView.estimatedProgress))) } } - + + private var delayedScriptMessage: WKScriptMessage? private func handleScriptMessage(_ message: WKScriptMessage) { guard let body = message.body as? [String: Any] else { return @@ -425,7 +428,7 @@ public final class WebAppController: ViewController, AttachmentContainable { } case "web_app_setup_main_button": if let webView = self.webView, !webView.didTouchOnce { - + self.delayedScriptMessage = message } else if let eventData = (body["eventData"] as? String)?.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: eventData, options: []) as? [String: Any] { if var isVisible = json["is_visible"] as? Bool { let text = json["text"] as? String diff --git a/submodules/WebUI/Sources/WebAppWebView.swift b/submodules/WebUI/Sources/WebAppWebView.swift index 74fb72e74f..4b699b6c3d 100644 --- a/submodules/WebUI/Sources/WebAppWebView.swift +++ b/submodules/WebUI/Sources/WebAppWebView.swift @@ -131,9 +131,7 @@ final class WebAppWebView: WKWebView { } private(set) var didTouchOnce = false - @objc func handleTap() { - self.didTouchOnce = true - } + var onFirstTouch: () -> Void = {} func scrollToActiveElement(layout: ContainerViewLayout, completion: @escaping (CGPoint) -> Void, transition: ContainedViewLayoutTransition) { self.evaluateJavaScript(findActiveElementY, completionHandler: { result, _ in @@ -159,6 +157,15 @@ final class WebAppWebView: WKWebView { }) } + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let result = super.hitTest(point, with: event) + if result != nil && !self.didTouchOnce { + self.didTouchOnce = true + self.onFirstTouch() + } + return result + } + override var inputAccessoryView: UIView? { return nil }