Web app improvements

This commit is contained in:
Ilya Laktyushin 2022-03-27 23:13:43 +04:00
parent 8f1811bad4
commit f0e03a2a4c
15 changed files with 279 additions and 76 deletions

View File

@ -13,7 +13,6 @@ func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: P
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
serializedThemeParams = .dataJSON(data: dataString)
}
return postbox.transaction { transaction -> Signal<String, RequestSimpleWebViewError> in
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
return .fail(.generic)
@ -38,8 +37,12 @@ func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: P
|> switchToLatest
}
public enum KeepWebViewError {
case generic
}
public enum RequestWebViewResult {
case webViewResult(queryId: Int64, url: String)
case webViewResult(queryId: Int64, url: String, keepAliveSignal: Signal<Never, KeepWebViewError>)
case requestConfirmation(botIcon: TelegramMediaFile)
}
@ -47,6 +50,29 @@ public enum RequestWebViewError {
case generic
}
private func keepWebView(network: Network, flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, queryId: Int64, replyToMessageId: MessageId?) -> Signal<Never, KeepWebViewError> {
let poll = Signal<Never, KeepWebViewError> { subscriber in
let signal: Signal<Never, KeepWebViewError> = network.request(Api.functions.messages.prolongWebView(flags: flags, peer: peer, bot: bot, queryId: queryId, replyToMsgId: replyToMessageId?.id))
|> mapError { _ -> KeepWebViewError in
return .generic
}
|> ignoreValues
return signal.start(error: { error in
subscriber.putError(error)
}, completed: {
subscriber.putCompletion()
})
}
return (
.complete()
|> suspendAwareDelay(60.0, queue: Queue.concurrentDefaultQueue())
|> then (poll)
)
|> restart
}
func _internal_requestWebView(postbox: Postbox, network: Network, peerId: PeerId, botId: PeerId, url: String?, themeParams: [String: Any]?, replyToMessageId: MessageId?) -> Signal<RequestWebViewResult, RequestWebViewError> {
var serializedThemeParams: Api.DataJSON?
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
@ -54,7 +80,7 @@ func _internal_requestWebView(postbox: Postbox, network: Network, peerId: PeerId
}
return postbox.transaction { transaction -> Signal<RequestWebViewResult, RequestWebViewError> in
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let bot = transaction.getPeer(botId), let inputBot = apiInputUser(bot) else {
return .fail(.generic)
}
@ -70,7 +96,7 @@ func _internal_requestWebView(postbox: Postbox, network: Network, peerId: PeerId
flags |= (1 << 0)
replyToMsgId = replyToMessageId.id
}
return network.request(Api.functions.messages.requestWebView(flags: flags, peer: inputPeer, bot: inputUser, url: url, themeParams: serializedThemeParams, replyToMsgId: replyToMsgId))
return network.request(Api.functions.messages.requestWebView(flags: flags, peer: inputPeer, bot: inputBot, url: url, themeParams: serializedThemeParams, replyToMsgId: replyToMsgId))
|> mapError { _ -> RequestWebViewError in
return .generic
}
@ -96,10 +122,34 @@ func _internal_requestWebView(postbox: Postbox, network: Network, peerId: PeerId
|> castError(RequestWebViewError.self)
|> switchToLatest
case let .webViewResultUrl(queryId, url):
return .single(.webViewResult(queryId: queryId, url: url))
return .single(.webViewResult(queryId: queryId, url: url, keepAliveSignal: keepWebView(network: network, flags: flags, peer: inputPeer, bot: inputBot, queryId: queryId, replyToMessageId: replyToMessageId)))
}
}
}
|> castError(RequestWebViewError.self)
|> switchToLatest
}
public enum SendWebViewDataError {
case generic
}
func _internal_sendWebViewData(postbox: Postbox, network: Network, stateManager: AccountStateManager, botId: PeerId, buttonText: String, data: String) -> Signal<Never, SendWebViewDataError> {
return postbox.transaction { transaction -> Signal<Never, SendWebViewDataError> in
guard let bot = transaction.getPeer(botId), let inputBot = apiInputUser(bot) else {
return .fail(.generic)
}
return network.request(Api.functions.messages.sendWebViewData(bot: inputBot, randomId: Int64.random(in: Int64.min ... Int64.max), buttonText: buttonText, data: data))
|> mapError { _ -> SendWebViewDataError in
return .generic
}
|> map { updates -> Api.Updates in
stateManager.addUpdates(updates)
return updates
}
|> ignoreValues
}
|> castError(SendWebViewDataError.self)
|> switchToLatest
}

