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
9d3cc5996b
commit
ffbc7921cf
@ -108,6 +108,7 @@
|
||||
"PUSH_MESSAGE_NOTHEME" = "%1$@|disabled chat theme";
|
||||
"PUSH_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@";
|
||||
"CHAT_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@";
|
||||
"PUSH_MESSAGE_PAID_MEDIA" = "%1$@sent you a paid post for %2$@ stars";
|
||||
|
||||
"PUSH_CHANNEL_MESSAGE_TEXT" = "%1$@|%2$@";
|
||||
"PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message";
|
||||
@ -138,6 +139,7 @@
|
||||
"PUSH_CHANNEL_ALBUM" = "%1$@|posted an album";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_1" = "posted a file";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_any" = "posted %d files";
|
||||
"PUSH_CHANNEL_MESSAGE_PAID_MEDIA" = "%1$@ sent a paid post for %2$@ stars";
|
||||
|
||||
"PUSH_CHAT_MESSAGE_TEXT" = "%2$@|%1$@:%3$@";
|
||||
"PUSH_CHAT_MESSAGE_NOTEXT" = "%2$@|%1$@ sent a message to the group";
|
||||
@ -183,6 +185,7 @@
|
||||
"PUSH_CHAT_MESSAGE_THEME" = "%1$@|set theme to %3$@ in the group %2$@";
|
||||
"PUSH_CHAT_MESSAGE_NOTHEME" = "%1$@|disabled theme in the group %2$@";
|
||||
"PUSH_CHAT_REQ_JOINED" = "%1$@ was accepted into the group %2$@";
|
||||
"PUSH_CHAT_MESSAGE_PAID_MEDIA" = "%1$@ sent a paid post to the group %2$@ for %3$@ stars";
|
||||
|
||||
"PUSH_PINNED_TEXT" = "%1$@|pinned \"%2$@\" ";
|
||||
"PUSH_PINNED_NOTEXT" = "%1$@|pinned a message";
|
||||
@ -200,6 +203,7 @@
|
||||
"PUSH_PINNED_GAME" = "%1$@|pinned a game";
|
||||
"PUSH_PINNED_INVOICE" = "%1$@|pinned an invoice";
|
||||
"PUSH_PINNED_GIF" = "%1$@|pinned a GIF";
|
||||
"PUSH_PINNED_PAID_MEDIA" = "%1$@|pinned a paid post for %2$@";
|
||||
|
||||
"PUSH_CONTACT_JOINED" = "%1$@|joined Telegram!";
|
||||
|
||||
@ -252,6 +256,7 @@
|
||||
"PUSH_CHAT_REACT_GAME" = "%2$@|%1$@ %3$@ to your game";
|
||||
"PUSH_CHAT_REACT_INVOICE" = "%2$@|%1$@ %3$@ to your invoice";
|
||||
"PUSH_CHAT_REACT_GIF" = "%2$@|%1$@ %3$@ to your GIF";
|
||||
"PUSH_CHAT_REACT_PAID_MEDIA" = "%2$@|%1$@ %3$@ to your paid post";
|
||||
|
||||
"PUSH_MESSAGE_SUGGEST_USERPIC" = "%1$@|suggested you new profile photo";
|
||||
|
||||
@ -273,6 +278,7 @@
|
||||
"PUSH_REACT_STORY" = "%1$@|%2$@ to your story";
|
||||
"PUSH_REACT_STORY_HIDDEN" = "New reaction to your story";
|
||||
|
||||
|
||||
"LOCAL_MESSAGE_FWDS" = "%1$@ forwarded you %2$d messages";
|
||||
"LOCAL_CHANNEL_MESSAGE_FWDS" = "%1$@ posted %2$d forwarded messages";
|
||||
"LOCAL_CHAT_MESSAGE_FWDS" = "%1$@ forwarded %2$d messages";
|
||||
|
@ -295,11 +295,13 @@ public struct ChatControllerInitialBotAppStart {
|
||||
public let botApp: BotApp
|
||||
public let payload: String?
|
||||
public let justInstalled: Bool
|
||||
public let compact: Bool
|
||||
|
||||
public init(botApp: BotApp, payload: String?, justInstalled: Bool) {
|
||||
public init(botApp: BotApp, payload: String?, justInstalled: Bool, compact: Bool) {
|
||||
self.botApp = botApp
|
||||
self.payload = payload
|
||||
self.justInstalled = justInstalled
|
||||
self.compact = compact
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
private var isDismissed = false
|
||||
private var isInteractiveDimissEnabled = true
|
||||
|
||||
private let isFullSize: Bool
|
||||
public private(set) var isExpanded = false
|
||||
|
||||
private var validLayout: (layout: ContainerViewLayout, controllers: [AttachmentContainable], coveredByModalTransition: CGFloat)?
|
||||
@ -72,7 +73,12 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
var isPanGestureEnabled: (() -> Bool)?
|
||||
var onExpandAnimationCompleted: () -> Void = {}
|
||||
|
||||
override init() {
|
||||
init(isFullSize: Bool) {
|
||||
self.isFullSize = isFullSize
|
||||
if isFullSize {
|
||||
self.isExpanded = true
|
||||
}
|
||||
|
||||
self.wrappingNode = ASDisplayNode()
|
||||
self.clipNode = ASDisplayNode()
|
||||
|
||||
@ -268,14 +274,14 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() {
|
||||
if !self.isExpanded || self.isFullSize, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() {
|
||||
self.cancelPanGesture()
|
||||
self.requestDismiss?()
|
||||
return
|
||||
}
|
||||
|
||||
var bounds = self.bounds
|
||||
if self.isExpanded {
|
||||
if self.isExpanded && !self.isFullSize {
|
||||
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
||||
} else {
|
||||
bounds.origin.y = -translation
|
||||
@ -307,7 +313,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
var bounds = self.bounds
|
||||
if self.isExpanded {
|
||||
if self.isExpanded && !self.isFullSize {
|
||||
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
||||
} else {
|
||||
bounds.origin.y = -translation
|
||||
@ -326,21 +332,29 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
|
||||
var minimizing = false
|
||||
var dismissing = false
|
||||
if (bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0)) && !ignoreDismiss {
|
||||
|
||||
let thresholdOffset: CGFloat
|
||||
if self.isFullSize {
|
||||
thresholdOffset = -180.0
|
||||
} else {
|
||||
thresholdOffset = -60.0
|
||||
}
|
||||
|
||||
if (bounds.minY < thresholdOffset || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0)) && !ignoreDismiss {
|
||||
if self.interactivelyDismissed?(velocity.y) == true {
|
||||
dismissing = true
|
||||
} else {
|
||||
minimizing = true
|
||||
}
|
||||
} else if self.isExpanded {
|
||||
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
||||
if (velocity.y > 300.0 || offset > topInset / 2.0) && !self.isFullSize {
|
||||
self.isExpanded = false
|
||||
if let listNode = listNode {
|
||||
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
||||
} else if let scrollView = scrollView {
|
||||
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: -scrollView.contentInset.top), animated: false)
|
||||
}
|
||||
|
||||
|
||||
let distance = topInset - offset
|
||||
let initialVelocity: CGFloat = distance.isZero ? 0.0 : abs(velocity.y / distance)
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
||||
@ -432,6 +446,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
}
|
||||
self.isUpdatingState = true
|
||||
|
||||
let isFirstTime = self.validLayout == nil
|
||||
self.validLayout = (layout, controllers, coveredByModalTransition)
|
||||
|
||||
self.panGestureRecognizer?.isEnabled = (layout.inputHeight == nil || layout.inputHeight == 0.0)
|
||||
@ -446,7 +461,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
let topInset: CGFloat
|
||||
if let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
||||
if !self.isFullSize, let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
||||
if effectiveExpanded {
|
||||
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
||||
} else {
|
||||
@ -459,9 +474,29 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
||||
completion()
|
||||
})
|
||||
|
||||
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / defaultTopInset)
|
||||
self.updateModalProgress?(modalProgress, topInset, self.bounds, transition)
|
||||
|
||||
let modalProgress: CGFloat
|
||||
if isLandscape {
|
||||
modalProgress = 0.0
|
||||
} else {
|
||||
if self.isFullSize, self.panGestureArguments != nil {
|
||||
modalProgress = 1.0 - min(1.0, max(0.0, -1.0 * self.bounds.minY / defaultTopInset))
|
||||
} else {
|
||||
modalProgress = 1.0 - topInset / defaultTopInset
|
||||
}
|
||||
}
|
||||
|
||||
if isFirstTime {
|
||||
Queue.mainQueue().justDispatch {
|
||||
var transition = transition
|
||||
if modalProgress == 1.0 {
|
||||
transition = .animated(duration: 0.4, curve: .spring)
|
||||
}
|
||||
self.updateModalProgress?(modalProgress, topInset, self.bounds, transition)
|
||||
}
|
||||
} else {
|
||||
self.updateModalProgress?(modalProgress, topInset, self.bounds, transition)
|
||||
}
|
||||
|
||||
let containerLayout: ContainerViewLayout
|
||||
let containerFrame: CGRect
|
||||
let clipFrame: CGRect
|
||||
|
@ -131,6 +131,8 @@ public protocol AttachmentContainable: ViewController {
|
||||
|
||||
func requestDismiss(completion: @escaping () -> Void)
|
||||
func shouldDismissImmediately() -> Bool
|
||||
|
||||
func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void)
|
||||
}
|
||||
|
||||
public extension AttachmentContainable {
|
||||
@ -154,6 +156,10 @@ public extension AttachmentContainable {
|
||||
return true
|
||||
}
|
||||
|
||||
func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
||||
completion()
|
||||
}
|
||||
|
||||
var isPanGestureEnabled: (() -> Bool)? {
|
||||
return nil
|
||||
}
|
||||
@ -234,6 +240,7 @@ public class AttachmentController: ViewController {
|
||||
private let initialButton: AttachmentButtonType
|
||||
private let fromMenu: Bool
|
||||
private var hasTextInput: Bool
|
||||
private let isFullSize: Bool
|
||||
private let makeEntityInputView: () -> AttachmentTextInputPanelInputView?
|
||||
public var animateAppearance: Bool = false
|
||||
|
||||
@ -345,7 +352,7 @@ public class AttachmentController: ViewController {
|
||||
self.wrapperNode = ASDisplayNode()
|
||||
self.wrapperNode.clipsToBounds = true
|
||||
|
||||
self.container = AttachmentContainer()
|
||||
self.container = AttachmentContainer(isFullSize: controller.isFullSize)
|
||||
self.container.canHaveKeyboardFocus = true
|
||||
self.panel = AttachmentPanel(controller: controller, context: controller.context, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, updatedPresentationData: controller.updatedPresentationData, makeEntityInputView: makeEntityInputView)
|
||||
self.panel.fromMenu = controller.fromMenu
|
||||
@ -574,7 +581,13 @@ public class AttachmentController: ViewController {
|
||||
guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
navigationController.minimizeViewController(controller, damping: damping, velocity: initialVelocity, setupContainer: { [weak self] current in
|
||||
navigationController.minimizeViewController(controller, damping: damping, velocity: initialVelocity, beforeMaximize: { navigationController, completion in
|
||||
if let controller = controller.mainController as? AttachmentContainable {
|
||||
controller.beforeMaximize(navigationController: navigationController, completion: completion)
|
||||
} else {
|
||||
completion()
|
||||
}
|
||||
}, setupContainer: { [weak self] current in
|
||||
let minimizedContainer: MinimizedContainerImpl?
|
||||
if let current = current as? MinimizedContainerImpl {
|
||||
minimizedContainer = current
|
||||
@ -1062,7 +1075,7 @@ public class AttachmentController: ViewController {
|
||||
|
||||
public var shouldMinimizeOnSwipe: ((AttachmentButtonType?) -> Bool)?
|
||||
|
||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, chatLocation: ChatLocation?, isScheduledMessages: Bool = false, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false, hasTextInput: Bool = true, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView? = { return nil}) {
|
||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, chatLocation: ChatLocation?, isScheduledMessages: Bool = false, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false, hasTextInput: Bool = true, isFullSize: Bool = false, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView? = { return nil}) {
|
||||
self.context = context
|
||||
self.updatedPresentationData = updatedPresentationData
|
||||
self.chatLocation = chatLocation
|
||||
@ -1071,6 +1084,7 @@ public class AttachmentController: ViewController {
|
||||
self.initialButton = initialButton
|
||||
self.fromMenu = fromMenu
|
||||
self.hasTextInput = hasTextInput
|
||||
self.isFullSize = isFullSize
|
||||
self.makeEntityInputView = makeEntityInputView
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
@ -447,7 +447,9 @@ public class BrowserScreen: ViewController {
|
||||
guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
navigationController.minimizeViewController(controller, damping: nil, setupContainer: { [weak self] current in
|
||||
navigationController.minimizeViewController(controller, damping: nil, beforeMaximize: { _, completion in
|
||||
completion()
|
||||
}, setupContainer: { [weak self] current in
|
||||
let minimizedContainer: MinimizedContainerImpl?
|
||||
if let current = current as? MinimizedContainerImpl {
|
||||
minimizedContainer = current
|
||||
|
@ -8,7 +8,7 @@ public protocol MinimizedContainer: ASDisplayNode {
|
||||
|
||||
var willMaximize: (() -> Void)? { get set }
|
||||
|
||||
func addController(_ viewController: ViewController, transition: ContainedViewLayoutTransition)
|
||||
func addController(_ viewController: ViewController, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void, transition: ContainedViewLayoutTransition)
|
||||
func maximizeController(_ viewController: ViewController, animated: Bool, completion: @escaping (Bool) -> Void)
|
||||
func collapse()
|
||||
func dismissAll(completion: @escaping () -> Void)
|
||||
|
@ -842,7 +842,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
if case .flat = navigationLayout.root, let minimizedContainer = self.minimizedContainer {
|
||||
if minimizedContainer.supernode !== self.displayNode {
|
||||
if let rootContainer = self.rootContainer, case let .flat(flatContainer) = rootContainer {
|
||||
self.displayNode.insertSubnode(minimizedContainer, aboveSubnode: flatContainer)
|
||||
if let rootModalFrame = self.rootModalFrame {
|
||||
self.displayNode.insertSubnode(minimizedContainer, aboveSubnode: rootModalFrame)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(minimizedContainer, aboveSubnode: flatContainer)
|
||||
}
|
||||
} else {
|
||||
self.displayNode.insertSubnode(minimizedContainer, at: 0)
|
||||
}
|
||||
@ -1572,7 +1576,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self._viewControllersPromise.set(self.viewControllers)
|
||||
}
|
||||
|
||||
public func minimizeViewController(_ viewController: ViewController, damping: CGFloat?, velocity: CGFloat? = nil, setupContainer: (MinimizedContainer?) -> MinimizedContainer?, animated: Bool) {
|
||||
public func minimizeViewController(_ viewController: ViewController, damping: CGFloat?, velocity: CGFloat? = nil, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void, setupContainer: (MinimizedContainer?) -> MinimizedContainer?, animated: Bool) {
|
||||
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.4, curve: .customSpring(damping: damping ?? 124.0, initialVelocity: velocity ?? 0.0)) : .immediate
|
||||
|
||||
let minimizedContainer = setupContainer(self.minimizedContainer)
|
||||
@ -1592,7 +1596,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
viewController.isMinimized = true
|
||||
self.filterController(viewController, animated: true)
|
||||
minimizedContainer?.addController(viewController, transition: transition)
|
||||
minimizedContainer?.addController(viewController, beforeMaximize: beforeMaximize, transition: transition)
|
||||
}
|
||||
|
||||
private var isMaximizing = false
|
||||
|
@ -485,6 +485,9 @@ final class NavigationModalContainer: ASDisplayNode, ASScrollViewDelegate, ASGes
|
||||
let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut)
|
||||
let positionTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut)
|
||||
alphaTransition.updateAlpha(node: self.dim, alpha: 0.0, beginWithCurrentState: true)
|
||||
if let lastController = self.container.controllers.last, lastController.isMinimized {
|
||||
self.dim.layer.removeAllAnimations()
|
||||
}
|
||||
positionTransition.updatePosition(node: self.container, position: CGPoint(x: self.container.position.x, y: self.bounds.height + self.container.bounds.height / 2.0 + self.bounds.height), beginWithCurrentState: true, completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -54,7 +54,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[571523412] = { return $0.readDouble() }
|
||||
dict[-1255641564] = { return parseString($0) }
|
||||
dict[-1194283041] = { return Api.AccountDaysTTL.parse_accountDaysTTL($0) }
|
||||
dict[1008422669] = { return Api.AppWebViewResult.parse_appWebViewResultUrl($0) }
|
||||
dict[-653423106] = { return Api.AttachMenuBot.parse_attachMenuBot($0) }
|
||||
dict[-1297663893] = { return Api.AttachMenuBotIcon.parse_attachMenuBotIcon($0) }
|
||||
dict[1165423600] = { return Api.AttachMenuBotIconColor.parse_attachMenuBotIconColor($0) }
|
||||
@ -446,6 +445,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[859091184] = { return Api.InputSecureFile.parse_inputSecureFileUploaded($0) }
|
||||
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
|
||||
dict[482797855] = { return Api.InputSingleMedia.parse_inputSingleMedia($0) }
|
||||
dict[543876817] = { return Api.InputStarsTransaction.parse_inputStarsTransaction($0) }
|
||||
dict[42402760] = { return Api.InputStickerSet.parse_inputStickerSetAnimatedEmoji($0) }
|
||||
dict[215889721] = { return Api.InputStickerSet.parse_inputStickerSetAnimatedEmojiAnimations($0) }
|
||||
dict[-427863538] = { return Api.InputStickerSet.parse_inputStickerSetDice($0) }
|
||||
@ -870,7 +870,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-378127636] = { return Api.SendMessageAction.parse_sendMessageUploadVideoAction($0) }
|
||||
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
||||
dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($0) }
|
||||
dict[-2010155333] = { return Api.SimpleWebViewResult.parse_simpleWebViewResultUrl($0) }
|
||||
dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
|
||||
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||
@ -1105,7 +1104,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[781501415] = { return Api.WebPageAttribute.parse_webPageAttributeStory($0) }
|
||||
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
|
||||
dict[211046684] = { return Api.WebViewMessageSent.parse_webViewMessageSent($0) }
|
||||
dict[202659196] = { return Api.WebViewResult.parse_webViewResultUrl($0) }
|
||||
dict[1294139288] = { return Api.WebViewResult.parse_webViewResultUrl($0) }
|
||||
dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
|
||||
dict[1275039392] = { return Api.account.Authorizations.parse_authorizations($0) }
|
||||
dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($0) }
|
||||
@ -1155,7 +1154,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1035688326] = { return Api.auth.SentCodeType.parse_sentCodeTypeApp($0) }
|
||||
dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) }
|
||||
dict[-196020837] = { return Api.auth.SentCodeType.parse_sentCodeTypeEmailCode($0) }
|
||||
dict[331943703] = { return Api.auth.SentCodeType.parse_sentCodeTypeFirebaseSms($0) }
|
||||
dict[10475318] = { return Api.auth.SentCodeType.parse_sentCodeTypeFirebaseSms($0) }
|
||||
dict[-1425815847] = { return Api.auth.SentCodeType.parse_sentCodeTypeFlashCall($0) }
|
||||
dict[-648651719] = { return Api.auth.SentCodeType.parse_sentCodeTypeFragmentSms($0) }
|
||||
dict[-2113903484] = { return Api.auth.SentCodeType.parse_sentCodeTypeMissedCall($0) }
|
||||
@ -1437,8 +1436,6 @@ public extension Api {
|
||||
switch object {
|
||||
case let _1 as Api.AccountDaysTTL:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.AppWebViewResult:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.AttachMenuBot:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.AttachMenuBotIcon:
|
||||
@ -1749,6 +1746,8 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputSingleMedia:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputStarsTransaction:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputStickerSet:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputStickerSetItem:
|
||||
@ -1979,8 +1978,6 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ShippingOption:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SimpleWebViewResult:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SmsJob:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SponsoredMessage:
|
||||
|
@ -34,42 +34,6 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum AppWebViewResult: TypeConstructorDescription {
|
||||
case appWebViewResultUrl(url: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .appWebViewResultUrl(let url):
|
||||
if boxed {
|
||||
buffer.appendInt32(1008422669)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .appWebViewResultUrl(let url):
|
||||
return ("appWebViewResultUrl", [("url", url as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_appWebViewResultUrl(_ reader: BufferReader) -> AppWebViewResult? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.AppWebViewResult.appWebViewResultUrl(url: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum AttachMenuBot: TypeConstructorDescription {
|
||||
case attachMenuBot(flags: Int32, botId: Int64, shortName: String, peerTypes: [Api.AttachMenuPeerType]?, icons: [Api.AttachMenuBotIcon])
|
||||
@ -1196,3 +1160,43 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum BotCommand: TypeConstructorDescription {
|
||||
case botCommand(command: String, description: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .botCommand(let command, let description):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1032140601)
|
||||
}
|
||||
serializeString(command, buffer: buffer, boxed: false)
|
||||
serializeString(description, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .botCommand(let command, let description):
|
||||
return ("botCommand", [("command", command as Any), ("description", description as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_botCommand(_ reader: BufferReader) -> BotCommand? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.BotCommand.botCommand(command: _1!, description: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,46 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputStarsTransaction: TypeConstructorDescription {
|
||||
case inputStarsTransaction(flags: Int32, id: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputStarsTransaction(let flags, let id):
|
||||
if boxed {
|
||||
buffer.appendInt32(543876817)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(id, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputStarsTransaction(let flags, let id):
|
||||
return ("inputStarsTransaction", [("flags", flags as Any), ("id", id as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputStarsTransaction(_ reader: BufferReader) -> InputStarsTransaction? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputStarsTransaction.inputStarsTransaction(flags: _1!, id: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputStickerSet: TypeConstructorDescription {
|
||||
case inputStickerSetAnimatedEmoji
|
||||
@ -918,119 +958,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputWebFileLocation: TypeConstructorDescription {
|
||||
case inputWebFileAudioAlbumThumbLocation(flags: Int32, document: Api.InputDocument?, title: String?, performer: String?)
|
||||
case inputWebFileGeoPointLocation(geoPoint: Api.InputGeoPoint, accessHash: Int64, w: Int32, h: Int32, zoom: Int32, scale: Int32)
|
||||
case inputWebFileLocation(url: String, accessHash: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
if boxed {
|
||||
buffer.appendInt32(-193992412)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(performer!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1625153079)
|
||||
}
|
||||
geoPoint.serialize(buffer, true)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(w, buffer: buffer, boxed: false)
|
||||
serializeInt32(h, buffer: buffer, boxed: false)
|
||||
serializeInt32(zoom, buffer: buffer, boxed: false)
|
||||
serializeInt32(scale, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputWebFileLocation(let url, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1036396922)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
return ("inputWebFileAudioAlbumThumbLocation", [("flags", flags as Any), ("document", document as Any), ("title", title as Any), ("performer", performer as Any)])
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
return ("inputWebFileGeoPointLocation", [("geoPoint", geoPoint as Any), ("accessHash", accessHash as Any), ("w", w as Any), ("h", h as Any), ("zoom", zoom as Any), ("scale", scale as Any)])
|
||||
case .inputWebFileLocation(let url, let accessHash):
|
||||
return ("inputWebFileLocation", [("url", url as Any), ("accessHash", accessHash as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputWebFileAudioAlbumThumbLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputDocument?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
|
||||
} }
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputWebFileLocation.inputWebFileAudioAlbumThumbLocation(flags: _1!, document: _2, title: _3, performer: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputWebFileGeoPointLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputWebFileLocation.inputWebFileGeoPointLocation(geoPoint: _1!, accessHash: _2!, w: _3!, h: _4!, zoom: _5!, scale: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputWebFileLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputWebFileLocation.inputWebFileLocation(url: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,119 @@
|
||||
public extension Api {
|
||||
enum InputWebFileLocation: TypeConstructorDescription {
|
||||
case inputWebFileAudioAlbumThumbLocation(flags: Int32, document: Api.InputDocument?, title: String?, performer: String?)
|
||||
case inputWebFileGeoPointLocation(geoPoint: Api.InputGeoPoint, accessHash: Int64, w: Int32, h: Int32, zoom: Int32, scale: Int32)
|
||||
case inputWebFileLocation(url: String, accessHash: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
if boxed {
|
||||
buffer.appendInt32(-193992412)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(performer!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1625153079)
|
||||
}
|
||||
geoPoint.serialize(buffer, true)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(w, buffer: buffer, boxed: false)
|
||||
serializeInt32(h, buffer: buffer, boxed: false)
|
||||
serializeInt32(zoom, buffer: buffer, boxed: false)
|
||||
serializeInt32(scale, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputWebFileLocation(let url, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1036396922)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputWebFileAudioAlbumThumbLocation(let flags, let document, let title, let performer):
|
||||
return ("inputWebFileAudioAlbumThumbLocation", [("flags", flags as Any), ("document", document as Any), ("title", title as Any), ("performer", performer as Any)])
|
||||
case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale):
|
||||
return ("inputWebFileGeoPointLocation", [("geoPoint", geoPoint as Any), ("accessHash", accessHash as Any), ("w", w as Any), ("h", h as Any), ("zoom", zoom as Any), ("scale", scale as Any)])
|
||||
case .inputWebFileLocation(let url, let accessHash):
|
||||
return ("inputWebFileLocation", [("url", url as Any), ("accessHash", accessHash as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputWebFileAudioAlbumThumbLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputDocument?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
|
||||
} }
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputWebFileLocation.inputWebFileAudioAlbumThumbLocation(flags: _1!, document: _2, title: _3, performer: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputWebFileGeoPointLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputWebFileLocation.inputWebFileGeoPointLocation(geoPoint: _1!, accessHash: _2!, w: _3!, h: _4!, zoom: _5!, scale: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputWebFileLocation(_ reader: BufferReader) -> InputWebFileLocation? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputWebFileLocation.inputWebFileLocation(url: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum Invoice: TypeConstructorDescription {
|
||||
case invoice(flags: Int32, currency: String, prices: [Api.LabeledPrice], maxTipAmount: Int64?, suggestedTipAmounts: [Int64]?, termsUrl: String?)
|
||||
@ -934,111 +1050,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LangPackString: TypeConstructorDescription {
|
||||
case langPackString(key: String, value: String)
|
||||
case langPackStringDeleted(key: String)
|
||||
case langPackStringPluralized(flags: Int32, key: String, zeroValue: String?, oneValue: String?, twoValue: String?, fewValue: String?, manyValue: String?, otherValue: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
if boxed {
|
||||
buffer.appendInt32(-892239370)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
serializeString(value, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringDeleted(let key):
|
||||
if boxed {
|
||||
buffer.appendInt32(695856818)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
if boxed {
|
||||
buffer.appendInt32(1816636575)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(zeroValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(oneValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(twoValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(fewValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeString(manyValue!, buffer: buffer, boxed: false)}
|
||||
serializeString(otherValue, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
return ("langPackString", [("key", key as Any), ("value", value as Any)])
|
||||
case .langPackStringDeleted(let key):
|
||||
return ("langPackStringDeleted", [("key", key as Any)])
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
return ("langPackStringPluralized", [("flags", flags as Any), ("key", key as Any), ("zeroValue", zeroValue as Any), ("oneValue", oneValue as Any), ("twoValue", twoValue as Any), ("fewValue", fewValue as Any), ("manyValue", manyValue as Any), ("otherValue", otherValue as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_langPackString(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.LangPackString.langPackString(key: _1!, value: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringDeleted(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.LangPackString.langPackStringDeleted(key: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringPluralized(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
|
||||
var _8: String?
|
||||
_8 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.LangPackString.langPackStringPluralized(flags: _1!, key: _2!, zeroValue: _3, oneValue: _4, twoValue: _5, fewValue: _6, manyValue: _7, otherValue: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,111 @@
|
||||
public extension Api {
|
||||
enum LangPackString: TypeConstructorDescription {
|
||||
case langPackString(key: String, value: String)
|
||||
case langPackStringDeleted(key: String)
|
||||
case langPackStringPluralized(flags: Int32, key: String, zeroValue: String?, oneValue: String?, twoValue: String?, fewValue: String?, manyValue: String?, otherValue: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
if boxed {
|
||||
buffer.appendInt32(-892239370)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
serializeString(value, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringDeleted(let key):
|
||||
if boxed {
|
||||
buffer.appendInt32(695856818)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
if boxed {
|
||||
buffer.appendInt32(1816636575)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(zeroValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(oneValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(twoValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(fewValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeString(manyValue!, buffer: buffer, boxed: false)}
|
||||
serializeString(otherValue, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
return ("langPackString", [("key", key as Any), ("value", value as Any)])
|
||||
case .langPackStringDeleted(let key):
|
||||
return ("langPackStringDeleted", [("key", key as Any)])
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
return ("langPackStringPluralized", [("flags", flags as Any), ("key", key as Any), ("zeroValue", zeroValue as Any), ("oneValue", oneValue as Any), ("twoValue", twoValue as Any), ("fewValue", fewValue as Any), ("manyValue", manyValue as Any), ("otherValue", otherValue as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_langPackString(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.LangPackString.langPackString(key: _1!, value: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringDeleted(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.LangPackString.langPackStringDeleted(key: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringPluralized(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
|
||||
var _8: String?
|
||||
_8 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.LangPackString.langPackStringPluralized(flags: _1!, key: _2!, zeroValue: _3, oneValue: _4, twoValue: _5, fewValue: _6, manyValue: _7, otherValue: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum MaskCoords: TypeConstructorDescription {
|
||||
case maskCoords(n: Int32, x: Double, y: Double, zoom: Double)
|
||||
|
@ -1,43 +1,3 @@
|
||||
public extension Api {
|
||||
enum BotCommand: TypeConstructorDescription {
|
||||
case botCommand(command: String, description: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .botCommand(let command, let description):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1032140601)
|
||||
}
|
||||
serializeString(command, buffer: buffer, boxed: false)
|
||||
serializeString(description, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .botCommand(let command, let description):
|
||||
return ("botCommand", [("command", command as Any), ("description", description as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_botCommand(_ reader: BufferReader) -> BotCommand? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.BotCommand.botCommand(command: _1!, description: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum BotCommandScope: TypeConstructorDescription {
|
||||
case botCommandScopeChatAdmins
|
||||
@ -1200,3 +1160,53 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum BusinessIntro: TypeConstructorDescription {
|
||||
case businessIntro(flags: Int32, title: String, description: String, sticker: Api.Document?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .businessIntro(let flags, let title, let description, let sticker):
|
||||
if boxed {
|
||||
buffer.appendInt32(1510606445)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(description, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {sticker!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .businessIntro(let flags, let title, let description, let sticker):
|
||||
return ("businessIntro", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("sticker", sticker as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_businessIntro(_ reader: BufferReader) -> BusinessIntro? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Api.Document?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Document
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.BusinessIntro.businessIntro(flags: _1!, title: _2!, description: _3!, sticker: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -396,42 +396,6 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SimpleWebViewResult: TypeConstructorDescription {
|
||||
case simpleWebViewResultUrl(url: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .simpleWebViewResultUrl(let url):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2010155333)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .simpleWebViewResultUrl(let url):
|
||||
return ("simpleWebViewResultUrl", [("url", url as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_simpleWebViewResultUrl(_ reader: BufferReader) -> SimpleWebViewResult? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.SimpleWebViewResult.simpleWebViewResultUrl(url: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SmsJob: TypeConstructorDescription {
|
||||
case smsJob(jobId: String, phoneNumber: String, text: String)
|
||||
|
@ -160,15 +160,16 @@ public extension Api {
|
||||
}
|
||||
public extension Api {
|
||||
enum WebViewResult: TypeConstructorDescription {
|
||||
case webViewResultUrl(queryId: Int64, url: String)
|
||||
case webViewResultUrl(flags: Int32, queryId: Int64?, url: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .webViewResultUrl(let queryId, let url):
|
||||
case .webViewResultUrl(let flags, let queryId, let url):
|
||||
if boxed {
|
||||
buffer.appendInt32(202659196)
|
||||
buffer.appendInt32(1294139288)
|
||||
}
|
||||
serializeInt64(queryId, buffer: buffer, boxed: false)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(queryId!, buffer: buffer, boxed: false)}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
@ -176,20 +177,23 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .webViewResultUrl(let queryId, let url):
|
||||
return ("webViewResultUrl", [("queryId", queryId as Any), ("url", url as Any)])
|
||||
case .webViewResultUrl(let flags, let queryId, let url):
|
||||
return ("webViewResultUrl", [("flags", flags as Any), ("queryId", queryId as Any), ("url", url as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int64?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt64() }
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.WebViewResult.webViewResultUrl(queryId: _1!, url: _2!)
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.WebViewResult.webViewResultUrl(flags: _1!, queryId: _2, url: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -589,7 +589,7 @@ public extension Api.auth {
|
||||
case sentCodeTypeApp(length: Int32)
|
||||
case sentCodeTypeCall(length: Int32)
|
||||
case sentCodeTypeEmailCode(flags: Int32, emailPattern: String, length: Int32, resetAvailablePeriod: Int32?, resetPendingDate: Int32?)
|
||||
case sentCodeTypeFirebaseSms(flags: Int32, nonce: Buffer?, playIntegrityNonce: Buffer?, receipt: String?, pushTimeout: Int32?, length: Int32)
|
||||
case sentCodeTypeFirebaseSms(flags: Int32, nonce: Buffer?, playIntegrityProjectId: Int64?, playIntegrityNonce: Buffer?, receipt: String?, pushTimeout: Int32?, length: Int32)
|
||||
case sentCodeTypeFlashCall(pattern: String)
|
||||
case sentCodeTypeFragmentSms(url: String, length: Int32)
|
||||
case sentCodeTypeMissedCall(prefix: String, length: Int32)
|
||||
@ -622,12 +622,13 @@ public extension Api.auth {
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(resetAvailablePeriod!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(resetPendingDate!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .sentCodeTypeFirebaseSms(let flags, let nonce, let playIntegrityNonce, let receipt, let pushTimeout, let length):
|
||||
case .sentCodeTypeFirebaseSms(let flags, let nonce, let playIntegrityProjectId, let playIntegrityNonce, let receipt, let pushTimeout, let length):
|
||||
if boxed {
|
||||
buffer.appendInt32(331943703)
|
||||
buffer.appendInt32(10475318)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(nonce!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt64(playIntegrityProjectId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeBytes(playIntegrityNonce!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(receipt!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(pushTimeout!, buffer: buffer, boxed: false)}
|
||||
@ -690,8 +691,8 @@ public extension Api.auth {
|
||||
return ("sentCodeTypeCall", [("length", length as Any)])
|
||||
case .sentCodeTypeEmailCode(let flags, let emailPattern, let length, let resetAvailablePeriod, let resetPendingDate):
|
||||
return ("sentCodeTypeEmailCode", [("flags", flags as Any), ("emailPattern", emailPattern as Any), ("length", length as Any), ("resetAvailablePeriod", resetAvailablePeriod as Any), ("resetPendingDate", resetPendingDate as Any)])
|
||||
case .sentCodeTypeFirebaseSms(let flags, let nonce, let playIntegrityNonce, let receipt, let pushTimeout, let length):
|
||||
return ("sentCodeTypeFirebaseSms", [("flags", flags as Any), ("nonce", nonce as Any), ("playIntegrityNonce", playIntegrityNonce as Any), ("receipt", receipt as Any), ("pushTimeout", pushTimeout as Any), ("length", length as Any)])
|
||||
case .sentCodeTypeFirebaseSms(let flags, let nonce, let playIntegrityProjectId, let playIntegrityNonce, let receipt, let pushTimeout, let length):
|
||||
return ("sentCodeTypeFirebaseSms", [("flags", flags as Any), ("nonce", nonce as Any), ("playIntegrityProjectId", playIntegrityProjectId as Any), ("playIntegrityNonce", playIntegrityNonce as Any), ("receipt", receipt as Any), ("pushTimeout", pushTimeout as Any), ("length", length as Any)])
|
||||
case .sentCodeTypeFlashCall(let pattern):
|
||||
return ("sentCodeTypeFlashCall", [("pattern", pattern as Any)])
|
||||
case .sentCodeTypeFragmentSms(let url, let length):
|
||||
@ -759,22 +760,25 @@ public extension Api.auth {
|
||||
_1 = reader.readInt32()
|
||||
var _2: Buffer?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
|
||||
var _3: Buffer?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_3 = parseBytes(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
|
||||
var _3: Int64?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt64() }
|
||||
var _4: Buffer?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_4 = parseBytes(reader) }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_6 = reader.readInt32() }
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.auth.SentCodeType.sentCodeTypeFirebaseSms(flags: _1!, nonce: _2, playIntegrityNonce: _3, receipt: _4, pushTimeout: _5, length: _6!)
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.auth.SentCodeType.sentCodeTypeFirebaseSms(flags: _1!, nonce: _2, playIntegrityProjectId: _3, playIntegrityNonce: _4, receipt: _5, pushTimeout: _6, length: _7!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -1,53 +1,3 @@
|
||||
public extension Api {
|
||||
enum BusinessIntro: TypeConstructorDescription {
|
||||
case businessIntro(flags: Int32, title: String, description: String, sticker: Api.Document?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .businessIntro(let flags, let title, let description, let sticker):
|
||||
if boxed {
|
||||
buffer.appendInt32(1510606445)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(description, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {sticker!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .businessIntro(let flags, let title, let description, let sticker):
|
||||
return ("businessIntro", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("sticker", sticker as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_businessIntro(_ reader: BufferReader) -> BusinessIntro? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Api.Document?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Document
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.BusinessIntro.businessIntro(flags: _1!, title: _2!, description: _3!, sticker: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum BusinessLocation: TypeConstructorDescription {
|
||||
case businessLocation(flags: Int32, geoPoint: Api.GeoPoint?, address: String)
|
||||
|
@ -7308,20 +7308,20 @@ public extension Api.functions.messages {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func requestAppWebView(flags: Int32, peer: Api.InputPeer, app: Api.InputBotApp, startParam: String?, themeParams: Api.DataJSON?, platform: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.AppWebViewResult>) {
|
||||
static func requestAppWebView(flags: Int32, peer: Api.InputPeer, app: Api.InputBotApp, startParam: String?, themeParams: Api.DataJSON?, platform: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.WebViewResult>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1940243652)
|
||||
buffer.appendInt32(1398901710)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
app.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)}
|
||||
serializeString(platform, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.requestAppWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("app", String(describing: app)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("platform", String(describing: platform))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AppWebViewResult? in
|
||||
return (FunctionDescription(name: "messages.requestAppWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("app", String(describing: app)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("platform", String(describing: platform))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.AppWebViewResult?
|
||||
var result: Api.WebViewResult?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.AppWebViewResult
|
||||
result = Api.parse(reader, signature: signature) as? Api.WebViewResult
|
||||
}
|
||||
return result
|
||||
})
|
||||
@ -7345,20 +7345,20 @@ public extension Api.functions.messages {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func requestSimpleWebView(flags: Int32, bot: Api.InputUser, url: String?, startParam: String?, themeParams: Api.DataJSON?, platform: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.SimpleWebViewResult>) {
|
||||
static func requestSimpleWebView(flags: Int32, bot: Api.InputUser, url: String?, startParam: String?, themeParams: Api.DataJSON?, platform: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.WebViewResult>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(440815626)
|
||||
buffer.appendInt32(1094336115)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
bot.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)}
|
||||
serializeString(platform, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.requestSimpleWebView", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("platform", String(describing: platform))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SimpleWebViewResult? in
|
||||
return (FunctionDescription(name: "messages.requestSimpleWebView", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("platform", String(describing: platform))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.SimpleWebViewResult?
|
||||
var result: Api.WebViewResult?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.SimpleWebViewResult
|
||||
result = Api.parse(reader, signature: signature) as? Api.WebViewResult
|
||||
}
|
||||
return result
|
||||
})
|
||||
@ -8827,6 +8827,26 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func getStarsTransactionsByID(peer: Api.InputPeer, id: [Api.InputStarsTransaction]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(662973742)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(id.count))
|
||||
for item in id {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
return (FunctionDescription(name: "payments.getStarsTransactionsByID", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.payments.StarsStatus?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.payments.StarsStatus
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func launchPrepaidGiveaway(peer: Api.InputPeer, giveawayId: Int64, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -274,7 +274,7 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
|
||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||
}
|
||||
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||
return firebaseSecretStream
|
||||
|> map { mapping -> String? in
|
||||
guard let receipt = receipt else {
|
||||
@ -432,7 +432,7 @@ private func internalResendAuthorizationCode(accountManager: AccountManager<Tele
|
||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||
}
|
||||
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||
return firebaseSecretStream
|
||||
|> map { mapping -> String? in
|
||||
guard let receipt = receipt else {
|
||||
@ -574,7 +574,7 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
|
||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||
}
|
||||
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = newType {
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = newType {
|
||||
return firebaseSecretStream
|
||||
|> map { mapping -> String? in
|
||||
guard let receipt = receipt else {
|
||||
|
@ -36,7 +36,7 @@ extension SentAuthorizationCodeType {
|
||||
self = .emailSetupRequired(appleSignInAllowed: (flags & (1 << 0)) != 0)
|
||||
case let .sentCodeTypeFragmentSms(url, length):
|
||||
self = .fragment(url: url, length: length)
|
||||
case let .sentCodeTypeFirebaseSms(_, _, _, _, pushTimeout, length):
|
||||
case let .sentCodeTypeFirebaseSms(_, _, _, _, _, pushTimeout, length):
|
||||
self = .firebase(pushTimeout: pushTimeout, length: length)
|
||||
case let .sentCodeTypeSmsWord(_, beginning):
|
||||
self = .word(startsWith: beginning)
|
||||
|
@ -72,7 +72,7 @@ func _internal_requestChangeAccountPhoneNumberVerification(account: Account, api
|
||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||
}
|
||||
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||
return firebaseSecretStream
|
||||
|> map { mapping -> String? in
|
||||
guard let receipt = receipt else {
|
||||
@ -147,7 +147,7 @@ private func internalResendChangeAccountPhoneNumberVerification(account: Account
|
||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||
}
|
||||
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
||||
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||
return firebaseSecretStream
|
||||
|> map { mapping -> String? in
|
||||
guard let receipt = receipt else {
|
||||
|
@ -16,16 +16,12 @@ public enum RequestSimpleWebViewSource {
|
||||
case settings
|
||||
}
|
||||
|
||||
public enum RequestSimpleWebViewError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> Signal<String, RequestSimpleWebViewError> {
|
||||
func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> 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) {
|
||||
serializedThemeParams = .dataJSON(data: dataString)
|
||||
}
|
||||
return postbox.transaction { transaction -> Signal<String, RequestSimpleWebViewError> in
|
||||
return postbox.transaction { transaction -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -46,17 +42,21 @@ func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: P
|
||||
flags |= (1 << 3)
|
||||
}
|
||||
return network.request(Api.functions.messages.requestSimpleWebView(flags: flags, bot: inputUser, url: url, startParam: nil, themeParams: serializedThemeParams, platform: botWebViewPlatform))
|
||||
|> mapError { _ -> RequestSimpleWebViewError in
|
||||
|> mapError { _ -> RequestWebViewError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<String, RequestSimpleWebViewError> in
|
||||
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||
switch result {
|
||||
case let .simpleWebViewResultUrl(url):
|
||||
return .single(url)
|
||||
case let .webViewResultUrl(flags, queryId, url):
|
||||
var resultFlags: RequestWebViewResult.Flags = []
|
||||
if (flags & (1 << 1)) != 0 {
|
||||
resultFlags.insert(.fullSize)
|
||||
}
|
||||
return .single(RequestWebViewResult(flags: resultFlags, queryId: queryId, url: url, keepAliveSignal: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|> castError(RequestSimpleWebViewError.self)
|
||||
|> castError(RequestWebViewError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
@ -65,9 +65,24 @@ public enum KeepWebViewError {
|
||||
}
|
||||
|
||||
public struct RequestWebViewResult {
|
||||
public let queryId: Int64
|
||||
public struct Flags: OptionSet {
|
||||
public var rawValue: Int32
|
||||
|
||||
public init(rawValue: Int32) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public init() {
|
||||
self.rawValue = 0
|
||||
}
|
||||
|
||||
public static let fullSize = Flags(rawValue: 1 << 0)
|
||||
}
|
||||
|
||||
public let flags: Flags
|
||||
public let queryId: Int64?
|
||||
public let url: String
|
||||
public let keepAliveSignal: Signal<Never, KeepWebViewError>
|
||||
public let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||
}
|
||||
|
||||
public enum RequestWebViewError {
|
||||
@ -166,8 +181,19 @@ func _internal_requestWebView(postbox: Postbox, network: Network, stateManager:
|
||||
}
|
||||
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||
switch result {
|
||||
case let .webViewResultUrl(queryId, url):
|
||||
return .single(RequestWebViewResult(queryId: queryId, url: url, keepAliveSignal: keepWebViewSignal(network: network, stateManager: stateManager, flags: flags, peer: inputPeer, bot: inputBot, queryId: queryId, replyToMessageId: replyToMessageId, threadId: threadId, sendAs: nil)))
|
||||
case let .webViewResultUrl(webViewFlags, queryId, url):
|
||||
var resultFlags: RequestWebViewResult.Flags = []
|
||||
if (webViewFlags & (1 << 1)) != 0 {
|
||||
resultFlags.insert(.fullSize)
|
||||
}
|
||||
let keepAlive: Signal<Never, KeepWebViewError>?
|
||||
if let queryId {
|
||||
keepAlive = keepWebViewSignal(network: network, stateManager: stateManager, flags: flags, peer: inputPeer, bot: inputBot, queryId: queryId, replyToMessageId: replyToMessageId, threadId: threadId, sendAs: nil)
|
||||
} else {
|
||||
keepAlive = nil
|
||||
}
|
||||
|
||||
return .single(RequestWebViewResult(flags: resultFlags, queryId: queryId, url: url, keepAliveSignal: keepAlive))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,17 +225,13 @@ func _internal_sendWebViewData(postbox: Postbox, network: Network, stateManager:
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
public enum RequestAppWebViewError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_requestAppWebView(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, appReference: BotAppReference, payload: String?, themeParams: [String: Any]?, allowWrite: Bool) -> Signal<String, RequestAppWebViewError> {
|
||||
func _internal_requestAppWebView(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, appReference: BotAppReference, payload: String?, themeParams: [String: Any]?, compact: Bool, allowWrite: Bool) -> 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) {
|
||||
serializedThemeParams = .dataJSON(data: dataString)
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Signal<String, RequestAppWebViewError> in
|
||||
return postbox.transaction { transaction -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -235,19 +257,26 @@ func _internal_requestAppWebView(postbox: Postbox, network: Network, stateManage
|
||||
if allowWrite {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
if compact {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
|
||||
return network.request(Api.functions.messages.requestAppWebView(flags: flags, peer: inputPeer, app: app, startParam: payload, themeParams: serializedThemeParams, platform: botWebViewPlatform))
|
||||
|> mapError { _ -> RequestAppWebViewError in
|
||||
|> mapError { _ -> RequestWebViewError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<String, RequestAppWebViewError> in
|
||||
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||
switch result {
|
||||
case let .appWebViewResultUrl(url):
|
||||
return .single(url)
|
||||
case let .webViewResultUrl(flags, queryId, url):
|
||||
var resultFlags: RequestWebViewResult.Flags = []
|
||||
if (flags & (1 << 1)) != 0 {
|
||||
resultFlags.insert(.fullSize)
|
||||
}
|
||||
return .single(RequestWebViewResult(flags: resultFlags, queryId: queryId, url: url, keepAliveSignal: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|> castError(RequestAppWebViewError.self)
|
||||
|> castError(RequestWebViewError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
|
@ -566,12 +566,12 @@ public extension TelegramEngine {
|
||||
return _internal_requestWebView(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, botId: botId, url: url, payload: payload, themeParams: themeParams, fromMenu: fromMenu, replyToMessageId: replyToMessageId, threadId: threadId)
|
||||
}
|
||||
|
||||
public func requestSimpleWebView(botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> Signal<String, RequestSimpleWebViewError> {
|
||||
public func requestSimpleWebView(botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> Signal<RequestWebViewResult, RequestWebViewError> {
|
||||
return _internal_requestSimpleWebView(postbox: self.account.postbox, network: self.account.network, botId: botId, url: url, source: source, themeParams: themeParams)
|
||||
}
|
||||
|
||||
public func requestAppWebView(peerId: PeerId, appReference: BotAppReference, payload: String?, themeParams: [String: Any]?, allowWrite: Bool) -> Signal<String, RequestAppWebViewError> {
|
||||
return _internal_requestAppWebView(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, appReference: appReference, payload: payload, themeParams: themeParams, allowWrite: allowWrite)
|
||||
public func requestAppWebView(peerId: PeerId, appReference: BotAppReference, payload: String?, themeParams: [String: Any]?, compact: Bool, allowWrite: Bool) -> Signal<RequestWebViewResult, RequestWebViewError> {
|
||||
return _internal_requestAppWebView(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, appReference: appReference, payload: payload, themeParams: themeParams, compact: compact, allowWrite: allowWrite)
|
||||
}
|
||||
|
||||
public func sendWebViewData(botId: PeerId, buttonText: String, data: String) -> Signal<Never, SendWebViewDataError> {
|
||||
|
@ -17,6 +17,7 @@ swift_library(
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/WallpaperBackgroundNode",
|
||||
"//submodules/UrlHandling",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -7,6 +7,7 @@ import Display
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import WallpaperBackgroundNode
|
||||
import UrlHandling
|
||||
|
||||
private let titleFont = Font.medium(16.0)
|
||||
|
||||
@ -178,7 +179,9 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
||||
case .text:
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingMessageIconImage : graphics.chatBubbleActionButtonOutgoingMessageIconImage
|
||||
case let .url(value):
|
||||
if value.lowercased().contains("?startgroup=") {
|
||||
if isTelegramMeLink(value), let internalUrl = parseFullInternalUrl(sharedContext: context.sharedContext, url: value), case .peer(_, .appStart) = internalUrl {
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingWebAppIconImage : graphics.chatBubbleActionButtonOutgoingWebAppIconImage
|
||||
} else if value.lowercased().contains("?startgroup=") {
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingAddToChatIconImage : graphics.chatBubbleActionButtonOutgoingAddToChatIconImage
|
||||
} else {
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLinkIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage
|
||||
|
@ -27,10 +27,12 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
final class Item {
|
||||
let id: AnyHashable
|
||||
let controller: ViewController
|
||||
let beforeMaximize: (NavigationController, @escaping () -> Void) -> Void
|
||||
|
||||
init(id: AnyHashable, controller: ViewController) {
|
||||
init(id: AnyHashable, controller: ViewController, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void) {
|
||||
self.id = id
|
||||
self.controller = controller
|
||||
self.beforeMaximize = beforeMaximize
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,6 +304,8 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
private var dismissingItemId: AnyHashable?
|
||||
private var dismissingItemOffset: CGFloat?
|
||||
|
||||
private var expandedTapGestureRecoginzer: UITapGestureRecognizer?
|
||||
|
||||
private var currentTransition: Transition?
|
||||
private var isApplyingTransition = false
|
||||
private var validLayout: ContainerViewLayout?
|
||||
@ -370,6 +374,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate
|
||||
panGestureRecognizer.delaysTouchesBegan = true
|
||||
self.scrollView.addGestureRecognizer(panGestureRecognizer)
|
||||
|
||||
let expandedTapGestureRecoginzer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
||||
expandedTapGestureRecoginzer.isEnabled = false
|
||||
self.expandedTapGestureRecoginzer = expandedTapGestureRecoginzer
|
||||
self.scrollView.addGestureRecognizer(expandedTapGestureRecoginzer)
|
||||
}
|
||||
|
||||
func item(at y: CGFloat) -> Int? {
|
||||
@ -401,6 +410,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return false
|
||||
}
|
||||
|
||||
@objc func tapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||
guard self.isExpanded else {
|
||||
return
|
||||
}
|
||||
if let result = self.scrollView.hitTest(gestureRecognizer.location(in: self.scrollView), with: nil), result === self.scrollView {
|
||||
self.collapse()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||
if self.isExpanded {
|
||||
self.dismissPanGesture(gestureRecognizer)
|
||||
@ -483,10 +501,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return result
|
||||
}
|
||||
|
||||
public func addController(_ viewController: ViewController, transition: ContainedViewLayoutTransition) {
|
||||
public func addController(_ viewController: ViewController, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void, transition: ContainedViewLayoutTransition) {
|
||||
let item = Item(
|
||||
id: AnyHashable(Int64.random(in: Int64.min ... Int64.max)),
|
||||
controller: viewController
|
||||
controller: viewController,
|
||||
beforeMaximize: beforeMaximize
|
||||
)
|
||||
self.items.append(item)
|
||||
|
||||
@ -552,7 +571,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return
|
||||
}
|
||||
if self.items.count == 1, let item = self.items.first {
|
||||
self.navigationController?.maximizeViewController(item.controller, animated: true)
|
||||
if let navigationController = self.navigationController {
|
||||
item.beforeMaximize(navigationController, { [weak self] in
|
||||
self?.navigationController?.maximizeViewController(item.controller, animated: true)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
self.isExpanded = true
|
||||
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
|
||||
@ -697,7 +720,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return
|
||||
}
|
||||
if self.isExpanded {
|
||||
self.navigationController?.maximizeViewController(item.controller, animated: true)
|
||||
if let navigationController = self.navigationController {
|
||||
itemNode.item.beforeMaximize(navigationController, { [weak self] in
|
||||
self?.navigationController?.maximizeViewController(item.controller, animated: true)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
self.expand()
|
||||
}
|
||||
@ -816,6 +843,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
}
|
||||
self.scrollView.passthrough = !self.isExpanded
|
||||
self.scrollView.isScrollEnabled = self.isExpanded
|
||||
self.expandedTapGestureRecoginzer?.isEnabled = self.isExpanded
|
||||
|
||||
if let currentTransition = self.currentTransition {
|
||||
self.isApplyingTransition = true
|
||||
@ -904,28 +932,33 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
||||
return
|
||||
}
|
||||
if self.items.count == 1 {
|
||||
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value {
|
||||
let dimView = UIView()
|
||||
dimView.frame = CGRect(origin: .zero, size: layout.size)
|
||||
dimView.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
|
||||
self.view.insertSubview(dimView, aboveSubview: self.blurView)
|
||||
dimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
|
||||
itemNode.animateOut()
|
||||
transition.updateTransform(node: itemNode, transform: CATransform3DIdentity)
|
||||
transition.updatePosition(node: itemNode, position: CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0 + topInset + self.scrollView.contentOffset.y), completion: { _ in
|
||||
self.isApplyingTransition = false
|
||||
if self.currentTransition == currentTransition {
|
||||
self.currentTransition = nil
|
||||
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value, let navigationController = self.navigationController {
|
||||
itemNode.item.beforeMaximize(navigationController, { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
completion(currentTransition)
|
||||
self.itemNodes[itemId] = nil
|
||||
itemNode.removeFromSupernode()
|
||||
dimView.removeFromSuperview()
|
||||
let dimView = UIView()
|
||||
dimView.frame = CGRect(origin: .zero, size: layout.size)
|
||||
dimView.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
|
||||
self.view.insertSubview(dimView, aboveSubview: self.blurView)
|
||||
dimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
|
||||
self.navigationController?.maximizeViewController(itemNode.item.controller, animated: false)
|
||||
|
||||
self.requestUpdate(transition: .immediate)
|
||||
itemNode.animateOut()
|
||||
transition.updateTransform(node: itemNode, transform: CATransform3DIdentity)
|
||||
transition.updatePosition(node: itemNode, position: CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0 + topInset + self.scrollView.contentOffset.y), completion: { _ in
|
||||
self.isApplyingTransition = false
|
||||
if self.currentTransition == currentTransition {
|
||||
self.currentTransition = nil
|
||||
}
|
||||
completion(currentTransition)
|
||||
self.itemNodes[itemId] = nil
|
||||
itemNode.removeFromSupernode()
|
||||
dimView.removeFromSuperview()
|
||||
|
||||
self.navigationController?.maximizeViewController(itemNode.item.controller, animated: false)
|
||||
|
||||
self.requestUpdate(transition: .immediate)
|
||||
})
|
||||
})
|
||||
}
|
||||
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y))
|
||||
|
@ -5312,7 +5312,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
return
|
||||
}
|
||||
|
||||
let params = WebAppParameters(source: .settings, peerId: self.context.account.peerId, botId: bot.peer.id, botName: bot.peer.compactDisplayTitle, url: nil, queryId: nil, payload: nil, buttonText: nil, keepAliveSignal: nil, forceHasSettings: bot.flags.contains(.hasSettings))
|
||||
let params = WebAppParameters(source: .settings, peerId: self.context.account.peerId, botId: bot.peer.id, botName: bot.peer.compactDisplayTitle, url: nil, queryId: nil, payload: nil, buttonText: nil, keepAliveSignal: nil, forceHasSettings: bot.flags.contains(.hasSettings), fullSize: true)
|
||||
let controller = standaloneWebAppController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, params: params, threadId: nil, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url: url, concealed: concealed, external: false, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { _, _, _ in
|
||||
|
@ -1808,7 +1808,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
//TODO:gift controller
|
||||
break
|
||||
case let .app(bot):
|
||||
let params = WebAppParameters(source: .attachMenu, peerId: peer.id, botId: bot.peer.id, botName: bot.shortName, url: nil, queryId: nil, payload: nil, buttonText: nil, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let params = WebAppParameters(source: .attachMenu, peerId: peer.id, botId: bot.peer.id, botName: bot.shortName, url: nil, queryId: nil, payload: nil, buttonText: nil, keepAliveSignal: nil, forceHasSettings: false, fullSize: true)
|
||||
let theme = component.theme
|
||||
let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>) = (component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: theme), component.context.sharedContext.presentationData |> map { $0.withUpdated(theme: theme) })
|
||||
let controller = WebAppController(context: component.context, updatedPresentationData: updatedPresentationData, params: params, replyToMessageId: nil, threadId: nil)
|
||||
|
@ -10,8 +10,9 @@ import AttachmentUI
|
||||
import AccountContext
|
||||
import TelegramNotices
|
||||
import PresentationDataUtils
|
||||
import UndoUI
|
||||
|
||||
extension ChatControllerImpl {
|
||||
public extension ChatControllerImpl {
|
||||
func openWebApp(buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource) {
|
||||
guard let peerId = self.chatLocation.peerId, let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
@ -76,14 +77,7 @@ extension ChatControllerImpl {
|
||||
if source == .menu {
|
||||
self.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||
return state.updatedForceInputCommandsHidden(true)
|
||||
// return state.updatedShowWebView(true).updatedForceInputCommandsHidden(true)
|
||||
}
|
||||
|
||||
if let currentMenuWebAppController = self.currentMenuWebAppController {
|
||||
if currentMenuWebAppController.isMinimized {
|
||||
(currentMenuWebAppController.navigationController as? NavigationController)?.maximizeViewController(currentMenuWebAppController, animated: true)
|
||||
return
|
||||
}
|
||||
// return state.updatedShowWebView(true).updatedForceInputCommandsHidden(true)
|
||||
}
|
||||
|
||||
if let navigationController = self.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
||||
@ -96,7 +90,7 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
let context = self.context
|
||||
let params = WebAppParameters(source: .menu, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let params = WebAppParameters(source: .menu, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: false)
|
||||
let controller = standaloneWebAppController(context: self.context, updatedPresentationData: self.updatedPresentationData, params: params, threadId: self.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
@ -146,7 +140,6 @@ extension ChatControllerImpl {
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
self.push(controller)
|
||||
self.currentMenuWebAppController = controller
|
||||
} else if simple {
|
||||
var isInline = false
|
||||
var botId = peerId
|
||||
@ -163,12 +156,12 @@ extension ChatControllerImpl {
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] url in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: isInline ? .inline : .simple, peerId: peerId, botId: botId, botName: botName, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let params = WebAppParameters(source: isInline ? .inline : .simple, peerId: peerId, botId: botId, botName: botName, url: result.url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: result.flags.contains(.fullSize))
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
@ -209,7 +202,7 @@ extension ChatControllerImpl {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false)
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false, fullSize: result.flags.contains(.fullSize))
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, completion: { [weak self] in
|
||||
@ -250,4 +243,164 @@ extension ChatControllerImpl {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func presentBotApp(botApp: BotApp, botPeer: EnginePeer, payload: String?, compact: Bool, concealed: Bool = false, commit: @escaping () -> Void = {}) {
|
||||
guard let peerId = self.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
self.attachmentController?.dismiss(animated: true, completion: nil)
|
||||
|
||||
let openBotApp: (Bool, Bool) -> Void = { [weak self] allowWrite, justInstalled in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
commit()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if !$0.contains(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.append(.requestInProgress)
|
||||
return updatedContexts.sorted()
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
|
||||
let updateProgress = { [weak self] in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if let index = $0.firstIndex(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.remove(at: index)
|
||||
return updatedContexts
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let botAddress = botPeer.addressName ?? ""
|
||||
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestAppWebView(peerId: peerId, appReference: .id(id: botApp.id, accessHash: botApp.accessHash), payload: payload, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), compact: compact, allowWrite: allowWrite)
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: botPeer.id, botName: botApp.title, url: result.url, queryId: 0, payload: payload, buttonText: "", keepAliveSignal: nil, forceHasSettings: botApp.flags.contains(.hasSettings), fullSize: result.flags.contains(.fullSize))
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
|
||||
if justInstalled {
|
||||
let content: UndoOverlayContent = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(botPeer.compactDisplayTitle).string, timeout: 5.0, customUndoText: nil)
|
||||
controller.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: content, elevatedLayout: false, position: .top, action: { _ in return false }), in: .current)
|
||||
}
|
||||
}, 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 _ = combineLatest(
|
||||
queue: Queue.mainQueue(),
|
||||
ApplicationSpecificNotice.getBotGameNotice(accountManager: self.context.sharedContext.accountManager, peerId: botPeer.id),
|
||||
self.context.engine.messages.attachMenuBots(),
|
||||
self.context.engine.messages.getAttachMenuBot(botId: botPeer.id, cached: true)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<AttachMenuBot?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
).startStandalone(next: { [weak self] noticed, attachMenuBots, attachMenuBot in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var isAttachMenuBotInstalled: Bool?
|
||||
if let _ = attachMenuBot {
|
||||
if let _ = attachMenuBots.first(where: { $0.peer.id == botPeer.id && !$0.flags.contains(.notActivated) }) {
|
||||
isAttachMenuBotInstalled = true
|
||||
} else {
|
||||
isAttachMenuBotInstalled = false
|
||||
}
|
||||
}
|
||||
|
||||
let context = self.context
|
||||
if !noticed || botApp.flags.contains(.notActivated) || isAttachMenuBotInstalled == false {
|
||||
if let isAttachMenuBotInstalled, let attachMenuBot {
|
||||
if !isAttachMenuBotInstalled {
|
||||
let controller = webAppTermsAlertController(context: context, updatedPresentationData: self.updatedPresentationData, bot: attachMenuBot, completion: { allowWrite in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
let _ = (context.engine.messages.addBotToAttachMenu(botId: botPeer.id, allowWrite: allowWrite)
|
||||
|> deliverOnMainQueue).startStandalone(error: { _ in
|
||||
}, completed: {
|
||||
openBotApp(allowWrite, true)
|
||||
})
|
||||
})
|
||||
self.present(controller, in: .window(.root))
|
||||
} else {
|
||||
openBotApp(false, false)
|
||||
}
|
||||
} else {
|
||||
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: self.updatedPresentationData, peer: botPeer, requestWriteAccess: botApp.flags.contains(.notActivated) && botApp.flags.contains(.requiresWriteAccess), completion: { allowWrite in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
openBotApp(allowWrite, false)
|
||||
}, showMore: { [weak self] in
|
||||
if let self {
|
||||
self.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
||||
}
|
||||
})
|
||||
self.present(controller, in: .window(.root))
|
||||
}
|
||||
} else {
|
||||
openBotApp(false, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +525,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||
|
||||
weak var attachmentController: AttachmentController?
|
||||
weak var currentMenuWebAppController: ViewController?
|
||||
weak var currentWebAppController: ViewController?
|
||||
|
||||
weak var currentImportMessageTooltip: UndoOverlayController?
|
||||
@ -7917,166 +7916,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.presentAttachmentMenu(subject: .bot(id: botId, payload: payload, justInstalled: justInstalled))
|
||||
}
|
||||
|
||||
public func presentBotApp(botApp: BotApp, botPeer: EnginePeer, payload: String?, concealed: Bool = false, commit: @escaping () -> Void = {}) {
|
||||
guard let peerId = self.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
self.attachmentController?.dismiss(animated: true, completion: nil)
|
||||
|
||||
let openBotApp: (Bool, Bool) -> Void = { [weak self] allowWrite, justInstalled in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
commit()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if !$0.contains(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.append(.requestInProgress)
|
||||
return updatedContexts.sorted()
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
|
||||
let updateProgress = { [weak self] in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||
return $0.updatedTitlePanelContext {
|
||||
if let index = $0.firstIndex(where: {
|
||||
switch $0 {
|
||||
case .requestInProgress:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
var updatedContexts = $0
|
||||
updatedContexts.remove(at: index)
|
||||
return updatedContexts
|
||||
}
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let botAddress = botPeer.addressName ?? ""
|
||||
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestAppWebView(peerId: peerId, appReference: .id(id: botApp.id, accessHash: botApp.accessHash), payload: payload, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), allowWrite: allowWrite)
|
||||
|> afterDisposed {
|
||||
updateProgress()
|
||||
})
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] url in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let params = WebAppParameters(source: .generic, peerId: peerId, botId: botPeer.id, botName: botApp.title, url: url, queryId: 0, payload: payload, buttonText: "", keepAliveSignal: nil, forceHasSettings: botApp.flags.contains(.hasSettings))
|
||||
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, threadId: strongSelf.chatLocation.threadId, openUrl: { [weak self] url, concealed, commit in
|
||||
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||
if let strongSelf = self {
|
||||
if let chatTypes {
|
||||
let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: chatTypes, hasContactSelector: false, hasCreation: false))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
if let strongSelf = self {
|
||||
completion()
|
||||
controller?.dismiss()
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peer.id, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
} else {
|
||||
strongSelf.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
||||
}
|
||||
}
|
||||
}, completion: { [weak self] in
|
||||
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}, getNavigationController: { [weak self] in
|
||||
return self?.effectiveNavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.currentWebAppController = controller
|
||||
strongSelf.push(controller)
|
||||
|
||||
if justInstalled {
|
||||
let content: UndoOverlayContent = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(botPeer.compactDisplayTitle).string, timeout: 5.0, customUndoText: nil)
|
||||
controller.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: content, elevatedLayout: false, position: .top, action: { _ in return false }), in: .current)
|
||||
}
|
||||
}, 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 _ = combineLatest(
|
||||
queue: Queue.mainQueue(),
|
||||
ApplicationSpecificNotice.getBotGameNotice(accountManager: self.context.sharedContext.accountManager, peerId: botPeer.id),
|
||||
self.context.engine.messages.attachMenuBots(),
|
||||
self.context.engine.messages.getAttachMenuBot(botId: botPeer.id, cached: true)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<AttachMenuBot?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
).startStandalone(next: { [weak self] value, attachMenuBots, attachMenuBot in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var isAttachMenuBotInstalled: Bool?
|
||||
if let _ = attachMenuBot {
|
||||
if let _ = attachMenuBots.first(where: { $0.peer.id == botPeer.id && !$0.flags.contains(.notActivated) }) {
|
||||
isAttachMenuBotInstalled = true
|
||||
} else {
|
||||
isAttachMenuBotInstalled = false
|
||||
}
|
||||
}
|
||||
|
||||
let context = self.context
|
||||
if !value || concealed || botApp.flags.contains(.notActivated) || isAttachMenuBotInstalled == false {
|
||||
if let isAttachMenuBotInstalled, let attachMenuBot {
|
||||
if !isAttachMenuBotInstalled {
|
||||
let controller = webAppTermsAlertController(context: context, updatedPresentationData: self.updatedPresentationData, bot: attachMenuBot, completion: { allowWrite in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
let _ = (context.engine.messages.addBotToAttachMenu(botId: botPeer.id, allowWrite: allowWrite)
|
||||
|> deliverOnMainQueue).startStandalone(error: { _ in
|
||||
}, completed: {
|
||||
openBotApp(allowWrite, true)
|
||||
})
|
||||
})
|
||||
self.present(controller, in: .window(.root))
|
||||
} else {
|
||||
openBotApp(false, false)
|
||||
}
|
||||
} else {
|
||||
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: self.updatedPresentationData, peer: botPeer, requestWriteAccess: botApp.flags.contains(.notActivated) && botApp.flags.contains(.requiresWriteAccess), completion: { allowWrite in
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||
openBotApp(allowWrite, false)
|
||||
}, showMore: { [weak self] in
|
||||
if let self {
|
||||
self.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
||||
}
|
||||
})
|
||||
self.present(controller, in: .window(.root))
|
||||
}
|
||||
} else {
|
||||
openBotApp(false, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func displayPollSolution(solution: TelegramMediaPollResults.Solution, sourceNode: ASDisplayNode, isAutomatic: Bool) {
|
||||
var maybeFoundItemNode: ChatMessageItemView?
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
@ -9305,7 +9144,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId.id))
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
||||
if let strongSelf = self, let peer {
|
||||
strongSelf.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, concealed: concealed, commit: {
|
||||
strongSelf.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, compact: botAppStart.compact, concealed: concealed, commit: {
|
||||
dismissWebAppControllers()
|
||||
commit()
|
||||
})
|
||||
|
@ -615,7 +615,7 @@ extension ChatControllerImpl {
|
||||
payload = botPayload
|
||||
fromAttachMenu = false
|
||||
}
|
||||
let params = WebAppParameters(source: fromAttachMenu ? .attachMenu : .generic, peerId: peer.id, botId: bot.peer.id, botName: bot.shortName, url: nil, queryId: nil, payload: payload, buttonText: nil, keepAliveSignal: nil, forceHasSettings: false)
|
||||
let params = WebAppParameters(source: fromAttachMenu ? .attachMenu : .generic, peerId: peer.id, botId: bot.peer.id, botName: bot.shortName, url: nil, queryId: nil, payload: payload, buttonText: nil, keepAliveSignal: nil, forceHasSettings: false, fullSize: false)
|
||||
let replyMessageSubject = strongSelf.presentationInterfaceState.interfaceState.replyMessageSubject
|
||||
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, replyToMessageId: replyMessageSubject?.messageId, threadId: strongSelf.chatLocation.threadId)
|
||||
controller.openUrl = { [weak self] url, concealed, commit in
|
||||
|
@ -165,7 +165,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
controller.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload, justInstalled: attachBotStart.justInstalled)
|
||||
}
|
||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload)
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, compact: botAppStart.compact)
|
||||
}
|
||||
params.setupController(controller)
|
||||
found = true
|
||||
@ -188,7 +188,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
}
|
||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
||||
Queue.mainQueue().after(0.1) {
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload)
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, compact: botAppStart.compact)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -196,7 +196,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
|
||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
||||
Queue.mainQueue().after(0.1) {
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload)
|
||||
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, compact: botAppStart.compact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public enum ParsedInternalPeerUrlParameter {
|
||||
case channelMessage(Int32, Double?)
|
||||
case replyThread(Int32, Int32)
|
||||
case voiceChat(String?)
|
||||
case appStart(String, String?)
|
||||
case appStart(String, String?, Bool)
|
||||
case story(Int32)
|
||||
case boost
|
||||
case text(String)
|
||||
@ -588,16 +588,19 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, query: String)
|
||||
} else if pathComponents.count == 2 {
|
||||
let appName = pathComponents[1]
|
||||
var startApp: String?
|
||||
var compact = false
|
||||
if let queryItems = components.queryItems {
|
||||
for queryItem in queryItems {
|
||||
if let value = queryItem.value {
|
||||
if queryItem.name == "startapp" {
|
||||
startApp = value
|
||||
} else if queryItem.name == "mode", value == "compact" {
|
||||
compact = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return .peer(.name(peerName), .appStart(appName, startApp))
|
||||
return .peer(.name(peerName), .appStart(appName, startApp, compact))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -713,7 +716,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .appStart(name, payload):
|
||||
case let .appStart(name, payload, compact):
|
||||
return .single(.progress) |> then(context.engine.messages.getBotApp(botId: peer.id, shortName: name, cached: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<BotApp?, NoError> in
|
||||
@ -721,7 +724,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
}
|
||||
|> mapToSignal { botApp -> Signal<ResolveInternalUrlResult, NoError> in
|
||||
if let botApp {
|
||||
return .single(.result(.peer(peer._asPeer(), .withBotApp(ChatControllerInitialBotAppStart(botApp: botApp, payload: payload, justInstalled: false)))))
|
||||
return .single(.result(.peer(peer._asPeer(), .withBotApp(ChatControllerInitialBotAppStart(botApp: botApp, payload: payload, justInstalled: false, compact: compact)))))
|
||||
} else {
|
||||
return .single(.result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))))
|
||||
}
|
||||
@ -1138,6 +1141,21 @@ public func parseAdUrl(sharedContext: SharedAccountContext, url: String) -> Pars
|
||||
return nil
|
||||
}
|
||||
|
||||
public func parseFullInternalUrl(sharedContext: SharedAccountContext, url: String) -> ParsedInternalUrl? {
|
||||
let schemes = ["http://", "https://", ""]
|
||||
for basePath in baseTelegramMePaths {
|
||||
for scheme in schemes {
|
||||
let basePrefix = scheme + basePath + "/"
|
||||
if url.lowercased().hasPrefix(basePrefix) {
|
||||
if let internalUrl = parseInternalUrl(sharedContext: sharedContext, query: String(url[basePrefix.endIndex...])) {
|
||||
return internalUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private struct UrlHandlingConfiguration {
|
||||
static var defaultValue: UrlHandlingConfiguration {
|
||||
return UrlHandlingConfiguration(domains: [], urlAuthDomains: [])
|
||||
|
@ -208,6 +208,7 @@ public struct WebAppParameters {
|
||||
let buttonText: String?
|
||||
let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||
let forceHasSettings: Bool
|
||||
let fullSize: Bool
|
||||
|
||||
public init(
|
||||
source: Source,
|
||||
@ -219,7 +220,8 @@ public struct WebAppParameters {
|
||||
payload: String?,
|
||||
buttonText: String?,
|
||||
keepAliveSignal: Signal<Never, KeepWebViewError>?,
|
||||
forceHasSettings: Bool
|
||||
forceHasSettings: Bool,
|
||||
fullSize: Bool
|
||||
) {
|
||||
self.source = source
|
||||
self.peerId = peerId
|
||||
@ -231,6 +233,7 @@ public struct WebAppParameters {
|
||||
self.buttonText = buttonText
|
||||
self.keepAliveSignal = keepAliveSignal
|
||||
self.forceHasSettings = forceHasSettings
|
||||
self.fullSize = fullSize
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +291,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
private let context: AccountContext
|
||||
var presentationData: PresentationData
|
||||
private var queryId: Int64?
|
||||
fileprivate let canMinimize = true
|
||||
|
||||
private var placeholderDisposable: Disposable?
|
||||
private var iconDisposable: Disposable?
|
||||
@ -306,7 +310,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
self.context = context
|
||||
self.controller = controller
|
||||
self.presentationData = controller.presentationData
|
||||
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.headerBackgroundNode = ASDisplayNode()
|
||||
self.topOverscrollNode = ASDisplayNode()
|
||||
@ -477,7 +481,8 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let parsedUrl = URL(string: result) {
|
||||
if let parsedUrl = URL(string: result.url) {
|
||||
strongSelf.queryId = result.queryId
|
||||
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
||||
}
|
||||
})
|
||||
@ -491,17 +496,19 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
strongSelf.queryId = result.queryId
|
||||
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
||||
|
||||
strongSelf.keepAliveDisposable = (result.keepAliveSignal
|
||||
|> deliverOnMainQueue).start(error: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.dismiss()
|
||||
}
|
||||
}, completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.completion()
|
||||
strongSelf.controller?.dismiss()
|
||||
}
|
||||
})
|
||||
if let keepAliveSignal = result.keepAliveSignal {
|
||||
strongSelf.keepAliveDisposable = (keepAliveSignal
|
||||
|> deliverOnMainQueue).start(error: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.dismiss()
|
||||
}
|
||||
}, completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.completion()
|
||||
strongSelf.controller?.dismiss()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -909,6 +916,11 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
case "web_app_open_link":
|
||||
if let json = json, let url = json["url"] as? String {
|
||||
let webAppConfiguration = WebAppConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
|
||||
if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: escapedUrl), let scheme = url.scheme?.lowercased(), !["http", "https"].contains(scheme) && !webAppConfiguration.allowedProtocols.contains(scheme) {
|
||||
return
|
||||
}
|
||||
|
||||
let tryInstantView = json["try_instant_view"] as? Bool ?? false
|
||||
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
||||
self.webView?.lastTouchTimestamp = nil
|
||||
@ -1877,6 +1889,25 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
}
|
||||
|
||||
public func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
||||
switch self.source {
|
||||
case .generic, .settings:
|
||||
completion()
|
||||
case .inline, .attachMenu, .menu, .simple:
|
||||
let _ = (self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId)
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] chatPeer in
|
||||
guard let self, let chatPeer else {
|
||||
return
|
||||
}
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(chatPeer), completion: { _ in
|
||||
completion()
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func updateNavigationBarTheme(transition: ContainedViewLayoutTransition) {
|
||||
let navigationBarPresentationData: NavigationBarPresentationData
|
||||
if let backgroundColor = self.controllerNode.headerColor, let textColor = self.controllerNode.headerPrimaryTextColor {
|
||||
@ -2095,6 +2126,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
public func shouldDismissImmediately() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate var canMinimize: Bool {
|
||||
return self.controllerNode.canMinimize
|
||||
}
|
||||
}
|
||||
|
||||
final class WebAppPickerContext: AttachmentMediaPickerContext {
|
||||
@ -2172,8 +2207,9 @@ public func standaloneWebAppController(
|
||||
willDismiss: @escaping () -> Void = {},
|
||||
didDismiss: @escaping () -> Void = {},
|
||||
getNavigationController: @escaping () -> NavigationController? = { return nil },
|
||||
getSourceRect: (() -> CGRect?)? = nil) -> ViewController {
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, makeEntityInputView: {
|
||||
getSourceRect: (() -> CGRect?)? = nil
|
||||
) -> ViewController {
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, isFullSize: params.fullSize, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
controller.requestController = { _, present in
|
||||
@ -2188,8 +2224,35 @@ public func standaloneWebAppController(
|
||||
controller.didDismiss = didDismiss
|
||||
controller.getSourceRect = getSourceRect
|
||||
controller.title = params.botName
|
||||
controller.shouldMinimizeOnSwipe = { _ in
|
||||
return true
|
||||
controller.shouldMinimizeOnSwipe = { [weak controller] _ in
|
||||
if let controller, let mainController = controller.mainController as? WebAppController {
|
||||
return mainController.canMinimize
|
||||
}
|
||||
return false
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
private struct WebAppConfiguration {
|
||||
static var defaultValue: WebAppConfiguration {
|
||||
return WebAppConfiguration(allowedProtocols: [])
|
||||
}
|
||||
|
||||
let allowedProtocols: [String]
|
||||
|
||||
fileprivate init(allowedProtocols: [String]) {
|
||||
self.allowedProtocols = allowedProtocols
|
||||
}
|
||||
|
||||
static func with(appConfiguration: AppConfiguration) -> WebAppConfiguration {
|
||||
if let data = appConfiguration.data {
|
||||
var allowedProtocols: [String] = []
|
||||
if let value = data["web_app_allowed_protocols"] as? [String] {
|
||||
allowedProtocols = value
|
||||
}
|
||||
return WebAppConfiguration(allowedProtocols: allowedProtocols)
|
||||
} else {
|
||||
return .defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user