Web app improvements

This commit is contained in:
Ilya Laktyushin 2022-03-31 16:14:02 +04:00
parent 61039505b7
commit 51613e0185
23 changed files with 687 additions and 490 deletions

View File

@ -258,7 +258,7 @@ public enum ResolvedUrl {
case settings(ResolvedUrlSettingsSection)
case joinVoiceChat(PeerId, String?)
case importStickers
case setAttach(PeerId)
case startAttach(peerId: PeerId, payload: String?)
}
public enum NavigateToChatKeepStack {
@ -346,7 +346,7 @@ public final class NavigateToChatControllerParams {
public let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
public let subject: ChatControllerSubject?
public let botStart: ChatControllerInitialBotStart?
public let attachBotId: PeerId?
public let attachBotStart: ChatControllerInitialAttachBotStart?
public let updateTextInputState: ChatTextInputState?
public let activateInput: Bool
public let keepStack: NavigateToChatKeepStack
@ -365,7 +365,7 @@ public final class NavigateToChatControllerParams {
public let changeColors: Bool
public let completion: (ChatController) -> Void
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotId: PeerId? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, completion: @escaping (ChatController) -> Void = { _ in }) {
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, completion: @escaping (ChatController) -> Void = { _ in }) {
self.navigationController = navigationController
self.chatController = chatController
self.chatLocationContextHolder = chatLocationContextHolder
@ -373,7 +373,7 @@ public final class NavigateToChatControllerParams {
self.chatLocation = chatLocation
self.subject = subject
self.botStart = botStart
self.attachBotId = attachBotId
self.attachBotStart = attachBotStart
self.updateTextInputState = updateTextInputState
self.activateInput = activateInput
self.keepStack = keepStack

View File

@ -143,12 +143,22 @@ public struct ChatControllerInitialBotStart {
}
}
public struct ChatControllerInitialAttachBotStart {
public let botId: PeerId
public let payload: String?
public init(botId: PeerId, payload: String?) {
self.botId = botId
self.payload = payload
}
}
public enum ChatControllerInteractionNavigateToPeer {
case `default`
case chat(textInputState: ChatTextInputState?, subject: ChatControllerSubject?, peekData: ChatPeekTimeout?)
case info
case withBotStartPayload(ChatControllerInitialBotStart)
case withAttachBot(PeerId)
case withAttachBot(ChatControllerInitialAttachBotStart)
}
public struct ChatInterfaceForwardOptionsState: Codable, Equatable {

View File

@ -1248,9 +1248,9 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
if let navigationController = strongSelf.getNavigationController() {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), botStart: botStart, keepStack: .always))
}
case let .withAttachBot(botId):
case let .withAttachBot(attachBotStart):
if let navigationController = strongSelf.getNavigationController() {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotId: botId))
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
}
case .info:
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peerId)

View File

@ -45,7 +45,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[571523412] = { return $0.readDouble() }
dict[-1255641564] = { return parseString($0) }
dict[-1194283041] = { return Api.AccountDaysTTL.parse_accountDaysTTL($0) }
dict[1340016040] = { return Api.AttachMenuBot.parse_attachMenuBot($0) }
dict[-381896846] = { return Api.AttachMenuBot.parse_attachMenuBot($0) }
dict[-1297663893] = { return Api.AttachMenuBotIcon.parse_attachMenuBotIcon($0) }
dict[1165423600] = { return Api.AttachMenuBotIconColor.parse_attachMenuBotIconColor($0) }
dict[1011024320] = { return Api.AttachMenuBots.parse_attachMenuBots($0) }
dict[-237467044] = { return Api.AttachMenuBots.parse_attachMenuBotsNotModified($0) }
dict[-1816172929] = { return Api.AttachMenuBotsBot.parse_attachMenuBotsBot($0) }
@ -837,7 +839,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-981018084] = { return Api.WebPage.parse_webPagePending($0) }
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
dict[211046684] = { return Api.WebViewMessageSent.parse_webViewMessageSent($0) }
dict[-1312107643] = { return Api.WebViewResult.parse_webViewResultConfirmationRequired($0) }
dict[202659196] = { return Api.WebViewResult.parse_webViewResultUrl($0) }
dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
dict[1275039392] = { return Api.account.Authorizations.parse_authorizations($0) }
@ -1087,6 +1088,10 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.AttachMenuBot:
_1.serialize(buffer, boxed)
case let _1 as Api.AttachMenuBotIcon:
_1.serialize(buffer, boxed)
case let _1 as Api.AttachMenuBotIconColor:
_1.serialize(buffer, boxed)
case let _1 as Api.AttachMenuBots:
_1.serialize(buffer, boxed)
case let _1 as Api.AttachMenuBotsBot:

View File

