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_NOTHEME" = "%1$@|disabled chat theme";
|
||||||
"PUSH_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@";
|
"PUSH_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@";
|
||||||
"CHAT_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_TEXT" = "%1$@|%2$@";
|
||||||
"PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message";
|
"PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message";
|
||||||
@ -138,6 +139,7 @@
|
|||||||
"PUSH_CHANNEL_ALBUM" = "%1$@|posted an album";
|
"PUSH_CHANNEL_ALBUM" = "%1$@|posted an album";
|
||||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_1" = "posted a file";
|
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_1" = "posted a file";
|
||||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_any" = "posted %d files";
|
"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_TEXT" = "%2$@|%1$@:%3$@";
|
||||||
"PUSH_CHAT_MESSAGE_NOTEXT" = "%2$@|%1$@ sent a message to the group";
|
"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_THEME" = "%1$@|set theme to %3$@ in the group %2$@";
|
||||||
"PUSH_CHAT_MESSAGE_NOTHEME" = "%1$@|disabled theme 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_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_TEXT" = "%1$@|pinned \"%2$@\" ";
|
||||||
"PUSH_PINNED_NOTEXT" = "%1$@|pinned a message";
|
"PUSH_PINNED_NOTEXT" = "%1$@|pinned a message";
|
||||||
@ -200,6 +203,7 @@
|
|||||||
"PUSH_PINNED_GAME" = "%1$@|pinned a game";
|
"PUSH_PINNED_GAME" = "%1$@|pinned a game";
|
||||||
"PUSH_PINNED_INVOICE" = "%1$@|pinned an invoice";
|
"PUSH_PINNED_INVOICE" = "%1$@|pinned an invoice";
|
||||||
"PUSH_PINNED_GIF" = "%1$@|pinned a GIF";
|
"PUSH_PINNED_GIF" = "%1$@|pinned a GIF";
|
||||||
|
"PUSH_PINNED_PAID_MEDIA" = "%1$@|pinned a paid post for %2$@";
|
||||||
|
|
||||||
"PUSH_CONTACT_JOINED" = "%1$@|joined Telegram!";
|
"PUSH_CONTACT_JOINED" = "%1$@|joined Telegram!";
|
||||||
|
|
||||||
@ -252,6 +256,7 @@
|
|||||||
"PUSH_CHAT_REACT_GAME" = "%2$@|%1$@ %3$@ to your game";
|
"PUSH_CHAT_REACT_GAME" = "%2$@|%1$@ %3$@ to your game";
|
||||||
"PUSH_CHAT_REACT_INVOICE" = "%2$@|%1$@ %3$@ to your invoice";
|
"PUSH_CHAT_REACT_INVOICE" = "%2$@|%1$@ %3$@ to your invoice";
|
||||||
"PUSH_CHAT_REACT_GIF" = "%2$@|%1$@ %3$@ to your GIF";
|
"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";
|
"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" = "%1$@|%2$@ to your story";
|
||||||
"PUSH_REACT_STORY_HIDDEN" = "New reaction to your story";
|
"PUSH_REACT_STORY_HIDDEN" = "New reaction to your story";
|
||||||
|
|
||||||
|
|
||||||
"LOCAL_MESSAGE_FWDS" = "%1$@ forwarded you %2$d messages";
|
"LOCAL_MESSAGE_FWDS" = "%1$@ forwarded you %2$d messages";
|
||||||
"LOCAL_CHANNEL_MESSAGE_FWDS" = "%1$@ posted %2$d forwarded messages";
|
"LOCAL_CHANNEL_MESSAGE_FWDS" = "%1$@ posted %2$d forwarded messages";
|
||||||
"LOCAL_CHAT_MESSAGE_FWDS" = "%1$@ forwarded %2$d messages";
|
"LOCAL_CHAT_MESSAGE_FWDS" = "%1$@ forwarded %2$d messages";
|
||||||
|
@ -295,11 +295,13 @@ public struct ChatControllerInitialBotAppStart {
|
|||||||
public let botApp: BotApp
|
public let botApp: BotApp
|
||||||
public let payload: String?
|
public let payload: String?
|
||||||
public let justInstalled: Bool
|
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.botApp = botApp
|
||||||
self.payload = payload
|
self.payload = payload
|
||||||
self.justInstalled = justInstalled
|
self.justInstalled = justInstalled
|
||||||
|
self.compact = compact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
private var isDismissed = false
|
private var isDismissed = false
|
||||||
private var isInteractiveDimissEnabled = true
|
private var isInteractiveDimissEnabled = true
|
||||||
|
|
||||||
|
private let isFullSize: Bool
|
||||||
public private(set) var isExpanded = false
|
public private(set) var isExpanded = false
|
||||||
|
|
||||||
private var validLayout: (layout: ContainerViewLayout, controllers: [AttachmentContainable], coveredByModalTransition: CGFloat)?
|
private var validLayout: (layout: ContainerViewLayout, controllers: [AttachmentContainable], coveredByModalTransition: CGFloat)?
|
||||||
@ -72,7 +73,12 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
var isPanGestureEnabled: (() -> Bool)?
|
var isPanGestureEnabled: (() -> Bool)?
|
||||||
var onExpandAnimationCompleted: () -> Void = {}
|
var onExpandAnimationCompleted: () -> Void = {}
|
||||||
|
|
||||||
override init() {
|
init(isFullSize: Bool) {
|
||||||
|
self.isFullSize = isFullSize
|
||||||
|
if isFullSize {
|
||||||
|
self.isExpanded = true
|
||||||
|
}
|
||||||
|
|
||||||
self.wrappingNode = ASDisplayNode()
|
self.wrappingNode = ASDisplayNode()
|
||||||
self.clipNode = 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.cancelPanGesture()
|
||||||
self.requestDismiss?()
|
self.requestDismiss?()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounds = self.bounds
|
var bounds = self.bounds
|
||||||
if self.isExpanded {
|
if self.isExpanded && !self.isFullSize {
|
||||||
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
||||||
} else {
|
} else {
|
||||||
bounds.origin.y = -translation
|
bounds.origin.y = -translation
|
||||||
@ -307,7 +313,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var bounds = self.bounds
|
var bounds = self.bounds
|
||||||
if self.isExpanded {
|
if self.isExpanded && !self.isFullSize {
|
||||||
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
bounds.origin.y = -max(0.0, translation - edgeTopInset)
|
||||||
} else {
|
} else {
|
||||||
bounds.origin.y = -translation
|
bounds.origin.y = -translation
|
||||||
@ -326,21 +332,29 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
|
|
||||||
var minimizing = false
|
var minimizing = false
|
||||||
var dismissing = 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 {
|
if self.interactivelyDismissed?(velocity.y) == true {
|
||||||
dismissing = true
|
dismissing = true
|
||||||
} else {
|
} else {
|
||||||
minimizing = true
|
minimizing = true
|
||||||
}
|
}
|
||||||
} else if self.isExpanded {
|
} 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
|
self.isExpanded = false
|
||||||
if let listNode = listNode {
|
if let listNode = listNode {
|
||||||
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
||||||
} else if let scrollView = scrollView {
|
} else if let scrollView = scrollView {
|
||||||
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: -scrollView.contentInset.top), animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
let distance = topInset - offset
|
let distance = topInset - offset
|
||||||
let initialVelocity: CGFloat = distance.isZero ? 0.0 : abs(velocity.y / distance)
|
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))
|
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
|
self.isUpdatingState = true
|
||||||
|
|
||||||
|
let isFirstTime = self.validLayout == nil
|
||||||
self.validLayout = (layout, controllers, coveredByModalTransition)
|
self.validLayout = (layout, controllers, coveredByModalTransition)
|
||||||
|
|
||||||
self.panGestureRecognizer?.isEnabled = (layout.inputHeight == nil || layout.inputHeight == 0.0)
|
self.panGestureRecognizer?.isEnabled = (layout.inputHeight == nil || layout.inputHeight == 0.0)
|
||||||
@ -446,7 +461,7 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let topInset: CGFloat
|
let topInset: CGFloat
|
||||||
if let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
if !self.isFullSize, let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
||||||
if effectiveExpanded {
|
if effectiveExpanded {
|
||||||
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
||||||
} else {
|
} else {
|
||||||
@ -459,9 +474,29 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
completion()
|
completion()
|
||||||
})
|
})
|
||||||
|
|
||||||
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / defaultTopInset)
|
let modalProgress: CGFloat
|
||||||
self.updateModalProgress?(modalProgress, topInset, self.bounds, transition)
|
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 containerLayout: ContainerViewLayout
|
||||||
let containerFrame: CGRect
|
let containerFrame: CGRect
|
||||||
let clipFrame: CGRect
|
let clipFrame: CGRect
|
||||||
|
@ -131,6 +131,8 @@ public protocol AttachmentContainable: ViewController {
|
|||||||
|
|
||||||
func requestDismiss(completion: @escaping () -> Void)
|
func requestDismiss(completion: @escaping () -> Void)
|
||||||
func shouldDismissImmediately() -> Bool
|
func shouldDismissImmediately() -> Bool
|
||||||
|
|
||||||
|
func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void)
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension AttachmentContainable {
|
public extension AttachmentContainable {
|
||||||
@ -154,6 +156,10 @@ public extension AttachmentContainable {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
||||||
|
completion()
|
||||||
|
}
|
||||||
|
|
||||||
var isPanGestureEnabled: (() -> Bool)? {
|
var isPanGestureEnabled: (() -> Bool)? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -234,6 +240,7 @@ public class AttachmentController: ViewController {
|
|||||||
private let initialButton: AttachmentButtonType
|
private let initialButton: AttachmentButtonType
|
||||||
private let fromMenu: Bool
|
private let fromMenu: Bool
|
||||||
private var hasTextInput: Bool
|
private var hasTextInput: Bool
|
||||||
|
private let isFullSize: Bool
|
||||||
private let makeEntityInputView: () -> AttachmentTextInputPanelInputView?
|
private let makeEntityInputView: () -> AttachmentTextInputPanelInputView?
|
||||||
public var animateAppearance: Bool = false
|
public var animateAppearance: Bool = false
|
||||||
|
|
||||||
@ -345,7 +352,7 @@ public class AttachmentController: ViewController {
|
|||||||
self.wrapperNode = ASDisplayNode()
|
self.wrapperNode = ASDisplayNode()
|
||||||
self.wrapperNode.clipsToBounds = true
|
self.wrapperNode.clipsToBounds = true
|
||||||
|
|
||||||
self.container = AttachmentContainer()
|
self.container = AttachmentContainer(isFullSize: controller.isFullSize)
|
||||||
self.container.canHaveKeyboardFocus = true
|
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 = AttachmentPanel(controller: controller, context: controller.context, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, updatedPresentationData: controller.updatedPresentationData, makeEntityInputView: makeEntityInputView)
|
||||||
self.panel.fromMenu = controller.fromMenu
|
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 {
|
guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else {
|
||||||
return
|
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?
|
let minimizedContainer: MinimizedContainerImpl?
|
||||||
if let current = current as? MinimizedContainerImpl {
|
if let current = current as? MinimizedContainerImpl {
|
||||||
minimizedContainer = current
|
minimizedContainer = current
|
||||||
@ -1062,7 +1075,7 @@ public class AttachmentController: ViewController {
|
|||||||
|
|
||||||
public var shouldMinimizeOnSwipe: ((AttachmentButtonType?) -> Bool)?
|
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.context = context
|
||||||
self.updatedPresentationData = updatedPresentationData
|
self.updatedPresentationData = updatedPresentationData
|
||||||
self.chatLocation = chatLocation
|
self.chatLocation = chatLocation
|
||||||
@ -1071,6 +1084,7 @@ public class AttachmentController: ViewController {
|
|||||||
self.initialButton = initialButton
|
self.initialButton = initialButton
|
||||||
self.fromMenu = fromMenu
|
self.fromMenu = fromMenu
|
||||||
self.hasTextInput = hasTextInput
|
self.hasTextInput = hasTextInput
|
||||||
|
self.isFullSize = isFullSize
|
||||||
self.makeEntityInputView = makeEntityInputView
|
self.makeEntityInputView = makeEntityInputView
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
|
@ -447,7 +447,9 @@ public class BrowserScreen: ViewController {
|
|||||||
guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else {
|
guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else {
|
||||||
return
|
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?
|
let minimizedContainer: MinimizedContainerImpl?
|
||||||
if let current = current as? MinimizedContainerImpl {
|
if let current = current as? MinimizedContainerImpl {
|
||||||
minimizedContainer = current
|
minimizedContainer = current
|
||||||
|
@ -8,7 +8,7 @@ public protocol MinimizedContainer: ASDisplayNode {
|
|||||||
|
|
||||||
var willMaximize: (() -> Void)? { get set }
|
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 maximizeController(_ viewController: ViewController, animated: Bool, completion: @escaping (Bool) -> Void)
|
||||||
func collapse()
|
func collapse()
|
||||||
func dismissAll(completion: @escaping () -> Void)
|
func dismissAll(completion: @escaping () -> Void)
|
||||||
|
@ -842,7 +842,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
if case .flat = navigationLayout.root, let minimizedContainer = self.minimizedContainer {
|
if case .flat = navigationLayout.root, let minimizedContainer = self.minimizedContainer {
|
||||||
if minimizedContainer.supernode !== self.displayNode {
|
if minimizedContainer.supernode !== self.displayNode {
|
||||||
if let rootContainer = self.rootContainer, case let .flat(flatContainer) = rootContainer {
|
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 {
|
} else {
|
||||||
self.displayNode.insertSubnode(minimizedContainer, at: 0)
|
self.displayNode.insertSubnode(minimizedContainer, at: 0)
|
||||||
}
|
}
|
||||||
@ -1572,7 +1576,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
self._viewControllersPromise.set(self.viewControllers)
|
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 transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.4, curve: .customSpring(damping: damping ?? 124.0, initialVelocity: velocity ?? 0.0)) : .immediate
|
||||||
|
|
||||||
let minimizedContainer = setupContainer(self.minimizedContainer)
|
let minimizedContainer = setupContainer(self.minimizedContainer)
|
||||||
@ -1592,7 +1596,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
}
|
}
|
||||||
viewController.isMinimized = true
|
viewController.isMinimized = true
|
||||||
self.filterController(viewController, animated: true)
|
self.filterController(viewController, animated: true)
|
||||||
minimizedContainer?.addController(viewController, transition: transition)
|
minimizedContainer?.addController(viewController, beforeMaximize: beforeMaximize, transition: transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var isMaximizing = false
|
private var isMaximizing = false
|
||||||
|
@ -485,6 +485,9 @@ final class NavigationModalContainer: ASDisplayNode, ASScrollViewDelegate, ASGes
|
|||||||
let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut)
|
let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut)
|
||||||
let positionTransition: 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)
|
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
|
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 {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
|
@ -54,7 +54,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[571523412] = { return $0.readDouble() }
|
dict[571523412] = { return $0.readDouble() }
|
||||||
dict[-1255641564] = { return parseString($0) }
|
dict[-1255641564] = { return parseString($0) }
|
||||||
dict[-1194283041] = { return Api.AccountDaysTTL.parse_accountDaysTTL($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[-653423106] = { return Api.AttachMenuBot.parse_attachMenuBot($0) }
|
||||||
dict[-1297663893] = { return Api.AttachMenuBotIcon.parse_attachMenuBotIcon($0) }
|
dict[-1297663893] = { return Api.AttachMenuBotIcon.parse_attachMenuBotIcon($0) }
|
||||||
dict[1165423600] = { return Api.AttachMenuBotIconColor.parse_attachMenuBotIconColor($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[859091184] = { return Api.InputSecureFile.parse_inputSecureFileUploaded($0) }
|
||||||
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
|
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
|
||||||
dict[482797855] = { return Api.InputSingleMedia.parse_inputSingleMedia($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[42402760] = { return Api.InputStickerSet.parse_inputStickerSetAnimatedEmoji($0) }
|
||||||
dict[215889721] = { return Api.InputStickerSet.parse_inputStickerSetAnimatedEmojiAnimations($0) }
|
dict[215889721] = { return Api.InputStickerSet.parse_inputStickerSetAnimatedEmojiAnimations($0) }
|
||||||
dict[-427863538] = { return Api.InputStickerSet.parse_inputStickerSetDice($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[-378127636] = { return Api.SendMessageAction.parse_sendMessageUploadVideoAction($0) }
|
||||||
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
||||||
dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($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[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
|
||||||
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
||||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($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[781501415] = { return Api.WebPageAttribute.parse_webPageAttributeStory($0) }
|
||||||
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
|
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
|
||||||
dict[211046684] = { return Api.WebViewMessageSent.parse_webViewMessageSent($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[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
|
||||||
dict[1275039392] = { return Api.account.Authorizations.parse_authorizations($0) }
|
dict[1275039392] = { return Api.account.Authorizations.parse_authorizations($0) }
|
||||||
dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($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[1035688326] = { return Api.auth.SentCodeType.parse_sentCodeTypeApp($0) }
|
||||||
dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) }
|
dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) }
|
||||||
dict[-196020837] = { return Api.auth.SentCodeType.parse_sentCodeTypeEmailCode($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[-1425815847] = { return Api.auth.SentCodeType.parse_sentCodeTypeFlashCall($0) }
|
||||||
dict[-648651719] = { return Api.auth.SentCodeType.parse_sentCodeTypeFragmentSms($0) }
|
dict[-648651719] = { return Api.auth.SentCodeType.parse_sentCodeTypeFragmentSms($0) }
|
||||||
dict[-2113903484] = { return Api.auth.SentCodeType.parse_sentCodeTypeMissedCall($0) }
|
dict[-2113903484] = { return Api.auth.SentCodeType.parse_sentCodeTypeMissedCall($0) }
|
||||||
@ -1437,8 +1436,6 @@ public extension Api {
|
|||||||
switch object {
|
switch object {
|
||||||
case let _1 as Api.AccountDaysTTL:
|
case let _1 as Api.AccountDaysTTL:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.AppWebViewResult:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.AttachMenuBot:
|
case let _1 as Api.AttachMenuBot:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.AttachMenuBotIcon:
|
case let _1 as Api.AttachMenuBotIcon:
|
||||||
@ -1749,6 +1746,8 @@ public extension Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputSingleMedia:
|
case let _1 as Api.InputSingleMedia:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.InputStarsTransaction:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputStickerSet:
|
case let _1 as Api.InputStickerSet:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputStickerSetItem:
|
case let _1 as Api.InputStickerSetItem:
|
||||||
@ -1979,8 +1978,6 @@ public extension Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.ShippingOption:
|
case let _1 as Api.ShippingOption:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.SimpleWebViewResult:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.SmsJob:
|
case let _1 as Api.SmsJob:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.SponsoredMessage:
|
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 {
|
public extension Api {
|
||||||
enum AttachMenuBot: TypeConstructorDescription {
|
enum AttachMenuBot: TypeConstructorDescription {
|
||||||
case attachMenuBot(flags: Int32, botId: Int64, shortName: String, peerTypes: [Api.AttachMenuPeerType]?, icons: [Api.AttachMenuBotIcon])
|
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 {
|
public extension Api {
|
||||||
enum InputStickerSet: TypeConstructorDescription {
|
enum InputStickerSet: TypeConstructorDescription {
|
||||||
case inputStickerSetAnimatedEmoji
|
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 {
|
public extension Api {
|
||||||
enum Invoice: TypeConstructorDescription {
|
enum Invoice: TypeConstructorDescription {
|
||||||
case invoice(flags: Int32, currency: String, prices: [Api.LabeledPrice], maxTipAmount: Int64?, suggestedTipAmounts: [Int64]?, termsUrl: String?)
|
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 {
|
public extension Api {
|
||||||
enum MaskCoords: TypeConstructorDescription {
|
enum MaskCoords: TypeConstructorDescription {
|
||||||
case maskCoords(n: Int32, x: Double, y: Double, zoom: Double)
|
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 {
|
public extension Api {
|
||||||
indirect enum BotCommandScope: TypeConstructorDescription {
|
indirect enum BotCommandScope: TypeConstructorDescription {
|
||||||
case botCommandScopeChatAdmins
|
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 {
|
public extension Api {
|
||||||
enum SmsJob: TypeConstructorDescription {
|
enum SmsJob: TypeConstructorDescription {
|
||||||
case smsJob(jobId: String, phoneNumber: String, text: String)
|
case smsJob(jobId: String, phoneNumber: String, text: String)
|
||||||
|
@ -160,15 +160,16 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum WebViewResult: TypeConstructorDescription {
|
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) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .webViewResultUrl(let queryId, let url):
|
case .webViewResultUrl(let flags, let queryId, let url):
|
||||||
if boxed {
|
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)
|
serializeString(url, buffer: buffer, boxed: false)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -176,20 +177,23 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .webViewResultUrl(let queryId, let url):
|
case .webViewResultUrl(let flags, let queryId, let url):
|
||||||
return ("webViewResultUrl", [("queryId", queryId as Any), ("url", url as Any)])
|
return ("webViewResultUrl", [("flags", flags as Any), ("queryId", queryId as Any), ("url", url as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? {
|
public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? {
|
||||||
var _1: Int64?
|
var _1: Int32?
|
||||||
_1 = reader.readInt64()
|
_1 = reader.readInt32()
|
||||||
var _2: String?
|
var _2: Int64?
|
||||||
_2 = parseString(reader)
|
if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt64() }
|
||||||
|
var _3: String?
|
||||||
|
_3 = parseString(reader)
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||||
if _c1 && _c2 {
|
let _c3 = _3 != nil
|
||||||
return Api.WebViewResult.webViewResultUrl(queryId: _1!, url: _2!)
|
if _c1 && _c2 && _c3 {
|
||||||
|
return Api.WebViewResult.webViewResultUrl(flags: _1!, queryId: _2, url: _3!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -589,7 +589,7 @@ public extension Api.auth {
|
|||||||
case sentCodeTypeApp(length: Int32)
|
case sentCodeTypeApp(length: Int32)
|
||||||
case sentCodeTypeCall(length: Int32)
|
case sentCodeTypeCall(length: Int32)
|
||||||
case sentCodeTypeEmailCode(flags: Int32, emailPattern: String, length: Int32, resetAvailablePeriod: Int32?, resetPendingDate: 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 sentCodeTypeFlashCall(pattern: String)
|
||||||
case sentCodeTypeFragmentSms(url: String, length: Int32)
|
case sentCodeTypeFragmentSms(url: String, length: Int32)
|
||||||
case sentCodeTypeMissedCall(prefix: 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 << 3) != 0 {serializeInt32(resetAvailablePeriod!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(resetPendingDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(resetPendingDate!, buffer: buffer, boxed: false)}
|
||||||
break
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(331943703)
|
buffer.appendInt32(10475318)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(nonce!, 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 << 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 {serializeString(receipt!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(pushTimeout!, 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)])
|
return ("sentCodeTypeCall", [("length", length as Any)])
|
||||||
case .sentCodeTypeEmailCode(let flags, let emailPattern, let length, let resetAvailablePeriod, let resetPendingDate):
|
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)])
|
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):
|
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), ("playIntegrityNonce", playIntegrityNonce as Any), ("receipt", receipt as Any), ("pushTimeout", pushTimeout as Any), ("length", length as Any)])
|
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):
|
case .sentCodeTypeFlashCall(let pattern):
|
||||||
return ("sentCodeTypeFlashCall", [("pattern", pattern as Any)])
|
return ("sentCodeTypeFlashCall", [("pattern", pattern as Any)])
|
||||||
case .sentCodeTypeFragmentSms(let url, let length):
|
case .sentCodeTypeFragmentSms(let url, let length):
|
||||||
@ -759,22 +760,25 @@ public extension Api.auth {
|
|||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
var _2: Buffer?
|
var _2: Buffer?
|
||||||
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
|
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
|
||||||
var _3: Buffer?
|
var _3: Int64?
|
||||||
if Int(_1!) & Int(1 << 2) != 0 {_3 = parseBytes(reader) }
|
if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt64() }
|
||||||
var _4: String?
|
var _4: Buffer?
|
||||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
if Int(_1!) & Int(1 << 2) != 0 {_4 = parseBytes(reader) }
|
||||||
var _5: Int32?
|
var _5: String?
|
||||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
||||||
var _6: Int32?
|
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 _c1 = _1 != nil
|
||||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != 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 _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||||
let _c6 = _6 != nil
|
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
let _c7 = _7 != nil
|
||||||
return Api.auth.SentCodeType.sentCodeTypeFirebaseSms(flags: _1!, nonce: _2, playIntegrityNonce: _3, receipt: _4, pushTimeout: _5, length: _6!)
|
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 {
|
else {
|
||||||
return nil
|
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 {
|
public extension Api {
|
||||||
enum BusinessLocation: TypeConstructorDescription {
|
enum BusinessLocation: TypeConstructorDescription {
|
||||||
case businessLocation(flags: Int32, geoPoint: Api.GeoPoint?, address: String)
|
case businessLocation(flags: Int32, geoPoint: Api.GeoPoint?, address: String)
|
||||||
|
@ -7308,20 +7308,20 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(-1940243652)
|
buffer.appendInt32(1398901710)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
app.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 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)}
|
||||||
serializeString(platform, buffer: buffer, boxed: false)
|
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)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.AppWebViewResult?
|
var result: Api.WebViewResult?
|
||||||
if let signature = reader.readInt32() {
|
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
|
return result
|
||||||
})
|
})
|
||||||
@ -7345,20 +7345,20 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(440815626)
|
buffer.appendInt32(1094336115)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
bot.serialize(buffer, true)
|
bot.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
|
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 << 4) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)}
|
||||||
serializeString(platform, buffer: buffer, boxed: false)
|
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)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.SimpleWebViewResult?
|
var result: Api.WebViewResult?
|
||||||
if let signature = reader.readInt32() {
|
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
|
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 {
|
public extension Api.functions.payments {
|
||||||
static func launchPrepaidGiveaway(peer: Api.InputPeer, giveawayId: Int64, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func launchPrepaidGiveaway(peer: Api.InputPeer, giveawayId: Int64, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
@ -274,7 +274,7 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
|
|||||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||||
return firebaseSecretStream
|
return firebaseSecretStream
|
||||||
|> map { mapping -> String? in
|
|> map { mapping -> String? in
|
||||||
guard let receipt = receipt else {
|
guard let receipt = receipt else {
|
||||||
@ -432,7 +432,7 @@ private func internalResendAuthorizationCode(accountManager: AccountManager<Tele
|
|||||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||||
return firebaseSecretStream
|
return firebaseSecretStream
|
||||||
|> map { mapping -> String? in
|
|> map { mapping -> String? in
|
||||||
guard let receipt = receipt else {
|
guard let receipt = receipt else {
|
||||||
@ -574,7 +574,7 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
|
|||||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = newType {
|
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = newType {
|
||||||
return firebaseSecretStream
|
return firebaseSecretStream
|
||||||
|> map { mapping -> String? in
|
|> map { mapping -> String? in
|
||||||
guard let receipt = receipt else {
|
guard let receipt = receipt else {
|
||||||
|
@ -36,7 +36,7 @@ extension SentAuthorizationCodeType {
|
|||||||
self = .emailSetupRequired(appleSignInAllowed: (flags & (1 << 0)) != 0)
|
self = .emailSetupRequired(appleSignInAllowed: (flags & (1 << 0)) != 0)
|
||||||
case let .sentCodeTypeFragmentSms(url, length):
|
case let .sentCodeTypeFragmentSms(url, length):
|
||||||
self = .fragment(url: url, length: length)
|
self = .fragment(url: url, length: length)
|
||||||
case let .sentCodeTypeFirebaseSms(_, _, _, _, pushTimeout, length):
|
case let .sentCodeTypeFirebaseSms(_, _, _, _, _, pushTimeout, length):
|
||||||
self = .firebase(pushTimeout: pushTimeout, length: length)
|
self = .firebase(pushTimeout: pushTimeout, length: length)
|
||||||
case let .sentCodeTypeSmsWord(_, beginning):
|
case let .sentCodeTypeSmsWord(_, beginning):
|
||||||
self = .word(startsWith: beginning)
|
self = .word(startsWith: beginning)
|
||||||
|
@ -72,7 +72,7 @@ func _internal_requestChangeAccountPhoneNumberVerification(account: Account, api
|
|||||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||||
return firebaseSecretStream
|
return firebaseSecretStream
|
||||||
|> map { mapping -> String? in
|
|> map { mapping -> String? in
|
||||||
guard let receipt = receipt else {
|
guard let receipt = receipt else {
|
||||||
@ -147,7 +147,7 @@ private func internalResendChangeAccountPhoneNumberVerification(account: Account
|
|||||||
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .sentCodeTypeFirebaseSms(_, _, _, receipt, pushTimeout, _) = type {
|
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
|
||||||
return firebaseSecretStream
|
return firebaseSecretStream
|
||||||
|> map { mapping -> String? in
|
|> map { mapping -> String? in
|
||||||
guard let receipt = receipt else {
|
guard let receipt = receipt else {
|
||||||
|
@ -16,16 +16,12 @@ public enum RequestSimpleWebViewSource {
|
|||||||
case settings
|
case settings
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RequestSimpleWebViewError {
|
func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> Signal<RequestWebViewResult, RequestWebViewError> {
|
||||||
case generic
|
|
||||||
}
|
|
||||||
|
|
||||||
func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: PeerId, url: String?, source: RequestSimpleWebViewSource, themeParams: [String: Any]?) -> Signal<String, RequestSimpleWebViewError> {
|
|
||||||
var serializedThemeParams: Api.DataJSON?
|
var serializedThemeParams: Api.DataJSON?
|
||||||
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
|
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
|
||||||
serializedThemeParams = .dataJSON(data: dataString)
|
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 {
|
guard let bot = transaction.getPeer(botId), let inputUser = apiInputUser(bot) else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
@ -46,17 +42,21 @@ func _internal_requestSimpleWebView(postbox: Postbox, network: Network, botId: P
|
|||||||
flags |= (1 << 3)
|
flags |= (1 << 3)
|
||||||
}
|
}
|
||||||
return network.request(Api.functions.messages.requestSimpleWebView(flags: flags, bot: inputUser, url: url, startParam: nil, themeParams: serializedThemeParams, platform: botWebViewPlatform))
|
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
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { result -> Signal<String, RequestSimpleWebViewError> in
|
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||||
switch result {
|
switch result {
|
||||||
case let .simpleWebViewResultUrl(url):
|
case let .webViewResultUrl(flags, queryId, url):
|
||||||
return .single(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
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,9 +65,24 @@ public enum KeepWebViewError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct RequestWebViewResult {
|
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 url: String
|
||||||
public let keepAliveSignal: Signal<Never, KeepWebViewError>
|
public let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RequestWebViewError {
|
public enum RequestWebViewError {
|
||||||
@ -166,8 +181,19 @@ func _internal_requestWebView(postbox: Postbox, network: Network, stateManager:
|
|||||||
}
|
}
|
||||||
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||||
switch result {
|
switch result {
|
||||||
case let .webViewResultUrl(queryId, url):
|
case let .webViewResultUrl(webViewFlags, 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)))
|
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
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum 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> {
|
||||||
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> {
|
|
||||||
var serializedThemeParams: Api.DataJSON?
|
var serializedThemeParams: Api.DataJSON?
|
||||||
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
|
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
|
||||||
serializedThemeParams = .dataJSON(data: dataString)
|
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 {
|
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
@ -235,19 +257,26 @@ func _internal_requestAppWebView(postbox: Postbox, network: Network, stateManage
|
|||||||
if allowWrite {
|
if allowWrite {
|
||||||
flags |= (1 << 0)
|
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))
|
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
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { result -> Signal<String, RequestAppWebViewError> in
|
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
|
||||||
switch result {
|
switch result {
|
||||||
case let .appWebViewResultUrl(url):
|
case let .webViewResultUrl(flags, queryId, url):
|
||||||
return .single(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
|
|> 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)
|
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)
|
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> {
|
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, allowWrite: allowWrite)
|
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> {
|
public func sendWebViewData(botId: PeerId, buttonText: String, data: String) -> Signal<Never, SendWebViewDataError> {
|
||||||
|
@ -17,6 +17,7 @@ swift_library(
|
|||||||
"//submodules/TelegramPresentationData",
|
"//submodules/TelegramPresentationData",
|
||||||
"//submodules/AccountContext",
|
"//submodules/AccountContext",
|
||||||
"//submodules/WallpaperBackgroundNode",
|
"//submodules/WallpaperBackgroundNode",
|
||||||
|
"//submodules/UrlHandling",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -7,6 +7,7 @@ import Display
|
|||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import WallpaperBackgroundNode
|
import WallpaperBackgroundNode
|
||||||
|
import UrlHandling
|
||||||
|
|
||||||
private let titleFont = Font.medium(16.0)
|
private let titleFont = Font.medium(16.0)
|
||||||
|
|
||||||
@ -178,7 +179,9 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
case .text:
|
case .text:
|
||||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingMessageIconImage : graphics.chatBubbleActionButtonOutgoingMessageIconImage
|
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingMessageIconImage : graphics.chatBubbleActionButtonOutgoingMessageIconImage
|
||||||
case let .url(value):
|
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
|
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingAddToChatIconImage : graphics.chatBubbleActionButtonOutgoingAddToChatIconImage
|
||||||
} else {
|
} else {
|
||||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLinkIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage
|
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLinkIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage
|
||||||
|
@ -27,10 +27,12 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
final class Item {
|
final class Item {
|
||||||
let id: AnyHashable
|
let id: AnyHashable
|
||||||
let controller: ViewController
|
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.id = id
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
self.beforeMaximize = beforeMaximize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +304,8 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
private var dismissingItemId: AnyHashable?
|
private var dismissingItemId: AnyHashable?
|
||||||
private var dismissingItemOffset: CGFloat?
|
private var dismissingItemOffset: CGFloat?
|
||||||
|
|
||||||
|
private var expandedTapGestureRecoginzer: UITapGestureRecognizer?
|
||||||
|
|
||||||
private var currentTransition: Transition?
|
private var currentTransition: Transition?
|
||||||
private var isApplyingTransition = false
|
private var isApplyingTransition = false
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
@ -370,6 +374,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate
|
panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate
|
||||||
panGestureRecognizer.delaysTouchesBegan = true
|
panGestureRecognizer.delaysTouchesBegan = true
|
||||||
self.scrollView.addGestureRecognizer(panGestureRecognizer)
|
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? {
|
func item(at y: CGFloat) -> Int? {
|
||||||
@ -401,6 +410,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
return false
|
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) {
|
@objc func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||||
if self.isExpanded {
|
if self.isExpanded {
|
||||||
self.dismissPanGesture(gestureRecognizer)
|
self.dismissPanGesture(gestureRecognizer)
|
||||||
@ -483,10 +501,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
return result
|
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(
|
let item = Item(
|
||||||
id: AnyHashable(Int64.random(in: Int64.min ... Int64.max)),
|
id: AnyHashable(Int64.random(in: Int64.min ... Int64.max)),
|
||||||
controller: viewController
|
controller: viewController,
|
||||||
|
beforeMaximize: beforeMaximize
|
||||||
)
|
)
|
||||||
self.items.append(item)
|
self.items.append(item)
|
||||||
|
|
||||||
@ -552,7 +571,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.items.count == 1, let item = self.items.first {
|
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 {
|
} else {
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
|
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
|
||||||
@ -697,7 +720,11 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.isExpanded {
|
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 {
|
} else {
|
||||||
self.expand()
|
self.expand()
|
||||||
}
|
}
|
||||||
@ -816,6 +843,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
}
|
}
|
||||||
self.scrollView.passthrough = !self.isExpanded
|
self.scrollView.passthrough = !self.isExpanded
|
||||||
self.scrollView.isScrollEnabled = self.isExpanded
|
self.scrollView.isScrollEnabled = self.isExpanded
|
||||||
|
self.expandedTapGestureRecoginzer?.isEnabled = self.isExpanded
|
||||||
|
|
||||||
if let currentTransition = self.currentTransition {
|
if let currentTransition = self.currentTransition {
|
||||||
self.isApplyingTransition = true
|
self.isApplyingTransition = true
|
||||||
@ -904,28 +932,33 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.items.count == 1 {
|
if self.items.count == 1 {
|
||||||
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value {
|
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value, let navigationController = self.navigationController {
|
||||||
let dimView = UIView()
|
itemNode.item.beforeMaximize(navigationController, { [weak self] in
|
||||||
dimView.frame = CGRect(origin: .zero, size: layout.size)
|
guard let self else {
|
||||||
dimView.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
|
return
|
||||||
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
|
|
||||||
}
|
}
|
||||||
completion(currentTransition)
|
let dimView = UIView()
|
||||||
self.itemNodes[itemId] = nil
|
dimView.frame = CGRect(origin: .zero, size: layout.size)
|
||||||
itemNode.removeFromSupernode()
|
dimView.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
|
||||||
dimView.removeFromSuperview()
|
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)
|
itemNode.animateOut()
|
||||||
|
transition.updateTransform(node: itemNode, transform: CATransform3DIdentity)
|
||||||
self.requestUpdate(transition: .immediate)
|
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))
|
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y))
|
||||||
|
@ -5312,7 +5312,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
return
|
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
|
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)
|
self?.openUrl(url: url, concealed: concealed, external: false, forceExternal: true, commit: commit)
|
||||||
}, requestSwitchInline: { _, _, _ in
|
}, requestSwitchInline: { _, _, _ in
|
||||||
|
@ -1808,7 +1808,7 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
//TODO:gift controller
|
//TODO:gift controller
|
||||||
break
|
break
|
||||||
case let .app(bot):
|
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 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 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)
|
let controller = WebAppController(context: component.context, updatedPresentationData: updatedPresentationData, params: params, replyToMessageId: nil, threadId: nil)
|
||||||
|
@ -10,8 +10,9 @@ import AttachmentUI
|
|||||||
import AccountContext
|
import AccountContext
|
||||||
import TelegramNotices
|
import TelegramNotices
|
||||||
import PresentationDataUtils
|
import PresentationDataUtils
|
||||||
|
import UndoUI
|
||||||
|
|
||||||
extension ChatControllerImpl {
|
public extension ChatControllerImpl {
|
||||||
func openWebApp(buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource) {
|
func openWebApp(buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource) {
|
||||||
guard let peerId = self.chatLocation.peerId, let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
guard let peerId = self.chatLocation.peerId, let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||||
return
|
return
|
||||||
@ -76,14 +77,7 @@ extension ChatControllerImpl {
|
|||||||
if source == .menu {
|
if source == .menu {
|
||||||
self.updateChatPresentationInterfaceState(interactive: false) { state in
|
self.updateChatPresentationInterfaceState(interactive: false) { state in
|
||||||
return state.updatedForceInputCommandsHidden(true)
|
return state.updatedForceInputCommandsHidden(true)
|
||||||
// return state.updatedShowWebView(true).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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let navigationController = self.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
if let navigationController = self.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
||||||
@ -96,7 +90,7 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let context = self.context
|
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
|
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)
|
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||||
@ -146,7 +140,6 @@ extension ChatControllerImpl {
|
|||||||
})
|
})
|
||||||
controller.navigationPresentation = .flatModal
|
controller.navigationPresentation = .flatModal
|
||||||
self.push(controller)
|
self.push(controller)
|
||||||
self.currentMenuWebAppController = controller
|
|
||||||
} else if simple {
|
} else if simple {
|
||||||
var isInline = false
|
var isInline = false
|
||||||
var botId = peerId
|
var botId = peerId
|
||||||
@ -163,12 +156,12 @@ extension ChatControllerImpl {
|
|||||||
|> afterDisposed {
|
|> afterDisposed {
|
||||||
updateProgress()
|
updateProgress()
|
||||||
})
|
})
|
||||||
|> deliverOnMainQueue).startStrict(next: { [weak self] url in
|
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let context = strongSelf.context
|
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
|
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)
|
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||||
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
}, requestSwitchInline: { [weak self] query, chatTypes, completion in
|
||||||
@ -209,7 +202,7 @@ extension ChatControllerImpl {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let context = strongSelf.context
|
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
|
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)
|
self?.openUrl(url, concealed: concealed, forceExternal: true, commit: commit)
|
||||||
}, completion: { [weak self] in
|
}, 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?>
|
let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||||
|
|
||||||
weak var attachmentController: AttachmentController?
|
weak var attachmentController: AttachmentController?
|
||||||
weak var currentMenuWebAppController: ViewController?
|
|
||||||
weak var currentWebAppController: ViewController?
|
weak var currentWebAppController: ViewController?
|
||||||
|
|
||||||
weak var currentImportMessageTooltip: UndoOverlayController?
|
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))
|
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) {
|
func displayPollSolution(solution: TelegramMediaPollResults.Solution, sourceNode: ASDisplayNode, isAutomatic: Bool) {
|
||||||
var maybeFoundItemNode: ChatMessageItemView?
|
var maybeFoundItemNode: ChatMessageItemView?
|
||||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
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))
|
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId.id))
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
||||||
if let strongSelf = self, let peer {
|
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()
|
dismissWebAppControllers()
|
||||||
commit()
|
commit()
|
||||||
})
|
})
|
||||||
|
@ -615,7 +615,7 @@ extension ChatControllerImpl {
|
|||||||
payload = botPayload
|
payload = botPayload
|
||||||
fromAttachMenu = false
|
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 replyMessageSubject = strongSelf.presentationInterfaceState.interfaceState.replyMessageSubject
|
||||||
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, params: params, replyToMessageId: replyMessageSubject?.messageId, threadId: strongSelf.chatLocation.threadId)
|
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
|
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)
|
controller.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload, justInstalled: attachBotStart.justInstalled)
|
||||||
}
|
}
|
||||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
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)
|
params.setupController(controller)
|
||||||
found = true
|
found = true
|
||||||
@ -188,7 +188,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
}
|
}
|
||||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
||||||
Queue.mainQueue().after(0.1) {
|
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 {
|
} else {
|
||||||
@ -196,7 +196,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
|
|
||||||
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
|
||||||
Queue.mainQueue().after(0.1) {
|
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 channelMessage(Int32, Double?)
|
||||||
case replyThread(Int32, Int32)
|
case replyThread(Int32, Int32)
|
||||||
case voiceChat(String?)
|
case voiceChat(String?)
|
||||||
case appStart(String, String?)
|
case appStart(String, String?, Bool)
|
||||||
case story(Int32)
|
case story(Int32)
|
||||||
case boost
|
case boost
|
||||||
case text(String)
|
case text(String)
|
||||||
@ -588,16 +588,19 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, query: String)
|
|||||||
} else if pathComponents.count == 2 {
|
} else if pathComponents.count == 2 {
|
||||||
let appName = pathComponents[1]
|
let appName = pathComponents[1]
|
||||||
var startApp: String?
|
var startApp: String?
|
||||||
|
var compact = false
|
||||||
if let queryItems = components.queryItems {
|
if let queryItems = components.queryItems {
|
||||||
for queryItem in queryItems {
|
for queryItem in queryItems {
|
||||||
if let value = queryItem.value {
|
if let value = queryItem.value {
|
||||||
if queryItem.name == "startapp" {
|
if queryItem.name == "startapp" {
|
||||||
startApp = value
|
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 {
|
} else {
|
||||||
return nil
|
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)
|
return .single(.progress) |> then(context.engine.messages.getBotApp(botId: peer.id, shortName: name, cached: false)
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<BotApp?, NoError> in
|
|> `catch` { _ -> Signal<BotApp?, NoError> in
|
||||||
@ -721,7 +724,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||||||
}
|
}
|
||||||
|> mapToSignal { botApp -> Signal<ResolveInternalUrlResult, NoError> in
|
|> mapToSignal { botApp -> Signal<ResolveInternalUrlResult, NoError> in
|
||||||
if let botApp {
|
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 {
|
} else {
|
||||||
return .single(.result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))))
|
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
|
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 {
|
private struct UrlHandlingConfiguration {
|
||||||
static var defaultValue: UrlHandlingConfiguration {
|
static var defaultValue: UrlHandlingConfiguration {
|
||||||
return UrlHandlingConfiguration(domains: [], urlAuthDomains: [])
|
return UrlHandlingConfiguration(domains: [], urlAuthDomains: [])
|
||||||
|
@ -208,6 +208,7 @@ public struct WebAppParameters {
|
|||||||
let buttonText: String?
|
let buttonText: String?
|
||||||
let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
let keepAliveSignal: Signal<Never, KeepWebViewError>?
|
||||||
let forceHasSettings: Bool
|
let forceHasSettings: Bool
|
||||||
|
let fullSize: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
source: Source,
|
source: Source,
|
||||||
@ -219,7 +220,8 @@ public struct WebAppParameters {
|
|||||||
payload: String?,
|
payload: String?,
|
||||||
buttonText: String?,
|
buttonText: String?,
|
||||||
keepAliveSignal: Signal<Never, KeepWebViewError>?,
|
keepAliveSignal: Signal<Never, KeepWebViewError>?,
|
||||||
forceHasSettings: Bool
|
forceHasSettings: Bool,
|
||||||
|
fullSize: Bool
|
||||||
) {
|
) {
|
||||||
self.source = source
|
self.source = source
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
@ -231,6 +233,7 @@ public struct WebAppParameters {
|
|||||||
self.buttonText = buttonText
|
self.buttonText = buttonText
|
||||||
self.keepAliveSignal = keepAliveSignal
|
self.keepAliveSignal = keepAliveSignal
|
||||||
self.forceHasSettings = forceHasSettings
|
self.forceHasSettings = forceHasSettings
|
||||||
|
self.fullSize = fullSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +291,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
var presentationData: PresentationData
|
var presentationData: PresentationData
|
||||||
private var queryId: Int64?
|
private var queryId: Int64?
|
||||||
|
fileprivate let canMinimize = true
|
||||||
|
|
||||||
private var placeholderDisposable: Disposable?
|
private var placeholderDisposable: Disposable?
|
||||||
private var iconDisposable: Disposable?
|
private var iconDisposable: Disposable?
|
||||||
@ -306,7 +310,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.context = context
|
self.context = context
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.presentationData = controller.presentationData
|
self.presentationData = controller.presentationData
|
||||||
|
|
||||||
self.backgroundNode = ASDisplayNode()
|
self.backgroundNode = ASDisplayNode()
|
||||||
self.headerBackgroundNode = ASDisplayNode()
|
self.headerBackgroundNode = ASDisplayNode()
|
||||||
self.topOverscrollNode = ASDisplayNode()
|
self.topOverscrollNode = ASDisplayNode()
|
||||||
@ -477,7 +481,8 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let parsedUrl = URL(string: result) {
|
if let parsedUrl = URL(string: result.url) {
|
||||||
|
strongSelf.queryId = result.queryId
|
||||||
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -491,17 +496,19 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
strongSelf.queryId = result.queryId
|
strongSelf.queryId = result.queryId
|
||||||
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
strongSelf.webView?.load(URLRequest(url: parsedUrl))
|
||||||
|
|
||||||
strongSelf.keepAliveDisposable = (result.keepAliveSignal
|
if let keepAliveSignal = result.keepAliveSignal {
|
||||||
|> deliverOnMainQueue).start(error: { [weak self] _ in
|
strongSelf.keepAliveDisposable = (keepAliveSignal
|
||||||
if let strongSelf = self {
|
|> deliverOnMainQueue).start(error: { [weak self] _ in
|
||||||
strongSelf.controller?.dismiss()
|
if let strongSelf = self {
|
||||||
}
|
strongSelf.controller?.dismiss()
|
||||||
}, completed: { [weak self] in
|
}
|
||||||
if let strongSelf = self {
|
}, completed: { [weak self] in
|
||||||
strongSelf.controller?.completion()
|
if let strongSelf = self {
|
||||||
strongSelf.controller?.dismiss()
|
strongSelf.controller?.completion()
|
||||||
}
|
strongSelf.controller?.dismiss()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -909,6 +916,11 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
case "web_app_open_link":
|
case "web_app_open_link":
|
||||||
if let json = json, let url = json["url"] as? String {
|
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
|
let tryInstantView = json["try_instant_view"] as? Bool ?? false
|
||||||
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
||||||
self.webView?.lastTouchTimestamp = nil
|
self.webView?.lastTouchTimestamp = nil
|
||||||
@ -1877,6 +1889,25 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.presentationDataDisposable?.dispose()
|
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) {
|
fileprivate func updateNavigationBarTheme(transition: ContainedViewLayoutTransition) {
|
||||||
let navigationBarPresentationData: NavigationBarPresentationData
|
let navigationBarPresentationData: NavigationBarPresentationData
|
||||||
if let backgroundColor = self.controllerNode.headerColor, let textColor = self.controllerNode.headerPrimaryTextColor {
|
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 {
|
public func shouldDismissImmediately() -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate var canMinimize: Bool {
|
||||||
|
return self.controllerNode.canMinimize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class WebAppPickerContext: AttachmentMediaPickerContext {
|
final class WebAppPickerContext: AttachmentMediaPickerContext {
|
||||||
@ -2172,8 +2207,9 @@ public func standaloneWebAppController(
|
|||||||
willDismiss: @escaping () -> Void = {},
|
willDismiss: @escaping () -> Void = {},
|
||||||
didDismiss: @escaping () -> Void = {},
|
didDismiss: @escaping () -> Void = {},
|
||||||
getNavigationController: @escaping () -> NavigationController? = { return nil },
|
getNavigationController: @escaping () -> NavigationController? = { return nil },
|
||||||
getSourceRect: (() -> CGRect?)? = nil) -> ViewController {
|
getSourceRect: (() -> CGRect?)? = nil
|
||||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, makeEntityInputView: {
|
) -> 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
|
return nil
|
||||||
})
|
})
|
||||||
controller.requestController = { _, present in
|
controller.requestController = { _, present in
|
||||||
@ -2188,8 +2224,35 @@ public func standaloneWebAppController(
|
|||||||
controller.didDismiss = didDismiss
|
controller.didDismiss = didDismiss
|
||||||
controller.getSourceRect = getSourceRect
|
controller.getSourceRect = getSourceRect
|
||||||
controller.title = params.botName
|
controller.title = params.botName
|
||||||
controller.shouldMinimizeOnSwipe = { _ in
|
controller.shouldMinimizeOnSwipe = { [weak controller] _ in
|
||||||
return true
|
if let controller, let mainController = controller.mainController as? WebAppController {
|
||||||
|
return mainController.canMinimize
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return controller
|
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