View File

@ -330,6 +330,11 @@ public extension TelegramEngine {
return _internal_requestSimpleWebView(postbox: self.account.postbox, network: self.account.network, botId: botId, url: url, themeParams: themeParams)
}
public func sendWebViewData(botId: PeerId, buttonText: String, data: String) -> Signal<Never, SendWebViewDataError> {
return _internal_sendWebViewData(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, botId: botId, buttonText: buttonText, data: data)
}
public func addBotToAttachMenu(peerId: PeerId) -> Signal<Bool, NoError> {
return _internal_addBotToAttachMenu(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
}

View File

@ -263,6 +263,16 @@ public enum PresentationResourceKey: Int32 {
case chatFreeCommentButtonIcon
case chatFreeNavigateButtonIcon
case chatFreeShareButtonIcon
case chatKeyboardActionButtonMessageIcon
case chatKeyboardActionButtonLinkIcon
case chatKeyboardActionButtonShareIcon
case chatKeyboardActionButtonPhoneIcon
case chatKeyboardActionButtonLocationIcon
case chatKeyboardActionButtonPaymentIcon
case chatKeyboardActionButtonProfileIcon
case chatKeyboardActionButtonAddToChatIcon
case chatKeyboardActionButtonWebAppIcon
}
public enum PresentationResourceParameterKey: Hashable {

View File

@ -1198,4 +1198,58 @@ public struct PresentationResourcesChat {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ShareIcon"), color: bubbleVariableColor(variableColor: theme.chat.message.shareButtonForegroundColor, wallpaper: wallpaper))
})
}
public static func chatKeyboardActionButtonMessageIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonMessageIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotMessage"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonLinkIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonLinkIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotLink"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonShareIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonShareIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotShare"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonPhoneIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonPhoneIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotPhone"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonLocationIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonLocationIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotLocation"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonPaymentIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonPaymentIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotPayment"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonProfileIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonProfileIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotProfile"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonAddToChatIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonAddToChatIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotAddToChat"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
public static func chatKeyboardActionButtonWebAppIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatKeyboardActionButtonWebAppIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotWebApp"), color: theme.chat.inputButtonPanel.buttonTextColor)
})
}
}

View File

@ -10,7 +10,12 @@ import AccountContext
import ChatPresentationInterfaceState
private final class ChatButtonKeyboardInputButtonNode: ASButtonNode {
var button: ReplyMarkupButton?
var button: ReplyMarkupButton? {
didSet {
self.updateIcon()
}
}
var iconNode: ASImageNode?
private var theme: PresentationTheme?
@ -20,12 +25,52 @@ private final class ChatButtonKeyboardInputButtonNode: ASButtonNode {
self.updateTheme(theme: theme)
}
private func updateIcon() {
guard let theme = self.theme else {
return
}
var iconImage: UIImage?
if let button = self.button {
switch button.action {
case .openWebView:
iconImage = PresentationResourcesChat.chatKeyboardActionButtonWebAppIconImage(theme)
default:
iconImage = nil
}
}
if iconImage != nil {
if self.iconNode == nil {
let iconNode = ASImageNode()
iconNode.contentMode = .center
self.iconNode = iconNode
self.addSubnode(iconNode)
}
self.iconNode?.image = iconImage
} else if let iconNode = self.iconNode {
iconNode.removeFromSupernode()
self.iconNode = nil
}
self.setNeedsLayout()
}
func updateTheme(theme: PresentationTheme) {
if theme !== self.theme {
self.theme = theme
self.setBackgroundImage(PresentationResourcesChat.chatInputButtonPanelButtonImage(theme), for: [])
self.setBackgroundImage(PresentationResourcesChat.chatInputButtonPanelButtonHighlightedImage(theme), for: [.highlighted])
self.updateIcon()
}
}
override func layout() {
super.layout()
if let iconNode = self.iconNode {
iconNode.frame = CGRect(x: self.frame.width - 16.0, y: 4.0, width: 12.0, height: 12.0)
}
}
}
@ -216,7 +261,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
case let .openUserProfile(peerId):
self.controllerInteraction.openPeer(peerId, .info, nil, nil)
case let .openWebView(url, simple):
self.controllerInteraction.openWebView(url, simple)
self.controllerInteraction.openWebView(markupButton.title, url, simple)
}
if dismissIfOnce {
if let message = self.message {

View File

@ -3301,7 +3301,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
strongSelf.openResolved(result: .join(joinHash), sourceMessageId: nil)
}, openWebView: { [weak self] url, simple in
}, openWebView: { [weak self] buttonText, url, simple in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
return
}
@ -3350,6 +3350,25 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
if simple {
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestSimpleWebView(botId: peerId, url: url, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme))
|> afterDisposed {
updateProgress()
})
|> deliverOnMainQueue).start(next: { [weak self] url in
guard let strongSelf = self else {
return
}
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, buttonText: buttonText, keepAliveSignal: nil)
controller.navigationPresentation = .modal
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, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), replyToMessageId: nil)
|> afterDisposed {
updateProgress()
@ -3359,8 +3378,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
switch result {
case let .webViewResult(queryId, url):
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: queryId)
case let .webViewResult(queryId, url, keepAliveSignal):
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: queryId, buttonText: buttonText, keepAliveSignal: keepAliveSignal)
controller.navigationPresentation = .modal
strongSelf.push(controller)
case .requestConfirmation:
@ -3372,6 +3391,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})]), in: .window(.root))
}
}))
}
}, requestMessageUpdate: { [weak self] id in
if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
@ -10809,7 +10829,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
completion(controller, nil)
strongSelf.controllerNavigationDisposable.set(nil)
case let .app(botId, botName, _):
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peer.id, botId: botId, botName: botName, url: nil, queryId: nil)
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peer.id, botId: botId, botName: botName, url: nil, queryId: nil, buttonText: nil, keepAliveSignal: nil)
completion(controller, nil)
strongSelf.controllerNavigationDisposable.set(nil)
}