@ -36,26 +36,30 @@ public extension Api {
}
public extension Api {
enum AttachMenuBot: TypeConstructorDescription {
case attachMenuBot(flags: Int32, botId: Int64, attachMenuName: String, attachMenuIcon: Api.Document)
case attachMenuBot(flags: Int32, botId: Int64, shortName: String, icons: [Api.AttachMenuBotIcon])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .attachMenuBot(let flags, let botId, let attachMenuName, let attachMenuIcon):
case .attachMenuBot(let flags, let botId, let shortName, let icons):
if boxed {
buffer.appendInt32(1340016040)
buffer.appendInt32(-381896846)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(botId, buffer: buffer, boxed: false)
serializeString(attachMenuName, buffer: buffer, boxed: false)
attachMenuIcon.serialize(buffer, true)
serializeString(shortName, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(icons.count))
for item in icons {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .attachMenuBot(let flags, let botId, let attachMenuName, let attachMenuIcon):
return ("attachMenuBot", [("flags", String(describing: flags)), ("botId", String(describing: botId)), ("attachMenuName", String(describing: attachMenuName)), ("attachMenuIcon", String(describing: attachMenuIcon))])
case .attachMenuBot(let flags, let botId, let shortName, let icons):
return ("attachMenuBot", [("flags", String(describing: flags)), ("botId", String(describing: botId)), ("shortName", String(describing: shortName)), ("icons", String(describing: icons))])
}
}
@ -66,16 +70,112 @@ public extension Api {
_2 = reader.readInt64()
var _3: String?
_3 = parseString(reader)
var _4: Api.Document?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Document
var _4: [Api.AttachMenuBotIcon]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AttachMenuBotIcon.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.AttachMenuBot.attachMenuBot(flags: _1!, botId: _2!, attachMenuName: _3!, attachMenuIcon: _4!)
return Api.AttachMenuBot.attachMenuBot(flags: _1!, botId: _2!, shortName: _3!, icons: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum AttachMenuBotIcon: TypeConstructorDescription {
case attachMenuBotIcon(flags: Int32, name: String, icon: Api.Document, colors: [Api.AttachMenuBotIconColor]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .attachMenuBotIcon(let flags, let name, let icon, let colors):
if boxed {
buffer.appendInt32(-1297663893)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(name, buffer: buffer, boxed: false)
icon.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(colors!.count))
for item in colors! {
item.serialize(buffer, true)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .attachMenuBotIcon(let flags, let name, let icon, let colors):
return ("attachMenuBotIcon", [("flags", String(describing: flags)), ("name", String(describing: name)), ("icon", String(describing: icon)), ("colors", String(describing: colors))])
}
}
public static func parse_attachMenuBotIcon(_ reader: BufferReader) -> AttachMenuBotIcon? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.Document?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Document
}
var _4: [Api.AttachMenuBotIconColor]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AttachMenuBotIconColor.self)
} }
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.AttachMenuBotIcon.attachMenuBotIcon(flags: _1!, name: _2!, icon: _3!, colors: _4)
}
else {
return nil
}
}
}
}
public extension Api {
enum AttachMenuBotIconColor: TypeConstructorDescription {
case attachMenuBotIconColor(name: String, color: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .attachMenuBotIconColor(let name, let color):
if boxed {
buffer.appendInt32(1165423600)
}
serializeString(name, buffer: buffer, boxed: false)
serializeInt32(color, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .attachMenuBotIconColor(let name, let color):
return ("attachMenuBotIconColor", [("name", String(describing: name)), ("color", String(describing: color))])
}
}
public static func parse_attachMenuBotIconColor(_ reader: BufferReader) -> AttachMenuBotIconColor? {
var _1: String?
_1 = parseString(reader)
var _2: Int32?
_2 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.AttachMenuBotIconColor.attachMenuBotIconColor(name: _1!, color: _2!)
}
else {
return nil
@ -1086,131 +1186,3 @@ public extension Api {
}
}
public extension Api {
enum BotInlineResult: TypeConstructorDescription {
case botInlineMediaResult(flags: Int32, id: String, type: String, photo: Api.Photo?, document: Api.Document?, title: String?, description: String?, sendMessage: Api.BotInlineMessage)
case botInlineResult(flags: Int32, id: String, type: String, title: String?, description: String?, url: String?, thumb: Api.WebDocument?, content: Api.WebDocument?, sendMessage: Api.BotInlineMessage)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .botInlineMediaResult(let flags, let id, let type, let photo, let document, let title, let description, let sendMessage):
if boxed {
buffer.appendInt32(400266251)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
serializeString(type, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {document!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
sendMessage.serialize(buffer, true)
break
case .botInlineResult(let flags, let id, let type, let title, let description, let url, let thumb, let content, let sendMessage):
if boxed {
buffer.appendInt32(295067450)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
serializeString(type, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {thumb!.serialize(buffer, true)}
if Int(flags) & Int(1 << 5) != 0 {content!.serialize(buffer, true)}
sendMessage.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .botInlineMediaResult(let flags, let id, let type, let photo, let document, let title, let description, let sendMessage):
return ("botInlineMediaResult", [("flags", String(describing: flags)), ("id", String(describing: id)), ("type", String(describing: type)), ("photo", String(describing: photo)), ("document", String(describing: document)), ("title", String(describing: title)), ("description", String(describing: description)), ("sendMessage", String(describing: sendMessage))])
case .botInlineResult(let flags, let id, let type, let title, let description, let url, let thumb, let content, let sendMessage):
return ("botInlineResult", [("flags", String(describing: flags)), ("id", String(describing: id)), ("type", String(describing: type)), ("title", String(describing: title)), ("description", String(describing: description)), ("url", String(describing: url)), ("thumb", String(describing: thumb)), ("content", String(describing: content)), ("sendMessage", String(describing: sendMessage))])
}
}
public static func parse_botInlineMediaResult(_ reader: BufferReader) -> BotInlineResult? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Api.Photo?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Photo
} }
var _5: Api.Document?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Document
} }
var _6: String?
if Int(_1!) & Int(1 << 2) != 0 {_6 = parseString(reader) }
var _7: String?
if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) }
var _8: Api.BotInlineMessage?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.BotInlineMessage
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
let _c8 = _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.BotInlineResult.botInlineMediaResult(flags: _1!, id: _2!, type: _3!, photo: _4, document: _5, title: _6, description: _7, sendMessage: _8!)
}
else {
return nil
}
}
public static func parse_botInlineResult(_ reader: BufferReader) -> BotInlineResult? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_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: Api.WebDocument?
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _8: Api.WebDocument?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _9: Api.BotInlineMessage?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.BotInlineMessage
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _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 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil
let _c9 = _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.BotInlineResult.botInlineResult(flags: _1!, id: _2!, type: _3!, title: _4, description: _5, url: _6, thumb: _7, content: _8, sendMessage: _9!)
}
else {
return nil
}
}
}
}

View File

