Web app improvements

This commit is contained in:
Ilya Laktyushin 2022-04-01 16:32:16 +04:00
parent c24af412cc
commit 43405ce029
7 changed files with 98 additions and 62 deletions

View File

@ -7417,6 +7417,9 @@ Sorry for the inconvenience.";
"WebApp.AddToAttachmentAlreadyAddedError" = "This bot is already added in the attachment menu.";
"WebApp.OpenWebViewAlertTitle" = "Open Web App";
"WebApp.OpenWebViewAlertText" = "**%@** would like to open its web app to proceed.\n\nIt will be able to access your **IP address** and basic device info.";
"WebApp.MessagePreview" = "Message Preview";
"WebApp.Send" = "Send";

View File

@ -13,8 +13,8 @@ public final class AlertControllerContext {
}
}
public func textAlertController(alertContext: AlertControllerContext, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {
let controller = standardTextAlertController(theme: alertContext.theme, title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissOnOutsideTap: dismissOnOutsideTap)
public func textAlertController(alertContext: AlertControllerContext, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, parseMarkdown: Bool = false, dismissOnOutsideTap: Bool = true) -> AlertController {
let controller = standardTextAlertController(theme: alertContext.theme, title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, parseMarkdown: parseMarkdown, dismissOnOutsideTap: dismissOnOutsideTap)
let presentationDataDisposable = alertContext.themeSignal.start(next: { [weak controller] theme in
controller?.theme = theme
})

View File

@ -5,11 +5,11 @@ import AccountContext
import SwiftSignalKit
import TelegramPresentationData
public func textAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {
return textAlertController(sharedContext: context.sharedContext, updatedPresentationData: updatedPresentationData, forceTheme: forceTheme, title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissOnOutsideTap: dismissOnOutsideTap)
public func textAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, parseMarkdown: Bool = false, dismissOnOutsideTap: Bool = true) -> AlertController {
return textAlertController(sharedContext: context.sharedContext, updatedPresentationData: updatedPresentationData, forceTheme: forceTheme, title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, parseMarkdown: parseMarkdown, dismissOnOutsideTap: dismissOnOutsideTap)
}
public func textAlertController(sharedContext: SharedAccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {
public func textAlertController(sharedContext: SharedAccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, parseMarkdown: Bool = false, dismissOnOutsideTap: Bool = true) -> AlertController {
var presentationData = updatedPresentationData?.initial ?? sharedContext.currentPresentationData.with { $0 }
if let forceTheme = forceTheme {
presentationData = presentationData.withUpdated(theme: forceTheme)
@ -21,7 +21,7 @@ public func textAlertController(sharedContext: SharedAccountContext, updatedPres
presentationData = presentationData.withUpdated(theme: forceTheme)
}
return AlertControllerTheme(presentationData: presentationData)
}), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissOnOutsideTap: dismissOnOutsideTap)
}), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, parseMarkdown: parseMarkdown, dismissOnOutsideTap: dismissOnOutsideTap)
}
public func textAlertController(sharedContext: SharedAccountContext, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {

View File

@ -35,7 +35,7 @@ public func flatMap<T, E, R>(_ f: @escaping (T) -> R) -> (Signal<T?, E>) -> Sign
return Signal<R?, E> { subscriber in
return signal.start(next: { next in
if let next = next {
subscriber.putNext(f(next))
subscriber.putNext(f(next))
} else {
subscriber.putNext(nil)
}

View File

@ -188,20 +188,20 @@ private func setCachedAttachMenuBots(transaction: Transaction, attachMenuBots: A
}
}
func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
let poll = Signal<Never, NoError> { subscriber in
let signal: Signal<Never, NoError> = cachedAttachMenuBots(postbox: postbox)
func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = Signal<Void, NoError> { subscriber in
let signal: Signal<Void, NoError> = cachedAttachMenuBots(postbox: postbox)
|> mapToSignal { current in
return (network.request(Api.functions.messages.getAttachMenuBots(hash: current?.hash ?? 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.AttachMenuBots?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<Never, NoError> in
|> mapToSignal { result -> Signal<Void, NoError> in
guard let result = result else {
return .complete()
}
return postbox.transaction { transaction in
return postbox.transaction { transaction -> Void in
switch result {
case let .attachMenuBots(hash, bots, users):
var peers: [Peer] = []
@ -237,11 +237,14 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Sig
case .attachMenuBotsNotModified:
break
}
} |> ignoreValues
return Void()
}
})
}
return signal.start(completed: {
return signal.start(next: { value in
subscriber.putNext(value)
}, completed: {
subscriber.putCompletion()
})
}
@ -273,9 +276,16 @@ func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: Pee
|> `catch` { error -> Signal<Bool, NoError> in
return .single(false)
}
|> afterCompleted {
let _ = (managedSynchronizeAttachMenuBots(postbox: postbox, network: network)
|> take(1)).start()
|> mapToSignal { value -> Signal<Bool, NoError> in
if value {
return managedSynchronizeAttachMenuBots(postbox: postbox, network: network)
|> take(1)
|> map { _ -> Bool in
return true
}
} else {
return .single(value)
}
}
}
|> switchToLatest

View File

@ -3302,7 +3302,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
strongSelf.openResolved(result: .join(joinHash), sourceMessageId: nil)
}, openWebView: { [weak self] buttonText, url, simple in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramUser else {
return
}
@ -3350,52 +3350,76 @@ 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 = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, buttonText: buttonText, keepAliveSignal: nil)
strongSelf.present(controller, in: .window(.root))
// controller.getNavigationController = { [weak self] in
// return self?.effectiveNavigationController
// }
// 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))
}
}))
let openWebView = {
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 = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, buttonText: buttonText, keepAliveSignal: nil)
strongSelf.present(controller, in: .window(.root))
// controller.getNavigationController = { [weak self] in
// return self?.effectiveNavigationController
// }
// 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, payload: nil, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), replyToMessageId: nil)
|> afterDisposed {
updateProgress()
})
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal)
strongSelf.present(controller, in: .window(.root))
// let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, replyToMessageId: nil, iconFile: nil)
// controller.getNavigationController = { [weak self] in
// return self?.effectiveNavigationController
// }
// 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))
}
}))
}
}
if peer.flags.contains(.isVerified) {
openWebView()
} else {
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestWebView(peerId: peerId, botId: peerId, url: url, payload: nil, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), replyToMessageId: nil)
|> afterDisposed {
updateProgress()
})
|> deliverOnMainQueue).start(next: { [weak self] result in
let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id)
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal)
strongSelf.present(controller, in: .window(.root))
// let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, replyToMessageId: nil, iconFile: nil)
// controller.getNavigationController = { [weak self] in
// return self?.effectiveNavigationController
// }
// 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))
if value {
openWebView()
} else {
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertTitle, text: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertText(botName).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
if let strongSelf = self {
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start()
openWebView()
}
})], parseMarkdown: true), in: .window(.root), with: nil)
}
}))
})
}
}, requestMessageUpdate: { [weak self] id in
if let strongSelf = self {

View File

@ -567,9 +567,8 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
return
}
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(botId: peerId).start()
Queue.mainQueue().after(1.0, {
let _ = (context.engine.messages.addBotToAttachMenu(botId: peerId)
|> deliverOnMainQueue).start(completed: {
if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext {
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peer.id, payload: payload), useExisting: true))
}