View File

@ -131,7 +131,7 @@ public final class ChatControllerInteraction {
let commitEmojiInteraction: (MessageId, String, EmojiInteraction, TelegramMediaFile) -> Void
let openLargeEmojiInfo: (String, String?, TelegramMediaFile) -> Void
let openJoinLink: (String) -> Void
let openWebView: (String, Bool) -> Void
let openWebView: (String, String, Bool) -> Void
let requestMessageUpdate: (MessageId) -> Void
let cancelInteractiveKeyboardGestures: () -> Void
@ -231,7 +231,7 @@ public final class ChatControllerInteraction {
commitEmojiInteraction: @escaping (MessageId, String, EmojiInteraction, TelegramMediaFile) -> Void,
openLargeEmojiInfo: @escaping (String, String?, TelegramMediaFile) -> Void,
openJoinLink: @escaping (String) -> Void,
openWebView: @escaping (String, Bool) -> Void,
openWebView: @escaping (String, String, Bool) -> Void,
requestMessageUpdate: @escaping (MessageId) -> Void,
cancelInteractiveKeyboardGestures: @escaping () -> Void,
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
@ -377,7 +377,7 @@ public final class ChatControllerInteraction {
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -855,7 +855,7 @@ public class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol
case let .openUserProfile(peerId):
item.controllerInteraction.openPeer(peerId, .info, nil, nil)
case let .openWebView(url, simple):
item.controllerInteraction.openWebView(url, simple)
item.controllerInteraction.openWebView(button.title, url, simple)
}
}
}

View File

@ -532,7 +532,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,

View File

@ -159,7 +159,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -151,7 +151,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false), presentationContext: ChatPresentationContext(backgroundNode: nil))

View File