@ -1,3 +1,131 @@
public extension Api {
enum BotInlineResult: TypeConstructorDescription {
case botInlineMediaResult(flags: Int32, id: String, type: String, photo: Api.Photo?, document: Api.Document?, title: String?, description: String?, sendMessage: Api.BotInlineMessage)
case botInlineResult(flags: Int32, id: String, type: String, title: String?, description: String?, url: String?, thumb: Api.WebDocument?, content: Api.WebDocument?, sendMessage: Api.BotInlineMessage)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .botInlineMediaResult(let flags, let id, let type, let photo, let document, let title, let description, let sendMessage):
if boxed {
buffer.appendInt32(400266251)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
serializeString(type, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {document!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
sendMessage.serialize(buffer, true)
break
case .botInlineResult(let flags, let id, let type, let title, let description, let url, let thumb, let content, let sendMessage):
if boxed {
buffer.appendInt32(295067450)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
serializeString(type, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {thumb!.serialize(buffer, true)}
if Int(flags) & Int(1 << 5) != 0 {content!.serialize(buffer, true)}
sendMessage.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .botInlineMediaResult(let flags, let id, let type, let photo, let document, let title, let description, let sendMessage):
return ("botInlineMediaResult", [("flags", String(describing: flags)), ("id", String(describing: id)), ("type", String(describing: type)), ("photo", String(describing: photo)), ("document", String(describing: document)), ("title", String(describing: title)), ("description", String(describing: description)), ("sendMessage", String(describing: sendMessage))])
case .botInlineResult(let flags, let id, let type, let title, let description, let url, let thumb, let content, let sendMessage):
return ("botInlineResult", [("flags", String(describing: flags)), ("id", String(describing: id)), ("type", String(describing: type)), ("title", String(describing: title)), ("description", String(describing: description)), ("url", String(describing: url)), ("thumb", String(describing: thumb)), ("content", String(describing: content)), ("sendMessage", String(describing: sendMessage))])
}
}
public static func parse_botInlineMediaResult(_ reader: BufferReader) -> BotInlineResult? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Api.Photo?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Photo
} }
var _5: Api.Document?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Document
} }
var _6: String?
if Int(_1!) & Int(1 << 2) != 0 {_6 = parseString(reader) }
var _7: String?
if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) }
var _8: Api.BotInlineMessage?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.BotInlineMessage
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
let _c8 = _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.BotInlineResult.botInlineMediaResult(flags: _1!, id: _2!, type: _3!, photo: _4, document: _5, title: _6, description: _7, sendMessage: _8!)
}
else {
return nil
}
}
public static func parse_botInlineResult(_ reader: BufferReader) -> BotInlineResult? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_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: Api.WebDocument?
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _8: Api.WebDocument?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _9: Api.BotInlineMessage?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.BotInlineMessage
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _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 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil
let _c9 = _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.BotInlineResult.botInlineResult(flags: _1!, id: _2!, type: _3!, title: _4, description: _5, url: _6, thumb: _7, content: _8, sendMessage: _9!)
}
else {
return nil
}
}
}
}
public extension Api {
enum CdnConfig: TypeConstructorDescription {
case cdnConfig(publicKeys: [Api.CdnPublicKey])

View File

@ -94,22 +94,10 @@ public extension Api {
}
public extension Api {
enum WebViewResult: TypeConstructorDescription {
case webViewResultConfirmationRequired(bot: Api.AttachMenuBot, users: [Api.User])
case webViewResultUrl(queryId: Int64, url: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .webViewResultConfirmationRequired(let bot, let users):
if boxed {
buffer.appendInt32(-1312107643)
}
bot.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
case .webViewResultUrl(let queryId, let url):
if boxed {
buffer.appendInt32(202659196)
@ -122,31 +110,11 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .webViewResultConfirmationRequired(let bot, let users):
return ("webViewResultConfirmationRequired", [("bot", String(describing: bot)), ("users", String(describing: users))])
case .webViewResultUrl(let queryId, let url):
return ("webViewResultUrl", [("queryId", String(describing: queryId)), ("url", String(describing: url))])
}
}
public static func parse_webViewResultConfirmationRequired(_ reader: BufferReader) -> WebViewResult? {
var _1: Api.AttachMenuBot?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.AttachMenuBot
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.WebViewResult.webViewResultConfirmationRequired(bot: _1!, users: _2!)
}
else {
return nil
}
}
public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? {
var _1: Int64?
_1 = reader.readInt64()
@ -1212,3 +1180,43 @@ public extension Api.auth {
}
}
public extension Api.auth {
enum LoggedOut: TypeConstructorDescription {
case loggedOut(flags: Int32, futureAuthToken: Buffer?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
if boxed {
buffer.appendInt32(-1012759713)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))])
}
}
public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
if _c1 && _c2 {
return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2)
}
else {
return nil
}
}
}
}

View File

@ -1,43 +1,3 @@
public extension Api.auth {
enum LoggedOut: TypeConstructorDescription {
case loggedOut(flags: Int32, futureAuthToken: Buffer?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
if boxed {
buffer.appendInt32(-1012759713)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))])
}
}
public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
if _c1 && _c2 {
return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2)
}
else {
return nil
}
}
}
}
public extension Api.auth {
enum LoginToken: TypeConstructorDescription {
case loginToken(expires: Int32, token: Buffer)
@ -1304,3 +1264,61 @@ public extension Api.help {
}
}
public extension Api.help {
enum Country: TypeConstructorDescription {
case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
if boxed {
buffer.appendInt32(-1014526429)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(iso2, buffer: buffer, boxed: false)
serializeString(defaultName, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(countryCodes.count))
for item in countryCodes {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))])
}
}
public static func parse_country(_ reader: BufferReader) -> Country? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.help.CountryCode]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!)
}
else {
return nil
}
}
}
}

View File

