mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Web app improvements
This commit is contained in:
parent
4236d30e04
commit
882d362180
@ -9854,3 +9854,14 @@ Sorry for the inconvenience.";
|
||||
"Location.TypeCity" = "City";
|
||||
"Location.TypeStreet" = "Street";
|
||||
"Location.TypeLocation" = "Location";
|
||||
|
||||
"WebApp.AllowWriteTitle" = "Allow Sending Messages?";
|
||||
"WebApp.AllowWriteConfirmation" = "This will allow the bot **%@** to message you on Telegram.";
|
||||
|
||||
"AuthSessions.MessageApp" = "You allowed this bot to message you when you opened %@.";
|
||||
"Notification.BotWriteAllowedMenu" = "You allowed this bot to message you when you added it to your attachment menu.";
|
||||
"Notification.BotWriteAllowedRequest" = "You allowed this bot to message you in the app.";
|
||||
|
||||
"WebApp.SharePhoneTitle" = "Share Phone Number?";
|
||||
"WebApp.SharePhoneConfirmation" = "**%@** will know your phone number. This can be useful for integration with other services.";
|
||||
"WebApp.SharePhoneConfirmationUnblock" = "**%@** will know your phone number. This can be useful for integration with other services.\n\nThis will also unblock the bot.";
|
||||
|
@ -1806,6 +1806,21 @@ public extension Api.functions.auth {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func allowSendMessage(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-248323089)
|
||||
bot.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "bots.allowSendMessage", parameters: [("bot", String(describing: bot))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func answerWebhookJSONQuery(queryId: Int64, data: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
@ -1822,6 +1837,21 @@ public extension Api.functions.bots {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func canSendMessage(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(324662502)
|
||||
bot.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "bots.canSendMessage", parameters: [("bot", String(describing: bot))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func getBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.BotCommand]>) {
|
||||
let buffer = Buffer()
|
||||
@ -1870,6 +1900,23 @@ public extension Api.functions.bots {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func invokeWebViewCustomMethod(bot: Api.InputUser, customMethod: String, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.DataJSON>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(142591463)
|
||||
bot.serialize(buffer, true)
|
||||
serializeString(customMethod, buffer: buffer, boxed: false)
|
||||
params.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "bots.invokeWebViewCustomMethod", parameters: [("bot", String(describing: bot)), ("customMethod", String(describing: customMethod)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.DataJSON? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.DataJSON?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.bots {
|
||||
static func reorderUsernames(bot: Api.InputUser, order: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -50,8 +50,23 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
||||
return TelegramMediaAction(action: .historyScreenshot)
|
||||
case let .messageActionCustomAction(message):
|
||||
return TelegramMediaAction(action: .customText(text: message, entities: []))
|
||||
case let .messageActionBotAllowed(_, domain, _):
|
||||
return TelegramMediaAction(action: .botDomainAccessGranted(domain: domain ?? ""))
|
||||
case let .messageActionBotAllowed(flags, domain, app):
|
||||
if let domain = domain {
|
||||
return TelegramMediaAction(action: .botDomainAccessGranted(domain: domain))
|
||||
} else {
|
||||
var appName: String?
|
||||
if case let .botApp(_, _, _, _, appNameValue, _, _, _, _) = app {
|
||||
appName = appNameValue
|
||||
}
|
||||
var type: BotSendMessageAccessGrantedType?
|
||||
if (flags & (1 << 1)) != 0 {
|
||||
type = .attachMenu
|
||||
}
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
type = .request
|
||||
}
|
||||
return TelegramMediaAction(action: .botAppAccessGranted(appName: appName, type: type))
|
||||
}
|
||||
case .messageActionSecureValuesSentMe:
|
||||
return nil
|
||||
case let .messageActionSecureValuesSent(types):
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 161
|
||||
return 162
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
@ -23,6 +23,11 @@ public enum SentSecureValueType: Int32 {
|
||||
case temporaryRegistration = 12
|
||||
}
|
||||
|
||||
public enum BotSendMessageAccessGrantedType: Int32 {
|
||||
case attachMenu = 0
|
||||
case request = 1
|
||||
}
|
||||
|
||||
public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
public enum ForumTopicEditComponent: PostboxCoding, Equatable {
|
||||
case title(String)
|
||||
@ -86,6 +91,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
case paymentSent(currency: String, totalAmount: Int64, invoiceSlug: String?, isRecurringInit: Bool, isRecurringUsed: Bool)
|
||||
case customText(text: String, entities: [MessageTextEntity])
|
||||
case botDomainAccessGranted(domain: String)
|
||||
case botAppAccessGranted(appName: String?, type: BotSendMessageAccessGrantedType?)
|
||||
case botSentSecureValues(types: [SentSecureValueType])
|
||||
case peerJoined
|
||||
case phoneNumberRequest
|
||||
@ -195,6 +201,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
} else {
|
||||
self = .unknown
|
||||
}
|
||||
case 35:
|
||||
self = .botAppAccessGranted(appName: decoder.decodeOptionalStringForKey("app"), type: decoder.decodeOptionalInt32ForKey("atp").flatMap { BotSendMessageAccessGrantedType(rawValue: $0) })
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
@ -362,6 +370,18 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
case let .setSameChatWallpaper(wallpaper):
|
||||
encoder.encodeInt32(34, forKey: "_rawValue")
|
||||
encoder.encode(TelegramWallpaperNativeCodable(wallpaper), forKey: "wallpaper")
|
||||
case let .botAppAccessGranted(appName, type):
|
||||
encoder.encodeInt32(35, forKey: "_rawValue")
|
||||
if let appName = appName {
|
||||
encoder.encodeString(appName, forKey: "app")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "app")
|
||||
}
|
||||
if let type = type {
|
||||
encoder.encodeInt32(type.rawValue, forKey: "atp")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "atp")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,3 +236,72 @@ func _internal_requestAppWebView(postbox: Postbox, network: Network, stateManage
|
||||
|> castError(RequestAppWebViewError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func _internal_canBotSendMessages(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Bool, NoError> in
|
||||
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
|
||||
return .single(false)
|
||||
}
|
||||
|
||||
return network.request(Api.functions.bots.canSendMessage(bot: inputUser))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|> map { result -> Bool in
|
||||
if case .boolTrue = result {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func _internal_allowBotSendMessages(postbox: Postbox, network: Network, stateManager: AccountStateManager, botId: PeerId) -> Signal<Never, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Never, NoError> in
|
||||
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
|
||||
return .never()
|
||||
}
|
||||
|
||||
return network.request(Api.functions.bots.allowSendMessage(bot: inputUser))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { updates -> Api.Updates? in
|
||||
if let updates = updates {
|
||||
stateManager.addUpdates(updates)
|
||||
}
|
||||
return updates
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
public enum InvokeBotCustomMethodError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_invokeBotCustomMethod(postbox: Postbox, network: Network, botId: PeerId, method: String, params: String) -> Signal<String, InvokeBotCustomMethodError> {
|
||||
let params = Api.DataJSON.dataJSON(data: params)
|
||||
return postbox.transaction { transaction -> Signal<String, InvokeBotCustomMethodError> in
|
||||
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
return network.request(Api.functions.bots.invokeWebViewCustomMethod(bot: inputUser, customMethod: method, params: params))
|
||||
|> mapError { _ -> InvokeBotCustomMethodError in
|
||||
return .generic
|
||||
}
|
||||
|> map { result -> String in
|
||||
if case let .dataJSON(data) = result {
|
||||
return data
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|> castError(InvokeBotCustomMethodError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
@ -507,6 +507,18 @@ public extension TelegramEngine {
|
||||
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 canBotSendMessages(botId: PeerId) -> Signal<Bool, NoError> {
|
||||
return _internal_canBotSendMessages(postbox: self.account.postbox, network: self.account.network, botId: botId)
|
||||
}
|
||||
|
||||
public func allowBotSendMessages(botId: PeerId) -> Signal<Never, NoError> {
|
||||
return _internal_allowBotSendMessages(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, sbotId: botId)
|
||||
}
|
||||
|
||||
public func invokeBotCustomMethod(botId: PeerId, method: String, params: String) -> Signal<String, InvokeBotCustomMethodError> {
|
||||
return _internal_invokeBotCustomMethod(postbox: self.account.postbox, network: self.account.network, botId: botId, method: method, params: params)
|
||||
}
|
||||
|
||||
public func addBotToAttachMenu(botId: PeerId, allowWrite: Bool) -> Signal<Bool, AddBotToAttachMenuError> {
|
||||
return _internal_addBotToAttachMenu(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId, allowWrite: allowWrite)
|
||||
|
@ -629,6 +629,16 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
attributedString = stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage())
|
||||
case let .botDomainAccessGranted(domain):
|
||||
attributedString = NSAttributedString(string: strings.AuthSessions_Message(domain).string, font: titleFont, textColor: primaryTextColor)
|
||||
case let .botAppAccessGranted(appName, type):
|
||||
let text: String
|
||||
if type == .attachMenu {
|
||||
text = strings.Notification_BotWriteAllowedMenu
|
||||
} else if type == .request {
|
||||
text = strings.Notification_BotWriteAllowedRequest
|
||||
} else {
|
||||
text = strings.AuthSessions_MessageApp(appName ?? "").string
|
||||
}
|
||||
attributedString = NSAttributedString(string: text, font: titleFont, textColor: primaryTextColor)
|
||||
case let .botSentSecureValues(types):
|
||||
var typesString = ""
|
||||
var hasIdentity = false
|
||||
|
@ -13188,7 +13188,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
let buttons: Signal<([AttachmentButtonType], [AttachmentButtonType], AttachmentButtonType?), NoError>
|
||||
if !isScheduledMessages {
|
||||
if !isScheduledMessages && !peer.isDeleted {
|
||||
buttons = self.context.engine.messages.attachMenuBots()
|
||||
|> map { attachMenuBots in
|
||||
var buttons = availableButtons
|
||||
|
@ -917,6 +917,20 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
self.sendClipboardTextEvent(requestId: requestId, fillData: fillData)
|
||||
}
|
||||
case "web_app_request_write_access":
|
||||
self.requestWriteAccess()
|
||||
case "web_app_request_phone":
|
||||
self.shareAccountContact()
|
||||
case "web_app_invoke_custom_method":
|
||||
if let json, let requestId = json["req_id"] as? String, let method = json["method"] as? String, let params = json["params"] {
|
||||
var paramsString: String?
|
||||
if let string = params as? String {
|
||||
paramsString = string
|
||||
} else if let data1 = try? JSONSerialization.data(withJSONObject: params, options: []), let convertedString = String(data: data1, encoding: String.Encoding.utf8) {
|
||||
paramsString = convertedString
|
||||
}
|
||||
self.invokeCustomMethod(requestId: requestId, method: method, params: paramsString ?? "{}")
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -959,7 +973,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
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) {
|
||||
} else if let data1 = try? JSONSerialization.data(withJSONObject: data, options: []), let convertedString = String(data: data1, encoding: String.Encoding.utf8) {
|
||||
resultString = convertedString
|
||||
}
|
||||
if let resultString = resultString {
|
||||
@ -1066,6 +1080,153 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
self.webView?.sendEvent(name: "clipboard_text_received", data: paramsString)
|
||||
}
|
||||
|
||||
fileprivate func requestWriteAccess() {
|
||||
guard let controller = self.controller, !self.dismissed else {
|
||||
return
|
||||
}
|
||||
|
||||
let sendEvent: (Bool) -> Void = { success in
|
||||
var paramsString: String
|
||||
if success {
|
||||
paramsString = "{status: \"allowed\"}"
|
||||
} else {
|
||||
paramsString = "{status: \"cancelled\"}"
|
||||
}
|
||||
self.webView?.sendEvent(name: "write_access_requested", data: paramsString)
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.messages.canBotSendMessages(botId: controller.botId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
guard let self, let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
if result {
|
||||
sendEvent(true)
|
||||
} else {
|
||||
let alertController = textAlertController(context: self.context, updatedPresentationData: controller.updatedPresentationData, title: self.presentationData.strings.WebApp_AllowWriteTitle, text: self.presentationData.strings.WebApp_AllowWriteConfirmation(controller.botName).string, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {
|
||||
sendEvent(false)
|
||||
}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.messages.allowBotSendMessages(botId: controller.botId)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
sendEvent(result)
|
||||
})
|
||||
})], parseMarkdown: true)
|
||||
alertController.dismissed = { byOutsideTap in
|
||||
if byOutsideTap {
|
||||
sendEvent(false)
|
||||
}
|
||||
}
|
||||
controller.present(alertController, in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func shareAccountContact() {
|
||||
guard let controller = self.controller, let botId = self.controller?.botId, let botName = self.controller?.botName else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let sendEvent: (Bool) -> Void = { success in
|
||||
var paramsString: String
|
||||
if success {
|
||||
paramsString = "{status: \"sent\"}"
|
||||
} else {
|
||||
paramsString = "{status: \"cancelled\"}"
|
||||
}
|
||||
self.webView?.sendEvent(name: "phone_requested", data: paramsString)
|
||||
}
|
||||
|
||||
let context = self.context
|
||||
let _ = (self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.IsBlocked(id: botId)
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak controller] accountPeer, isBlocked in
|
||||
guard let self, let controller, let accountPeer else {
|
||||
return
|
||||
}
|
||||
var requiresUnblock = false
|
||||
if case let .known(value) = isBlocked, value {
|
||||
requiresUnblock = true
|
||||
}
|
||||
|
||||
let text: String
|
||||
if requiresUnblock {
|
||||
text = self.presentationData.strings.WebApp_SharePhoneConfirmationUnblock(botName).string
|
||||
} else {
|
||||
text = self.presentationData.strings.WebApp_SharePhoneConfirmation(botName).string
|
||||
}
|
||||
|
||||
let alertController = textAlertController(context: self.context, updatedPresentationData: controller.updatedPresentationData, title: self.presentationData.strings.WebApp_SharePhoneTitle, text: text, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {
|
||||
sendEvent(false)
|
||||
}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { [weak self] in
|
||||
guard let self, case let .user(user) = accountPeer, let phone = user.phone, !phone.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
let sendMessageSignal = enqueueMessages(account: self.context.account, peerId: botId, messages: [
|
||||
.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: user.firstName ?? "", lastName: user.lastName ?? "", phoneNumber: phone, peerId: user.id, vCardData: nil)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
|
||||
])
|
||||
|> mapToSignal { messageIds in
|
||||
if let maybeMessageId = messageIds.first, let messageId = maybeMessageId {
|
||||
return context.account.pendingMessageManager.pendingMessageStatus(messageId)
|
||||
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
||||
if status != nil {
|
||||
return .never()
|
||||
} else {
|
||||
return .single(true)
|
||||
}
|
||||
}
|
||||
|> take(1)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
let sendMessage = {
|
||||
let _ = (sendMessageSignal
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
sendEvent(true)
|
||||
})
|
||||
}
|
||||
|
||||
if requiresUnblock {
|
||||
let _ = (context.engine.privacy.requestUpdatePeerIsBlocked(peerId: botId, isBlocked: false)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
sendMessage()
|
||||
})
|
||||
} else {
|
||||
sendMessage()
|
||||
}
|
||||
})], parseMarkdown: true)
|
||||
alertController.dismissed = { byOutsideTap in
|
||||
if byOutsideTap {
|
||||
sendEvent(false)
|
||||
}
|
||||
}
|
||||
controller.present(alertController, in: .window(.root))
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func invokeCustomMethod(requestId: String, method: String, params: String) {
|
||||
guard let controller = self.controller, !self.dismissed else {
|
||||
return
|
||||
}
|
||||
let _ = (self.context.engine.messages.invokeBotCustomMethod(botId: controller.botId, method: method, params: params)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let paramsString = "{req_id: \"\(requestId)\", result: \(result)}"
|
||||
self.webView?.sendEvent(name: "custom_method_invoked", data: paramsString)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate var controllerNode: Node {
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"app": "10.0.1",
|
||||
"app": "10.0.2",
|
||||
"bazel": "6.1.1",
|
||||
"xcode": "14.2"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user