mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-28 02:45:58 +00:00
Update API
This commit is contained in:
parent
751f4801d6
commit
f468cea13c
@ -303,6 +303,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-29248689] = { return Api.GlobalPrivacySettings.parse_globalPrivacySettings($0) }
|
||||
dict[1429932961] = { return Api.GroupCall.parse_groupCall($0) }
|
||||
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
|
||||
dict[-2018173984] = { return Api.GroupCallMessage.parse_groupCallMessage($0) }
|
||||
dict[708691884] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
||||
dict[1735736008] = { return Api.GroupCallParticipantVideo.parse_groupCallParticipantVideo($0) }
|
||||
dict[-592373577] = { return Api.GroupCallParticipantVideoSourceGroup.parse_groupCallParticipantVideoSourceGroup($0) }
|
||||
@ -1112,7 +1113,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1535694705] = { return Api.Update.parse_updateGroupCallChainBlocks($0) }
|
||||
dict[192428418] = { return Api.Update.parse_updateGroupCallConnection($0) }
|
||||
dict[-917002394] = { return Api.Update.parse_updateGroupCallEncryptedMessage($0) }
|
||||
dict[-964095818] = { return Api.Update.parse_updateGroupCallMessage($0) }
|
||||
dict[-667783411] = { return Api.Update.parse_updateGroupCallMessage($0) }
|
||||
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
|
||||
dict[1763610706] = { return Api.Update.parse_updateInlineBotCallbackQuery($0) }
|
||||
dict[1442983757] = { return Api.Update.parse_updateLangPack($0) }
|
||||
@ -1816,6 +1817,8 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.GroupCall:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.GroupCallMessage:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.GroupCallParticipant:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.GroupCallParticipantVideo:
|
||||
|
||||
@ -1,3 +1,313 @@
|
||||
public extension Api {
|
||||
indirect enum InputFileLocation: TypeConstructorDescription {
|
||||
case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
|
||||
case inputEncryptedFileLocation(id: Int64, accessHash: Int64)
|
||||
case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer)
|
||||
case inputGroupCallStream(flags: Int32, call: Api.InputGroupCall, timeMs: Int64, scale: Int32, videoChannel: Int32?, videoQuality: Int32?)
|
||||
case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, photoId: Int64)
|
||||
case inputPhotoFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
|
||||
case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64)
|
||||
case inputSecureFileLocation(id: Int64, accessHash: Int64)
|
||||
case inputStickerSetThumb(stickerset: Api.InputStickerSet, thumbVersion: Int32)
|
||||
case inputTakeoutFileLocation
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1160743548)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeString(thumbSize, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputEncryptedFileLocation(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-182231723)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputFileLocation(let volumeId, let localId, let secret, let fileReference):
|
||||
if boxed {
|
||||
buffer.appendInt32(-539317279)
|
||||
}
|
||||
serializeInt64(volumeId, buffer: buffer, boxed: false)
|
||||
serializeInt32(localId, buffer: buffer, boxed: false)
|
||||
serializeInt64(secret, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
if boxed {
|
||||
buffer.appendInt32(93890858)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
serializeInt64(timeMs, buffer: buffer, boxed: false)
|
||||
serializeInt32(scale, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoChannel!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoQuality!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputPeerPhotoFileLocation(let flags, let peer, let photoId):
|
||||
if boxed {
|
||||
buffer.appendInt32(925204121)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt64(photoId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
if boxed {
|
||||
buffer.appendInt32(1075322878)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeString(thumbSize, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret):
|
||||
if boxed {
|
||||
buffer.appendInt32(-667654413)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeInt64(volumeId, buffer: buffer, boxed: false)
|
||||
serializeInt32(localId, buffer: buffer, boxed: false)
|
||||
serializeInt64(secret, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputSecureFileLocation(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-876089816)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputStickerSetThumb(let stickerset, let thumbVersion):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1652231205)
|
||||
}
|
||||
stickerset.serialize(buffer, true)
|
||||
serializeInt32(thumbVersion, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputTakeoutFileLocation:
|
||||
if boxed {
|
||||
buffer.appendInt32(700340377)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
return ("inputDocumentFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)])
|
||||
case .inputEncryptedFileLocation(let id, let accessHash):
|
||||
return ("inputEncryptedFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputFileLocation(let volumeId, let localId, let secret, let fileReference):
|
||||
return ("inputFileLocation", [("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any), ("fileReference", fileReference as Any)])
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
return ("inputGroupCallStream", [("flags", flags as Any), ("call", call as Any), ("timeMs", timeMs as Any), ("scale", scale as Any), ("videoChannel", videoChannel as Any), ("videoQuality", videoQuality as Any)])
|
||||
case .inputPeerPhotoFileLocation(let flags, let peer, let photoId):
|
||||
return ("inputPeerPhotoFileLocation", [("flags", flags as Any), ("peer", peer as Any), ("photoId", photoId as Any)])
|
||||
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
return ("inputPhotoFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)])
|
||||
case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret):
|
||||
return ("inputPhotoLegacyFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any)])
|
||||
case .inputSecureFileLocation(let id, let accessHash):
|
||||
return ("inputSecureFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputStickerSetThumb(let stickerset, let thumbVersion):
|
||||
return ("inputStickerSetThumb", [("stickerset", stickerset as Any), ("thumbVersion", thumbVersion as Any)])
|
||||
case .inputTakeoutFileLocation:
|
||||
return ("inputTakeoutFileLocation", [])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputDocumentFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputDocumentFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputEncryptedFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputEncryptedFileLocation(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Buffer?
|
||||
_4 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputFileLocation(volumeId: _1!, localId: _2!, secret: _3!, fileReference: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputGroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
}
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputFileLocation.inputGroupCallStream(flags: _1!, call: _2!, timeMs: _3!, scale: _4!, videoChannel: _5, videoQuality: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPeerPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
||||
}
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.InputFileLocation.inputPeerPhotoFileLocation(flags: _1!, peer: _2!, photoId: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputPhotoFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPhotoLegacyFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int64?
|
||||
_6 = reader.readInt64()
|
||||
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.InputFileLocation.inputPhotoLegacyFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, volumeId: _4!, localId: _5!, secret: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputSecureFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputSecureFileLocation(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputStickerSetThumb(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Api.InputStickerSet?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputStickerSet
|
||||
}
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputStickerSetThumb(stickerset: _1!, thumbVersion: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputTakeoutFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
return Api.InputFileLocation.inputTakeoutFileLocation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum InputFolderPeer: TypeConstructorDescription {
|
||||
case inputFolderPeer(peer: Api.InputPeer, folderId: Int32)
|
||||
@ -630,681 +940,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum InputMedia: TypeConstructorDescription {
|
||||
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
|
||||
case inputMediaDice(emoticon: String)
|
||||
case inputMediaDocument(flags: Int32, id: Api.InputDocument, videoCover: Api.InputPhoto?, videoTimestamp: Int32?, ttlSeconds: Int32?, query: String?)
|
||||
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?, videoCover: Api.InputPhoto?, videoTimestamp: Int32?)
|
||||
case inputMediaEmpty
|
||||
case inputMediaGame(id: Api.InputGame)
|
||||
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
|
||||
case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint)
|
||||
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String?, providerData: Api.DataJSON, startParam: String?, extendedMedia: Api.InputMedia?)
|
||||
case inputMediaPaidMedia(flags: Int32, starsAmount: Int64, extendedMedia: [Api.InputMedia], payload: String?)
|
||||
case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, ttlSeconds: Int32?)
|
||||
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
|
||||
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
|
||||
case inputMediaStory(peer: Api.InputPeer, id: Int32)
|
||||
case inputMediaTodo(todo: Api.TodoList)
|
||||
case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], stickers: [Api.InputDocument]?, videoCover: Api.InputPhoto?, videoTimestamp: Int32?, ttlSeconds: Int32?)
|
||||
case inputMediaUploadedPhoto(flags: Int32, file: Api.InputFile, stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
|
||||
case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
|
||||
case inputMediaWebPage(flags: Int32, url: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
|
||||
if boxed {
|
||||
buffer.appendInt32(-122978821)
|
||||
}
|
||||
serializeString(phoneNumber, buffer: buffer, boxed: false)
|
||||
serializeString(firstName, buffer: buffer, boxed: false)
|
||||
serializeString(lastName, buffer: buffer, boxed: false)
|
||||
serializeString(vcard, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaDice(let emoticon):
|
||||
if boxed {
|
||||
buffer.appendInt32(-428884101)
|
||||
}
|
||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let videoTimestamp, let ttlSeconds, let query):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1468646731)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
id.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 3) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover, let videoTimestamp):
|
||||
if boxed {
|
||||
buffer.appendInt32(2006319353)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaEmpty:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1771768449)
|
||||
}
|
||||
|
||||
break
|
||||
case .inputMediaGame(let id):
|
||||
if boxed {
|
||||
buffer.appendInt32(-750828557)
|
||||
}
|
||||
id.serialize(buffer, true)
|
||||
break
|
||||
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1759532989)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
geoPoint.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaGeoPoint(let geoPoint):
|
||||
if boxed {
|
||||
buffer.appendInt32(-104578748)
|
||||
}
|
||||
geoPoint.serialize(buffer, true)
|
||||
break
|
||||
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
|
||||
if boxed {
|
||||
buffer.appendInt32(1080028941)
|
||||
}
|
||||
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 {photo!.serialize(buffer, true)}
|
||||
invoice.serialize(buffer, true)
|
||||
serializeBytes(payload, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(provider!, buffer: buffer, boxed: false)}
|
||||
providerData.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {extendedMedia!.serialize(buffer, true)}
|
||||
break
|
||||
case .inputMediaPaidMedia(let flags, let starsAmount, let extendedMedia, let payload):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1005571194)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(starsAmount, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(extendedMedia.count))
|
||||
for item in extendedMedia {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(payload!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1279654347)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
id.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(-440664550)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
|
||||
if boxed {
|
||||
buffer.appendInt32(261416433)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
poll.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(correctAnswers!.count))
|
||||
for item in correctAnswers! {
|
||||
serializeBytes(item, buffer: buffer, boxed: false)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(solution!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(solutionEntities!.count))
|
||||
for item in solutionEntities! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
break
|
||||
case .inputMediaStory(let peer, let id):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1979852936)
|
||||
}
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaTodo(let todo):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1614454818)
|
||||
}
|
||||
todo.serialize(buffer, true)
|
||||
break
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(58495792)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
file.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {thumb!.serialize(buffer, true)}
|
||||
serializeString(mimeType, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(attributes.count))
|
||||
for item in attributes {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(stickers!.count))
|
||||
for item in stickers! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 6) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(505969924)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
file.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(stickers!.count))
|
||||
for item in stickers! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1052959727)
|
||||
}
|
||||
geoPoint.serialize(buffer, true)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(address, buffer: buffer, boxed: false)
|
||||
serializeString(provider, buffer: buffer, boxed: false)
|
||||
serializeString(venueId, buffer: buffer, boxed: false)
|
||||
serializeString(venueType, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaWebPage(let flags, let url):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1038383031)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
|
||||
return ("inputMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any)])
|
||||
case .inputMediaDice(let emoticon):
|
||||
return ("inputMediaDice", [("emoticon", emoticon as Any)])
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let videoTimestamp, let ttlSeconds, let query):
|
||||
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover, let videoTimestamp):
|
||||
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any)])
|
||||
case .inputMediaEmpty:
|
||||
return ("inputMediaEmpty", [])
|
||||
case .inputMediaGame(let id):
|
||||
return ("inputMediaGame", [("id", id as Any)])
|
||||
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
|
||||
return ("inputMediaGeoLive", [("flags", flags as Any), ("geoPoint", geoPoint as Any), ("heading", heading as Any), ("period", period as Any), ("proximityNotificationRadius", proximityNotificationRadius as Any)])
|
||||
case .inputMediaGeoPoint(let geoPoint):
|
||||
return ("inputMediaGeoPoint", [("geoPoint", geoPoint as Any)])
|
||||
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
|
||||
return ("inputMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("payload", payload as Any), ("provider", provider as Any), ("providerData", providerData as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)])
|
||||
case .inputMediaPaidMedia(let flags, let starsAmount, let extendedMedia, let payload):
|
||||
return ("inputMediaPaidMedia", [("flags", flags as Any), ("starsAmount", starsAmount as Any), ("extendedMedia", extendedMedia as Any), ("payload", payload as Any)])
|
||||
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
|
||||
return ("inputMediaPhoto", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
|
||||
return ("inputMediaPhotoExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
|
||||
return ("inputMediaPoll", [("flags", flags as Any), ("poll", poll as Any), ("correctAnswers", correctAnswers as Any), ("solution", solution as Any), ("solutionEntities", solutionEntities as Any)])
|
||||
case .inputMediaStory(let peer, let id):
|
||||
return ("inputMediaStory", [("peer", peer as Any), ("id", id as Any)])
|
||||
case .inputMediaTodo(let todo):
|
||||
return ("inputMediaTodo", [("todo", todo as Any)])
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
return ("inputMediaUploadedDocument", [("flags", flags as Any), ("file", file as Any), ("thumb", thumb as Any), ("mimeType", mimeType as Any), ("attributes", attributes as Any), ("stickers", stickers as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
|
||||
return ("inputMediaUploadedPhoto", [("flags", flags as Any), ("file", file as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
|
||||
return ("inputMediaVenue", [("geoPoint", geoPoint as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)])
|
||||
case .inputMediaWebPage(let flags, let url):
|
||||
return ("inputMediaWebPage", [("flags", flags as Any), ("url", url as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputMediaContact(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputMedia.inputMediaContact(phoneNumber: _1!, firstName: _2!, lastName: _3!, vcard: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaDice(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputMedia.inputMediaDice(emoticon: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaDocument(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputDocument?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
|
||||
}
|
||||
var _3: Api.InputPhoto?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, videoCover: _3, videoTimestamp: _4, ttlSeconds: _5, query: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaDocumentExternal(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Api.InputPhoto?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3, videoCover: _4, videoTimestamp: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaEmpty(_ reader: BufferReader) -> InputMedia? {
|
||||
return Api.InputMedia.inputMediaEmpty
|
||||
}
|
||||
public static func parse_inputMediaGame(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Api.InputGame?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGame
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputMedia.inputMediaGame(id: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaGeoLive(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
|
||||
}
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputMedia.inputMediaGeoLive(flags: _1!, geoPoint: _2!, heading: _3, period: _4, proximityNotificationRadius: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaGeoPoint(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputMedia.inputMediaGeoPoint(geoPoint: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaInvoice(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Api.InputWebDocument?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.InputWebDocument
|
||||
} }
|
||||
var _5: Api.Invoice?
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.Invoice
|
||||
}
|
||||
var _6: Buffer?
|
||||
_6 = parseBytes(reader)
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) }
|
||||
var _8: Api.DataJSON?
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
}
|
||||
var _9: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_9 = parseString(reader) }
|
||||
var _10: Api.InputMedia?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_10 = Api.parse(reader, signature: signature) as? Api.InputMedia
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
|
||||
let _c10 = (Int(_1!) & Int(1 << 2) == 0) || _10 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||
return Api.InputMedia.inputMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7, providerData: _8!, startParam: _9, extendedMedia: _10)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaPaidMedia(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: [Api.InputMedia]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputMedia.self)
|
||||
}
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
|
||||
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.InputMedia.inputMediaPaidMedia(flags: _1!, starsAmount: _2!, extendedMedia: _3!, payload: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaPhoto(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputPhoto?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
}
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.InputMedia.inputMediaPhoto(flags: _1!, id: _2!, ttlSeconds: _3)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaPhotoExternal(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.InputMedia.inputMediaPhotoExternal(flags: _1!, url: _2!, ttlSeconds: _3)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaPoll(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.Poll?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.Poll
|
||||
}
|
||||
var _3: [Buffer]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self)
|
||||
} }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: [Api.MessageEntity]?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
|
||||
} }
|
||||
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 << 1) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputMedia.inputMediaPoll(flags: _1!, poll: _2!, correctAnswers: _3, solution: _4, solutionEntities: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaStory(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Api.InputPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
||||
}
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputMedia.inputMediaStory(peer: _1!, id: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaTodo(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Api.TodoList?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.TodoList
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputMedia.inputMediaTodo(todo: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaUploadedDocument(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputFile?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
|
||||
}
|
||||
var _3: Api.InputFile?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.InputFile
|
||||
} }
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: [Api.DocumentAttribute]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self)
|
||||
}
|
||||
var _6: [Api.InputDocument]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
|
||||
} }
|
||||
var _7: Api.InputPhoto?
|
||||
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _8: Int32?
|
||||
if Int(_1!) & Int(1 << 7) != 0 {_8 = reader.readInt32() }
|
||||
var _9: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_9 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 7) == 0) || _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, videoCover: _7, videoTimestamp: _8, ttlSeconds: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaUploadedPhoto(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputFile?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
|
||||
}
|
||||
var _3: [Api.InputDocument]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
|
||||
} }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
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
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputMedia.inputMediaUploadedPhoto(flags: _1!, file: _2!, stickers: _3, ttlSeconds: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaVenue(_ reader: BufferReader) -> InputMedia? {
|
||||
var _1: Api.InputGeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: String?
|
||||
_5 = parseString(reader)
|
||||
var _6: String?
|
||||
_6 = parseString(reader)
|
||||
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.InputMedia.inputMediaVenue(geoPoint: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaWebPage(_ reader: BufferReader) -> InputMedia? {
|
||||
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.InputMedia.inputMediaWebPage(flags: _1!, url: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,675 @@
|
||||
public extension Api {
|
||||
enum KeyboardButtonRow: TypeConstructorDescription {
|
||||
case keyboardButtonRow(buttons: [Api.KeyboardButton])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .keyboardButtonRow(let buttons):
|
||||
if boxed {
|
||||
buffer.appendInt32(2002815875)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(buttons.count))
|
||||
for item in buttons {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .keyboardButtonRow(let buttons):
|
||||
return ("keyboardButtonRow", [("buttons", buttons as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_keyboardButtonRow(_ reader: BufferReader) -> KeyboardButtonRow? {
|
||||
var _1: [Api.KeyboardButton]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButton.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.KeyboardButtonRow.keyboardButtonRow(buttons: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LabeledPrice: TypeConstructorDescription {
|
||||
case labeledPrice(label: String, amount: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .labeledPrice(let label, let amount):
|
||||
if boxed {
|
||||
buffer.appendInt32(-886477832)
|
||||
}
|
||||
serializeString(label, buffer: buffer, boxed: false)
|
||||
serializeInt64(amount, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .labeledPrice(let label, let amount):
|
||||
return ("labeledPrice", [("label", label as Any), ("amount", amount as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_labeledPrice(_ reader: BufferReader) -> LabeledPrice? {
|
||||
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.LabeledPrice.labeledPrice(label: _1!, amount: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LangPackDifference: TypeConstructorDescription {
|
||||
case langPackDifference(langCode: String, fromVersion: Int32, version: Int32, strings: [Api.LangPackString])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackDifference(let langCode, let fromVersion, let version, let strings):
|
||||
if boxed {
|
||||
buffer.appendInt32(-209337866)
|
||||
}
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
serializeInt32(fromVersion, buffer: buffer, boxed: false)
|
||||
serializeInt32(version, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(strings.count))
|
||||
for item in strings {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackDifference(let langCode, let fromVersion, let version, let strings):
|
||||
return ("langPackDifference", [("langCode", langCode as Any), ("fromVersion", fromVersion as Any), ("version", version as Any), ("strings", strings as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_langPackDifference(_ reader: BufferReader) -> LangPackDifference? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: [Api.LangPackString]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackString.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.LangPackDifference.langPackDifference(langCode: _1!, fromVersion: _2!, version: _3!, strings: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LangPackLanguage: TypeConstructorDescription {
|
||||
case langPackLanguage(flags: Int32, name: String, nativeName: String, langCode: String, baseLangCode: String?, pluralCode: String, stringsCount: Int32, translatedCount: Int32, translationsUrl: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount, let translationsUrl):
|
||||
if boxed {
|
||||
buffer.appendInt32(-288727837)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(name, buffer: buffer, boxed: false)
|
||||
serializeString(nativeName, buffer: buffer, boxed: false)
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(baseLangCode!, buffer: buffer, boxed: false)}
|
||||
serializeString(pluralCode, buffer: buffer, boxed: false)
|
||||
serializeInt32(stringsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(translatedCount, buffer: buffer, boxed: false)
|
||||
serializeString(translationsUrl, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackLanguage(let flags, let name, let nativeName, let langCode, let baseLangCode, let pluralCode, let stringsCount, let translatedCount, let translationsUrl):
|
||||
return ("langPackLanguage", [("flags", flags as Any), ("name", name as Any), ("nativeName", nativeName as Any), ("langCode", langCode as Any), ("baseLangCode", baseLangCode as Any), ("pluralCode", pluralCode as Any), ("stringsCount", stringsCount as Any), ("translatedCount", translatedCount as Any), ("translationsUrl", translationsUrl as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_langPackLanguage(_ reader: BufferReader) -> LangPackLanguage? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
||||
var _6: String?
|
||||
_6 = parseString(reader)
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
var _8: Int32?
|
||||
_8 = reader.readInt32()
|
||||
var _9: String?
|
||||
_9 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.LangPackLanguage.langPackLanguage(flags: _1!, name: _2!, nativeName: _3!, langCode: _4!, baseLangCode: _5, pluralCode: _6!, stringsCount: _7!, translatedCount: _8!, translationsUrl: _9!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LangPackString: TypeConstructorDescription {
|
||||
case langPackString(key: String, value: String)
|
||||
case langPackStringDeleted(key: String)
|
||||
case langPackStringPluralized(flags: Int32, key: String, zeroValue: String?, oneValue: String?, twoValue: String?, fewValue: String?, manyValue: String?, otherValue: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
if boxed {
|
||||
buffer.appendInt32(-892239370)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
serializeString(value, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringDeleted(let key):
|
||||
if boxed {
|
||||
buffer.appendInt32(695856818)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
if boxed {
|
||||
buffer.appendInt32(1816636575)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(zeroValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(oneValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(twoValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(fewValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeString(manyValue!, buffer: buffer, boxed: false)}
|
||||
serializeString(otherValue, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
return ("langPackString", [("key", key as Any), ("value", value as Any)])
|
||||
case .langPackStringDeleted(let key):
|
||||
return ("langPackStringDeleted", [("key", key as Any)])
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
return ("langPackStringPluralized", [("flags", flags as Any), ("key", key as Any), ("zeroValue", zeroValue as Any), ("oneValue", oneValue as Any), ("twoValue", twoValue as Any), ("fewValue", fewValue as Any), ("manyValue", manyValue as Any), ("otherValue", otherValue as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_langPackString(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.LangPackString.langPackString(key: _1!, value: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringDeleted(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.LangPackString.langPackStringDeleted(key: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_langPackStringPluralized(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
|
||||
var _8: String?
|
||||
_8 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.LangPackString.langPackStringPluralized(flags: _1!, key: _2!, zeroValue: _3, oneValue: _4, twoValue: _5, fewValue: _6, manyValue: _7, otherValue: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum MaskCoords: TypeConstructorDescription {
|
||||
case maskCoords(n: Int32, x: Double, y: Double, zoom: Double)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .maskCoords(let n, let x, let y, let zoom):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1361650766)
|
||||
}
|
||||
serializeInt32(n, buffer: buffer, boxed: false)
|
||||
serializeDouble(x, buffer: buffer, boxed: false)
|
||||
serializeDouble(y, buffer: buffer, boxed: false)
|
||||
serializeDouble(zoom, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .maskCoords(let n, let x, let y, let zoom):
|
||||
return ("maskCoords", [("n", n as Any), ("x", x as Any), ("y", y as Any), ("zoom", zoom as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_maskCoords(_ reader: BufferReader) -> MaskCoords? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Double?
|
||||
_2 = reader.readDouble()
|
||||
var _3: Double?
|
||||
_3 = reader.readDouble()
|
||||
var _4: Double?
|
||||
_4 = reader.readDouble()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.MaskCoords.maskCoords(n: _1!, x: _2!, y: _3!, zoom: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum MediaArea: TypeConstructorDescription {
|
||||
case inputMediaAreaChannelPost(coordinates: Api.MediaAreaCoordinates, channel: Api.InputChannel, msgId: Int32)
|
||||
case inputMediaAreaVenue(coordinates: Api.MediaAreaCoordinates, queryId: Int64, resultId: String)
|
||||
case mediaAreaChannelPost(coordinates: Api.MediaAreaCoordinates, channelId: Int64, msgId: Int32)
|
||||
case mediaAreaGeoPoint(flags: Int32, coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint, address: Api.GeoPointAddress?)
|
||||
case mediaAreaStarGift(coordinates: Api.MediaAreaCoordinates, slug: String)
|
||||
case mediaAreaSuggestedReaction(flags: Int32, coordinates: Api.MediaAreaCoordinates, reaction: Api.Reaction)
|
||||
case mediaAreaUrl(coordinates: Api.MediaAreaCoordinates, url: String)
|
||||
case mediaAreaVenue(coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
|
||||
case mediaAreaWeather(coordinates: Api.MediaAreaCoordinates, emoji: String, temperatureC: Double, color: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputMediaAreaChannelPost(let coordinates, let channel, let msgId):
|
||||
if boxed {
|
||||
buffer.appendInt32(577893055)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
channel.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaAreaVenue(let coordinates, let queryId, let resultId):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1300094593)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
serializeInt64(queryId, buffer: buffer, boxed: false)
|
||||
serializeString(resultId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .mediaAreaChannelPost(let coordinates, let channelId, let msgId):
|
||||
if boxed {
|
||||
buffer.appendInt32(1996756655)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
serializeInt64(channelId, buffer: buffer, boxed: false)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .mediaAreaGeoPoint(let flags, let coordinates, let geo, let address):
|
||||
if boxed {
|
||||
buffer.appendInt32(-891992787)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
coordinates.serialize(buffer, true)
|
||||
geo.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {address!.serialize(buffer, true)}
|
||||
break
|
||||
case .mediaAreaStarGift(let coordinates, let slug):
|
||||
if boxed {
|
||||
buffer.appendInt32(1468491885)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
serializeString(slug, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .mediaAreaSuggestedReaction(let flags, let coordinates, let reaction):
|
||||
if boxed {
|
||||
buffer.appendInt32(340088945)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
coordinates.serialize(buffer, true)
|
||||
reaction.serialize(buffer, true)
|
||||
break
|
||||
case .mediaAreaUrl(let coordinates, let url):
|
||||
if boxed {
|
||||
buffer.appendInt32(926421125)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .mediaAreaVenue(let coordinates, let geo, let title, let address, let provider, let venueId, let venueType):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1098720356)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
geo.serialize(buffer, true)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(address, buffer: buffer, boxed: false)
|
||||
serializeString(provider, buffer: buffer, boxed: false)
|
||||
serializeString(venueId, buffer: buffer, boxed: false)
|
||||
serializeString(venueType, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .mediaAreaWeather(let coordinates, let emoji, let temperatureC, let color):
|
||||
if boxed {
|
||||
buffer.appendInt32(1235637404)
|
||||
}
|
||||
coordinates.serialize(buffer, true)
|
||||
serializeString(emoji, buffer: buffer, boxed: false)
|
||||
serializeDouble(temperatureC, buffer: buffer, boxed: false)
|
||||
serializeInt32(color, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputMediaAreaChannelPost(let coordinates, let channel, let msgId):
|
||||
return ("inputMediaAreaChannelPost", [("coordinates", coordinates as Any), ("channel", channel as Any), ("msgId", msgId as Any)])
|
||||
case .inputMediaAreaVenue(let coordinates, let queryId, let resultId):
|
||||
return ("inputMediaAreaVenue", [("coordinates", coordinates as Any), ("queryId", queryId as Any), ("resultId", resultId as Any)])
|
||||
case .mediaAreaChannelPost(let coordinates, let channelId, let msgId):
|
||||
return ("mediaAreaChannelPost", [("coordinates", coordinates as Any), ("channelId", channelId as Any), ("msgId", msgId as Any)])
|
||||
case .mediaAreaGeoPoint(let flags, let coordinates, let geo, let address):
|
||||
return ("mediaAreaGeoPoint", [("flags", flags as Any), ("coordinates", coordinates as Any), ("geo", geo as Any), ("address", address as Any)])
|
||||
case .mediaAreaStarGift(let coordinates, let slug):
|
||||
return ("mediaAreaStarGift", [("coordinates", coordinates as Any), ("slug", slug as Any)])
|
||||
case .mediaAreaSuggestedReaction(let flags, let coordinates, let reaction):
|
||||
return ("mediaAreaSuggestedReaction", [("flags", flags as Any), ("coordinates", coordinates as Any), ("reaction", reaction as Any)])
|
||||
case .mediaAreaUrl(let coordinates, let url):
|
||||
return ("mediaAreaUrl", [("coordinates", coordinates as Any), ("url", url as Any)])
|
||||
case .mediaAreaVenue(let coordinates, let geo, let title, let address, let provider, let venueId, let venueType):
|
||||
return ("mediaAreaVenue", [("coordinates", coordinates as Any), ("geo", geo as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)])
|
||||
case .mediaAreaWeather(let coordinates, let emoji, let temperatureC, let color):
|
||||
return ("mediaAreaWeather", [("coordinates", coordinates as Any), ("emoji", emoji as Any), ("temperatureC", temperatureC as Any), ("color", color as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputMediaAreaChannelPost(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: Api.InputChannel?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputChannel
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.MediaArea.inputMediaAreaChannelPost(coordinates: _1!, channel: _2!, msgId: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputMediaAreaVenue(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.MediaArea.inputMediaAreaVenue(coordinates: _1!, queryId: _2!, resultId: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaChannelPost(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.MediaArea.mediaAreaChannelPost(coordinates: _1!, channelId: _2!, msgId: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaGeoPoint(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _3: Api.GeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.GeoPoint
|
||||
}
|
||||
var _4: Api.GeoPointAddress?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.GeoPointAddress
|
||||
} }
|
||||
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.MediaArea.mediaAreaGeoPoint(flags: _1!, coordinates: _2!, geo: _3!, address: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaStarGift(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.MediaArea.mediaAreaStarGift(coordinates: _1!, slug: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaSuggestedReaction(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _3: Api.Reaction?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.Reaction
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.MediaArea.mediaAreaSuggestedReaction(flags: _1!, coordinates: _2!, reaction: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaUrl(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.MediaArea.mediaAreaUrl(coordinates: _1!, url: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaVenue(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: Api.GeoPoint?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.GeoPoint
|
||||
}
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: String?
|
||||
_5 = parseString(reader)
|
||||
var _6: String?
|
||||
_6 = parseString(reader)
|
||||
var _7: String?
|
||||
_7 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.MediaArea.mediaAreaVenue(coordinates: _1!, geo: _2!, title: _3!, address: _4!, provider: _5!, venueId: _6!, venueType: _7!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_mediaAreaWeather(_ reader: BufferReader) -> MediaArea? {
|
||||
var _1: Api.MediaAreaCoordinates?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: Double?
|
||||
_3 = reader.readDouble()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.MediaArea.mediaAreaWeather(coordinates: _1!, emoji: _2!, temperatureC: _3!, color: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum MediaAreaCoordinates: TypeConstructorDescription {
|
||||
case mediaAreaCoordinates(flags: Int32, x: Double, y: Double, w: Double, h: Double, rotation: Double, radius: Double?)
|
||||
|
||||
@ -608,7 +608,7 @@ public extension Api {
|
||||
case updateGroupCallChainBlocks(call: Api.InputGroupCall, subChainId: Int32, blocks: [Buffer], nextOffset: Int32)
|
||||
case updateGroupCallConnection(flags: Int32, params: Api.DataJSON)
|
||||
case updateGroupCallEncryptedMessage(call: Api.InputGroupCall, fromId: Api.Peer, encryptedMessage: Buffer)
|
||||
case updateGroupCallMessage(flags: Int32, call: Api.InputGroupCall, fromId: Api.Peer, randomId: Int64, message: Api.TextWithEntities, paidMessageStars: Int64?)
|
||||
case updateGroupCallMessage(call: Api.InputGroupCall, message: Api.GroupCallMessage)
|
||||
case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32)
|
||||
case updateInlineBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, msgId: Api.InputBotInlineMessageID, chatInstance: Int64, data: Buffer?, gameShortName: String?)
|
||||
case updateLangPack(difference: Api.LangPackDifference)
|
||||
@ -1307,16 +1307,12 @@ public extension Api {
|
||||
fromId.serialize(buffer, true)
|
||||
serializeBytes(encryptedMessage, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateGroupCallMessage(let flags, let call, let fromId, let randomId, let message, let paidMessageStars):
|
||||
case .updateGroupCallMessage(let call, let message):
|
||||
if boxed {
|
||||
buffer.appendInt32(-964095818)
|
||||
buffer.appendInt32(-667783411)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
fromId.serialize(buffer, true)
|
||||
serializeInt64(randomId, buffer: buffer, boxed: false)
|
||||
message.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(paidMessageStars!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .updateGroupCallParticipants(let call, let participants, let version):
|
||||
if boxed {
|
||||
@ -2120,8 +2116,8 @@ public extension Api {
|
||||
return ("updateGroupCallConnection", [("flags", flags as Any), ("params", params as Any)])
|
||||
case .updateGroupCallEncryptedMessage(let call, let fromId, let encryptedMessage):
|
||||
return ("updateGroupCallEncryptedMessage", [("call", call as Any), ("fromId", fromId as Any), ("encryptedMessage", encryptedMessage as Any)])
|
||||
case .updateGroupCallMessage(let flags, let call, let fromId, let randomId, let message, let paidMessageStars):
|
||||
return ("updateGroupCallMessage", [("flags", flags as Any), ("call", call as Any), ("fromId", fromId as Any), ("randomId", randomId as Any), ("message", message as Any), ("paidMessageStars", paidMessageStars as Any)])
|
||||
case .updateGroupCallMessage(let call, let message):
|
||||
return ("updateGroupCallMessage", [("call", call as Any), ("message", message as Any)])
|
||||
case .updateGroupCallParticipants(let call, let participants, let version):
|
||||
return ("updateGroupCallParticipants", [("call", call as Any), ("participants", participants as Any), ("version", version as Any)])
|
||||
case .updateInlineBotCallbackQuery(let flags, let queryId, let userId, let msgId, let chatInstance, let data, let gameShortName):
|
||||
@ -3595,32 +3591,18 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
public static func parse_updateGroupCallMessage(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputGroupCall?
|
||||
var _1: Api.InputGroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
}
|
||||
var _3: Api.Peer?
|
||||
var _2: Api.GroupCallMessage?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.GroupCallMessage
|
||||
}
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
var _5: Api.TextWithEntities?
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.TextWithEntities
|
||||
}
|
||||
var _6: Int64?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt64() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.Update.updateGroupCallMessage(flags: _1!, call: _2!, fromId: _3!, randomId: _4!, message: _5!, paidMessageStars: _6)
|
||||
if _c1 && _c2 {
|
||||
return Api.Update.updateGroupCallMessage(call: _1!, message: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
||||
@ -1328,6 +1328,66 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum GroupCallMessage: TypeConstructorDescription {
|
||||
case groupCallMessage(flags: Int32, fromId: Api.Peer, date: Int32, randomId: Int64, message: Api.TextWithEntities, paidMessageStars: Int64?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallMessage(let flags, let fromId, let date, let randomId, let message, let paidMessageStars):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2018173984)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
fromId.serialize(buffer, true)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeInt64(randomId, buffer: buffer, boxed: false)
|
||||
message.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(paidMessageStars!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallMessage(let flags, let fromId, let date, let randomId, let message, let paidMessageStars):
|
||||
return ("groupCallMessage", [("flags", flags as Any), ("fromId", fromId as Any), ("date", date as Any), ("randomId", randomId as Any), ("message", message as Any), ("paidMessageStars", paidMessageStars as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallMessage(_ reader: BufferReader) -> GroupCallMessage? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
var _5: Api.TextWithEntities?
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.TextWithEntities
|
||||
}
|
||||
var _6: Int64?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt64() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.GroupCallMessage.groupCallMessage(flags: _1!, fromId: _2!, date: _3!, randomId: _4!, message: _5!, paidMessageStars: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum GroupCallParticipant: TypeConstructorDescription {
|
||||
case groupCallParticipant(flags: Int32, peer: Api.Peer, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?, about: String?, raiseHandRating: Int64?, video: Api.GroupCallParticipantVideo?, presentation: Api.GroupCallParticipantVideo?, paidStarsTotal: Int64?)
|
||||
@ -1410,57 +1470,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum GroupCallParticipantVideo: TypeConstructorDescription {
|
||||
case groupCallParticipantVideo(flags: Int32, endpoint: String, sourceGroups: [Api.GroupCallParticipantVideoSourceGroup], audioSource: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallParticipantVideo(let flags, let endpoint, let sourceGroups, let audioSource):
|
||||
if boxed {
|
||||
buffer.appendInt32(1735736008)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(endpoint, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(sourceGroups.count))
|
||||
for item in sourceGroups {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(audioSource!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallParticipantVideo(let flags, let endpoint, let sourceGroups, let audioSource):
|
||||
return ("groupCallParticipantVideo", [("flags", flags as Any), ("endpoint", endpoint as Any), ("sourceGroups", sourceGroups as Any), ("audioSource", audioSource as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallParticipantVideo(_ reader: BufferReader) -> GroupCallParticipantVideo? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: [Api.GroupCallParticipantVideoSourceGroup]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipantVideoSourceGroup.self)
|
||||
}
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.GroupCallParticipantVideo.groupCallParticipantVideo(flags: _1!, endpoint: _2!, sourceGroups: _3!, audioSource: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,57 @@
|
||||
public extension Api {
|
||||
enum GroupCallParticipantVideo: TypeConstructorDescription {
|
||||
case groupCallParticipantVideo(flags: Int32, endpoint: String, sourceGroups: [Api.GroupCallParticipantVideoSourceGroup], audioSource: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallParticipantVideo(let flags, let endpoint, let sourceGroups, let audioSource):
|
||||
if boxed {
|
||||
buffer.appendInt32(1735736008)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(endpoint, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(sourceGroups.count))
|
||||
for item in sourceGroups {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(audioSource!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallParticipantVideo(let flags, let endpoint, let sourceGroups, let audioSource):
|
||||
return ("groupCallParticipantVideo", [("flags", flags as Any), ("endpoint", endpoint as Any), ("sourceGroups", sourceGroups as Any), ("audioSource", audioSource as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallParticipantVideo(_ reader: BufferReader) -> GroupCallParticipantVideo? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: [Api.GroupCallParticipantVideoSourceGroup]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipantVideoSourceGroup.self)
|
||||
}
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.GroupCallParticipantVideo.groupCallParticipantVideo(flags: _1!, endpoint: _2!, sourceGroups: _3!, audioSource: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum GroupCallParticipantVideoSourceGroup: TypeConstructorDescription {
|
||||
case groupCallParticipantVideoSourceGroup(semantics: String, sources: [Int32])
|
||||
@ -1192,57 +1246,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputBusinessChatLink: TypeConstructorDescription {
|
||||
case inputBusinessChatLink(flags: Int32, message: String, entities: [Api.MessageEntity]?, title: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputBusinessChatLink(let flags, let message, let entities, let title):
|
||||
if boxed {
|
||||
buffer.appendInt32(292003751)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(message, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(entities!.count))
|
||||
for item in entities! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputBusinessChatLink(let flags, let message, let entities, let title):
|
||||
return ("inputBusinessChatLink", [("flags", flags as Any), ("message", message as Any), ("entities", entities as Any), ("title", title as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputBusinessChatLink(_ reader: BufferReader) -> InputBusinessChatLink? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: [Api.MessageEntity]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
|
||||
} }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = 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
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputBusinessChatLink.inputBusinessChatLink(flags: _1!, message: _2!, entities: _3, title: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,57 @@
|
||||
public extension Api {
|
||||
enum InputBusinessChatLink: TypeConstructorDescription {
|
||||
case inputBusinessChatLink(flags: Int32, message: String, entities: [Api.MessageEntity]?, title: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputBusinessChatLink(let flags, let message, let entities, let title):
|
||||
if boxed {
|
||||
buffer.appendInt32(292003751)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(message, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(entities!.count))
|
||||
for item in entities! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputBusinessChatLink(let flags, let message, let entities, let title):
|
||||
return ("inputBusinessChatLink", [("flags", flags as Any), ("message", message as Any), ("entities", entities as Any), ("title", title as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputBusinessChatLink(_ reader: BufferReader) -> InputBusinessChatLink? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: [Api.MessageEntity]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
|
||||
} }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = 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
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputBusinessChatLink.inputBusinessChatLink(flags: _1!, message: _2!, entities: _3, title: _4)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputBusinessGreetingMessage: TypeConstructorDescription {
|
||||
case inputBusinessGreetingMessage(shortcutId: Int32, recipients: Api.InputBusinessRecipients, noActivityDays: Int32)
|
||||
@ -992,313 +1046,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum InputFileLocation: TypeConstructorDescription {
|
||||
case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
|
||||
case inputEncryptedFileLocation(id: Int64, accessHash: Int64)
|
||||
case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer)
|
||||
case inputGroupCallStream(flags: Int32, call: Api.InputGroupCall, timeMs: Int64, scale: Int32, videoChannel: Int32?, videoQuality: Int32?)
|
||||
case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, photoId: Int64)
|
||||
case inputPhotoFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
|
||||
case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64)
|
||||
case inputSecureFileLocation(id: Int64, accessHash: Int64)
|
||||
case inputStickerSetThumb(stickerset: Api.InputStickerSet, thumbVersion: Int32)
|
||||
case inputTakeoutFileLocation
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1160743548)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeString(thumbSize, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputEncryptedFileLocation(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-182231723)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputFileLocation(let volumeId, let localId, let secret, let fileReference):
|
||||
if boxed {
|
||||
buffer.appendInt32(-539317279)
|
||||
}
|
||||
serializeInt64(volumeId, buffer: buffer, boxed: false)
|
||||
serializeInt32(localId, buffer: buffer, boxed: false)
|
||||
serializeInt64(secret, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
if boxed {
|
||||
buffer.appendInt32(93890858)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
serializeInt64(timeMs, buffer: buffer, boxed: false)
|
||||
serializeInt32(scale, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoChannel!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoQuality!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputPeerPhotoFileLocation(let flags, let peer, let photoId):
|
||||
if boxed {
|
||||
buffer.appendInt32(925204121)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt64(photoId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
if boxed {
|
||||
buffer.appendInt32(1075322878)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeString(thumbSize, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret):
|
||||
if boxed {
|
||||
buffer.appendInt32(-667654413)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeInt64(volumeId, buffer: buffer, boxed: false)
|
||||
serializeInt32(localId, buffer: buffer, boxed: false)
|
||||
serializeInt64(secret, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputSecureFileLocation(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-876089816)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputStickerSetThumb(let stickerset, let thumbVersion):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1652231205)
|
||||
}
|
||||
stickerset.serialize(buffer, true)
|
||||
serializeInt32(thumbVersion, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputTakeoutFileLocation:
|
||||
if boxed {
|
||||
buffer.appendInt32(700340377)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
return ("inputDocumentFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)])
|
||||
case .inputEncryptedFileLocation(let id, let accessHash):
|
||||
return ("inputEncryptedFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputFileLocation(let volumeId, let localId, let secret, let fileReference):
|
||||
return ("inputFileLocation", [("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any), ("fileReference", fileReference as Any)])
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
return ("inputGroupCallStream", [("flags", flags as Any), ("call", call as Any), ("timeMs", timeMs as Any), ("scale", scale as Any), ("videoChannel", videoChannel as Any), ("videoQuality", videoQuality as Any)])
|
||||
case .inputPeerPhotoFileLocation(let flags, let peer, let photoId):
|
||||
return ("inputPeerPhotoFileLocation", [("flags", flags as Any), ("peer", peer as Any), ("photoId", photoId as Any)])
|
||||
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
|
||||
return ("inputPhotoFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)])
|
||||
case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret):
|
||||
return ("inputPhotoLegacyFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any)])
|
||||
case .inputSecureFileLocation(let id, let accessHash):
|
||||
return ("inputSecureFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputStickerSetThumb(let stickerset, let thumbVersion):
|
||||
return ("inputStickerSetThumb", [("stickerset", stickerset as Any), ("thumbVersion", thumbVersion as Any)])
|
||||
case .inputTakeoutFileLocation:
|
||||
return ("inputTakeoutFileLocation", [])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputDocumentFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputDocumentFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputEncryptedFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputEncryptedFileLocation(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Buffer?
|
||||
_4 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputFileLocation(volumeId: _1!, localId: _2!, secret: _3!, fileReference: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputGroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
}
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputFileLocation.inputGroupCallStream(flags: _1!, call: _2!, timeMs: _3!, scale: _4!, videoChannel: _5, videoQuality: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPeerPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
||||
}
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.InputFileLocation.inputPeerPhotoFileLocation(flags: _1!, peer: _2!, photoId: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputFileLocation.inputPhotoFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputPhotoLegacyFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Buffer?
|
||||
_3 = parseBytes(reader)
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int64?
|
||||
_6 = reader.readInt64()
|
||||
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.InputFileLocation.inputPhotoLegacyFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, volumeId: _4!, localId: _5!, secret: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputSecureFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputSecureFileLocation(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputStickerSetThumb(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Api.InputStickerSet?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputStickerSet
|
||||
}
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputFileLocation.inputStickerSetThumb(stickerset: _1!, thumbVersion: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputTakeoutFileLocation(_ reader: BufferReader) -> InputFileLocation? {
|
||||
return Api.InputFileLocation.inputTakeoutFileLocation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,10 +492,6 @@ public final class MediaStreamVideoComponent: Component {
|
||||
} else if !self.hadVideo {
|
||||
aspect = 16.0 / 9
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
aspect = 9.0 / 16.0
|
||||
#endif
|
||||
|
||||
if component.isFullscreen || !component.addInset {
|
||||
videoSize = CGSize(width: aspect * 100.0, height: 100.0).aspectFitted(.init(width: availableSize.width - videoInset * 2, height: availableSize.height))
|
||||
|
||||
@ -930,11 +930,15 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if let data = accountContext.currentAppConfiguration.with({ $0 }).data, let value = data["group_call_message_ttl"] as? Double {
|
||||
messageLifetime = Int32(value)
|
||||
}
|
||||
if isStream {
|
||||
messageLifetime = Int32.max
|
||||
}
|
||||
self.messagesContext = accountContext.engine.messages.groupCallMessages(
|
||||
callId: initialCall.description.id,
|
||||
reference: .id(id: initialCall.description.id, accessHash: initialCall.description.accessHash),
|
||||
e2eContext: self.e2eContext,
|
||||
messageLifetime: messageLifetime
|
||||
messageLifetime: messageLifetime,
|
||||
isLiveStream: isStream
|
||||
)
|
||||
self.messagesStatePromise.set(self.messagesContext!.state)
|
||||
}
|
||||
@ -4032,9 +4036,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
})
|
||||
}
|
||||
|
||||
public func sendMessage(randomId: Int64? = nil, text: String, entities: [MessageTextEntity]) {
|
||||
public func sendMessage(randomId: Int64? = nil, text: String, entities: [MessageTextEntity], paidStars: Int64?) {
|
||||
if let messagesContext = self.messagesContext {
|
||||
messagesContext.send(fromId: self.joinAsPeerId, randomId: randomId, text: text, entities: entities)
|
||||
messagesContext.send(fromId: self.joinAsPeerId, randomId: randomId, text: text, entities: entities, paidStars: paidStars)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1415,7 +1415,7 @@ final class VideoChatScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
let entities = generateTextEntities(text.string, enabledTypes: [.mention, .hashtag], currentEntities: generateChatInputTextEntities(text))
|
||||
call.sendMessage(randomId: randomId, text: text.string, entities: entities)
|
||||
call.sendMessage(randomId: randomId, text: text.string, entities: entities, paidStars: nil)
|
||||
}
|
||||
|
||||
inputPanelView.clearSendMessageInput(updateState: true)
|
||||
@ -3572,6 +3572,7 @@ final class VideoChatScreenComponent: Component {
|
||||
},
|
||||
timeoutAction: nil,
|
||||
forwardAction: nil,
|
||||
paidMessageAction: nil,
|
||||
moreAction: nil,
|
||||
presentCaptionPositionTooltip: nil,
|
||||
presentVoiceMessagesUnavailableTooltip: nil,
|
||||
@ -3833,7 +3834,7 @@ final class VideoChatScreenComponent: Component {
|
||||
guard case let .group(groupCall) = self.currentCall, let call = groupCall as? PresentationGroupCallImpl else {
|
||||
return
|
||||
}
|
||||
call.sendMessage(text: text, entities: entities)
|
||||
call.sendMessage(text: text, entities: entities, paidStars: nil)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ enum AccountStateMutationOperation {
|
||||
case UpdateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32)
|
||||
case UpdateGroupCall(peerId: PeerId?, call: Api.GroupCall)
|
||||
case UpdateGroupCallChainBlocks(id: Int64, accessHash: Int64, subChainId: Int32, blocks: [Data], nextOffset: Int32)
|
||||
case UpdateGroupCallMessage(id: Int64, authorId: PeerId, randomId: Int64, text: Api.TextWithEntities)
|
||||
case UpdateGroupCallMessage(id: Int64, authorId: PeerId, randomId: Int64, text: Api.TextWithEntities, date: Int32, paidMessageStars: Int64?)
|
||||
case UpdateGroupCallOpaqueMessage(id: Int64, authorId: PeerId, data: Data)
|
||||
case UpdateAutoremoveTimeout(peer: Api.Peer, value: CachedPeerAutoremoveTimeout.Value?)
|
||||
case UpdateAttachMenuBots
|
||||
@ -411,8 +411,8 @@ struct AccountMutableState {
|
||||
self.addOperation(.UpdateGroupCallChainBlocks(id: id, accessHash: accessHash, subChainId: subChainId, blocks: blocks, nextOffset: nextOffset))
|
||||
}
|
||||
|
||||
mutating func updateGroupCallMessage(id: Int64, authorId: PeerId, randomId: Int64, text: Api.TextWithEntities) {
|
||||
self.addOperation(.UpdateGroupCallMessage(id: id, authorId: authorId, randomId: randomId, text: text))
|
||||
mutating func updateGroupCallMessage(id: Int64, authorId: PeerId, randomId: Int64, text: Api.TextWithEntities, date: Int32, paidMessageStars: Int64?) {
|
||||
self.addOperation(.UpdateGroupCallMessage(id: id, authorId: authorId, randomId: randomId, text: text, date: date, paidMessageStars: paidMessageStars))
|
||||
}
|
||||
|
||||
mutating func updateGroupCallOpaqueMessage(id: Int64, authorId: PeerId, data: Data) {
|
||||
|
||||
@ -202,10 +202,10 @@ public enum CreateForumChannelTopicError {
|
||||
}
|
||||
|
||||
func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: String, iconColor: Int32, iconFileId: Int64?) -> Signal<Int64, CreateForumChannelTopicError> {
|
||||
return _internal_createForumChannelTopic(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, title: title, iconColor: iconColor, iconFileId: iconFileId)
|
||||
return _internal_createForumChannelTopic(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, title: title, iconColor: iconColor, iconFileId: iconFileId, isTitleMissing: false)
|
||||
}
|
||||
|
||||
func _internal_createForumChannelTopic(postbox: Postbox, network: Network, stateManager: AccountStateManager, accountPeerId: PeerId, peerId: PeerId, title: String, iconColor: Int32, iconFileId: Int64?) -> Signal<Int64, CreateForumChannelTopicError> {
|
||||
func _internal_createForumChannelTopic(postbox: Postbox, network: Network, stateManager: AccountStateManager, accountPeerId: PeerId, peerId: PeerId, title: String, iconColor: Int32, iconFileId: Int64?, isTitleMissing: Bool) -> Signal<Int64, CreateForumChannelTopicError> {
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
@ -222,6 +222,9 @@ func _internal_createForumChannelTopic(postbox: Postbox, network: Network, state
|
||||
flags |= (1 << 3)
|
||||
}
|
||||
flags |= (1 << 0)
|
||||
if isTitleMissing {
|
||||
flags |= (1 << 4)
|
||||
}
|
||||
return network.request(Api.functions.messages.createForumTopic(
|
||||
flags: flags,
|
||||
peer: inputPeer,
|
||||
|
||||
@ -1683,9 +1683,12 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
if case let .inputGroupCall(id, accessHash) = call {
|
||||
updatedState.updateGroupCallChainBlocks(id: id, accessHash: accessHash, subChainId: subChainId, blocks: blocks.map { $0.makeData() }, nextOffset: nextOffset)
|
||||
}
|
||||
case let .updateGroupCallMessage(_, call, fromId, randomId, message, _):
|
||||
case let .updateGroupCallMessage(call, message):
|
||||
if case let .inputGroupCall(id, _) = call {
|
||||
updatedState.updateGroupCallMessage(id: id, authorId: fromId.peerId, randomId: randomId, text: message)
|
||||
switch message {
|
||||
case let .groupCallMessage(_, fromId, date, randomId, message, paidMessageStars):
|
||||
updatedState.updateGroupCallMessage(id: id, authorId: fromId.peerId, randomId: randomId, text: message, date: date, paidMessageStars: paidMessageStars)
|
||||
}
|
||||
}
|
||||
case let .updateGroupCallEncryptedMessage(call, fromId, encryptedMessage):
|
||||
if case let .inputGroupCall(id, _) = call {
|
||||
@ -4879,10 +4882,10 @@ func replayFinalState(
|
||||
callId,
|
||||
.state(update: GroupCallParticipantsContext.Update.StateUpdate(participants: participants, version: version))
|
||||
))
|
||||
case let .UpdateGroupCallMessage(callId, authorId, randomId, text):
|
||||
case let .UpdateGroupCallMessage(callId, authorId, randomId, text, date, paidMessageStars):
|
||||
switch text {
|
||||
case let .textWithEntities(text, entities):
|
||||
groupCallMessageUpdates.append(GroupCallMessageUpdate(callId: callId, update: .newPlaintextMessage(authorId: authorId, randomId: randomId, text: text, entities: messageTextEntitiesFromApiEntities(entities))))
|
||||
groupCallMessageUpdates.append(GroupCallMessageUpdate(callId: callId, update: .newPlaintextMessage(authorId: authorId, randomId: randomId, text: text, entities: messageTextEntitiesFromApiEntities(entities), timestamp: date, paidMessageStars: paidMessageStars)))
|
||||
}
|
||||
case let .UpdateGroupCallOpaqueMessage(callId, authorId, data):
|
||||
groupCallMessageUpdates.append(GroupCallMessageUpdate(callId: callId, update: .newOpaqueMessage(authorId: authorId, data: data)))
|
||||
|
||||
@ -488,15 +488,21 @@ public final class PendingMessageManager {
|
||||
let disposable = MetaDisposable()
|
||||
strongSelf.newTopicDisposables[messagePeerId] = disposable
|
||||
|
||||
var topicName = "New Thread"
|
||||
if !message.text.isEmpty {
|
||||
topicName = String(message.text.prefix(16))
|
||||
}
|
||||
|
||||
disposable.set(_internal_createForumChannelTopic(
|
||||
postbox: strongSelf.postbox,
|
||||
network: strongSelf.network,
|
||||
stateManager: strongSelf.stateManager,
|
||||
accountPeerId: strongSelf.accountPeerId,
|
||||
peerId: message.id.peerId,
|
||||
title: "New Thread",
|
||||
title: topicName,
|
||||
iconColor: 0,
|
||||
iconFileId: nil
|
||||
iconFileId: nil,
|
||||
isTitleMissing: true
|
||||
).startStrict(next: { [weak strongSelf] topicId in
|
||||
guard let strongSelf else {
|
||||
return
|
||||
|
||||
@ -3460,7 +3460,7 @@ func _internal_refreshInlineGroupCall(account: Account, messageId: MessageId) ->
|
||||
|
||||
struct GroupCallMessageUpdate {
|
||||
enum Update {
|
||||
case newPlaintextMessage(authorId: PeerId, randomId: Int64, text: String, entities: [MessageTextEntity])
|
||||
case newPlaintextMessage(authorId: PeerId, randomId: Int64, text: String, entities: [MessageTextEntity], timestamp: Int32, paidMessageStars: Int64?)
|
||||
case newOpaqueMessage(authorId: PeerId, data: Data)
|
||||
}
|
||||
|
||||
@ -3680,14 +3680,16 @@ public final class GroupCallMessagesContext {
|
||||
public let entities: [MessageTextEntity]
|
||||
public let date: Int32
|
||||
public let lifetime: Int32
|
||||
public let paidStars: Int64?
|
||||
|
||||
public init(id: Int64, author: EnginePeer?, text: String, entities: [MessageTextEntity], date: Int32, lifetime: Int32) {
|
||||
public init(id: Int64, author: EnginePeer?, text: String, entities: [MessageTextEntity], date: Int32, lifetime: Int32, paidStars: Int64?) {
|
||||
self.id = id
|
||||
self.author = author
|
||||
self.text = text
|
||||
self.entities = entities
|
||||
self.date = date
|
||||
self.lifetime = lifetime
|
||||
self.paidStars = paidStars
|
||||
}
|
||||
|
||||
public static func ==(lhs: Message, rhs: Message) -> Bool {
|
||||
@ -3712,6 +3714,9 @@ public final class GroupCallMessagesContext {
|
||||
if lhs.lifetime != rhs.lifetime {
|
||||
return false
|
||||
}
|
||||
if lhs.paidStars != rhs.paidStars {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -3726,6 +3731,7 @@ public final class GroupCallMessagesContext {
|
||||
|
||||
private final class Impl {
|
||||
private let messageLifetime: Int32
|
||||
private let isLiveStream: Bool
|
||||
|
||||
let queue: Queue
|
||||
let account: Account
|
||||
@ -3747,13 +3753,14 @@ public final class GroupCallMessagesContext {
|
||||
|
||||
private var messageLifeTimer: SwiftSignalKit.Timer?
|
||||
|
||||
init(queue: Queue, account: Account, callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32) {
|
||||
init(queue: Queue, account: Account, callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32, isLiveStream: Bool) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.callId = callId
|
||||
self.reference = reference
|
||||
self.e2eContext = e2eContext
|
||||
self.messageLifetime = messageLifetime
|
||||
self.isLiveStream = isLiveStream
|
||||
|
||||
self.state = State(messages: [])
|
||||
self.stateValue.set(self.state)
|
||||
@ -3764,16 +3771,16 @@ public final class GroupCallMessagesContext {
|
||||
return
|
||||
}
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent())
|
||||
var addedMessages: [(authorId: PeerId, randomId: Int64, text: String, entities: [MessageTextEntity])] = []
|
||||
var addedMessages: [(authorId: PeerId, randomId: Int64, text: String, entities: [MessageTextEntity], timestamp: Int32, paidMessageStars: Int64?)] = []
|
||||
var addedOpaqueMessages: [(authorId: PeerId, data: Data)] = []
|
||||
for update in updates {
|
||||
if update.callId != self.callId {
|
||||
continue
|
||||
}
|
||||
switch update.update {
|
||||
case let .newPlaintextMessage(authorId, randomId, text, entities):
|
||||
case let .newPlaintextMessage(authorId, randomId, text, entities, timestamp, paidMessageStars):
|
||||
if authorId != self.account.peerId {
|
||||
addedMessages.append((authorId, randomId, text, entities))
|
||||
addedMessages.append((authorId, randomId, text, entities, timestamp, paidMessageStars))
|
||||
}
|
||||
case let .newOpaqueMessage(authorId, data):
|
||||
if authorId != self.account.peerId {
|
||||
@ -3783,6 +3790,9 @@ public final class GroupCallMessagesContext {
|
||||
}
|
||||
|
||||
if !addedMessages.isEmpty || !addedOpaqueMessages.isEmpty {
|
||||
let messageLifetime = self.messageLifetime
|
||||
let isLiveStream = self.isLiveStream
|
||||
|
||||
let _ = (self.account.postbox.transaction { transaction -> [Message] in
|
||||
var messages: [Message] = []
|
||||
if let e2eContext = self.e2eContext {
|
||||
@ -3814,7 +3824,8 @@ public final class GroupCallMessagesContext {
|
||||
text: text,
|
||||
entities: entities,
|
||||
date: currentTime,
|
||||
lifetime: self.messageLifetime
|
||||
lifetime: messageLifetime,
|
||||
paidStars: nil
|
||||
))
|
||||
}
|
||||
} else {
|
||||
@ -3822,13 +3833,22 @@ public final class GroupCallMessagesContext {
|
||||
if self.processedIds.contains(addedMessage.randomId) {
|
||||
continue
|
||||
}
|
||||
|
||||
let lifetime: Int32
|
||||
if isLiveStream {
|
||||
lifetime = Int32(GroupCallMessagesContext.getStarAmountParamMapping(value: addedMessage.paidMessageStars ?? 0).period)
|
||||
} else {
|
||||
lifetime = self.messageLifetime
|
||||
}
|
||||
|
||||
messages.append(Message(
|
||||
id: addedMessage.randomId,
|
||||
author: transaction.getPeer(addedMessage.authorId).flatMap(EnginePeer.init),
|
||||
text: addedMessage.text,
|
||||
entities: addedMessage.entities,
|
||||
date: currentTime,
|
||||
lifetime: self.messageLifetime
|
||||
date: addedMessage.timestamp,
|
||||
lifetime: lifetime,
|
||||
paidStars: addedMessage.paidMessageStars
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -3871,7 +3891,7 @@ public final class GroupCallMessagesContext {
|
||||
}
|
||||
}
|
||||
|
||||
func send(fromId: EnginePeer.Id, randomId requestedRandomId: Int64?, text: String, entities: [MessageTextEntity]) {
|
||||
func send(fromId: EnginePeer.Id, randomId requestedRandomId: Int64?, text: String, entities: [MessageTextEntity], paidStars: Int64?) {
|
||||
let _ = (self.account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(fromId)
|
||||
}
|
||||
@ -3888,6 +3908,14 @@ public final class GroupCallMessagesContext {
|
||||
} else {
|
||||
arc4random_buf(&randomId, 8)
|
||||
}
|
||||
|
||||
let lifetime: Int32
|
||||
if isLiveStream {
|
||||
lifetime = Int32(GroupCallMessagesContext.getStarAmountParamMapping(value: paidStars ?? 0).period)
|
||||
} else {
|
||||
lifetime = self.messageLifetime
|
||||
}
|
||||
|
||||
var state = self.state
|
||||
state.messages.append(Message(
|
||||
id: randomId,
|
||||
@ -3895,10 +3923,18 @@ public final class GroupCallMessagesContext {
|
||||
text: text,
|
||||
entities: entities,
|
||||
date: currentTime,
|
||||
lifetime: self.messageLifetime
|
||||
lifetime: lifetime,
|
||||
paidStars: paidStars
|
||||
))
|
||||
self.state = state
|
||||
|
||||
#if DEBUG
|
||||
var paidStars = paidStars
|
||||
if "".isEmpty {
|
||||
paidStars = nil
|
||||
}
|
||||
#endif
|
||||
|
||||
self.processedIds.insert(randomId)
|
||||
|
||||
if let e2eContext = self.e2eContext, let messageData = serializeGroupCallMessage(randomId: randomId, text: text, entities: entities) {
|
||||
@ -3921,6 +3957,10 @@ public final class GroupCallMessagesContext {
|
||||
} else {
|
||||
arc4random_buf(&randomId, 8)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
if paidStars != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
self.sendMessageDisposables.add(self.account.network.request(Api.functions.phone.sendGroupCallMessage(
|
||||
flags: 0,
|
||||
call: self.reference.apiInputGroupCall,
|
||||
@ -3929,7 +3969,7 @@ public final class GroupCallMessagesContext {
|
||||
text: text,
|
||||
entities: apiEntitiesFromMessageTextEntities(entities, associatedPeers: SimpleDictionary())
|
||||
),
|
||||
allowPaidStars: nil
|
||||
allowPaidStars: paidStars
|
||||
)).startStrict())
|
||||
}
|
||||
})
|
||||
@ -3945,17 +3985,42 @@ public final class GroupCallMessagesContext {
|
||||
}
|
||||
}
|
||||
|
||||
init(account: Account, callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32) {
|
||||
init(account: Account, callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32, isLiveStream: Bool) {
|
||||
let queue = Queue(name: "GroupCallMessagesContext")
|
||||
self.queue = queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return Impl(queue: queue, account: account, callId: callId, reference: reference, e2eContext: e2eContext, messageLifetime: messageLifetime)
|
||||
return Impl(queue: queue, account: account, callId: callId, reference: reference, e2eContext: e2eContext, messageLifetime: messageLifetime, isLiveStream: isLiveStream)
|
||||
})
|
||||
}
|
||||
|
||||
public func send(fromId: EnginePeer.Id, randomId: Int64?, text: String, entities: [MessageTextEntity]) {
|
||||
public func send(fromId: EnginePeer.Id, randomId: Int64?, text: String, entities: [MessageTextEntity], paidStars: Int64?) {
|
||||
self.impl.with { impl in
|
||||
impl.send(fromId: fromId, randomId: randomId, text: text, entities: entities)
|
||||
impl.send(fromId: fromId, randomId: randomId, text: text, entities: entities, paidStars: paidStars)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getStarAmountParamMapping(value: Int64) -> (period: Int, maxLength: Int, emojiCount: Int) {
|
||||
if value >= 10000 {
|
||||
return (3600, 400, 20)
|
||||
}
|
||||
if value >= 2000 {
|
||||
return (1800, 280, 10)
|
||||
}
|
||||
if value >= 500 {
|
||||
return (900, 200, 7)
|
||||
}
|
||||
if value >= 250 {
|
||||
return (600, 150, 4)
|
||||
}
|
||||
if value >= 100 {
|
||||
return (300, 110, 3)
|
||||
}
|
||||
if value >= 50 {
|
||||
return (120, 80, 2)
|
||||
}
|
||||
if value >= 10 {
|
||||
return (60, 60, 1)
|
||||
}
|
||||
return (30, 30, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1648,8 +1648,8 @@ public extension TelegramEngine {
|
||||
return _internal_refreshGlobalPostSearchState(account: self.account)
|
||||
}
|
||||
|
||||
public func groupCallMessages(callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32) -> GroupCallMessagesContext {
|
||||
return GroupCallMessagesContext(account: self.account, callId: callId, reference: reference, e2eContext: e2eContext, messageLifetime: messageLifetime)
|
||||
public func groupCallMessages(callId: Int64, reference: InternalGroupCallReference, e2eContext: ConferenceCallE2EContext?, messageLifetime: Int32, isLiveStream: Bool) -> GroupCallMessagesContext {
|
||||
return GroupCallMessagesContext(account: self.account, callId: callId, reference: reference, e2eContext: e2eContext, messageLifetime: messageLifetime, isLiveStream: isLiveStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,13 +135,16 @@ private final class BalanceComponent: CombinedComponent {
|
||||
private final class BadgeComponent: Component {
|
||||
let theme: PresentationTheme
|
||||
let title: String
|
||||
let color: UIColor
|
||||
|
||||
init(
|
||||
theme: PresentationTheme,
|
||||
title: String
|
||||
title: String,
|
||||
color: UIColor
|
||||
) {
|
||||
self.theme = theme
|
||||
self.title = title
|
||||
self.color = color
|
||||
}
|
||||
|
||||
static func ==(lhs: BadgeComponent, rhs: BadgeComponent) -> Bool {
|
||||
@ -151,6 +154,9 @@ private final class BadgeComponent: Component {
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.color != rhs.color {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -242,6 +248,7 @@ private final class BadgeComponent: Component {
|
||||
self.badgeIcon.image = UIImage(bundleImageName: "Premium/SendStarsStarSliderIcon")?.withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
|
||||
let previousComponent = self.component
|
||||
self.component = component
|
||||
self.badgeIcon.tintColor = .white
|
||||
|
||||
@ -268,12 +275,12 @@ private final class BadgeComponent: Component {
|
||||
let size = badgeSize
|
||||
transition.setFrame(view: self.badgeLabel, frame: CGRect(origin: CGPoint(x: 14.0 + floorToScreenPixels((badgeFullSize.width - badgeLabelSize.width) / 2.0), y: 5.0), size: badgeLabelSize))
|
||||
|
||||
if self.previousAvailableSize != availableSize {
|
||||
if self.previousAvailableSize != availableSize || previousComponent?.color != component.color {
|
||||
self.previousAvailableSize = availableSize
|
||||
|
||||
let activeColors: [UIColor] = [
|
||||
UIColor(rgb: 0xFFAB03),
|
||||
UIColor(rgb: 0xFFCB37)
|
||||
component.color,
|
||||
component.color
|
||||
]
|
||||
|
||||
var locations: [CGFloat] = []
|
||||
@ -421,7 +428,7 @@ private final class PeerBadgeComponent: Component {
|
||||
let contentSize = CGSize(width: iconSize.width + titleSpacing + titleSize.width, height: titleSize.height)
|
||||
let size = CGSize(width: contentSize.width + sideInset * 2.0, height: contentSize.height + 3.0 * 2.0)
|
||||
|
||||
self.backgroundMaskLayer.backgroundColor = component.theme.list.plainBackgroundColor.cgColor
|
||||
self.backgroundMaskLayer.backgroundColor = component.theme.overallDarkAppearance ? component.theme.list.blocksBackgroundColor.cgColor : component.theme.list.plainBackgroundColor.cgColor
|
||||
self.backgroundLayer.backgroundColor = UIColor(rgb: 0xFFB10D).cgColor
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(), size: size)
|
||||
@ -599,17 +606,20 @@ private final class SliderBackgroundComponent: Component {
|
||||
let strings: PresentationStrings
|
||||
let value: CGFloat
|
||||
let topCutoff: CGFloat?
|
||||
let color: UIColor
|
||||
|
||||
init(
|
||||
theme: PresentationTheme,
|
||||
strings: PresentationStrings,
|
||||
value: CGFloat,
|
||||
topCutoff: CGFloat?
|
||||
topCutoff: CGFloat?,
|
||||
color: UIColor
|
||||
) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.value = value
|
||||
self.topCutoff = topCutoff
|
||||
self.color = color
|
||||
}
|
||||
|
||||
static func ==(lhs: SliderBackgroundComponent, rhs: SliderBackgroundComponent) -> Bool {
|
||||
@ -625,6 +635,9 @@ private final class SliderBackgroundComponent: Component {
|
||||
if lhs.topCutoff != rhs.topCutoff {
|
||||
return false
|
||||
}
|
||||
if lhs.color != rhs.color {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -692,7 +705,7 @@ private final class SliderBackgroundComponent: Component {
|
||||
|
||||
func update(component: SliderBackgroundComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.sliderBackground.backgroundColor = component.theme.list.itemPrimaryTextColor.withMultipliedAlpha(component.theme.overallDarkAppearance ? 0.2 : 0.07)
|
||||
self.sliderForeground.backgroundColor = UIColor(rgb: 0xFFB10D)
|
||||
self.sliderForeground.backgroundColor = component.color
|
||||
self.topForegroundLine.backgroundColor = component.theme.list.plainBackgroundColor.cgColor
|
||||
self.topBackgroundLine.backgroundColor = component.theme.list.plainBackgroundColor.cgColor
|
||||
|
||||
@ -1429,6 +1442,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
switch component.initialData.subjectInitialData {
|
||||
case let .react(reactData):
|
||||
targetPeerId = reactData.peer.id
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
targetPeerId = liveStreamMessageData.peer.id
|
||||
}
|
||||
|
||||
let _ = (context.engine.payments.starsTopUpOptions()
|
||||
@ -1502,6 +1517,11 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
})
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
self.currentMyPeer = nil
|
||||
self.amount = Amount(realValue: 50, maxRealValue: liveStreamMessageData.maxAmount, maxSliderValue: 999, isLogarithmic: true)
|
||||
|
||||
self.privacyPeer = .account
|
||||
}
|
||||
|
||||
if let starsContext = component.context.starsContext {
|
||||
@ -1559,6 +1579,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
switch component.initialData.subjectInitialData {
|
||||
case let .react(reactData):
|
||||
maxAmount = reactData.maxAmount
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
maxAmount = liveStreamMessageData.maxAmount
|
||||
}
|
||||
|
||||
self.amount = self.amount.withSliderValue(value)
|
||||
@ -1612,6 +1634,7 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
var topCutoffFraction: CGFloat?
|
||||
|
||||
var topCount: Int?
|
||||
var sliderColor: UIColor = UIColor(rgb: 0xFFB10D)
|
||||
switch component.initialData.subjectInitialData {
|
||||
case let .react(reactData):
|
||||
let topOthersCount: Int? = reactData.topPeers.filter({ !$0.isMy }).max(by: { $0.count < $1.count })?.count
|
||||
@ -1638,6 +1661,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
} else {
|
||||
self.isPastTopCutoff = nil
|
||||
}
|
||||
case .liveStreamMessage:
|
||||
sliderColor = getLiveStreamStarAmountColorMapping(value: Int64(self.amount.realValue))
|
||||
}
|
||||
|
||||
let _ = self.sliderBackground.update(
|
||||
@ -1646,7 +1671,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
value: progressFraction,
|
||||
topCutoff: topCutoffFraction
|
||||
topCutoff: topCutoffFraction,
|
||||
color: sliderColor
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: sliderBackgroundFrame.size
|
||||
@ -1666,7 +1692,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(BadgeComponent(
|
||||
theme: environment.theme,
|
||||
title: "\(self.amount.realValue)"
|
||||
title: "\(self.amount.realValue)",
|
||||
color: sliderColor
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
||||
@ -1761,6 +1788,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
transition.setFrame(view: peerSelectorButtonView, frame: peerSelectorButtonFrame)
|
||||
peerSelectorButtonView.isHidden = sendAsPeers.count <= 1
|
||||
}
|
||||
case .liveStreamMessage:
|
||||
break
|
||||
}
|
||||
|
||||
if themeUpdated {
|
||||
@ -1812,6 +1841,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
case let .react(reactData):
|
||||
let currentMyPeer = self.currentMyPeer ?? reactData.myPeer
|
||||
subtitleText = environment.strings.SendStarReactions_SubtitleFrom(currentMyPeer.compactDisplayTitle).string
|
||||
case .liveStreamMessage:
|
||||
subtitleText = nil
|
||||
}
|
||||
|
||||
var subtitleSize: CGSize?
|
||||
@ -1830,6 +1861,9 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
switch component.initialData.subjectInitialData {
|
||||
case .react:
|
||||
titleText = environment.strings.SendStarReactions_Title
|
||||
case .liveStreamMessage:
|
||||
//TODO:localize
|
||||
titleText = "Highlight and Pin"
|
||||
}
|
||||
|
||||
let titleSize = title.update(
|
||||
@ -1877,6 +1911,9 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
} else {
|
||||
text = environment.strings.SendStarReactions_TextGeneric(reactData.peer.debugDisplayTitle).string
|
||||
}
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
//TODO:localize
|
||||
text = "Highlight and pin a message\nby adding Stars for **\(liveStreamMessageData.peer.displayTitle(strings: environment.strings, displayOrder: .firstLast))**."
|
||||
}
|
||||
|
||||
let body = MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)
|
||||
@ -2242,6 +2279,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
}
|
||||
|
||||
contentHeight += anonymousContentsSize.height + 27.0
|
||||
case .liveStreamMessage:
|
||||
break
|
||||
}
|
||||
|
||||
initialContentHeight = contentHeight
|
||||
@ -2254,11 +2293,14 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
switch component.initialData.subjectInitialData {
|
||||
case .react:
|
||||
buttonString = environment.strings.SendStarReactions_SendButtonTitle("\(self.amount.realValue)").string
|
||||
case .liveStreamMessage:
|
||||
//TODO:localize
|
||||
buttonString = "Add # \(self.amount.realValue)"
|
||||
}
|
||||
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: .white, paragraphAlignment: .center)
|
||||
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||
if let range = buttonAttributedString.string.range(of: "#"), let starImage = self.cachedStarImage?.0 {
|
||||
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
||||
buttonAttributedString.addAttribute(.foregroundColor, value: UIColor(rgb: 0xffffff), range: NSRange(range, in: buttonAttributedString.string))
|
||||
buttonAttributedString.addAttribute(.foregroundColor, value: environment.theme.list.itemCheckColors.foregroundColor, range: NSRange(range, in: buttonAttributedString.string))
|
||||
buttonAttributedString.addAttribute(.baselineOffset, value: 1.0, range: NSRange(range, in: buttonAttributedString.string))
|
||||
}
|
||||
|
||||
@ -2300,6 +2342,9 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
switch component.initialData.subjectInitialData {
|
||||
case let .react(reactData):
|
||||
purchasePurpose = .reactions(peerId: reactData.peer.id, requiredStars: Int64(self.amount.realValue))
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
//TODO:localize
|
||||
purchasePurpose = .reactions(peerId: liveStreamMessageData.peer.id, requiredStars: Int64(self.amount.realValue))
|
||||
}
|
||||
|
||||
let purchaseScreen = component.context.sharedContext.makeStarsPurchaseScreen(context: component.context, starsContext: starsContext, options: options, purpose: purchasePurpose, targetPeerId: nil, completion: { result in
|
||||
@ -2343,6 +2388,13 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
sourceView: badgeView.badgeIcon
|
||||
)
|
||||
)
|
||||
case let .liveStreamMessage(liveStreamMessageData):
|
||||
liveStreamMessageData.completion(
|
||||
Int64(self.amount.realValue),
|
||||
ChatSendStarsScreen.TransitionOut(
|
||||
sourceView: badgeView.badgeIcon
|
||||
)
|
||||
)
|
||||
}
|
||||
self.environment?.controller()?.dismiss()
|
||||
}
|
||||
@ -2486,7 +2538,20 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
}
|
||||
|
||||
final class LiveStreamMessage {
|
||||
let peer: EnginePeer
|
||||
let maxAmount: Int
|
||||
let completion: (Int64, ChatSendStarsScreen.TransitionOut) -> Void
|
||||
|
||||
init(peer: EnginePeer, maxAmount: Int, completion: @escaping (Int64, ChatSendStarsScreen.TransitionOut) -> Void) {
|
||||
self.peer = peer
|
||||
self.maxAmount = maxAmount
|
||||
self.completion = completion
|
||||
}
|
||||
}
|
||||
|
||||
case react(React)
|
||||
case liveStreamMessage(LiveStreamMessage)
|
||||
}
|
||||
|
||||
public final class InitialData {
|
||||
@ -2565,15 +2630,15 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
|
||||
private var didPlayAppearAnimation: Bool = false
|
||||
private var isDismissed: Bool = false
|
||||
|
||||
private var presenceDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext, initialData: InitialData) {
|
||||
public init(context: AccountContext, initialData: InitialData, theme: PresentationTheme? = nil) {
|
||||
self.context = context
|
||||
|
||||
super.init(context: context, component: ChatSendStarsScreenComponent(
|
||||
context: context,
|
||||
initialData: initialData
|
||||
), navigationBarAppearance: .none)
|
||||
), navigationBarAppearance: .none, theme: theme.flatMap {
|
||||
return .custom($0)
|
||||
} ?? .default)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
self.navigationPresentation = .flatModal
|
||||
@ -2585,7 +2650,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.presenceDisposable?.dispose()
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
@ -2739,6 +2803,45 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
}
|
||||
|
||||
public static func initialDataLiveStreamMessage(context: AccountContext, peerId: EnginePeer.Id, completion: @escaping (Int64, TransitionOut) -> Void) -> Signal<InitialData?, NoError> {
|
||||
let balance: Signal<StarsAmount?, NoError>
|
||||
if let starsContext = context.starsContext {
|
||||
balance = starsContext.state
|
||||
|> map { state in
|
||||
return state?.balance
|
||||
}
|
||||
|> take(1)
|
||||
} else {
|
||||
balance = .single(nil)
|
||||
}
|
||||
|
||||
var maxAmount = 10000
|
||||
if let data = context.currentAppConfiguration.with({ $0 }).data, let value = data["stars_live_stream_pin_amount_max"] as? Double {
|
||||
maxAmount = Int(value)
|
||||
}
|
||||
|
||||
return combineLatest(
|
||||
context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
|
||||
),
|
||||
balance
|
||||
)
|
||||
|> map { peer, balance -> InitialData? in
|
||||
guard let peer else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return InitialData(
|
||||
subjectInitialData: .liveStreamMessage(SubjectInitialData.LiveStreamMessage(
|
||||
peer: peer,
|
||||
maxAmount: maxAmount,
|
||||
completion: completion
|
||||
)),
|
||||
balance: balance
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||
if !self.isDismissed {
|
||||
self.isDismissed = true
|
||||
@ -3138,3 +3241,25 @@ final class HeaderContextReferenceContentSource: ContextReferenceContentSource {
|
||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds, actionsPosition: self.actionsOnTop ? .top : .bottom)
|
||||
}
|
||||
}
|
||||
|
||||
private func getLiveStreamStarAmountColorMapping(value: Int64) -> UIColor {
|
||||
if value >= 10000 {
|
||||
return UIColor(rgb: 0x7C8695)
|
||||
}
|
||||
if value >= 2000 {
|
||||
return UIColor(rgb: 0xE6514E)
|
||||
}
|
||||
if value >= 500 {
|
||||
return UIColor(rgb: 0xEE7E20)
|
||||
}
|
||||
if value >= 250 {
|
||||
return UIColor(rgb: 0xE4A20A)
|
||||
}
|
||||
if value >= 100 {
|
||||
return UIColor(rgb: 0x5AB03D)
|
||||
}
|
||||
if value >= 50 {
|
||||
return UIColor(rgb: 0x3E9CDF)
|
||||
}
|
||||
return UIColor(rgb: 0x985FDC)
|
||||
}
|
||||
|
||||
@ -261,6 +261,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
||||
}
|
||||
} : nil,
|
||||
forwardAction: nil,
|
||||
paidMessageAction: nil,
|
||||
moreAction: nil,
|
||||
presentCaptionPositionTooltip: { [weak self] sourceView in
|
||||
if let self {
|
||||
|
||||
@ -1453,6 +1453,7 @@ final class MediaEditorScreenComponent: Component {
|
||||
controller.presentTimeoutSetup(sourceView: view, gesture: gesture)
|
||||
},
|
||||
forwardAction: nil,
|
||||
paidMessageAction: nil,
|
||||
moreAction: nil,
|
||||
presentCaptionPositionTooltip: nil,
|
||||
presentVoiceMessagesUnavailableTooltip: nil,
|
||||
|
||||
@ -275,6 +275,7 @@ final class StoryPreviewComponent: Component {
|
||||
inputModeAction: nil,
|
||||
timeoutAction: nil,
|
||||
forwardAction: {},
|
||||
paidMessageAction: nil,
|
||||
moreAction: { _, _ in },
|
||||
presentCaptionPositionTooltip: nil,
|
||||
presentVoiceMessagesUnavailableTooltip: nil,
|
||||
|
||||
@ -261,6 +261,8 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
private var backgroundView: GlassBackgroundView?
|
||||
private let sendIconView: UIImageView
|
||||
private var reactionHeartView: UIImageView?
|
||||
private var starsIconView: UIImageView?
|
||||
private var starsTextView: ComponentView<Empty>?
|
||||
private var moreButton: MoreHeaderButton?
|
||||
private var animation: ComponentView<Empty>?
|
||||
private var reactionIconView: ReactionIconView?
|
||||
@ -684,6 +686,42 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if case let .stars(amount) = component.mode {
|
||||
let _ = amount
|
||||
var starsTransition = transition
|
||||
|
||||
let starsIconView: UIImageView
|
||||
if let current = self.starsIconView {
|
||||
starsIconView = current
|
||||
} else {
|
||||
starsTransition = starsTransition.withAnimation(.none)
|
||||
starsIconView = UIImageView()
|
||||
self.starsIconView = starsIconView
|
||||
starsIconView.image = UIImage(bundleImageName: "Premium/Stars/ButtonStar")?.withRenderingMode(.alwaysTemplate)
|
||||
starsIconView.tintColor = .white
|
||||
self.addSubview(starsIconView)
|
||||
|
||||
if !transition.animation.isImmediate {
|
||||
starsIconView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
|
||||
}
|
||||
}
|
||||
|
||||
if let image = starsIconView.image {
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - image.size.width) * 0.5), y: floorToScreenPixels((availableSize.height - image.size.height) * 0.5)), size: image.size)
|
||||
starsTransition.setPosition(view: starsIconView, position: iconFrame.center)
|
||||
starsTransition.setBounds(view: starsIconView, bounds: CGRect(origin: CGPoint(), size: iconFrame.size))
|
||||
}
|
||||
} else {
|
||||
if let starsIconView = self.starsIconView {
|
||||
self.starsIconView = nil
|
||||
starsIconView.removeFromSuperview()
|
||||
}
|
||||
if let starsTextView = self.starsTextView {
|
||||
self.starsTextView = nil
|
||||
starsTextView.view?.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.button.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
transition.setFrame(view: self.containerNode.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
transition.setFrame(view: self.referenceNode.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
|
||||
@ -201,6 +201,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
public let inputModeAction: (() -> Void)?
|
||||
public let timeoutAction: ((UIView, ContextGesture?) -> Void)?
|
||||
public let forwardAction: (() -> Void)?
|
||||
public let paidMessageAction: (() -> Void)?
|
||||
public let moreAction: ((UIView, ContextGesture?) -> Void)?
|
||||
public let presentCaptionPositionTooltip: ((UIView) -> Void)?
|
||||
public let presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?
|
||||
@ -260,6 +261,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
inputModeAction: (() -> Void)?,
|
||||
timeoutAction: ((UIView, ContextGesture?) -> Void)?,
|
||||
forwardAction: (() -> Void)?,
|
||||
paidMessageAction: (() -> Void)?,
|
||||
moreAction: ((UIView, ContextGesture?) -> Void)?,
|
||||
presentCaptionPositionTooltip: ((UIView) -> Void)?,
|
||||
presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?,
|
||||
@ -318,6 +320,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
self.inputModeAction = inputModeAction
|
||||
self.timeoutAction = timeoutAction
|
||||
self.forwardAction = forwardAction
|
||||
self.paidMessageAction = paidMessageAction
|
||||
self.moreAction = moreAction
|
||||
self.presentCaptionPositionTooltip = presentCaptionPositionTooltip
|
||||
self.presentVoiceMessagesUnavailableTooltip = presentVoiceMessagesUnavailableTooltip
|
||||
@ -501,6 +504,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
private let inputActionButton = ComponentView<Empty>()
|
||||
private let likeButton = ComponentView<Empty>()
|
||||
private let stickerButton = ComponentView<Empty>()
|
||||
private var paidMessageButton: ComponentView<Empty>?
|
||||
private let timeoutButton = ComponentView<Empty>()
|
||||
|
||||
private var mediaRecordingVibrancyContainer: UIView
|
||||
@ -816,6 +820,11 @@ public final class MessageInputPanelComponent: Component {
|
||||
if component.bottomInset <= 32.0 && !component.forceIsEditing && !component.hideKeyboard && !self.textFieldExternalState.isEditing {
|
||||
textFieldSideInset += 18.0
|
||||
insets.right += 18.0
|
||||
} else {
|
||||
#if DEBUG
|
||||
textFieldSideInset += 8.0
|
||||
insets.right += 8.0
|
||||
#endif
|
||||
}
|
||||
|
||||
var mediaInsets = UIEdgeInsets(top: insets.top, left: textFieldSideInset, bottom: insets.bottom, right: 40.0 + 8.0)
|
||||
@ -1078,6 +1087,10 @@ public final class MessageInputPanelComponent: Component {
|
||||
} else if isEditing || component.style == .editor || component.style == .media {
|
||||
fieldBackgroundFrame = fieldFrame
|
||||
} else {
|
||||
#if DEBUG
|
||||
fieldBackgroundFrame = fieldFrame
|
||||
fieldBackgroundFrame.size.width += 16.0
|
||||
#else
|
||||
if component.forwardAction != nil && component.likeAction != nil {
|
||||
fieldBackgroundFrame = CGRect(origin: CGPoint(x: mediaInsets.left, y: insets.top), size: CGSize(width: availableSize.width - mediaInsets.left - insets.right - 49.0, height: textFieldSize.height))
|
||||
} else if component.forwardAction != nil {
|
||||
@ -1085,6 +1098,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
} else {
|
||||
fieldBackgroundFrame = CGRect(origin: CGPoint(x: mediaInsets.left, y: insets.top), size: CGSize(width: availableSize.width - mediaInsets.left - 50.0, height: textFieldSize.height))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
let rawFieldBackgroundFrame = fieldBackgroundFrame
|
||||
@ -1103,7 +1117,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
self.fieldBackgroundTint.isHidden = true
|
||||
}
|
||||
if let fieldGlassBackgroundView = self.fieldGlassBackgroundView {
|
||||
fieldGlassBackgroundView.update(size: fieldBackgroundFrame.size, cornerRadius: baseFieldHeight * 0.5, isDark: true, tintColor: component.style == .story ? .init(kind: .panel, color: defaultDarkPresentationTheme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)) : .init(kind: .custom, color: UIColor(rgb: 0x25272e, alpha: 0.72)), transition: transition)
|
||||
fieldGlassBackgroundView.update(size: fieldBackgroundFrame.size, cornerRadius: baseFieldHeight * 0.5, isDark: true, tintColor: component.style == .story ? .init(kind: .panel, color: defaultDarkPresentationTheme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)) : .init(kind: .custom, color: UIColor(rgb: 0x25272e, alpha: 0.72)), isInteractive: true, transition: transition)
|
||||
transition.setFrame(view: fieldGlassBackgroundView, frame: fieldBackgroundFrame)
|
||||
}
|
||||
default:
|
||||
@ -1552,22 +1566,35 @@ public final class MessageInputPanelComponent: Component {
|
||||
if case .story = component.style {
|
||||
inputActionButtonAvailableSize = CGSize(width: 40.0, height: 40.0)
|
||||
}
|
||||
if hasMediaEditing {
|
||||
inputActionButtonMode = .send
|
||||
} else {
|
||||
|
||||
if let storyItem = component.storyItem, case .liveStream = storyItem.media {
|
||||
if self.textFieldExternalState.hasText {
|
||||
if let sendPaidMessageStars = component.sendPaidMessageStars, !"".isEmpty {
|
||||
inputActionButtonMode = .stars(sendPaidMessageStars.value)
|
||||
} else {
|
||||
inputActionButtonMode = .send
|
||||
}
|
||||
} else if !isEditing && component.forwardAction != nil {
|
||||
inputActionButtonMode = .forward
|
||||
} else {
|
||||
if component.areVoiceMessagesAvailable {
|
||||
inputActionButtonMode = self.currentMediaInputIsVoice ? .voiceInput : .videoInput
|
||||
inputActionButtonMode = .stars(123)
|
||||
}
|
||||
} else {
|
||||
if hasMediaEditing {
|
||||
inputActionButtonMode = .send
|
||||
} else {
|
||||
if self.textFieldExternalState.hasText {
|
||||
if let sendPaidMessageStars = component.sendPaidMessageStars, !"".isEmpty {
|
||||
inputActionButtonMode = .stars(sendPaidMessageStars.value)
|
||||
} else {
|
||||
inputActionButtonMode = .send
|
||||
}
|
||||
} else if !isEditing && component.forwardAction != nil {
|
||||
inputActionButtonMode = .forward
|
||||
} else {
|
||||
inputActionButtonMode = .unavailableVoiceInput
|
||||
if component.areVoiceMessagesAvailable {
|
||||
inputActionButtonMode = self.currentMediaInputIsVoice ? .voiceInput : .videoInput
|
||||
} else {
|
||||
inputActionButtonMode = .unavailableVoiceInput
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1803,6 +1830,13 @@ public final class MessageInputPanelComponent: Component {
|
||||
if isEditing {
|
||||
inputModeVisible = true
|
||||
}
|
||||
var isLiveStream = false
|
||||
if let storyItem = component.storyItem, case .liveStream = storyItem.media {
|
||||
isLiveStream = true
|
||||
}
|
||||
if isLiveStream && component.sendPaidMessageStars == nil {
|
||||
inputModeVisible = false
|
||||
}
|
||||
|
||||
let animationName: String
|
||||
var animationPlay = false
|
||||
@ -1900,6 +1934,58 @@ public final class MessageInputPanelComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if let _ = component.paidMessageAction {
|
||||
let paidMessageButton: ComponentView<Empty>
|
||||
var paidMessageButtonTransition = transition
|
||||
if let current = self.paidMessageButton {
|
||||
paidMessageButton = current
|
||||
} else {
|
||||
paidMessageButton = ComponentView()
|
||||
self.paidMessageButton = paidMessageButton
|
||||
paidMessageButtonTransition = paidMessageButtonTransition.withAnimation(.none)
|
||||
}
|
||||
|
||||
let paidMessageButtonSize = paidMessageButton.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(Button(
|
||||
content: AnyComponent(BundleIconComponent(
|
||||
name: "Chat/Input/Text/AccessoryIconSuggestPost",
|
||||
tintColor: defaultDarkPresentationTheme.chat.inputPanel.inputControlColor
|
||||
)),
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.component?.paidMessageAction?()
|
||||
}
|
||||
).minSize(CGSize(width: 32.0, height: 32.0))),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 32.0, height: 32.0)
|
||||
)
|
||||
if let paidMessageButtonView = paidMessageButton.view as? Button.View {
|
||||
if paidMessageButtonView.superview == nil {
|
||||
paidMessageButtonView.alpha = 0.0
|
||||
self.addSubview(paidMessageButtonView)
|
||||
}
|
||||
let paidMessageButtonFrame = CGRect(origin: CGPoint(x: fieldIconNextX - paidMessageButtonSize.width, y: fieldBackgroundFrame.maxY - 4.0 - paidMessageButtonSize.height), size: paidMessageButtonSize)
|
||||
transition.setPosition(view: paidMessageButtonView, position: paidMessageButtonFrame.center)
|
||||
transition.setBounds(view: paidMessageButtonView, bounds: CGRect(origin: CGPoint(), size: paidMessageButtonFrame.size))
|
||||
|
||||
transition.setAlpha(view: paidMessageButtonView, alpha: 1.0)
|
||||
|
||||
fieldIconNextX -= paidMessageButtonSize.width + 2.0
|
||||
}
|
||||
} else {
|
||||
if let paidMessageButton = self.paidMessageButton {
|
||||
self.paidMessageButton = nil
|
||||
if let paidMessageButtonView = paidMessageButton.view {
|
||||
transition.setAlpha(view: paidMessageButtonView, alpha: 0.0, completion: { [weak paidMessageButtonView] _ in
|
||||
paidMessageButtonView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let accentColor = component.theme.chat.inputPanel.panelControlAccentColor
|
||||
if let timeoutAction = component.timeoutAction, let timeoutValue = component.timeoutValue {
|
||||
let timeoutButtonSize = self.timeoutButton.update(
|
||||
|
||||
@ -102,6 +102,11 @@ swift_library(
|
||||
"//submodules/DirectMediaImageCache",
|
||||
"//submodules/PromptUI",
|
||||
"//submodules/TelegramCallsUI",
|
||||
"//submodules/TelegramUI/Components/AsyncListComponent",
|
||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatSendStarsScreen",
|
||||
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
||||
@ -68,6 +68,7 @@ public final class StoryContentItem: Equatable {
|
||||
public let externalState: ExternalState
|
||||
public let sharedState: SharedState
|
||||
public let theme: PresentationTheme
|
||||
public let containerInsets: UIEdgeInsets
|
||||
public let presentationProgressUpdated: (Double, Bool, Bool) -> Void
|
||||
public let markAsSeen: (StoryId) -> Void
|
||||
|
||||
@ -75,12 +76,14 @@ public final class StoryContentItem: Equatable {
|
||||
externalState: ExternalState,
|
||||
sharedState: SharedState,
|
||||
theme: PresentationTheme,
|
||||
containerInsets: UIEdgeInsets,
|
||||
presentationProgressUpdated: @escaping (Double, Bool, Bool) -> Void,
|
||||
markAsSeen: @escaping (StoryId) -> Void
|
||||
) {
|
||||
self.externalState = externalState
|
||||
self.sharedState = sharedState
|
||||
self.theme = theme
|
||||
self.containerInsets = containerInsets
|
||||
self.presentationProgressUpdated = presentationProgressUpdated
|
||||
self.markAsSeen = markAsSeen
|
||||
}
|
||||
@ -95,6 +98,9 @@ public final class StoryContentItem: Equatable {
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.containerInsets != rhs.containerInsets {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,849 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import ComponentFlow
|
||||
import MultilineTextComponent
|
||||
import AccountContext
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import SwiftSignalKit
|
||||
import TelegramCallsUI
|
||||
import AsyncListComponent
|
||||
import AvatarNode
|
||||
import MultilineTextWithEntitiesComponent
|
||||
import GlassBackgroundComponent
|
||||
import MultilineTextComponent
|
||||
|
||||
private final class MessageItemComponent: Component {
|
||||
let context: AccountContext
|
||||
let strings: PresentationStrings
|
||||
let theme: PresentationTheme
|
||||
let message: GroupCallMessagesContext.Message
|
||||
|
||||
init(context: AccountContext, strings: PresentationStrings, theme: PresentationTheme, message: GroupCallMessagesContext.Message) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.message = message
|
||||
}
|
||||
|
||||
static func ==(lhs: MessageItemComponent, rhs: MessageItemComponent) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.message != rhs.message {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let contentContainer: UIView
|
||||
private var avatarNode: AvatarNode?
|
||||
private let text = ComponentView<Empty>()
|
||||
private var backgroundView: UIImageView?
|
||||
|
||||
private var component: MessageItemComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
private var isUpdating: Bool = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.contentContainer = UIView()
|
||||
self.contentContainer.transform = CGAffineTransformMakeRotation(-CGFloat.pi)
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.contentContainer)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let result = super.hitTest(point, with: event) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func update(component: MessageItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.isUpdating = true
|
||||
defer {
|
||||
self.isUpdating = false
|
||||
}
|
||||
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
let insets = UIEdgeInsets(top: 8.0, left: 20.0, bottom: 8.0, right: 20.0)
|
||||
let avatarSize: CGFloat = 24.0
|
||||
let avatarSpacing: CGFloat = 6.0
|
||||
|
||||
let textString = NSMutableAttributedString()
|
||||
textString.append(NSAttributedString(string: component.message.author?.displayTitle(strings: component.strings, displayOrder: .firstLast) ?? " ", font: Font.semibold(15.0), textColor: UIColor(white: 0.9, alpha: 1.0)))
|
||||
textString.append(NSAttributedString(string: " ", font: Font.semibold(15.0), textColor: UIColor(white: 0.9, alpha: 1.0)))
|
||||
textString.append(NSAttributedString(string: component.message.text, font: Font.regular(15.0), textColor: UIColor(white: 1.0, alpha: 1.0)))
|
||||
|
||||
let textSize = self.text.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextWithEntitiesComponent(
|
||||
context: component.context,
|
||||
animationCache: component.context.animationCache,
|
||||
animationRenderer: component.context.animationRenderer,
|
||||
placeholderColor: .gray,
|
||||
text: .plain(textString),
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - insets.left - insets.right - avatarSize - avatarSpacing, height: 100000.0)
|
||||
)
|
||||
|
||||
let size = CGSize(width: availableSize.width, height: insets.top + textSize.height + insets.bottom)
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: insets.left, y: insets.top - 4.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
do {
|
||||
let avatarNode: AvatarNode
|
||||
if let current = self.avatarNode {
|
||||
avatarNode = current
|
||||
} else {
|
||||
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 10.0))
|
||||
self.avatarNode = avatarNode
|
||||
self.contentContainer.addSubview(avatarNode.view)
|
||||
}
|
||||
transition.setFrame(view: avatarNode.view, frame: avatarFrame)
|
||||
avatarNode.updateSize(size: avatarFrame.size)
|
||||
if let peer = component.message.author {
|
||||
if peer.smallProfileImage != nil {
|
||||
avatarNode.setPeerV2(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||
} else {
|
||||
avatarNode.setPeer(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||
}
|
||||
} else {
|
||||
avatarNode.setCustomLetters([" "])
|
||||
}
|
||||
}
|
||||
|
||||
let textFrame = CGRect(origin: CGPoint(x: insets.left + avatarSize + avatarSpacing, y: insets.top), size: textSize)
|
||||
if let textView = self.text.view {
|
||||
if textView.superview == nil {
|
||||
textView.layer.anchorPoint = CGPoint()
|
||||
self.contentContainer.addSubview(textView)
|
||||
}
|
||||
transition.setPosition(view: textView, position: textFrame.origin)
|
||||
textView.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
||||
}
|
||||
|
||||
if let paidStars = component.message.paidStars {
|
||||
let backgroundView: UIImageView
|
||||
if let current = self.backgroundView {
|
||||
backgroundView = current
|
||||
} else {
|
||||
backgroundView = UIImageView()
|
||||
self.backgroundView = backgroundView
|
||||
self.contentContainer.insertSubview(backgroundView, at: 0)
|
||||
backgroundView.image = generateStretchableFilledCircleImage(diameter: 28.0, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: 16.0, y: 2.0), size: CGSize(width: textFrame.maxX + 8.0 - 16.0, height: textFrame.maxY + 3.0))
|
||||
transition.setFrame(view: backgroundView, frame: backgroundFrame)
|
||||
backgroundView.tintColor = getStarAmountColorMapping(value: paidStars)
|
||||
} else if let backgroundView = self.backgroundView {
|
||||
self.backgroundView = nil
|
||||
backgroundView.removeFromSuperview()
|
||||
}
|
||||
|
||||
let contentFrame = CGRect(origin: CGPoint(), size: size)
|
||||
transition.setPosition(view: self.contentContainer, position: contentFrame.center)
|
||||
transition.setBounds(view: self.contentContainer, bounds: CGRect(origin: CGPoint(), size: contentFrame.size))
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private func getStarAmountColorMapping(value: Int64) -> UIColor {
|
||||
if value >= 10000 {
|
||||
return UIColor(rgb: 0x7C8695)
|
||||
}
|
||||
if value >= 2000 {
|
||||
return UIColor(rgb: 0xE6514E)
|
||||
}
|
||||
if value >= 500 {
|
||||
return UIColor(rgb: 0xEE7E20)
|
||||
}
|
||||
if value >= 250 {
|
||||
return UIColor(rgb: 0xE4A20A)
|
||||
}
|
||||
if value >= 100 {
|
||||
return UIColor(rgb: 0x5AB03D)
|
||||
}
|
||||
if value >= 50 {
|
||||
return UIColor(rgb: 0x3E9CDF)
|
||||
}
|
||||
return UIColor(rgb: 0x985FDC)
|
||||
}
|
||||
|
||||
private final class PinnedBarMessageComponent: Component {
|
||||
let context: AccountContext
|
||||
let strings: PresentationStrings
|
||||
let theme: PresentationTheme
|
||||
let message: GroupCallMessagesContext.Message
|
||||
|
||||
init(context: AccountContext, strings: PresentationStrings, theme: PresentationTheme, message: GroupCallMessagesContext.Message) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.message = message
|
||||
}
|
||||
|
||||
static func ==(lhs: PinnedBarMessageComponent, rhs: PinnedBarMessageComponent) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.message != rhs.message {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let backgroundView: UIImageView
|
||||
private let foregroundClippingView: UIView
|
||||
private let foregroundView: UIImageView
|
||||
|
||||
private var avatarNode: AvatarNode?
|
||||
private let title = ComponentView<Empty>()
|
||||
|
||||
private var component: PinnedBarMessageComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
private var isUpdating: Bool = false
|
||||
|
||||
private var updateTimer: Foundation.Timer?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.backgroundView = UIImageView()
|
||||
self.foregroundClippingView = UIView()
|
||||
self.foregroundClippingView.clipsToBounds = true
|
||||
self.foregroundView = UIImageView()
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.backgroundView)
|
||||
|
||||
self.foregroundClippingView.addSubview(self.foregroundView)
|
||||
self.addSubview(self.foregroundClippingView)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.updateTimer?.invalidate()
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let result = super.hitTest(point, with: event) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func update(component: PinnedBarMessageComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.isUpdating = true
|
||||
defer {
|
||||
self.isUpdating = false
|
||||
}
|
||||
|
||||
if self.updateTimer == nil {
|
||||
self.updateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 1.0 / 30.0, repeats: true, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .immediate, isLocal: true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
let itemHeight: CGFloat = 32.0
|
||||
let avatarInset: CGFloat = 4.0
|
||||
let avatarSize: CGFloat = 24.0
|
||||
let avatarSpacing: CGFloat = 6.0
|
||||
let rightInset: CGFloat = 10.0
|
||||
|
||||
let titleSize = self.title.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: component.message.author?.displayTitle(strings: component.strings, displayOrder: .firstLast) ?? " ", font: Font.semibold(15.0), textColor: .white))
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 1000.0, height: itemHeight)
|
||||
)
|
||||
|
||||
let size = CGSize(width: avatarInset + avatarSize + avatarSpacing + titleSize.width + rightInset, height: itemHeight)
|
||||
|
||||
if self.backgroundView.image == nil {
|
||||
self.backgroundView.image = generateStretchableFilledCircleImage(diameter: itemHeight, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
self.foregroundView.image = self.backgroundView.image
|
||||
}
|
||||
|
||||
let baseColor = getStarAmountColorMapping(value: component.message.paidStars ?? 0)
|
||||
self.backgroundView.tintColor = baseColor.withMultipliedBrightnessBy(0.7)
|
||||
self.foregroundView.tintColor = baseColor
|
||||
|
||||
let timestamp = CFAbsoluteTimeGetCurrent()
|
||||
let currentDuration = max(0.0, timestamp - Double(component.message.date))
|
||||
let timeFraction: CGFloat = 1.0 - min(1.0, currentDuration / Double(component.message.lifetime))
|
||||
|
||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(), size: size))
|
||||
transition.setFrame(view: self.foregroundView, frame: CGRect(origin: CGPoint(), size: size))
|
||||
transition.setFrame(view: self.foregroundClippingView, frame: CGRect(origin: CGPoint(), size: CGSize(width: floorToScreenPixels(size.width * timeFraction), height: size.height)))
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: avatarInset, y: floor((itemHeight - avatarSize) * 0.5)), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
do {
|
||||
let avatarNode: AvatarNode
|
||||
if let current = self.avatarNode {
|
||||
avatarNode = current
|
||||
} else {
|
||||
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 10.0))
|
||||
self.avatarNode = avatarNode
|
||||
self.addSubview(avatarNode.view)
|
||||
}
|
||||
transition.setFrame(view: avatarNode.view, frame: avatarFrame)
|
||||
avatarNode.updateSize(size: avatarFrame.size)
|
||||
if let peer = component.message.author {
|
||||
if peer.smallProfileImage != nil {
|
||||
avatarNode.setPeerV2(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||
} else {
|
||||
avatarNode.setPeer(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||
}
|
||||
} else {
|
||||
avatarNode.setCustomLetters([" "])
|
||||
}
|
||||
}
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: avatarInset + avatarSize + avatarSpacing, y: floor((itemHeight - titleSize.height) * 0.5)), size: titleSize)
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
titleView.layer.anchorPoint = CGPoint()
|
||||
self.addSubview(titleView)
|
||||
}
|
||||
transition.setPosition(view: titleView, position: titleFrame.origin)
|
||||
titleView.bounds = CGRect(origin: CGPoint(), size: titleFrame.size)
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private final class PinnedBarComponent: Component {
|
||||
let context: AccountContext
|
||||
let strings: PresentationStrings
|
||||
let theme: PresentationTheme
|
||||
let isExpanded: Bool
|
||||
let messages: [GroupCallMessagesContext.Message]
|
||||
let toggleExpandedAction: () -> Void
|
||||
|
||||
init(context: AccountContext, strings: PresentationStrings, theme: PresentationTheme, isExpanded: Bool, messages: [GroupCallMessagesContext.Message], toggleExpandedAction: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.isExpanded = isExpanded
|
||||
self.messages = messages
|
||||
self.toggleExpandedAction = toggleExpandedAction
|
||||
}
|
||||
|
||||
static func ==(lhs: PinnedBarComponent, rhs: PinnedBarComponent) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.isExpanded != rhs.isExpanded {
|
||||
return false
|
||||
}
|
||||
if lhs.messages != rhs.messages {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let listContainer: UIView
|
||||
private let listState = AsyncListComponent.ExternalState()
|
||||
private let list = ComponentView<Empty>()
|
||||
|
||||
private let toggleButtonBackground: GlassBackgroundView
|
||||
private let toggleButton: HighlightTrackingButton
|
||||
private let toggleButtonIcon: UIImageView
|
||||
|
||||
private var component: PinnedBarComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
private var isUpdating: Bool = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.listContainer = UIView()
|
||||
self.listContainer.clipsToBounds = true
|
||||
|
||||
self.toggleButtonBackground = GlassBackgroundView()
|
||||
self.toggleButton = HighlightTrackingButton()
|
||||
self.toggleButtonIcon = UIImageView()
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.listContainer)
|
||||
|
||||
self.toggleButtonBackground.contentView.addSubview(self.toggleButtonIcon)
|
||||
self.toggleButtonBackground.contentView.addSubview(self.toggleButton)
|
||||
self.addSubview(self.toggleButtonBackground)
|
||||
|
||||
self.toggleButton.addTarget(self, action: #selector(self.toggleButtonPressed), for: .touchUpInside)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
}
|
||||
|
||||
@objc private func toggleButtonPressed() {
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
component.toggleExpandedAction()
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let result = super.hitTest(point, with: event) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func update(component: PinnedBarComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.isUpdating = true
|
||||
defer {
|
||||
self.isUpdating = false
|
||||
}
|
||||
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
let itemHeight: CGFloat = 32.0
|
||||
|
||||
let insets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0)
|
||||
|
||||
let size = CGSize(width: availableSize.width, height: insets.top + itemHeight + insets.bottom)
|
||||
|
||||
let toggleButtonFrame = CGRect(origin: CGPoint(x: insets.left, y: insets.top), size: CGSize(width: itemHeight, height: itemHeight))
|
||||
transition.setFrame(view: self.toggleButtonBackground, frame: toggleButtonFrame)
|
||||
self.toggleButtonBackground.update(size: toggleButtonFrame.size, cornerRadius: toggleButtonFrame.height * 0.5, isDark: true, tintColor: .init(kind: .panel, color: component.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), isInteractive: true, transition: transition)
|
||||
transition.setFrame(view: self.toggleButton, frame: CGRect(origin: CGPoint(), size: toggleButtonFrame.size))
|
||||
if self.toggleButtonIcon.image == nil {
|
||||
self.toggleButtonIcon.image = UIImage(bundleImageName: "Chat/Context Menu/ReactionExpandArrow")?.withRenderingMode(.alwaysTemplate)
|
||||
self.toggleButtonIcon.tintColor = .white
|
||||
}
|
||||
if let image = self.toggleButtonIcon.image {
|
||||
var iconFrame = image.size.centered(in: CGRect(origin: CGPoint(), size: toggleButtonFrame.size))
|
||||
iconFrame.origin.y += 1.0
|
||||
transition.setTransform(view: self.toggleButtonIcon, transform: CATransform3DMakeRotation((!component.isExpanded) ? CGFloat.pi : 0.0, 0.0, 0.0, 1.0))
|
||||
transition.setPosition(view: self.toggleButtonIcon, position: iconFrame.center)
|
||||
transition.setBounds(view: self.toggleButtonIcon, bounds: CGRect(origin: CGPoint(), size: iconFrame.size))
|
||||
}
|
||||
|
||||
var listItems: [AnyComponentWithIdentity<Empty>] = []
|
||||
for message in component.messages {
|
||||
if let author = message.author {
|
||||
listItems.append(AnyComponentWithIdentity(id: author.id, component: AnyComponent(PinnedBarMessageComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
theme: component.theme,
|
||||
message: message
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
let listInsets = UIEdgeInsets(top: 0.0, left: 5.0, bottom: 0.0, right: 5.0 + 20.0)
|
||||
let listFrame = CGRect(origin: CGPoint(x: toggleButtonFrame.maxX, y: 0.0), size: CGSize(width: size.width - toggleButtonFrame.maxX, height: size.height))
|
||||
let _ = self.list.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(AsyncListComponent(
|
||||
externalState: self.listState,
|
||||
items: listItems,
|
||||
itemSetId: AnyHashable(0),
|
||||
direction: .horizontal,
|
||||
insets: listInsets
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: listFrame.size
|
||||
)
|
||||
if let listView = self.list.view {
|
||||
if listView.superview == nil {
|
||||
self.listContainer.addSubview(listView)
|
||||
}
|
||||
transition.setPosition(view: listView, position: CGRect(origin: CGPoint(), size: listFrame.size).center)
|
||||
transition.setBounds(view: listView, bounds: CGRect(origin: CGPoint(), size: listFrame.size))
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.listContainer, frame: listFrame)
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
final class StoryContentLiveChatComponent: Component {
|
||||
let context: AccountContext
|
||||
let strings: PresentationStrings
|
||||
let theme: PresentationTheme
|
||||
let call: PresentationGroupCall
|
||||
let insets: UIEdgeInsets
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
strings: PresentationStrings,
|
||||
theme: PresentationTheme,
|
||||
call: PresentationGroupCall,
|
||||
insets: UIEdgeInsets
|
||||
) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.call = call
|
||||
self.insets = insets
|
||||
}
|
||||
|
||||
static func ==(lhs: StoryContentLiveChatComponent, rhs: StoryContentLiveChatComponent) -> Bool {
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.call !== rhs.call {
|
||||
return false
|
||||
}
|
||||
if lhs.insets != rhs.insets {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let listContainer: UIView
|
||||
private let listMaskContainer: UIView
|
||||
private let maskGradientView: UIImageView
|
||||
|
||||
private let pinnedBar = ComponentView<Empty>()
|
||||
|
||||
private let listState = AsyncListComponent.ExternalState()
|
||||
private let list = ComponentView<Empty>()
|
||||
private let listShadowView: UIView
|
||||
|
||||
private var component: StoryContentLiveChatComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
private var isUpdating: Bool = false
|
||||
|
||||
private var messagesState: GroupCallMessagesContext.State?
|
||||
private var stateDisposable: Disposable?
|
||||
|
||||
private var isChatExpanded: Bool = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.listContainer = UIView()
|
||||
|
||||
self.listMaskContainer = UIView()
|
||||
self.listContainer.mask = self.listMaskContainer
|
||||
|
||||
self.maskGradientView = UIImageView()
|
||||
do {
|
||||
let height: CGFloat = 40.0
|
||||
let baseGradientAlpha: CGFloat = 1.0
|
||||
let numSteps = 8
|
||||
let firstStep = 0
|
||||
let firstLocation = 0.0
|
||||
let colors = (0 ..< numSteps).map { i -> UIColor in
|
||||
if i < firstStep {
|
||||
return UIColor(white: 1.0, alpha: 1.0)
|
||||
} else {
|
||||
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
||||
let value: CGFloat = 1.0 - bezierPoint(0.42, 0.0, 0.58, 1.0, step)
|
||||
return UIColor(white: 1.0, alpha: baseGradientAlpha * value)
|
||||
}
|
||||
}
|
||||
let locations = (0 ..< numSteps).map { i -> CGFloat in
|
||||
if i < firstStep {
|
||||
return 0.0
|
||||
} else {
|
||||
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
||||
return (firstLocation + (1.0 - firstLocation) * step)
|
||||
}
|
||||
}
|
||||
|
||||
let image = generateGradientImage(size: CGSize(width: 8.0, height: height), colors: colors.reversed(), locations: locations.reversed().map { 1.0 - $0 })!
|
||||
self.maskGradientView.image = generateImage(CGSize(width: image.size.width, height: image.size.height * 2.0), rotatedContext: { size, context in
|
||||
UIGraphicsPushContext(context)
|
||||
defer {
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
image.draw(in: CGRect(origin: CGPoint(), size: image.size))
|
||||
|
||||
let bottomFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - image.size.height), size: image.size)
|
||||
context.translateBy(x: bottomFrame.midX, y: bottomFrame.midY)
|
||||
context.scaleBy(x: 1.0, y: -1.0)
|
||||
context.translateBy(x: -bottomFrame.midX, y: -bottomFrame.midY)
|
||||
|
||||
image.draw(in: bottomFrame)
|
||||
})!.stretchableImage(withLeftCapWidth: 0, topCapHeight: Int(height - 1.0))
|
||||
}
|
||||
self.listMaskContainer.addSubview(self.maskGradientView)
|
||||
|
||||
self.listShadowView = UIView()
|
||||
self.listShadowView.isUserInteractionEnabled = false
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.listShadowView)
|
||||
self.addSubview(self.listContainer)
|
||||
|
||||
self.isChatExpanded = true
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.stateDisposable?.dispose()
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let result = super.hitTest(point, with: event) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func update(component: StoryContentLiveChatComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.isUpdating = true
|
||||
defer {
|
||||
self.isUpdating = false
|
||||
}
|
||||
|
||||
if self.component?.call !== component.call {
|
||||
self.stateDisposable?.dispose()
|
||||
if let call = component.call as? PresentationGroupCallImpl {
|
||||
self.stateDisposable = (call.messagesState
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] state in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var updateTransition: ComponentTransition = .easeInOut(duration: 0.2)
|
||||
if self.messagesState == nil {
|
||||
updateTransition = .immediate
|
||||
}
|
||||
self.messagesState = state
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: updateTransition)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
var listItems: [AnyComponentWithIdentity<Empty>] = []
|
||||
var topMessageByPeerId: [EnginePeer.Id: GroupCallMessagesContext.Message] = [:]
|
||||
if let messagesState = self.messagesState {
|
||||
for message in messagesState.messages.reversed() {
|
||||
listItems.append(AnyComponentWithIdentity(id: message.id, component: AnyComponent(MessageItemComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
theme: component.theme,
|
||||
message: message
|
||||
))))
|
||||
|
||||
if let author = message.author, let paidStars = message.paidStars {
|
||||
if let current = topMessageByPeerId[author.id] {
|
||||
if let currentPaidStars = current.paidStars, currentPaidStars < paidStars {
|
||||
topMessageByPeerId[author.id] = message
|
||||
}
|
||||
} else {
|
||||
topMessageByPeerId[author.id] = message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let topMessages: [GroupCallMessagesContext.Message] = topMessageByPeerId.values.sorted(by: { lhs, rhs in
|
||||
let lhsValue = lhs.paidStars ?? 0
|
||||
let rhsValue = rhs.paidStars ?? 0
|
||||
if lhsValue != rhsValue {
|
||||
return lhsValue > rhsValue
|
||||
}
|
||||
return lhs.date > rhs.date
|
||||
})
|
||||
|
||||
let pinnedBarSize = self.pinnedBar.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(PinnedBarComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
theme: component.theme,
|
||||
isExpanded: self.isChatExpanded,
|
||||
messages: topMessages,
|
||||
toggleExpandedAction: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.isChatExpanded = !self.isChatExpanded
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
}
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
let pinnedBarFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - component.insets.bottom - pinnedBarSize.height), size: pinnedBarSize)
|
||||
if let pinnedBarView = self.pinnedBar.view {
|
||||
if pinnedBarView.superview == nil {
|
||||
self.addSubview(pinnedBarView)
|
||||
}
|
||||
transition.setFrame(view: pinnedBarView, frame: pinnedBarFrame)
|
||||
transition.setAlpha(view: pinnedBarView, alpha: (listItems.isEmpty && topMessages.isEmpty) ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
var listInsets = UIEdgeInsets(top: availableSize.height - pinnedBarFrame.minY, left: component.insets.right, bottom: component.insets.top, right: component.insets.left)
|
||||
listInsets.top += 4.0
|
||||
let _ = self.list.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(AsyncListComponent(
|
||||
externalState: self.listState,
|
||||
items: listItems,
|
||||
itemSetId: AnyHashable(0),
|
||||
direction: .vertical,
|
||||
insets: listInsets
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
let listFrame = CGRect(origin: CGPoint(), size: availableSize)
|
||||
if let listView = self.list.view {
|
||||
if listView.superview == nil {
|
||||
listView.transform = CGAffineTransformMakeRotation(CGFloat.pi)
|
||||
self.listContainer.addSubview(listView)
|
||||
}
|
||||
transition.setPosition(view: listView, position: listFrame.offsetBy(dx: 0.0, dy: self.isChatExpanded ? 0.0 : listFrame.height).center)
|
||||
transition.setBounds(view: listView, bounds: CGRect(origin: CGPoint(), size: listFrame.size))
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.listContainer, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
transition.setFrame(view: self.listMaskContainer, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
||||
let maskTopInset: CGFloat = component.insets.top - 20.0
|
||||
let maskBottomInset: CGFloat = availableSize.height - pinnedBarFrame.minY - 26.0
|
||||
transition.setFrame(view: self.maskGradientView, frame: CGRect(origin: CGPoint(x: 0.0, y: maskTopInset), size: CGSize(width: availableSize.width, height: max(0.0, availableSize.height - maskTopInset - maskBottomInset))))
|
||||
|
||||
transition.setFrame(view: self.listShadowView, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
||||
self.listShadowView.backgroundColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
transition.setAlpha(view: self.listShadowView, alpha: self.isChatExpanded ? 1.0 : 0.0)
|
||||
|
||||
return availableSize
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
@ -93,11 +93,13 @@ final class StoryItemContentComponent: Component {
|
||||
private let imageView: StoryItemImageView
|
||||
private let overlaysView: StoryItemOverlaysView
|
||||
private var videoNode: UniversalVideoNode?
|
||||
private var mediaStreamCall: PresentationGroupCallImpl?
|
||||
private(set) var mediaStreamCall: PresentationGroupCallImpl?
|
||||
private var mediaStream: ComponentView<Empty>?
|
||||
private var loadingEffectView: StoryItemLoadingEffectView?
|
||||
private var loadingEffectAppearanceTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private var liveChat: ComponentView<Empty>?
|
||||
|
||||
private var mediaAreasEffectView: StoryItemLoadingEffectView?
|
||||
|
||||
private var currentMessageMedia: EngineMedia?
|
||||
@ -544,6 +546,11 @@ final class StoryItemContentComponent: Component {
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let liveChatView = self.liveChat?.view {
|
||||
if let result = liveChatView.hitTest(self.convert(point, to: liveChatView), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
if let unsupportedButtonView = self.unsupportedButton?.view {
|
||||
if let result = unsupportedButtonView.hitTest(self.convert(point, to: unsupportedButtonView), with: event) {
|
||||
return result
|
||||
@ -777,6 +784,34 @@ final class StoryItemContentComponent: Component {
|
||||
})
|
||||
}
|
||||
|
||||
let liveChat: ComponentView<Empty>
|
||||
if let current = self.liveChat {
|
||||
liveChat = current
|
||||
} else {
|
||||
liveChat = ComponentView()
|
||||
self.liveChat = liveChat
|
||||
}
|
||||
|
||||
let _ = liveChat.update(
|
||||
transition: mediaStreamTransition,
|
||||
component: AnyComponent(StoryContentLiveChatComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
theme: environment.theme,
|
||||
call: mediaStreamCall,
|
||||
insets: environment.containerInsets
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
let liveChatFrame = CGRect(origin: CGPoint(), size: availableSize)
|
||||
if let liveChatView = liveChat.view {
|
||||
if liveChatView.superview == nil {
|
||||
self.insertSubview(liveChatView, aboveSubview: self.imageView)
|
||||
}
|
||||
mediaStreamTransition.setFrame(view: liveChatView, frame: liveChatFrame)
|
||||
}
|
||||
|
||||
let _ = mediaStream.update(
|
||||
transition: mediaStreamTransition,
|
||||
component: AnyComponent(MediaStreamVideoComponent(
|
||||
@ -833,6 +868,11 @@ final class StoryItemContentComponent: Component {
|
||||
mediaStream.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let liveChat = self.liveChat {
|
||||
self.liveChat = nil
|
||||
liveChat.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let messageMedia {
|
||||
var applyState = false
|
||||
self.imageView.didLoadContents = { [weak self] in
|
||||
|
||||
@ -278,6 +278,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
struct ItemLayout {
|
||||
var containerSize: CGSize
|
||||
var contentFrame: CGRect
|
||||
var contentInsets: UIEdgeInsets
|
||||
var contentMinScale: CGFloat
|
||||
var contentScaleFraction: CGFloat
|
||||
var contentOverflowFraction: CGFloat
|
||||
@ -292,12 +293,14 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
init(
|
||||
containerSize: CGSize,
|
||||
contentFrame: CGRect,
|
||||
contentInsets: UIEdgeInsets,
|
||||
contentMinScale: CGFloat,
|
||||
contentScaleFraction: CGFloat,
|
||||
contentOverflowFraction: CGFloat
|
||||
) {
|
||||
self.containerSize = containerSize
|
||||
self.contentFrame = contentFrame
|
||||
self.contentInsets = contentInsets
|
||||
self.contentMinScale = contentMinScale
|
||||
self.contentScaleFraction = contentScaleFraction
|
||||
self.contentOverflowFraction = contentOverflowFraction
|
||||
@ -1527,6 +1530,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
externalState: visibleItem.externalState,
|
||||
sharedState: component.storyItemSharedState,
|
||||
theme: component.theme,
|
||||
containerInsets: itemLayout.contentInsets,
|
||||
presentationProgressUpdated: { [weak self, weak visibleItem] progress, isBuffering, canSwitch in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
@ -2575,8 +2579,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let isFirstTime = self.component == nil
|
||||
|
||||
let startTime1 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
if self.component == nil {
|
||||
self.sendMessageContext.setup(context: component.context, view: self, inputPanelExternalState: self.inputPanelExternalState, keyboardInputData: component.keyboardInputData)
|
||||
@ -2704,6 +2706,11 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
var isLiveStream = false
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
isLiveStream = true
|
||||
}
|
||||
|
||||
var dismissPanOffset: CGFloat = 0.0
|
||||
var dismissPanScale: CGFloat = 1.0
|
||||
var verticalPanFraction: CGFloat = 0.0
|
||||
@ -2719,8 +2726,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
component.externalState.dismissFraction = dismissFraction
|
||||
|
||||
let startTime2 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
transition.setPosition(view: self.componentContainerView, position: CGPoint(x: availableSize.width * 0.5, y: availableSize.height * 0.5 + dismissPanOffset))
|
||||
transition.setBounds(view: self.componentContainerView, bounds: CGRect(origin: CGPoint(), size: availableSize))
|
||||
transition.setScale(view: self.componentContainerView, scale: dismissPanScale)
|
||||
@ -2732,8 +2737,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
transition.setBounds(view: self.overlayContainerView, bounds: CGRect(origin: CGPoint(), size: availableSize))
|
||||
transition.setScale(view: self.overlayContainerView, scale: dismissPanScale)
|
||||
|
||||
let startTime21 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
var bottomContentInset: CGFloat
|
||||
if !component.safeInsets.bottom.isZero {
|
||||
bottomContentInset = component.safeInsets.bottom + 1.0
|
||||
@ -2860,8 +2863,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let startTime22 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
var currentHasFirstResponder = false
|
||||
if let reactionContextNode = self.reactionContextNode {
|
||||
if hasFirstResponder(reactionContextNode.view) {
|
||||
@ -2881,8 +2882,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
var inputPanelSize: CGSize?
|
||||
|
||||
let _ = inputNodeVisible
|
||||
|
||||
let startTime23 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
if showMessageInputPanel {
|
||||
var haveLikeOptions = false
|
||||
@ -2902,6 +2901,11 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
displayAttachmentAction = false
|
||||
}
|
||||
|
||||
var maxInputLength = 4096
|
||||
if isLiveStream {
|
||||
maxInputLength = GroupCallMessagesContext.getStarAmountParamMapping(value: self.sendMessageContext.currentLiveStreamMessageStars?.value ?? 0).maxLength
|
||||
}
|
||||
|
||||
inputPanelSize = self.inputPanel.update(
|
||||
transition: inputPanelTransition,
|
||||
component: AnyComponent(MessageInputPanelComponent(
|
||||
@ -2911,8 +2915,8 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
strings: component.strings,
|
||||
style: .story,
|
||||
placeholder: inputPlaceholder,
|
||||
sendPaidMessageStars: component.slice.additionalPeerData.sendPaidMessageStars,
|
||||
maxLength: 4096,
|
||||
sendPaidMessageStars: isLiveStream ? self.sendMessageContext.currentLiveStreamMessageStars : component.slice.additionalPeerData.sendPaidMessageStars,
|
||||
maxLength: maxInputLength,
|
||||
queryTypes: [.mention, .hashtag, .emoji],
|
||||
alwaysDarkWhenHasText: component.metrics.widthClass == .regular,
|
||||
resetInputContents: resetInputContents,
|
||||
@ -3020,7 +3024,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
return MessageInputPanelComponent.MyReaction(reaction: value, file: centerAnimation, animationFileId: animationFileId)
|
||||
},
|
||||
likeAction: component.slice.effectivePeer.isService ? nil : { [weak self] in
|
||||
likeAction: (component.slice.effectivePeer.isService || isLiveStream) ? nil : { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -3045,12 +3049,18 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
},
|
||||
timeoutAction: nil,
|
||||
forwardAction: component.slice.item.storyItem.isPublic && !component.slice.item.storyItem.isForwardingDisabled ? { [weak self] in
|
||||
forwardAction: (!isLiveStream && component.slice.item.storyItem.isPublic && !component.slice.item.storyItem.isForwardingDisabled) ? { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.sendMessageContext.performShareAction(view: self)
|
||||
} : nil,
|
||||
paidMessageAction: (isLiveStream && self.sendMessageContext.currentLiveStreamMessageStars == nil) ? { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.sendMessageContext.performPaidMessageAction(view: self)
|
||||
} : nil,
|
||||
moreAction: { [weak self] sourceView, gesture in
|
||||
guard let self else {
|
||||
return
|
||||
@ -3129,8 +3139,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
)
|
||||
}
|
||||
|
||||
let startTime3 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
var inputPanelInset: CGFloat = component.containerInsets.bottom
|
||||
var inputHeight = component.inputHeight
|
||||
|
||||
@ -3211,14 +3219,18 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
inputPanelIsOverlay = true
|
||||
}
|
||||
|
||||
var inputPanelFrameValue: CGRect?
|
||||
if let inputPanelSize {
|
||||
let inputPanelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - inputPanelSize.width) / 2.0), y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize)
|
||||
inputPanelFrameValue = inputPanelFrame
|
||||
}
|
||||
|
||||
var minimizedBottomContentHeight: CGFloat = 0.0
|
||||
var maximizedBottomContentHeight: CGFloat = 0.0
|
||||
|
||||
let minimizedHeight = max(100.0, availableSize.height - (325.0 + 12.0))
|
||||
let defaultHeight = 60.0 + component.safeInsets.bottom + 1.0
|
||||
|
||||
let startTime4 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
var validViewListIds: [StoryId] = []
|
||||
|
||||
var displayViewLists = false
|
||||
@ -3717,8 +3729,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.viewLists.removeValue(forKey: id)
|
||||
}
|
||||
|
||||
let startTime5 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let itemSize = CGSize(width: availableSize.width, height: ceil(availableSize.width * 1.77778))
|
||||
let contentDefaultBottomInset: CGFloat = bottomContentInset
|
||||
|
||||
@ -3751,6 +3761,10 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let contentFrame = CGRect(origin: CGPoint(x: 0.0, y: component.containerInsets.top - (contentSize.height - contentVisualHeight) * 0.5 - contentBottomInsetOverflow), size: contentSize)
|
||||
var contentInsets = UIEdgeInsets(top: 54.0, left: 0.0, bottom: 0.0, right: 0.0)
|
||||
if let inputPanelFrameValue {
|
||||
contentInsets.bottom = max(0.0, contentFrame.maxY - (inputPanelFrameValue.minY + 8.0))
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.viewListsContainer, frame: CGRect(origin: CGPoint(x: contentFrame.minX, y: 0.0), size: CGSize(width: contentSize.width, height: availableSize.height)))
|
||||
let viewListsRadius: CGFloat
|
||||
@ -3766,6 +3780,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
let itemLayout = ItemLayout(
|
||||
containerSize: availableSize,
|
||||
contentFrame: contentFrame,
|
||||
contentInsets: contentInsets,
|
||||
contentMinScale: contentMinScale,
|
||||
contentScaleFraction: contentScaleFraction,
|
||||
contentOverflowFraction: contentOverflowFraction
|
||||
@ -3882,8 +3897,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let startTime6 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let soundButtonState = isSilentVideo || component.isAudioMuted
|
||||
let soundButtonSize = self.soundButton.update(
|
||||
transition: transition,
|
||||
@ -4061,11 +4074,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
|
||||
let focusedItem: StoryContentItem? = component.slice.item
|
||||
|
||||
var isLiveStream = false
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
isLiveStream = true
|
||||
}
|
||||
|
||||
var currentLeftInfoItem: InfoItem?
|
||||
if focusedItem != nil {
|
||||
let leftInfoComponent = AnyComponent(StoryAvatarInfoComponent(context: component.context, peer: component.slice.effectivePeer, isLiveStream: isLiveStream))
|
||||
@ -4204,18 +4212,12 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let startTime7 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let topGradientHeight: CGFloat = 90.0
|
||||
let topContentGradientRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentFrame.width, height: topGradientHeight))
|
||||
transition.setPosition(view: self.topContentGradientView, position: topContentGradientRect.center)
|
||||
transition.setBounds(view: self.topContentGradientView, bounds: CGRect(origin: CGPoint(), size: topContentGradientRect.size))
|
||||
|
||||
var inputPanelFrameValue: CGRect?
|
||||
if let inputPanelSize {
|
||||
let inputPanelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - inputPanelSize.width) / 2.0), y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize)
|
||||
inputPanelFrameValue = inputPanelFrame
|
||||
|
||||
if let inputPanelFrame = inputPanelFrameValue {
|
||||
var inputPanelAlpha: CGFloat = (component.hideUI || self.isEditingStory || component.slice.item.storyItem.isPending) ? 0.0 : 1.0
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
} else if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
@ -4462,7 +4464,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
captionItemTransition.setAlpha(view: captionItemView, alpha: captionAlpha)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let reactionsAnchorRect: CGRect
|
||||
|
||||
if self.inputPanelExternalState.isEditing, let inputPanelFrameValue {
|
||||
@ -4499,6 +4501,9 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
if self.sendMessageContext.currentInputMode != .text {
|
||||
effectiveDisplayReactions = false
|
||||
}
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
effectiveDisplayReactions = false
|
||||
}
|
||||
|
||||
if let reactionContextNode = self.reactionContextNode, self.willDismissReactionContextNode !== reactionContextNode, (reactionContextNode.isReactionSearchActive && !reactionContextNode.isAnimatingOutToReaction && !reactionContextNode.isAnimatingOut) {
|
||||
effectiveDisplayReactions = true
|
||||
@ -4925,6 +4930,9 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
var dimAlpha: CGFloat = (inputPanelIsOverlay || self.inputPanelExternalState.isEditing) ? 1.0 : normalDimAlpha
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
dimAlpha = normalDimAlpha
|
||||
}
|
||||
if component.hideUI || self.viewListDisplayState != .hidden || self.isEditingStory {
|
||||
dimAlpha = 0.0
|
||||
}
|
||||
@ -4964,14 +4972,10 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let startTime8 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
self.ignoreScrolling = false
|
||||
|
||||
self.updateScrolling(transition: itemsTransition)
|
||||
|
||||
let startTime9 = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let navigationStripSideInset: CGFloat = 8.0
|
||||
let navigationStripTopInset: CGFloat = 8.0
|
||||
if let focusedItem, let visibleItem = self.visibleItems[focusedItem.id], let index = focusedItem.position {
|
||||
@ -5051,23 +5055,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if !"".isEmpty {
|
||||
print("inner update time:\n" +
|
||||
" 1: \((CFAbsoluteTimeGetCurrent() - startTime1) * 1000.0) ms\n" +
|
||||
" 2: \((CFAbsoluteTimeGetCurrent() - startTime2) * 1000.0) ms\n" +
|
||||
" 2.1: \((CFAbsoluteTimeGetCurrent() - startTime21) * 1000.0) ms\n" +
|
||||
" 2.2: \((CFAbsoluteTimeGetCurrent() - startTime22) * 1000.0) ms\n" +
|
||||
" 2.3: \((CFAbsoluteTimeGetCurrent() - startTime23) * 1000.0) ms\n" +
|
||||
" 3: \((CFAbsoluteTimeGetCurrent() - startTime3) * 1000.0) ms\n" +
|
||||
" 4: \((CFAbsoluteTimeGetCurrent() - startTime4) * 1000.0) ms\n" +
|
||||
" 5: \((CFAbsoluteTimeGetCurrent() - startTime5) * 1000.0) ms\n" +
|
||||
" 6: \((CFAbsoluteTimeGetCurrent() - startTime6) * 1000.0) ms\n" +
|
||||
" 7: \((CFAbsoluteTimeGetCurrent() - startTime7) * 1000.0) ms\n" +
|
||||
" 8: \((CFAbsoluteTimeGetCurrent() - startTime8) * 1000.0) ms\n" +
|
||||
" 9: \((CFAbsoluteTimeGetCurrent() - startTime9) * 1000.0) ms\n"
|
||||
)
|
||||
}
|
||||
|
||||
if let scheduledStoryUnpinnedUndoOverlay = self.scheduledStoryUnpinnedUndoOverlay {
|
||||
self.scheduledStoryUnpinnedUndoOverlay = nil
|
||||
if !self.isAnimatingOut && !component.isDismissed {
|
||||
|
||||
@ -51,6 +51,7 @@ import ReactionSelectionNode
|
||||
import StoryQualityUpgradeSheetScreen
|
||||
import AudioWaveform
|
||||
import ChatMessagePaymentAlertController
|
||||
import ChatSendStarsScreen
|
||||
|
||||
private var ObjCKey_DeinitWatcher: Int?
|
||||
|
||||
@ -101,6 +102,8 @@ final class StoryItemSetContainerSendMessage {
|
||||
|
||||
var currentSpeechHolder: SpeechSynthesizerHolder?
|
||||
|
||||
var currentLiveStreamMessageStars: StarsAmount?
|
||||
|
||||
private(set) var isMediaRecordingLocked: Bool = false
|
||||
var wasRecordingDismissed: Bool = false
|
||||
|
||||
@ -581,6 +584,43 @@ final class StoryItemSetContainerSendMessage {
|
||||
silentPosting: Bool = false,
|
||||
scheduleTime: Int32? = nil
|
||||
) {
|
||||
guard let component = view.component else {
|
||||
return
|
||||
}
|
||||
if case .liveStream = component.slice.item.storyItem.media {
|
||||
if let visibleItem = view.visibleItems[component.slice.item.id], let itemView = visibleItem.view.view as? StoryItemContentComponent.View {
|
||||
if let call = itemView.mediaStreamCall {
|
||||
let focusedItem = component.slice.item
|
||||
guard let peerId = focusedItem.peerId else {
|
||||
return
|
||||
}
|
||||
guard let inputPanelView = view.inputPanel.view as? MessageInputPanelComponent.View else {
|
||||
return
|
||||
}
|
||||
|
||||
switch inputPanelView.getSendMessageInput() {
|
||||
case let .text(text):
|
||||
if !text.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
let entities = generateChatInputTextEntities(text)
|
||||
|
||||
call.sendMessage(text: text.string, entities: entities, paidStars: self.currentLiveStreamMessageStars?.value)
|
||||
|
||||
component.storyItemSharedState.replyDrafts.removeValue(forKey: StoryId(peerId: peerId, id: focusedItem.storyItem.id))
|
||||
inputPanelView.clearSendMessageInput(updateState: true)
|
||||
|
||||
self.currentInputMode = .text
|
||||
self.currentLiveStreamMessageStars = nil
|
||||
view.state?.updated(transition: .spring(duration: 0.3))
|
||||
|
||||
let controller = component.controller() as? StoryContainerScreen
|
||||
controller?.requestLayout(forceUpdate: true, transition: .animated(duration: 0.3, curve: .spring))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
self.performWithPossibleStealthModeConfirmation(view: view, action: { [weak self, weak view] in
|
||||
guard let self, let view else {
|
||||
return
|
||||
@ -1201,6 +1241,40 @@ final class StoryItemSetContainerSendMessage {
|
||||
}
|
||||
}
|
||||
|
||||
func performPaidMessageAction(view: StoryItemSetContainerComponent.View) {
|
||||
Task { @MainActor [weak view] in
|
||||
guard let view else {
|
||||
return
|
||||
}
|
||||
guard let component = view.component else {
|
||||
return
|
||||
}
|
||||
guard let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
let focusedItem = component.slice.item
|
||||
guard let peerId = focusedItem.peerId else {
|
||||
return
|
||||
}
|
||||
|
||||
let initialData = await ChatSendStarsScreen.initialDataLiveStreamMessage(context: component.context, peerId: peerId, completion: { [weak self, weak view] amount, _ in
|
||||
guard let self, let view else {
|
||||
return
|
||||
}
|
||||
|
||||
self.currentLiveStreamMessageStars = StarsAmount(value: amount, nanos: 0)
|
||||
view.state?.updated(transition: .spring(duration: 0.4))
|
||||
}).get()
|
||||
if let initialData {
|
||||
controller.push(ChatSendStarsScreen(
|
||||
context: component.context,
|
||||
initialData: initialData,
|
||||
theme: component.theme
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func performShareTextAction(view: StoryItemSetContainerComponent.View, text: String) {
|
||||
guard let component = view.component else {
|
||||
return
|
||||
|
||||
@ -369,9 +369,11 @@ public final class TabBarComponent: Component {
|
||||
|
||||
if let nativeTabBar = self.nativeTabBar {
|
||||
if previousComponent?.items.map(\.item.title) != component.items.map(\.item.title) {
|
||||
nativeTabBar.items = (0 ..< component.items.count).map { i in
|
||||
let items: [UITabBarItem] = (0 ..< component.items.count).map { i in
|
||||
return UITabBarItem(title: component.items[i].item.title, image: nil, tag: i)
|
||||
}
|
||||
//items.append(UITabBarItem(tabBarSystemItem: .search, tag: 100))
|
||||
nativeTabBar.items = items
|
||||
for (_, itemView) in self.itemViews {
|
||||
itemView.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user