@ -1,61 +1,3 @@
public extension Api.help {
enum Country: TypeConstructorDescription {
case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
if boxed {
buffer.appendInt32(-1014526429)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(iso2, buffer: buffer, boxed: false)
serializeString(defaultName, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(countryCodes.count))
for item in countryCodes {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))])
}
}
public static func parse_country(_ reader: BufferReader) -> Country? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.help.CountryCode]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!)
}
else {
return nil
}
}
}
}
public extension Api.help {
enum CountryCode: TypeConstructorDescription {
case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?)
@ -1350,3 +1292,39 @@ public extension Api.messages {
}
}
public extension Api.messages {
enum CheckedHistoryImportPeer: TypeConstructorDescription {
case checkedHistoryImportPeer(confirmText: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
if boxed {
buffer.appendInt32(-1571952873)
}
serializeString(confirmText, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))])
}
}
public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!)
}
else {
return nil
}
}
}
}

View File

@ -1,39 +1,3 @@
public extension Api.messages {
enum CheckedHistoryImportPeer: TypeConstructorDescription {
case checkedHistoryImportPeer(confirmText: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
if boxed {
buffer.appendInt32(-1571952873)
}
serializeString(confirmText, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))])
}
}
public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum DhConfig: TypeConstructorDescription {
case dhConfig(g: Int32, p: Buffer, version: Int32, random: Buffer)

View File

@ -5202,16 +5202,17 @@ public extension Api.functions.messages {
}
}
public extension Api.functions.messages {
static func requestWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, url: String?, themeParams: Api.DataJSON?, replyToMsgId: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.WebViewResult>) {
static func requestWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, url: String?, startParam: String?, themeParams: Api.DataJSON?, replyToMsgId: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.WebViewResult>) {
let buffer = Buffer()
buffer.appendInt32(572653208)
buffer.appendInt32(262163967)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
bot.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)}
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.requestWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("themeParams", String(describing: themeParams)), ("replyToMsgId", String(describing: replyToMsgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in
return (FunctionDescription(name: "messages.requestWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("replyToMsgId", String(describing: replyToMsgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in
let reader = BufferReader(buffer)
var result: Api.WebViewResult?
if let signature = reader.readInt32() {

View File

@ -83,8 +83,8 @@ public struct Namespaces {
public static let cachedSendAsPeers: Int8 = 18
public static let availableReactions: Int8 = 19
public static let resolvedByPhonePeers: Int8 = 20
public static let attachMenuBots: Int8 = 21
public static let notificationSoundList: Int8 = 22
public static let attachMenuBots: Int8 = 23
}
public struct UnorderedItemList {

View File

@ -3,27 +3,75 @@ import TelegramApi
import Postbox
import SwiftSignalKit
//# inactive:flags.0?true bot_id:long attach_menu_name:string attach_menu_icon:Document = AttachMenuBot;
public final class AttachMenuBots: Equatable, Codable {
public final class Bot: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case peerId
case name
case icon
case botIcons
}
public enum IconName: Int32, Codable {
case `default` = 0
case iOSStatic
case iOSAnimated
case macOSAnimated
init?(string: String) {
switch string {
case "default_static":
self = .default
case "ios_static":
self = .iOSStatic
case "ios_animated":
self = .iOSAnimated
case "macos_animated":
self = .macOSAnimated
default:
return nil
}
}
}
private struct IconPair: Codable {
var name: IconName
var value: TelegramMediaFile
init(_ name: IconName, value: TelegramMediaFile) {
self.name = name
self.value = value
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.name = IconName(rawValue: try container.decode(Int32.self, forKey: "k")) ?? .default
let data = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "v")
self.value = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: data.data)))
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.name.rawValue, forKey: "k")
try container.encode(PostboxEncoder().encodeObjectToRawData(self.value), forKey: "v")
}
}
public let peerId: PeerId
public let name: String
public let icon: TelegramMediaFile
public let icons: [IconName: TelegramMediaFile]
public init(
peerId: PeerId,
name: String,
icon: TelegramMediaFile
icons: [IconName: TelegramMediaFile]
) {
self.peerId = peerId
self.name = name
self.icon = icon
self.icons = icons
}
public static func ==(lhs: Bot, rhs: Bot) -> Bool {
@ -33,7 +81,7 @@ public final class AttachMenuBots: Equatable, Codable {
if lhs.name != rhs.name {
return false
}
if lhs.icon != rhs.icon {
if lhs.icons != rhs.icons {
return false
}
return true
@ -47,8 +95,12 @@ public final class AttachMenuBots: Equatable, Codable {
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
let iconData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .icon)
self.icon = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: iconData.data)))
let iconPairs = try container.decodeIfPresent([IconPair].self, forKey: .botIcons) ?? []
var icons: [IconName: TelegramMediaFile] = [:]
for iconPair in iconPairs {
icons[iconPair.name] = iconPair.value
}
self.icons = icons
}
public func encode(to encoder: Encoder) throws {
@ -56,7 +108,12 @@ public final class AttachMenuBots: Equatable, Codable {
try container.encode(self.peerId.toInt64(), forKey: .peerId)
try container.encode(self.name, forKey: .name)
try container.encode(PostboxEncoder().encodeObjectToRawData(self.icon), forKey: .icon)
var iconPairs: [IconPair] = []
for (key, value) in self.icons {
iconPairs.append(IconPair(key, value: value))
}
try container.encode(iconPairs, forKey: .botIcons)
}
}
@ -135,7 +192,7 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Sig
let poll = Signal<Never, NoError> { subscriber in
let signal: Signal<Never, NoError> = cachedAttachMenuBots(postbox: postbox)
|> mapToSignal { current in
return (network.request(Api.functions.messages.getAttachMenuBots(hash: current?.hash ?? 0))
return (network.request(Api.functions.messages.getAttachMenuBots(hash: 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.AttachMenuBots?, NoError> in
return .single(nil)
@ -159,9 +216,18 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Sig
var resultBots: [AttachMenuBots.Bot] = []
for bot in bots {
switch bot {
case let .attachMenuBot(_, botId, name, attachMenuIcon):
if let icon = telegramMediaFileFromApiDocument(attachMenuIcon) {
resultBots.append(AttachMenuBots.Bot(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), name: name, icon: icon))
case let .attachMenuBot(_, botId, name, botIcons):
var icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile] = [:]
for icon in botIcons {
switch icon {
case let .attachMenuBotIcon(_, name, icon, _):
if let iconName = AttachMenuBots.Bot.IconName(string: name), let icon = telegramMediaFileFromApiDocument(icon) {
icons[iconName] = icon
}
}
}
if !icons.isEmpty {
resultBots.append(AttachMenuBots.Bot(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), name: name, icons: icons))
}
}
}
@ -190,9 +256,9 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network) -> Sig
|> restart
}
func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<Bool, NoError> {
func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
return postbox.transaction { transaction -> Signal<Bool, NoError> in
guard let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) else {
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
return .complete()
}
return network.request(Api.functions.messages.toggleBotInAttachMenu(bot: inputUser, enabled: .boolTrue))
@ -215,9 +281,9 @@ func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, peerId: Pe
|> switchToLatest
}
func _internal_removeBotFromAttachMenu(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<Bool, NoError> {
func _internal_removeBotFromAttachMenu(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
return postbox.transaction { transaction -> Signal<Bool, NoError> in
guard let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) else {
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
return .complete()
}
return network.request(Api.functions.messages.toggleBotInAttachMenu(bot: inputUser, enabled: .boolFalse))
@ -242,11 +308,13 @@ func _internal_removeBotFromAttachMenu(postbox: Postbox, network: Network, peerI
public struct AttachMenuBot {
public let peer: Peer
public let icon: TelegramMediaFile
public let shortName: String
public let icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile]
init(peer: Peer, icon: TelegramMediaFile) {
init(peer: Peer, shortName: String, icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile]) {
self.peer = peer
self.icon = icon
self.shortName = shortName
self.icons = icons
}
}
@ -258,9 +326,67 @@ func _internal_attachMenuBots(postbox: Postbox) -> Signal<[AttachMenuBot], NoErr
var resultBots: [AttachMenuBot] = []
for bot in cachedBots {
if let peer = transaction.getPeer(bot.peerId) {
resultBots.append(AttachMenuBot(peer: peer, icon: bot.icon))
resultBots.append(AttachMenuBot(peer: peer, shortName: bot.name, icons: bot.icons))
}
}
return resultBots
}
}
public enum GetAttachMenuBotError {
case generic
}
public func _internal_getAttachMenuBot(postbox: Postbox, network: Network, botId: PeerId) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
return postbox.transaction { transaction -> Signal<AttachMenuBot, GetAttachMenuBotError> in
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
return .complete()
}
return network.request(Api.functions.messages.getAttachMenuBot(bot: inputUser))
|> mapError { _ -> GetAttachMenuBotError in
return .generic
}
|> mapToSignal { result -> Signal<AttachMenuBot, GetAttachMenuBotError> in
return postbox.transaction { transaction -> Signal<AttachMenuBot, GetAttachMenuBotError> in
switch result {
case let .attachMenuBotsBot(bot, users):
var peers: [Peer] = []
var peer: Peer?
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
if telegramUser.id == botId {
peer = telegramUser
}
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
guard let peer = peer else {
return .fail(.generic)
}
switch bot {
case let .attachMenuBot(_, _, name, botIcons):
var icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile] = [:]
for icon in botIcons {
switch icon {
case let .attachMenuBotIcon(_, name, icon, _):
if let iconName = AttachMenuBots.Bot.IconName(string: name), let icon = telegramMediaFileFromApiDocument(icon) {
icons[iconName] = icon
}
}
}
return .single(AttachMenuBot(peer: peer, shortName: name, icons: icons))
}
}
}
|> castError(GetAttachMenuBotError.self)
|> switchToLatest
}
}
|> castError(GetAttachMenuBotError.self)
|> switchToLatest
}