@ -2266,7 +2266,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -1325,7 +1325,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, commitEmojiInteraction: { _, _, _, _ in
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _ in
}, openWebView: { _, _, _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -59,10 +59,12 @@ public final class WebAppController: ViewController, AttachmentContainable {
private let present: (ViewController, Any?) -> Void
private var queryId: Int64?
init(context: AccountContext, controller: WebAppController, presentationData: PresentationData, peerId: PeerId, botId: PeerId, url: String?, queryId: Int64?, present: @escaping (ViewController, Any?) -> Void) {
private var keepAliveDisposable: Disposable?
init(context: AccountContext, controller: WebAppController, present: @escaping (ViewController, Any?) -> Void) {
self.context = context
self.controller = controller
self.presentationData = presentationData
self.presentationData = controller.presentationData
self.present = present
super.init()
@ -127,22 +129,36 @@ public final class WebAppController: ViewController, AttachmentContainable {
webView.scrollView.delegate = self
self.webView = webView
if let url = url, let queryId = queryId {
if let url = controller.url, let queryId = controller.queryId, let keepAliveSignal = controller.keepAliveSignal {
self.queryId = queryId
if let parsedUrl = URL(string: url) {
self.webView?.load(URLRequest(url: parsedUrl))
}
self.keepAliveDisposable = (keepAliveSignal
|> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
})
} else {
let _ = (context.engine.messages.requestWebView(peerId: peerId, botId: botId, url: url, themeParams: generateWebAppThemeParams(presentationData.theme), replyToMessageId: nil)
let _ = (context.engine.messages.requestWebView(peerId: controller.peerId, botId: controller.botId, url: controller.url, themeParams: generateWebAppThemeParams(presentationData.theme), replyToMessageId: nil)
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
switch result {
case let .webViewResult(queryId, url):
case let .webViewResult(queryId, url, keepAliveSignal):
if let parsedUrl = URL(string: url) {
strongSelf.queryId = queryId
strongSelf.webView?.load(URLRequest(url: parsedUrl))
strongSelf.keepAliveDisposable = (keepAliveSignal
|> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
})
}
case .requestConfirmation:
break
@ -151,6 +167,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
}
}
deinit {
self.keepAliveDisposable?.dispose()
}
override func didLoad() {
super.didLoad()
@ -218,7 +238,9 @@ public final class WebAppController: ViewController, AttachmentContainable {
switch eventName {
case "webview_data_send":
self.handleSendResultMessage()
if let eventData = body["eventData"] as? String {
self.handleSendData(data: eventData)
}
case "webview_close":
self.controller?.dismiss()
default:
@ -226,6 +248,26 @@ public final class WebAppController: ViewController, AttachmentContainable {
}
}
private var dismissed = false
private func handleSendData(data string: String) {
guard let controller = self.controller, let buttonText = controller.buttonText, !self.dismissed else {
return
}
controller.dismiss()
if let data = string.data(using: .utf8), let jsonArray = try? JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String: Any], let data = jsonArray["data"] {
var resultString: String?
if let string = data as? String {
resultString = string
} else if let data1 = try? JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions.prettyPrinted), let convertedString = String(data: data1, encoding: String.Encoding.utf8) {
resultString = convertedString
}
if let resultString = resultString {
let _ = (self.context.engine.messages.sendWebViewData(botId: controller.botId, buttonText: buttonText, data: resultString)).start()
}
}
}
func sendEvent(name: String, data: String) {
let script = "window.TelegramGameProxy.receiveEvent(\"\(name)\", \(data))"
self.webView?.evaluateJavaScript(script, completionHandler: { _, _ in
@ -257,33 +299,6 @@ public final class WebAppController: ViewController, AttachmentContainable {
themeParamsString.append("}}")
self.sendEvent(name: "theme_changed", data: themeParamsString)
}
private func handleSendResultMessage() {
guard let controller = self.controller else {
return
}
controller.dismiss()
// guard let controller = self.controller, let queryId = self.queryId, self.currentAlertController == nil else {
// return
// }
//
// let _ = (self.context.engine.messages.getWebViewResult(peerId: controller.peerId, botId: controller.botId, queryId: queryId)
// |> deliverOnMainQueue).start(next: { [weak self] result in
// guard let strongSelf = self, let controller = strongSelf.controller else {
// return
// }
//
// let alertController = webAppPreviewResultController(context: strongSelf.context, to: controller.peerId, botId: controller.botId, result: result, completion: { [weak self] in
// guard let strongSelf = self, let controller = strongSelf.controller else {
// return
// }
// let _ = strongSelf.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: controller.peerId, botId: controller.botId, result: result)
// controller.dismiss()
// })
// controller.present(alertController, in: .window(.root))
// strongSelf.currentAlertController = alertController
// })
}
}
private var controllerNode: Node {
@ -298,17 +313,21 @@ public final class WebAppController: ViewController, AttachmentContainable {
private let botId: PeerId
private let url: String?
private let queryId: Int64?
private let buttonText: String?
private let keepAliveSignal: Signal<Never, KeepWebViewError>?
private var presentationData: PresentationData
fileprivate let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
private var presentationDataDisposable: Disposable?
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: PeerId, botId: PeerId, botName: String, url: String?, queryId: Int64?) {
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: PeerId, botId: PeerId, botName: String, url: String?, queryId: Int64?, buttonText: String?, keepAliveSignal: Signal<Never, KeepWebViewError>?) {
self.context = context
self.peerId = peerId
self.botId = botId
self.url = url
self.queryId = queryId
self.buttonText = buttonText
self.keepAliveSignal = keepAliveSignal
self.updatedPresentationData = updatedPresentationData
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
@ -432,7 +451,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
}
override public func loadDisplayNode() {
self.displayNode = Node(context: self.context, controller: self, presentationData: self.presentationData, peerId: self.peerId, botId: self.botId, url: self.url, queryId: self.queryId, present: { [weak self] c, a in
self.displayNode = Node(context: self.context, controller: self, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a)
})