View File

@ -41,9 +41,10 @@ public enum KeepWebViewError {
case generic
}
public enum RequestWebViewResult {
case webViewResult(queryId: Int64, url: String, keepAliveSignal: Signal<Never, KeepWebViewError>)
case requestConfirmation(botIcon: TelegramMediaFile)
public struct RequestWebViewResult {
public let queryId: Int64
public let url: String
public let keepAliveSignal: Signal<Never, KeepWebViewError>
}
public enum RequestWebViewError {
@ -92,7 +93,7 @@ private func keepWebViewSignal(network: Network, stateManager: AccountStateManag
return signal
}
func _internal_requestWebView(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, botId: PeerId, url: String?, themeParams: [String: Any]?, replyToMessageId: MessageId?) -> Signal<RequestWebViewResult, RequestWebViewError> {
func _internal_requestWebView(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, botId: PeerId, url: String?, payload: String?, themeParams: [String: Any]?, replyToMessageId: MessageId?) -> Signal<RequestWebViewResult, RequestWebViewError> {
var serializedThemeParams: Api.DataJSON?
if let themeParams = themeParams, let data = try? JSONSerialization.data(withJSONObject: themeParams, options: []), let dataString = String(data: data, encoding: .utf8) {
serializedThemeParams = .dataJSON(data: dataString)
@ -115,33 +116,17 @@ func _internal_requestWebView(postbox: Postbox, network: Network, stateManager:
flags |= (1 << 0)
replyToMsgId = replyToMessageId.id
}
return network.request(Api.functions.messages.requestWebView(flags: flags, peer: inputPeer, bot: inputBot, url: url, themeParams: serializedThemeParams, replyToMsgId: replyToMsgId))
if let _ = payload {
flags |= (1 << 3)
}
return network.request(Api.functions.messages.requestWebView(flags: flags, peer: inputPeer, bot: inputBot, url: url, startParam: payload, themeParams: serializedThemeParams, replyToMsgId: replyToMsgId))
|> mapError { _ -> RequestWebViewError in
return .generic
}
|> mapToSignal { result -> Signal<RequestWebViewResult, RequestWebViewError> in
switch result {
case let .webViewResultConfirmationRequired(bot, users):
return postbox.transaction { transaction -> Signal<RequestWebViewResult, RequestWebViewError> in
var peers: [Peer] = []
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated
})
if case let .attachMenuBot(_, _, _, attachMenuIcon) = bot, let icon = telegramMediaFileFromApiDocument(attachMenuIcon) {
return .single(.requestConfirmation(botIcon: icon))
} else {
return .complete()
}
}
|> castError(RequestWebViewError.self)
|> switchToLatest
case let .webViewResultUrl(queryId, url):
return .single(.webViewResult(queryId: queryId, url: url, keepAliveSignal: keepWebViewSignal(network: network, stateManager: stateManager, flags: flags, peer: inputPeer, bot: inputBot, queryId: queryId, replyToMessageId: replyToMessageId)))
return .single(RequestWebViewResult(queryId: queryId, url: url, keepAliveSignal: keepWebViewSignal(network: network, stateManager: stateManager, flags: flags, peer: inputPeer, bot: inputBot, queryId: queryId, replyToMessageId: replyToMessageId)))
}
}
}

View File

@ -322,8 +322,8 @@ public extension TelegramEngine {
return _internal_translate(network: self.account.network, text: text, fromLang: fromLang, toLang: toLang)
}
public func requestWebView(peerId: PeerId, botId: PeerId, url: String?, themeParams: [String: Any]?, replyToMessageId: MessageId?) -> Signal<RequestWebViewResult, RequestWebViewError> {
return _internal_requestWebView(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, botId: botId, url: url, themeParams: themeParams, replyToMessageId: replyToMessageId)
public func requestWebView(peerId: PeerId, botId: PeerId, url: String?, payload: String?, themeParams: [String: Any]?, replyToMessageId: MessageId?) -> Signal<RequestWebViewResult, RequestWebViewError> {
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, replyToMessageId: replyToMessageId)
}
public func requestSimpleWebView(botId: PeerId, url: String, themeParams: [String: Any]?) -> Signal<String, RequestSimpleWebViewError> {
@ -334,13 +334,17 @@ public extension TelegramEngine {
public func sendWebViewData(botId: PeerId, buttonText: String, data: String) -> Signal<Never, SendWebViewDataError> {
return _internal_sendWebViewData(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, botId: botId, buttonText: buttonText, data: data)
}
public func addBotToAttachMenu(peerId: PeerId) -> Signal<Bool, NoError> {
return _internal_addBotToAttachMenu(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
public func addBotToAttachMenu(botId: PeerId) -> Signal<Bool, NoError> {
return _internal_addBotToAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId)
}
public func removeBotFromAttachMenu(peerId: PeerId) -> Signal<Bool, NoError> {
return _internal_removeBotFromAttachMenu(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
public func removeBotFromAttachMenu(botId: PeerId) -> Signal<Bool, NoError> {
return _internal_removeBotFromAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId)
}
public func getAttachMenuBot(botId: PeerId) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
return _internal_getAttachMenuBot(postbox: self.account.postbox, network: self.account.network, botId: botId)
}
public func attachMenuBots() -> Signal<[AttachMenuBot], NoError> {

View File

@ -219,7 +219,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
public let chatLocation: ChatLocation
public let subject: ChatControllerSubject?
private let botStart: ChatControllerInitialBotStart?
private var attachBotId: PeerId?
private var attachBotStart: ChatControllerInitialAttachBotStart?
private let peerDisposable = MetaDisposable()
private let titleDisposable = MetaDisposable()
@ -500,7 +500,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var inviteRequestsContext: PeerInvitationImportersContext?
private var inviteRequestsDisposable = MetaDisposable()
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotId: PeerId? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = []) {
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = []) {
let _ = ChatControllerCount.modify { value in
return value + 1
}
@ -510,7 +510,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatLocationContextHolder = chatLocationContextHolder
self.subject = subject
self.botStart = botStart
self.attachBotId = attachBotId
self.attachBotStart = attachBotStart
self.peekData = peekData
self.currentChatListFilter = chatListFilter
self.chatNavigationStack = chatNavigationStack
@ -3372,7 +3372,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}))
} else {
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestWebView(peerId: peerId, botId: peerId, url: url, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), replyToMessageId: nil)
strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestWebView(peerId: peerId, botId: peerId, url: url, payload: nil, themeParams: generateWebAppThemeParams(strongSelf.presentationData.theme), replyToMessageId: nil)
|> afterDisposed {
updateProgress()
})
@ -3380,17 +3380,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
switch result {
case let .webViewResult(queryId, url, keepAliveSignal):
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: queryId, buttonText: buttonText, keepAliveSignal: keepAliveSignal, replyToMessageId: nil, iconFile: nil)
controller.getNavigationController = { [weak self] in
return self?.effectiveNavigationController
}
controller.navigationPresentation = .modal
strongSelf.push(controller)
case .requestConfirmation:
break
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, replyToMessageId: nil, iconFile: nil)
controller.getNavigationController = { [weak self] in
return self?.effectiveNavigationController
}
controller.navigationPresentation = .modal
strongSelf.push(controller)
}, error: { [weak self] error in
if let strongSelf = self {
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
@ -9146,9 +9141,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.historyNode.preloadPages = true
}
if let attachBotId = self.attachBotId {
self.attachBotId = nil
self.presentAttachmentBot(botId: attachBotId)
if let attachBotStart = self.attachBotStart {
self.attachBotStart = nil
self.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload)
}
}
@ -10491,11 +10486,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
public func presentAttachmentBot(botId: PeerId) {
self.presentAttachmentMenu(editMediaOptions: nil, editMediaReference: nil, botId: botId)
public func presentAttachmentBot(botId: PeerId, payload: String?) {
self.presentAttachmentMenu(editMediaOptions: nil, editMediaReference: nil, botId: botId, botPayload: payload)
}
private func presentAttachmentMenu(editMediaOptions: MessageMediaEditingOptions?, editMediaReference: AnyMediaReference?, botId: PeerId? = nil) {
private func presentAttachmentMenu(editMediaOptions: MessageMediaEditingOptions?, editMediaReference: AnyMediaReference?, botId: PeerId? = nil, botPayload: String? = nil) {
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return
}
@ -10550,12 +10545,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
initialButton = .gallery
}
for bot in attachMenuBots.reversed() {
let peerTitle = EnginePeer(bot.peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
let button: AttachmentButtonType = .app(bot.peer.id, peerTitle, bot.icon)
buttons.insert(button, at: 1)
if initialButton == nil && bot.peer.id == botId {
initialButton = button
let iconFile: TelegramMediaFile?
if let file = bot.icons[.iOSAnimated] {
iconFile = file
} else if let file = bot.icons[.iOSStatic] {
iconFile = file
} else if let file = bot.icons[.default] {
iconFile = file
} else {
iconFile = nil
}
if let iconFile = iconFile {
let button: AttachmentButtonType = .app(bot.peer.id, bot.shortName, iconFile)
buttons.insert(button, at: 1)
if initialButton == nil && bot.peer.id == botId {
initialButton = button
}
}
}
return (buttons, initialButton)
@ -10572,30 +10578,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let initialButton = initialButton else {
if let botId = botId {
let _ = (strongSelf.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: botId)
)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer else {
let _ = (context.engine.messages.getAttachMenuBot(botId: botId)
|> deliverOnMainQueue).start(next: { bot in
let peer = EnginePeer(bot.peer)
guard let icon = bot.icons[.default] else {
return
}
let _ = (strongSelf.context.engine.messages.requestWebView(peerId: peer.id, botId: botId, url: nil, themeParams: nil, replyToMessageId: nil)
|> deliverOnMainQueue).start(next: { [weak self] result in
if let strongSelf = self, case let .requestConfirmation(botIcon) = result {
if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.canBeAddedToAttachMenu) {
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: botIcon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(peerId: botId).start()
Queue.mainQueue().after(1.0, {
strongSelf.presentAttachmentBot(botId: botId)
})
})
strongSelf.present(controller, in: .window(.root))
} else {
strongSelf.present(textAlertController(context: context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
}
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(botId: botId).start()
Queue.mainQueue().after(1.0, {
strongSelf.presentAttachmentBot(botId: botId, payload: botPayload)
})
})
strongSelf.present(controller, in: .window(.root))
}, error: { _ in
strongSelf.present(textAlertController(context: context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
})
}
return
@ -13934,9 +13932,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
case let .withBotStartPayload(botStart):
self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peerId), botStart: botStart))
case let .withAttachBot(botId):
case let .withAttachBot(attachBotStart):
if let navigationController = self.effectiveNavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), attachBotId: botId))
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
}
}
}
@ -14398,9 +14396,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else if let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), botStart: startPayload))
}
case let .withAttachBot(botId):
case let .withAttachBot(attachBotStart):
if let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotId: botId))
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
}
default:
break

View File

@ -938,7 +938,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}), .window(.root), nil)
case .importStickers:
break
case .setAttach:
case .startAttach:
break
}
}

View File

@ -61,8 +61,8 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
return state.updatedBotStartPayload(botStart.payload)
})
}
if let botId = params.attachBotId {
controller.presentAttachmentBot(botId: botId)
if let attachBotStart = params.attachBotStart {
controller.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload)
}
found = true
break
@ -79,11 +79,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
return state.updatedBotStartPayload(botStart.payload)
})
}
if let botId = params.attachBotId {
controller.presentAttachmentBot(botId: botId)
if let attachBotStart = params.attachBotStart {
controller.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload)
}
} else {
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotId: params.attachBotId, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack)
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotStart: params.attachBotStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack)
}
controller.purposefulAction = params.purposefulAction
if let search = params.activateMessageSearch {

View File

@ -547,7 +547,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
present(controller, nil)
}
}
case let .setAttach(peerId):
case let .startAttach(peerId, payload):
let presentError: (String) -> Void = { errorText in
present(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}
@ -555,39 +555,29 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|> deliverOnMainQueue).start(next: { attachMenuBots in
if let _ = attachMenuBots.firstIndex(where: { $0.peer.id == peerId }) {
if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext {
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotId: peerId, useExisting: true))
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload), useExisting: true))
} else {
presentError(presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError)
}
} else {
let _ = (context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
)
|> deliverOnMainQueue).start(next: { peer in
guard let peer = peer else {
let _ = (context.engine.messages.getAttachMenuBot(botId: peerId)
|> deliverOnMainQueue).start(next: { bot in
let peer = EnginePeer(bot.peer)
guard let icon = bot.icons[.default] else {
return
}
let _ = (context.engine.messages.requestWebView(peerId: peer.id, botId: peer.id, url: nil, themeParams: nil, replyToMessageId: nil)
|> deliverOnMainQueue).start(next: { result in
if case let .requestConfirmation(botIcon) = result {
if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.canBeAddedToAttachMenu) {
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: botIcon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(peerId: peerId).start()
Queue.mainQueue().after(1.0, {
if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext {
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotId: peer.id, useExisting: true))
}
})
})
present(controller, nil)
} else {
presentError(presentationData.strings.Login_UnknownError)
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(botId: peerId).start()
Queue.mainQueue().after(1.0, {
if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext {
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peer.id, payload: payload), useExisting: true))
}
}
}, error: { _ in
presentError(presentationData.strings.Login_UnknownError)
})
})
present(controller, nil)
}, error: { _ in
presentError(presentationData.strings.Login_UnknownError)
})
}
})

View File

@ -208,10 +208,10 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
if let navigationController = navigationController {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), botStart: payload))
}
case let .withAttachBot(botId):
case let .withAttachBot(attachBotStart):
context.sharedContext.applicationBindings.dismissNativeController()
if let navigationController = navigationController {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), attachBotId: botId))
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
}
default:
break
@ -642,6 +642,8 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
voiceChat = value
} else if queryItem.name == "attach" {
attach = value
} else if queryItem.name == "startattach" {
startAttach = value
}
} else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) {
voiceChat = ""
@ -675,8 +677,12 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
}
} else if let attach = attach {
result += "?attach=\(attach)"
} else if let _ = startAttach {
result += "?startattach"
} else if let startAttach = startAttach {
if !startAttach.isEmpty {
result += "?startattach=\(startAttach)"
} else {
result += "?startattach"
}
}
convertedUrl = result
}

View File

@ -3307,8 +3307,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}))
case let .withBotStartPayload(startPayload):
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), botStart: startPayload))
case let .withAttachBot(botId):
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotId: botId))
case let .withAttachBot(attachBotStart):
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
default:
break
}
@ -3385,9 +3385,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if let navigationController = self.controller?.navigationController as? NavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), botStart: startPayload))
}
case let .withAttachBot(botId):
case let .withAttachBot(attachBotStart):
if let navigationController = self.controller?.navigationController as? NavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), attachBotId: botId))
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart))
}
}
}

View File

@ -66,7 +66,7 @@ extension ResolvedBotAdminRights {
public enum ParsedInternalPeerUrlParameter {
case botStart(String)
case groupBotStart(String, ResolvedBotAdminRights?)
case attachBotStart(String)
case attachBotStart(String, String?)
case channelMessage(Int32, Double?)
case replyThread(Int32, Int32)
case voiceChat(String?)
@ -87,7 +87,7 @@ public enum ParsedInternalUrl {
case wallpaper(WallpaperUrlParameter)
case theme(String)
case phone(String)
case setAttach(String)
case startAttach(String, String?)
}
private enum ParsedUrl {
@ -185,7 +185,14 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
for queryItem in queryItems {
if let value = queryItem.value {
if queryItem.name == "attach" {
return .peerName(peerName, .attachBotStart(value))
var startAttach: String?
for queryItem in queryItems {
if queryItem.name == "startattach", let value = queryItem.value {
startAttach = value
break
}
}
return .peerName(peerName, .attachBotStart(value, startAttach))
} else if queryItem.name == "start" {
return .peerName(peerName, .botStart(value))
} else if queryItem.name == "startgroup" {
@ -201,11 +208,13 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
return nil
} else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) {
return .peerName(peerName, .voiceChat(value))
} else if queryItem.name == "startattach" {
return .startAttach(peerName, value)
}
} else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) {
return .peerName(peerName, .voiceChat(nil))
} else if queryItem.name == "startattach" {
return .setAttach(peerName)
return .startAttach(peerName, nil)
}
}
}
@ -437,7 +446,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
return .single(.botStart(peerId: peer.id, payload: payload))
case let .groupBotStart(payload, adminRights):
return .single(.groupBotStart(peerId: peer.id, payload: payload, adminRights: adminRights))
case let .attachBotStart(name):
case let .attachBotStart(name, payload):
return context.engine.peers.resolvePeerByName(name: name)
|> take(1)
|> mapToSignal { botPeer -> Signal<Peer?, NoError> in
@ -445,7 +454,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
}
|> mapToSignal { botPeer -> Signal<ResolvedUrl?, NoError> in
if let botPeer = botPeer {
return .single(.peer(peer.id, .withAttachBot(botPeer.id)))
return .single(.peer(peer.id, .withAttachBot(ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload))))
} else {
return .single(.peer(peer.id, .chat(textInputState: nil, subject: nil, peekData: nil)))
}
@ -542,7 +551,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
return .single(.wallpaper(parameter))
case let .theme(slug):
return .single(.theme(slug))
case let .setAttach(name):
case let .startAttach(name, payload):
return context.engine.peers.resolvePeerByName(name: name)
|> take(1)
|> mapToSignal { peer -> Signal<Peer?, NoError> in
@ -550,7 +559,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
}
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
if let peer = peer {
return .single(.setAttach(peer.id))
return .single(.startAttach(peerId: peer.id, payload: payload))
} else {
return .single(.inaccessiblePeer)
}

View File

@ -248,30 +248,25 @@ public final class WebAppController: ViewController, AttachmentContainable {
})
}
} else {
let _ = (context.engine.messages.requestWebView(peerId: controller.peerId, botId: controller.botId, url: controller.url, themeParams: generateWebAppThemeParams(presentationData.theme), replyToMessageId: controller.replyToMessageId)
let _ = (context.engine.messages.requestWebView(peerId: controller.peerId, botId: controller.botId, url: controller.url, payload: nil, themeParams: generateWebAppThemeParams(presentationData.theme), replyToMessageId: controller.replyToMessageId)
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
switch result {
case let .webViewResult(queryId, url, keepAliveSignal):
if let parsedUrl = URL(string: url) {
strongSelf.queryId = queryId
strongSelf.webView?.load(URLRequest(url: parsedUrl))
strongSelf.keepAliveDisposable = (keepAliveSignal
|> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
}, completed: { [weak self] in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
})
if let parsedUrl = URL(string: result.url) {
strongSelf.queryId = result.queryId
strongSelf.webView?.load(URLRequest(url: parsedUrl))
strongSelf.keepAliveDisposable = (result.keepAliveSignal
|> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
case .requestConfirmation:
break
}, completed: { [weak self] in
if let strongSelf = self {
strongSelf.controller?.dismiss()
}
})
}
})
}
@ -628,7 +623,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
f(.default)
if let strongSelf = self {
let _ = context.engine.messages.removeBotFromAttachMenu(peerId: strongSelf.botId).start()
let _ = context.engine.messages.removeBotFromAttachMenu(botId: strongSelf.botId).start()
strongSelf.dismiss()
}
})))