[WIP] Serialization

This commit is contained in:
Isaac 2025-02-13 22:32:59 +04:00
parent c178023779
commit 8918f70173
30 changed files with 1515 additions and 64 deletions

View File

@ -42,9 +42,19 @@ public struct ItemCollectionViewEntry {
}
}
private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [ItemCollectionViewEntry] {
public struct RawItemCollectionViewEntry {
public let index: ItemCollectionViewEntryIndex
public let data: Data
var entries: [ItemCollectionViewEntry] = []
public init(index: ItemCollectionViewEntryIndex, data: Data) {
self.index = index
self.data = data
}
}
private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [RawItemCollectionViewEntry] {
var entries: [RawItemCollectionViewEntry] = []
var currentCollectionIndex = collectionIndex
var currentCollectionId = collectionId
@ -75,9 +85,9 @@ private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collect
return entries
}
private func fetchHigherEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [ItemCollectionViewEntry] {
private func fetchHigherEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [RawItemCollectionViewEntry] {
var entries: [ItemCollectionViewEntry] = []
var entries: [RawItemCollectionViewEntry] = []
var currentCollectionIndex = collectionIndex
var currentCollectionId = collectionId
@ -115,11 +125,11 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace],
lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?,
fetchLowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem],
higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?,
fetchHigherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> ([ItemCollectionViewEntry], ItemCollectionViewEntry?, ItemCollectionViewEntry?) {
var lowerEntries: [ItemCollectionViewEntry] = []
var upperEntries: [ItemCollectionViewEntry] = []
var lower: ItemCollectionViewEntry?
var upper: ItemCollectionViewEntry?
fetchHigherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> ([RawItemCollectionViewEntry], RawItemCollectionViewEntry?, RawItemCollectionViewEntry?) {
var lowerEntries: [RawItemCollectionViewEntry] = []
var upperEntries: [RawItemCollectionViewEntry] = []
var lower: RawItemCollectionViewEntry?
var upper: RawItemCollectionViewEntry?
let selectedAroundIndex: ItemCollectionViewEntryIndex
if let aroundIndex = aroundIndex, let aroundCollectionIndex = collectionIndexById(aroundIndex.collectionId) {
@ -153,7 +163,7 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace],
}
if lowerEntries.count != 0 && lowerEntries.count + upperEntries.count < count {
var additionalLowerEntries: [ItemCollectionViewEntry] = fetchLowerEntries(namespaces: namespaces, collectionId: lowerEntries.last!.index.collectionId, collectionIndex: lowerEntries.last!.index.collectionIndex, itemIndex: lowerEntries.last!.index.itemIndex, count: count - lowerEntries.count - upperEntries.count + 1, lowerCollectionId: lowerCollectionId, lowerItems: fetchLowerItems)
var additionalLowerEntries: [RawItemCollectionViewEntry] = fetchLowerEntries(namespaces: namespaces, collectionId: lowerEntries.last!.index.collectionId, collectionIndex: lowerEntries.last!.index.collectionIndex, itemIndex: lowerEntries.last!.index.itemIndex, count: count - lowerEntries.count - upperEntries.count + 1, lowerCollectionId: lowerCollectionId, lowerItems: fetchLowerItems)
if additionalLowerEntries.count >= count - lowerEntries.count + upperEntries.count + 1 {
lower = additionalLowerEntries.last
@ -162,7 +172,7 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace],
lowerEntries.append(contentsOf: additionalLowerEntries)
}
var entries: [ItemCollectionViewEntry] = []
var entries: [RawItemCollectionViewEntry] = []
entries.append(contentsOf: lowerEntries.reversed())
entries.append(contentsOf: upperEntries)
return (entries: entries, lower: lower, upper: upper)

View File

@ -23,6 +23,7 @@ swift_library(
"//submodules/Utils/RangeSet:RangeSet",
"//submodules/Utils/DarwinDirStat",
"//submodules/Emoji",
"//submodules/TelegramCore/FlatBuffers",
"//submodules/TelegramCore/FlatSerialization",
],
visibility = [

View File

@ -26,7 +26,7 @@ genrule(
rm -rf "$$BUILD_DIR"
mkdir -p "$$BUILD_DIR"
"$$FLATC" --swift -o "$$BUILD_DIR" {flatc_input}
"$$FLATC" --require-explicit-ids --swift -o "$$BUILD_DIR" {flatc_input}
""".format(
flatc_input=flatc_input
) + "\n" + "\n".join([

View File

@ -0,0 +1,9 @@
include "PeerId.fbs";
namespace TelegramCore;
struct MessageId {
peerId: PeerId (id: 0);
namespace: int32 (id: 1);
id: int32 (id: 2);
}

View File

@ -0,0 +1,57 @@
include "MessageId.fbs";
include "PeerId.fbs";
include "PeerReference.fbs";
include "StickerPackReference.fbs";
namespace TelegramCore;
table MessageReference {
peer:PeerReference (id: 0, required);
author:PeerReference (id: 1);
messageId:MessageId (id: 2, required);
timestamp:int32 (id: 3);
incoming:bool (id: 4);
secret:bool (id: 5);
threadId:int64 (id: 6);
}
table WebpageReference {
webpageId:int64 (id: 0);
url:string (id: 1, required);
}
table PartialMediaReference_Message {
message:MessageReference (id: 0);
}
table PartialMediaReference_WebPage {
webPage:WebpageReference (id: 0);
}
table PartialMediaReference_StickerPack {
stickerPack:StickerPackReference (id: 0, required);
}
table PartialMediaReference_SavedGif {
}
table PartialMediaReference_SavedSticker {
}
table PartialMediaReference_RecentSticker {
}
union PartialMediaReference_Value {
PartialMediaReference_Message,
PartialMediaReference_WebPage,
PartialMediaReference_StickerPack,
PartialMediaReference_SavedGif,
PartialMediaReference_SavedSticker,
PartialMediaReference_RecentSticker
}
table PartialMediaReference {
value:PartialMediaReference_Value (id: 1, required);
}
root_type PartialMediaReference;

View File

@ -0,0 +1,6 @@
namespace TelegramCore;
struct PeerId {
namespace: int32 (id: 0);
id: int64 (id: 1);
}

View File

@ -0,0 +1,27 @@
namespace TelegramCore;
table PeerReference_User {
id:int64 (id: 0);
accessHash:int64 (id: 1);
}
table PeerReference_Group {
id:int64 (id: 0);
}
table PeerReference_Channel {
id:int64 (id: 0);
accessHash:int64 (id: 1);
}
union PeerReference_Value {
PeerReference_User,
PeerReference_Group,
PeerReference_Channel
}
table PeerReference {
value:PeerReference_Value (id: 1, required);
}
root_type PeerReference;

View File

@ -0,0 +1,54 @@
namespace TelegramCore;
table StickerPackReference_Id {
id:int64 (id: 0);
accessHash:int64 (id: 1);
}
table StickerPackReference_Name {
name:string (id: 0, required);
}
table StickerPackReference_AnimatedEmoji {
}
table StickerPackReference_Dice {
emoji:string (id: 0, required);
}
table StickerPackReference_AnimatedEmojiAnimations {
}
table StickerPackReference_PremiumGifts {
}
table StickerPackReference_EmojiGenericAnimations {
}
table StickerPackReference_IconStatusEmoji {
}
table StickerPackReference_IconTopicEmoji {
}
table StickerPackReference_IconChannelStatusEmoji {
}
union StickerPackReference_Value {
StickerPackReference_Id,
StickerPackReference_Name,
StickerPackReference_AnimatedEmoji,
StickerPackReference_Dice,
StickerPackReference_AnimatedEmojiAnimations,
StickerPackReference_PremiumGifts,
StickerPackReference_EmojiGenericAnimations,
StickerPackReference_IconStatusEmoji,
StickerPackReference_IconTopicEmoji,
StickerPackReference_IconChannelStatusEmoji
}
table StickerPackReference {
value:StickerPackReference_Value (id: 1, required);
}
root_type StickerPackReference;

View File

@ -1,11 +1,25 @@
include "MediaId.fbs";
include "TelegramMediaResource.fbs";
include "TelegramMediaFileAttribute.fbs";
include "TelegramMediaImageRepresentation.fbs";
include "VideoThumbnail.fbs";
include "TelegramMediaImage.fbs";
include "PartialMediaReference.fbs";
namespace TelegramCore;
table TelegramMediaFile {
id: MediaId;
videoThumbnails: [VideoThumbnail];
fileId:MediaId (id: 0, required);
partialReference:PartialMediaReference (id: 1);
resource:TelegramMediaResource (id: 2, required);
previewRepresentations:[TelegramMediaImageRepresentation] (id: 3);
videoThumbnails:[VideoThumbnail] (id: 4);
videoCover:TelegramMediaImage (id: 5);
immediateThumbnailData:[ubyte] (id: 6);
mimeType:string (id: 7, required);
size:int64 (id: 8);
attributes:[TelegramMediaFileAttribute] (id: 9);
alternativeRepresentations:[TelegramMediaFile] (id: 10);
}
root_type TelegramMediaFile;

View File

@ -0,0 +1,85 @@
include "StickerPackReference.fbs";
namespace TelegramCore;
table TelegramMediaFileAttribute_FileName {
fileName:string (id: 0, required);
}
table StickerMaskCoords {
n:int32 (id: 0);
x:float32 (id: 1);
y:float32 (id: 2);
zoom:float32 (id: 3);
}
table TelegramMediaFileAttribute_Sticker {
displayText:string (id: 0, required);
packReference:StickerPackReference (id: 1);
maskData:StickerMaskCoords (id: 2);
}
table TelegramMediaFileAttribute_ImageSize {
width:int32 (id: 0);
height:int32 (id: 1);
}
table TelegramMediaFileAttribute_Animated {
}
table TelegramMediaFileAttribute_Video {
duration:float32 (id: 0);
width:int32 (id: 1);
height:int32 (id: 2);
flags:int32 (id: 3);
preloadSize:int32 (id: 4);
coverTime:float32 (id: 5);
videoCodec:string (id: 6);
}
table TelegramMediaFileAttribute_Audio {
isVoice:bool (id: 0);
duration:int32 (id: 1);
title:string (id: 2);
performer:string (id: 3);
waveform:[ubyte] (id: 4);
}
table TelegramMediaFileAttribute_HasLinkedStickers {
}
table TelegramMediaFileAttribute_HintFileIsLarge {
}
table TelegramMediaFileAttribute_HintIsValidated {
}
table TelegramMediaFileAttribute_NoPremium {
}
table TelegramMediaFileAttribute_CustomEmoji {
isPremium:bool (id: 0);
isSingleColor:bool (id: 1);
alt:string (id: 2, required);
packReference:StickerPackReference (id: 3);
}
union TelegramMediaFileAttribute_Value {
TelegramMediaFileAttribute_FileName,
TelegramMediaFileAttribute_Sticker,
TelegramMediaFileAttribute_ImageSize,
TelegramMediaFileAttribute_Animated,
TelegramMediaFileAttribute_Video,
TelegramMediaFileAttribute_Audio,
TelegramMediaFileAttribute_HasLinkedStickers,
TelegramMediaFileAttribute_HintFileIsLarge,
TelegramMediaFileAttribute_HintIsValidated,
TelegramMediaFileAttribute_NoPremium,
TelegramMediaFileAttribute_CustomEmoji
}
table TelegramMediaFileAttribute {
value:TelegramMediaFileAttribute_Value (id: 1, required);
}
root_type TelegramMediaFileAttribute;

View File

@ -0,0 +1,51 @@
include "MediaId.fbs";
include "TelegramMediaImageRepresentation.fbs";
include "StickerPackReference.fbs";
include "PartialMediaReference.fbs";
namespace TelegramCore;
table TelegramMediaImageReference {
imageId:int64 (id: 0);
accessHash:int64 (id: 1);
fileReference:[ubyte] (id: 2);
}
table VideoRepresentation {
width:int32 (id: 0);
height:int32 (id: 1);
resource:TelegramMediaResource (id: 2, required);
startTimestamp:float32 (id: 3);
}
table EmojiMarkup_Content_Emoji {
fileId:int64 (id: 0);
}
table EmojiMarkup_Content_Sticker {
packReference:StickerPackReference (id: 0, required);
fileId:int64 (id: 1);
}
union EmojiMarkup_Content {
EmojiMarkup_Content_Emoji,
EmojiMarkup_Content_Sticker
}
table EmojiMarkup {
content:EmojiMarkup_Content (id: 1, required);
backgroundColors:[int32] (id: 2);
}
table TelegramMediaImage {
imageId:MediaId (id: 0, required);
representations:[TelegramMediaImageRepresentation] (id: 1);
videoRepresentations:[VideoRepresentation] (id: 2);
immediateThumbnailData:[ubyte] (id: 3);
emojiMarkup:EmojiMarkup (id: 4);
reference:TelegramMediaImageReference (id: 5);
partialReference:PartialMediaReference (id: 6);
flags:int32 (id: 7);
}
root_type TelegramMediaImage;

View File

@ -0,0 +1,22 @@
include "TelegramMediaResource.fbs";
namespace TelegramCore;
enum TelegramMediaImageRepresentation_TypeHint:int32 {
generic = 0,
animated = 1,
video = 2
}
table TelegramMediaImageRepresentation {
width:int32 (id: 0);
height:int32 (id: 1);
resource:TelegramMediaResource (id: 2, required);
progressiveSizes:[int32] (id: 3);
immediateThumbnailData:[ubyte] (id: 4);
hasVideo:bool (id: 5);
isPersonal:bool (id: 6);
typeHint:TelegramMediaImageRepresentation_TypeHint (id: 7);
}
root_type TelegramMediaImageRepresentation;

View File

@ -0,0 +1,78 @@
namespace TelegramCore;
table TelegramMediaResource_CloudFileMediaResource {
datacenterId:int32 (id: 0);
volumeId:int64 (id: 1);
localId:int32 (id: 2);
secret:int64 (id: 3);
size:int64 (id: 4);
fileReference:[ubyte] (id: 5);
}
table TelegramMediaResource_CloudDocumentSizeMediaResource {
datacenterId:int32 (id: 0);
documentId:int64 (id: 1);
accessHash:int64 (id: 2);
sizeSpec:string (id: 3, required);
fileReference:[ubyte] (id: 4);
}
table TelegramMediaResource_CloudPhotoSizeMediaResource {
datacenterId:int32 (id: 0);
photoId:int64 (id: 1);
accessHash:int64 (id: 2);
sizeSpec:string (id: 3, required);
size:int64 (id: 4);
fileReference:[ubyte] (id: 5);
}
enum CloudPeerPhotoSizeSpec:int32 {
small = 0,
fullSize = 1
}
table TelegramMediaResource_CloudPeerPhotoSizeMediaResource {
datacenterId:int32 (id: 0);
photoId:int64 (id: 1);
sizeSpec:CloudPeerPhotoSizeSpec (id: 2);
volumeId:int64 (id: 3);
localId:int32 (id: 4);
}
table TelegramMediaResource_CloudStickerPackThumbnailMediaResource {
datacenterId:int32 (id: 0);
thumbVersion:int32 (id: 1);
volumeId:int64 (id: 2);
localId:int32 (id: 3);
}
table TelegramMediaResource_CloudDocumentMediaResource {
datacenterId:int32 (id: 0);
fileId:int64 (id: 1);
accessHash:int64 (id: 2);
size:int64 (id: 3);
fileReference:[ubyte] (id: 4);
fileName:string (id: 5);
}
table TelegramMediaResource_LocalFileMediaResource {
fileId:int64 (id: 0);
size:int64 (id: 1);
isSecretRelated:bool (id: 2);
}
union TelegramMediaResource_Value {
TelegramMediaResource_CloudFileMediaResource,
TelegramMediaResource_CloudDocumentSizeMediaResource,
TelegramMediaResource_CloudPhotoSizeMediaResource,
TelegramMediaResource_CloudPeerPhotoSizeMediaResource,
TelegramMediaResource_CloudStickerPackThumbnailMediaResource,
TelegramMediaResource_CloudDocumentMediaResource,
TelegramMediaResource_LocalFileMediaResource
}
table TelegramMediaResource {
value:TelegramMediaResource_Value (id: 1, required);
}
root_type TelegramMediaResource;

View File

@ -1,7 +1,11 @@
include "PixelDimensions.fbs";
include "TelegramMediaResource.fbs";
namespace TelegramCore;
struct VideoThumbnail {
dimensions: PixelDimensions;
table VideoThumbnail {
width:int32 (id: 0);
height:int32 (id: 1);
resource:TelegramMediaResource (id: 2, required);
}
root_type VideoThumbnail;

View File

@ -2,7 +2,6 @@ import Foundation
import Postbox
import TelegramApi
func dimensionsForFileAttributes(_ attributes: [TelegramMediaFileAttribute]) -> PixelDimensions? {
for attribute in attributes {
switch attribute {
@ -183,7 +182,7 @@ func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [A
}
}
var alternativeRepresentations: [Media] = []
var alternativeRepresentations: [TelegramMediaFile] = []
if let altDocuments {
alternativeRepresentations = altDocuments.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
}

View File

@ -1,6 +1,8 @@
import Foundation
import Postbox
import TelegramApi
import FlatBuffers
import FlatSerialization
public struct CloudFileMediaResourceId: Hashable, Equatable {
let datacenterId: Int
@ -956,3 +958,215 @@ public final class WallpaperDataResource: TelegramMediaResource {
return true
}
}
public func TelegramMediaResource_parse(flatBuffersData data: Data) throws -> TelegramMediaResource {
var byteBuffer = ByteBuffer(data: data)
let flatBuffersObject: TelegramCore_TelegramMediaResource = try getCheckedRoot(byteBuffer: &byteBuffer)
return try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject)
}
public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_TelegramMediaResource) throws -> TelegramMediaResource {
switch flatBuffersObject.valueType {
case .telegrammediaresourceCloudfilemediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudFileMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return CloudFileMediaResource(
datacenterId: Int(value.datacenterId),
volumeId: value.volumeId,
localId: value.localId,
secret: value.secret,
size: value.size == 0 ? nil : value.size,
fileReference: value.fileReference.isEmpty ? nil : Data(value.fileReference)
)
case .telegrammediaresourceClouddocumentsizemediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return CloudDocumentSizeMediaResource(
datacenterId: value.datacenterId,
documentId: value.documentId,
accessHash: value.accessHash,
sizeSpec: value.sizeSpec,
fileReference: value.fileReference.isEmpty ? nil : Data(value.fileReference)
)
case .telegrammediaresourceCloudphotosizemediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return CloudPhotoSizeMediaResource(
datacenterId: value.datacenterId,
photoId: value.photoId,
accessHash: value.accessHash,
sizeSpec: value.sizeSpec,
size: value.size == 0 ? nil : value.size,
fileReference: value.fileReference.isEmpty ? nil : Data(value.fileReference)
)
case .telegrammediaresourceCloudpeerphotosizemediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
let sizeSpec: CloudPeerPhotoSizeSpec
switch value.sizeSpec {
case .small:
sizeSpec = .small
case .fullSize:
sizeSpec = .fullSize
}
return CloudPeerPhotoSizeMediaResource(
datacenterId: value.datacenterId,
photoId: value.photoId == Int64.min ? nil : value.photoId,
sizeSpec: sizeSpec,
volumeId: value.volumeId == Int64.min ? nil : value.volumeId,
localId: value.localId == Int32.min ? nil : value.localId
)
case .telegrammediaresourceCloudstickerpackthumbnailmediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return CloudStickerPackThumbnailMediaResource(
datacenterId: value.datacenterId,
thumbVersion: value.thumbVersion == Int32.min ? nil : value.thumbVersion,
volumeId: value.volumeId == Int64.min ? nil : value.volumeId,
localId: value.localId == Int32.min ? nil : value.localId
)
case .telegrammediaresourceClouddocumentmediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return CloudDocumentMediaResource(
datacenterId: Int(value.datacenterId),
fileId: value.fileId,
accessHash: value.accessHash,
size: value.size == 0 ? nil : value.size,
fileReference: value.fileReference.isEmpty ? nil : Data(value.fileReference),
fileName: value.fileName
)
case .telegrammediaresourceLocalfilemediaresource:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_LocalFileMediaResource.self) else {
throw FlatBuffersError.missingRequiredField
}
return LocalFileMediaResource(
fileId: value.fileId,
size: value.size == Int64.min ? nil : value.size,
isSecretRelated: value.isSecretRelated
)
case .none_:
throw FlatBuffersError.missingRequiredField
}
}
public func TelegramMediaResource_serialize(resource: TelegramMediaResource, flatBuffersBuilder builder: inout FlatBufferBuilder) -> Offset? {
switch resource {
case let resource as CloudFileMediaResource:
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaResource_CloudFileMediaResource.startTelegramMediaResource_CloudFileMediaResource(&builder)
TelegramCore_TelegramMediaResource_CloudFileMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudFileMediaResource.add(volumeId: resource.volumeId, &builder)
TelegramCore_TelegramMediaResource_CloudFileMediaResource.add(localId: resource.localId, &builder)
TelegramCore_TelegramMediaResource_CloudFileMediaResource.add(secret: resource.secret, &builder)
TelegramCore_TelegramMediaResource_CloudFileMediaResource.add(size: resource.size ?? 0, &builder)
if let fileReferenceOffset {
TelegramCore_TelegramMediaResource_CloudFileMediaResource.addVectorOf(fileReference: fileReferenceOffset, &builder)
}
let offset = TelegramCore_TelegramMediaResource_CloudFileMediaResource.endTelegramMediaResource_CloudFileMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceCloudfilemediaresource, valueOffset: offset)
case let resource as CloudDocumentSizeMediaResource:
let sizeSpecOffset = builder.create(string: resource.sizeSpec)
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.startTelegramMediaResource_CloudDocumentSizeMediaResource(&builder)
TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.add(documentId: resource.documentId, &builder)
TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.add(accessHash: resource.accessHash, &builder)
TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.add(sizeSpec: sizeSpecOffset, &builder)
if let fileReferenceOffset {
TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.addVectorOf(fileReference: fileReferenceOffset, &builder)
}
let offset = TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.endTelegramMediaResource_CloudDocumentSizeMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceClouddocumentsizemediaresource, valueOffset: offset)
case let resource as CloudPhotoSizeMediaResource:
let sizeSpecOffset = builder.create(string: resource.sizeSpec)
let start = TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.startTelegramMediaResource_CloudPhotoSizeMediaResource(&builder)
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(photoId: resource.photoId, &builder)
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(accessHash: resource.accessHash, &builder)
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(sizeSpec: sizeSpecOffset, &builder)
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(size: resource.size ?? 0, &builder)
if let fileReferenceOffset {
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.addVectorOf(fileReference: fileReferenceOffset, &builder)
}
let offset = TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.endTelegramMediaResource_CloudPhotoSizeMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceCloudphotosizemediaresource, valueOffset: offset)
case let resource as CloudPeerPhotoSizeMediaResource:
let start = TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.startTelegramMediaResource_CloudPeerPhotoSizeMediaResource(&builder)
let sizeSpec: TelegramCore_CloudPeerPhotoSizeSpec
switch resource.sizeSpec {
case .small:
sizeSpec = .small
case .fullSize:
sizeSpec = .fullSize
}
TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.add(photoId: resource.photoId ?? Int64.min, &builder)
TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.add(sizeSpec: sizeSpec, &builder)
TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.add(volumeId: resource.volumeId ?? Int64.min, &builder)
TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.add(localId: resource.localId ?? Int32.min, &builder)
let offset = TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.endTelegramMediaResource_CloudPeerPhotoSizeMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceCloudpeerphotosizemediaresource, valueOffset: offset)
case let resource as CloudStickerPackThumbnailMediaResource:
let start = TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.startTelegramMediaResource_CloudStickerPackThumbnailMediaResource(&builder)
TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.add(thumbVersion: resource.thumbVersion ?? Int32.min, &builder)
TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.add(volumeId: resource.volumeId ?? Int64.min, &builder)
TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.add(localId: resource.localId ?? Int32.min, &builder)
let offset = TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.endTelegramMediaResource_CloudStickerPackThumbnailMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceCloudstickerpackthumbnailmediaresource, valueOffset: offset)
case let resource as CloudDocumentMediaResource:
let fileNameOffset = resource.fileName.flatMap { builder.create(string: $0) }
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.startTelegramMediaResource_CloudDocumentMediaResource(&builder)
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.add(fileId: resource.fileId, &builder)
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.add(accessHash: resource.accessHash, &builder)
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.add(size: resource.size ?? 0, &builder)
if let fileReferenceOffset {
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.addVectorOf(fileReference: fileReferenceOffset, &builder)
}
if let fileNameOffset {
TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.add(fileName: fileNameOffset, &builder)
}
let offset = TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.endTelegramMediaResource_CloudDocumentMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceClouddocumentmediaresource, valueOffset: offset)
case let resource as LocalFileMediaResource:
let start = TelegramCore_TelegramMediaResource_LocalFileMediaResource.startTelegramMediaResource_LocalFileMediaResource(&builder)
TelegramCore_TelegramMediaResource_LocalFileMediaResource.add(fileId: resource.fileId, &builder)
TelegramCore_TelegramMediaResource_LocalFileMediaResource.add(size: resource.size ?? Int64.min, &builder)
TelegramCore_TelegramMediaResource_LocalFileMediaResource.add(isSecretRelated: resource.isSecretRelated, &builder)
let offset = TelegramCore_TelegramMediaResource_LocalFileMediaResource.endTelegramMediaResource_LocalFileMediaResource(&builder, start: start)
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceLocalfilemediaresource, valueOffset: offset)
default:
assertionFailure()
return nil
}
}

View File

@ -65,6 +65,10 @@ public struct MessageReference: PostboxCoding, Hashable, Equatable {
}
}
init(content: MessageReferenceContent) {
self.content = content
}
public init(_ message: Message) {
if message.id.namespace != Namespaces.Message.Local, let peer = message.peers[message.id.peerId], let inputPeer = PeerReference(peer) {
let author: PeerReference?
@ -145,6 +149,10 @@ public enum MessageReferenceContent: PostboxCoding, Hashable, Equatable {
public struct WebpageReference: PostboxCoding, Hashable, Equatable {
public let content: WebpageReferenceContent
init(content: WebpageReferenceContent) {
self.content = content
}
public init(_ webPage: TelegramMediaWebpage) {
if case let .Loaded(content) = webPage.content {
self.content = .webPage(id: webPage.webpageId.id, url: content.url)

View File

@ -0,0 +1,146 @@
import Postbox
import FlatBuffers
import FlatSerialization
public extension PeerId {
init(flatBuffersObject: TelegramCore_PeerId) {
self.init(namespace: PeerId.Namespace._internalFromInt32Value(flatBuffersObject.namespace), id: PeerId.Id._internalFromInt64Value(flatBuffersObject.id))
}
}
public extension MessageId {
init(flatBuffersObject: TelegramCore_MessageId) {
self.init(peerId: PeerId(flatBuffersObject: flatBuffersObject.peerId), namespace: flatBuffersObject.namespace, id: flatBuffersObject.id)
}
}
public extension MessageReference {
init(flatBuffersObject: TelegramCore_MessageReference) throws {
self.init(content: .message(
peer: try PeerReference(flatBuffersObject: flatBuffersObject.peer),
author: try flatBuffersObject.author.flatMap { try PeerReference(flatBuffersObject: $0) },
id: MessageId(flatBuffersObject: flatBuffersObject.messageId),
timestamp: flatBuffersObject.timestamp,
incoming: flatBuffersObject.incoming,
secret: flatBuffersObject.secret,
threadId: flatBuffersObject.threadId == Int64.min ? nil : flatBuffersObject.threadId)
)
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset? {
switch self.content {
case let .message(peer, author, id, timestamp, incoming, secret, threadId):
let peerOffset = peer.encodeToFlatBuffers(builder: &builder)
let authorOffset = author.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let start = TelegramCore_MessageReference.startMessageReference(&builder)
TelegramCore_MessageReference.add(peer: peerOffset, &builder)
if let authorOffset {
TelegramCore_MessageReference.add(author: authorOffset, &builder)
}
TelegramCore_MessageReference.add(messageId: TelegramCore_MessageId(peerId: TelegramCore_PeerId(namespace: id.peerId.namespace._internalGetInt32Value(), id: id.peerId.id._internalGetInt64Value()), namespace: id.namespace, id: id.id), &builder)
TelegramCore_MessageReference.add(timestamp: timestamp, &builder)
TelegramCore_MessageReference.add(incoming: incoming, &builder)
TelegramCore_MessageReference.add(secret: secret, &builder)
TelegramCore_MessageReference.add(threadId: threadId ?? Int64.min, &builder)
return TelegramCore_MessageReference.endMessageReference(&builder, start: start)
case .none:
return nil
}
}
}
public extension WebpageReference {
init(flatBuffersObject: TelegramCore_WebpageReference) throws {
self.init(content: .webPage(id: flatBuffersObject.webpageId, url: flatBuffersObject.url))
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset? {
switch self.content {
case let .webPage(id, url):
let urlOffset = builder.create(string: url)
let start = TelegramCore_WebpageReference.startWebpageReference(&builder)
TelegramCore_WebpageReference.add(webpageId: id, &builder)
TelegramCore_WebpageReference.add(url: urlOffset, &builder)
return TelegramCore_WebpageReference.endWebpageReference(&builder, start: start)
case .none:
return nil
}
}
}
public extension PartialMediaReference {
init(flatBuffersObject: TelegramCore_PartialMediaReference) throws {
switch flatBuffersObject.valueType {
case .partialmediareferenceMessage:
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_Message.self) else {
throw FlatBuffersError.missingRequiredField
}
if let message = value.message {
self = .message(message: try MessageReference(flatBuffersObject: message))
} else {
self = .message(message: MessageReference(content: .none))
}
case .partialmediareferenceWebpage:
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_WebPage.self) else {
throw FlatBuffersError.missingRequiredField
}
if let webPage = value.webPage {
self = .webPage(webPage: try WebpageReference(flatBuffersObject: webPage))
} else {
self = .webPage(webPage: WebpageReference(content: .none))
}
case .partialmediareferenceStickerpack:
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_StickerPack.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .stickerPack(stickerPack: try StickerPackReference(flatBuffersObject: value.stickerPack))
case .partialmediareferenceSavedgif:
self = .savedGif
case .partialmediareferenceSavedsticker:
self = .savedSticker
case .partialmediareferenceRecentsticker:
self = .recentSticker
case .none_:
throw FlatBuffersError.missingRequiredField
}
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
switch self {
case let .message(message):
let messageOffset = message.encodeToFlatBuffers(builder: &builder)
let start = TelegramCore_PartialMediaReference_Message.startPartialMediaReference_Message(&builder)
if let messageOffset {
TelegramCore_PartialMediaReference_Message.add(message: messageOffset, &builder)
}
return TelegramCore_PartialMediaReference_Message.endPartialMediaReference_Message(&builder, start: start)
case let .webPage(webPage):
let webpageOffset = webPage.encodeToFlatBuffers(builder: &builder)
let start = TelegramCore_PartialMediaReference_WebPage.startPartialMediaReference_WebPage(&builder)
if let webpageOffset {
TelegramCore_PartialMediaReference_WebPage.add(webPage: webpageOffset, &builder)
}
return TelegramCore_PartialMediaReference_WebPage.endPartialMediaReference_WebPage(&builder, start: start)
case let .stickerPack(stickerPack):
let stickerPackOffset = stickerPack.encodeToFlatBuffers(builder: &builder)
let start = TelegramCore_PartialMediaReference_StickerPack.startPartialMediaReference_StickerPack(&builder)
TelegramCore_PartialMediaReference_StickerPack.add(stickerPack: stickerPackOffset, &builder)
return TelegramCore_PartialMediaReference_StickerPack.endPartialMediaReference_StickerPack(&builder, start: start)
case .savedGif:
let start = TelegramCore_PartialMediaReference_SavedGif.startPartialMediaReference_SavedGif(&builder)
return TelegramCore_PartialMediaReference_SavedGif.endPartialMediaReference_SavedGif(&builder, start: start)
case .savedSticker:
let start = TelegramCore_PartialMediaReference_SavedSticker.startPartialMediaReference_SavedSticker(&builder)
return TelegramCore_PartialMediaReference_SavedSticker.endPartialMediaReference_SavedSticker(&builder, start: start)
case .recentSticker:
let start = TelegramCore_PartialMediaReference_RecentSticker.startPartialMediaReference_RecentSticker(&builder)
return TelegramCore_PartialMediaReference_RecentSticker.endPartialMediaReference_RecentSticker(&builder, start: start)
}
}
}

View File

@ -1,4 +1,6 @@
import Postbox
import FlatBuffers
import FlatSerialization
public enum PeerReference: PostboxCoding, Hashable, Equatable {
case user(id: Int64, accessHash: Int64)
@ -73,4 +75,48 @@ public enum PeerReference: PostboxCoding, Hashable, Equatable {
return nil
}
}
public init(flatBuffersObject: TelegramCore_PeerReference) throws {
switch flatBuffersObject.valueType {
case .peerreferenceUser:
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_User.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .user(id: value.id, accessHash: value.accessHash)
case .peerreferenceGroup:
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Group.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .group(id: value.id)
case .peerreferenceChannel:
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Channel.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .channel(id: value.id, accessHash: value.accessHash)
case .none_:
throw FlatBuffersError.missingRequiredField
}
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
switch self {
case let .user(id, accessHash):
let start = TelegramCore_PeerReference.startPeerReference(&builder)
TelegramCore_PeerReference_User.add(id: id, &builder)
TelegramCore_PeerReference_User.add(accessHash: accessHash, &builder)
let offset = TelegramCore_PeerReference_User.endPeerReference_User(&builder, start: start)
return TelegramCore_PeerReference.createPeerReference(&builder, valueType: .peerreferenceUser, valueOffset: offset)
case let .group(id):
let start = TelegramCore_PeerReference.startPeerReference(&builder)
TelegramCore_PeerReference_Group.add(id: id, &builder)
let offset = TelegramCore_PeerReference_Group.endPeerReference_Group(&builder, start: start)
return TelegramCore_PeerReference.createPeerReference(&builder, valueType: .peerreferenceUser, valueOffset: offset)
case let .channel(id, accessHash):
let start = TelegramCore_PeerReference.startPeerReference(&builder)
TelegramCore_PeerReference_Channel.add(id: id, &builder)
TelegramCore_PeerReference_Channel.add(accessHash: accessHash, &builder)
let offset = TelegramCore_PeerReference_Channel.endPeerReference_Channel(&builder, start: start)
return TelegramCore_PeerReference.createPeerReference(&builder, valueType: .peerreferenceUser, valueOffset: offset)
}
}
}

View File

@ -1,19 +1,25 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
public final class StickerPackItem: ItemCollectionItem, Equatable {
public let index: ItemCollectionItemIndex
public let file: TelegramMediaFile
public let serializedFile: Data
public let indexKeys: [MemoryBuffer]
public init(index: ItemCollectionItemIndex, file: TelegramMediaFile, indexKeys: [MemoryBuffer]) {
self.index = index
self.file = file
self.serializedFile = file.encodeToFlatBuffersData()
self.indexKeys = indexKeys
}
public init(decoder: PostboxDecoder) {
self.index = ItemCollectionItemIndex(index: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0))
self.file = decoder.decodeObjectForKey("f") as! TelegramMediaFile
self.serializedFile = decoder.decodeDataForKey("fd") ?? self.file.encodeToFlatBuffersData()
self.indexKeys = decoder.decodeBytesArrayForKey("s")
}
@ -21,6 +27,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
encoder.encodeInt32(self.index.index, forKey: "i.n")
encoder.encodeInt64(self.index.id, forKey: "i.i")
encoder.encodeObject(self.file, forKey: "f")
encoder.encodeData(self.serializedFile, forKey: "fd")
encoder.encodeBytesArray(self.indexKeys, forKey: "s")
}

View File

@ -1,5 +1,7 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
private let typeFileName: Int32 = 0
private let typeSticker: Int32 = 1
@ -13,6 +15,11 @@ private let typeHintIsValidated: Int32 = 8
private let typeNoPremium: Int32 = 9
private let typeCustomEmoji: Int32 = 10
enum FlatBuffersError: Error {
case missingRequiredField
case invalidUnionType
}
public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
case id(id: Int64, accessHash: Int64)
case name(String)
@ -120,6 +127,96 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
}
}
init(flatBuffersObject: TelegramCore_StickerPackReference) throws {
switch flatBuffersObject.valueType {
case .stickerpackreferenceId:
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Id.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .id(id: value.id, accessHash: value.accessHash)
case .stickerpackreferenceName:
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Name.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .name(value.name)
case .stickerpackreferenceAnimatedemoji:
self = .animatedEmoji
case .stickerpackreferenceDice:
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Dice.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .dice(value.emoji)
case .stickerpackreferenceAnimatedemojianimations:
self = .animatedEmojiAnimations
case .stickerpackreferencePremiumgifts:
self = .premiumGifts
case .stickerpackreferenceEmojigenericanimations:
self = .emojiGenericAnimations
case .stickerpackreferenceIconstatusemoji:
self = .iconStatusEmoji
case .stickerpackreferenceIcontopicemoji:
self = .iconTopicEmoji
case .stickerpackreferenceIconchannelstatusemoji:
self = .iconChannelStatusEmoji
case .none_:
throw FlatBuffersError.missingRequiredField
}
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let valueType: TelegramCore_StickerPackReference_Value
let offset: Offset
switch self {
case let .id(id, accessHash):
valueType = .stickerpackreferenceId
let start = TelegramCore_StickerPackReference_Id.startStickerPackReference_Id(&builder)
TelegramCore_StickerPackReference_Id.add(id: id, &builder)
TelegramCore_StickerPackReference_Id.add(accessHash: accessHash, &builder)
offset = TelegramCore_StickerPackReference_Id.endStickerPackReference_Id(&builder, start: start)
case let .name(name):
valueType = .stickerpackreferenceName
let nameOffset = builder.create(string: name)
let start = TelegramCore_StickerPackReference_Name.startStickerPackReference_Name(&builder)
TelegramCore_StickerPackReference_Name.add(name: nameOffset, &builder)
offset = TelegramCore_StickerPackReference_Name.endStickerPackReference_Name(&builder, start: start)
case .animatedEmoji:
valueType = .stickerpackreferenceAnimatedemoji
let start = TelegramCore_StickerPackReference_AnimatedEmoji.startStickerPackReference_AnimatedEmoji(&builder)
offset = TelegramCore_StickerPackReference_AnimatedEmoji.endStickerPackReference_AnimatedEmoji(&builder, start: start)
case let .dice(emoji):
valueType = .stickerpackreferenceDice
let emojiOffset = builder.create(string: emoji)
let start = TelegramCore_StickerPackReference_Dice.startStickerPackReference_Dice(&builder)
TelegramCore_StickerPackReference_Dice.add(emoji: emojiOffset, &builder)
offset = TelegramCore_StickerPackReference_Dice.endStickerPackReference_Dice(&builder, start: start)
case .animatedEmojiAnimations:
valueType = .stickerpackreferenceAnimatedemojianimations
let start = TelegramCore_StickerPackReference_AnimatedEmojiAnimations.startStickerPackReference_AnimatedEmojiAnimations(&builder)
offset = TelegramCore_StickerPackReference_AnimatedEmojiAnimations.endStickerPackReference_AnimatedEmojiAnimations(&builder, start: start)
case .premiumGifts:
valueType = .stickerpackreferencePremiumgifts
let start = TelegramCore_StickerPackReference_PremiumGifts.startStickerPackReference_PremiumGifts(&builder)
offset = TelegramCore_StickerPackReference_PremiumGifts.endStickerPackReference_PremiumGifts(&builder, start: start)
case .emojiGenericAnimations:
valueType = .stickerpackreferenceEmojigenericanimations
let start = TelegramCore_StickerPackReference_EmojiGenericAnimations.startStickerPackReference_EmojiGenericAnimations(&builder)
offset = TelegramCore_StickerPackReference_EmojiGenericAnimations.endStickerPackReference_EmojiGenericAnimations(&builder, start: start)
case .iconStatusEmoji:
valueType = .stickerpackreferenceIconstatusemoji
let start = TelegramCore_StickerPackReference_IconStatusEmoji.startStickerPackReference_IconStatusEmoji(&builder)
offset = TelegramCore_StickerPackReference_IconStatusEmoji.endStickerPackReference_IconStatusEmoji(&builder, start: start)
case .iconTopicEmoji:
valueType = .stickerpackreferenceIcontopicemoji
let start = TelegramCore_StickerPackReference_IconTopicEmoji.startStickerPackReference_IconTopicEmoji(&builder)
offset = TelegramCore_StickerPackReference_IconTopicEmoji.endStickerPackReference_IconTopicEmoji(&builder, start: start)
case .iconChannelStatusEmoji:
valueType = .stickerpackreferenceIconchannelstatusemoji
let start = TelegramCore_StickerPackReference_IconChannelStatusEmoji.startStickerPackReference_IconChannelStatusEmoji(&builder)
offset = TelegramCore_StickerPackReference_IconChannelStatusEmoji.endStickerPackReference_IconChannelStatusEmoji(&builder, start: start)
}
return TelegramCore_StickerPackReference.createStickerPackReference(&builder, valueType: valueType, valueOffset: offset)
}
public static func ==(lhs: StickerPackReference, rhs: StickerPackReference) -> Bool {
switch lhs {
case let .id(id, accessHash):
@ -217,9 +314,9 @@ public struct StickerMaskCoords: PostboxCoding, Equatable {
public init(decoder: PostboxDecoder) {
self.n = decoder.decodeInt32ForKey("n", orElse: 0)
self.x = decoder.decodeDoubleForKey("x", orElse: 0.0)
self.y = decoder.decodeDoubleForKey("y", orElse: 0.0)
self.zoom = decoder.decodeDoubleForKey("z", orElse: 0.0)
self.x = Double(Float32(decoder.decodeDoubleForKey("x", orElse: 0.0)))
self.y = Double(Float32(decoder.decodeDoubleForKey("y", orElse: 0.0)))
self.zoom = Double(Float32(decoder.decodeDoubleForKey("z", orElse: 0.0)))
}
public func encode(_ encoder: PostboxEncoder) {
@ -228,6 +325,13 @@ public struct StickerMaskCoords: PostboxCoding, Equatable {
encoder.encodeDouble(self.y, forKey: "y")
encoder.encodeDouble(self.zoom, forKey: "z")
}
init(flatBuffersObject: TelegramCore_StickerMaskCoords) {
self.n = flatBuffersObject.n
self.x = Double(flatBuffersObject.x)
self.y = Double(flatBuffersObject.y)
self.zoom = Double(flatBuffersObject.zoom)
}
}
public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
@ -262,7 +366,12 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
duration = Double(decoder.decodeInt32ForKey("du", orElse: 0))
}
self = .Video(duration: duration, size: PixelDimensions(width: decoder.decodeInt32ForKey("w", orElse: 0), height: decoder.decodeInt32ForKey("h", orElse: 0)), flags: TelegramMediaVideoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0)), preloadSize: decoder.decodeOptionalInt32ForKey("prs"), coverTime: decoder.decodeOptionalDoubleForKey("ct"), videoCodec: decoder.decodeOptionalStringForKey("vc"))
var coverTime: Double?
if let coverTimeValue = decoder.decodeOptionalDoubleForKey("ct") {
coverTime = Double(Float32(coverTimeValue))
}
self = .Video(duration: Double(Float32(duration)), size: PixelDimensions(width: decoder.decodeInt32ForKey("w", orElse: 0), height: decoder.decodeInt32ForKey("h", orElse: 0)), flags: TelegramMediaVideoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0)), preloadSize: decoder.decodeOptionalInt32ForKey("prs"), coverTime: coverTime, videoCodec: decoder.decodeOptionalStringForKey("vc"))
case typeAudio:
let waveformBuffer = decoder.decodeBytesForKeyNoCopy("wf")
var waveform: Data?
@ -363,6 +472,171 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
}
}
}
init(flatBuffersData data: Data) throws {
var byteBuffer = ByteBuffer(data: data)
let flatBuffersObject: TelegramCore_TelegramMediaFileAttribute = try getCheckedRoot(byteBuffer: &byteBuffer)
try self.init(flatBuffersObject: flatBuffersObject)
}
init(flatBuffersObject: TelegramCore_TelegramMediaFileAttribute) throws {
switch flatBuffersObject.valueType {
case .telegrammediafileattributeFilename:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_FileName.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .FileName(fileName: value.fileName)
case .telegrammediafileattributeSticker:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Sticker.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .Sticker(displayText: value.displayText, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }), maskData: value.maskData.flatMap({ StickerMaskCoords(flatBuffersObject: $0) }))
case .telegrammediafileattributeImagesize:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_ImageSize.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .ImageSize(size: PixelDimensions(width: value.width, height: value.height))
case .telegrammediafileattributeAnimated:
self = .Animated
case .telegrammediafileattributeVideo:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .Video(duration: Double(value.duration), size: PixelDimensions(width: value.width, height: value.height), flags: TelegramMediaVideoFlags(rawValue: value.flags), preloadSize: value.preloadSize == 0 ? nil : value.preloadSize, coverTime: value.coverTime == 0.0 ? nil : Double(value.coverTime), videoCodec: value.videoCodec)
case .telegrammediafileattributeAudio:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Audio.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .Audio(isVoice: value.isVoice, duration: Int(value.duration), title: value.title, performer: value.performer, waveform: value.waveform.isEmpty ? nil : Data(value.waveform))
case .telegrammediafileattributeHaslinkedstickers:
self = .HasLinkedStickers
case .telegrammediafileattributeHintfileislarge:
self = .hintFileIsLarge
case .telegrammediafileattributeHintisvalidated:
self = .hintIsValidated
case .telegrammediafileattributeNopremium:
self = .NoPremium
case .none_:
throw FlatBuffersError.missingRequiredField
case .telegrammediafileattributeCustomemoji:
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) else {
throw FlatBuffersError.missingRequiredField
}
self = .CustomEmoji(isPremium: value.isPremium, isSingleColor: value.isSingleColor, alt: value.alt, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }))
}
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let valueType: TelegramCore_TelegramMediaFileAttribute_Value
let offset: Offset
switch self {
case let .FileName(fileName):
valueType = .telegrammediafileattributeFilename
let fileNameOffset = builder.create(string: fileName)
let start = TelegramCore_TelegramMediaFileAttribute_FileName.startTelegramMediaFileAttribute_FileName(&builder)
TelegramCore_TelegramMediaFileAttribute_FileName.add(fileName: fileNameOffset, &builder)
offset = TelegramCore_TelegramMediaFileAttribute_FileName.endTelegramMediaFileAttribute_FileName(&builder, start: start)
case let .Sticker(displayText, packReference, maskData):
valueType = .telegrammediafileattributeSticker
let displayTextOffset = builder.create(string: displayText)
let packReferenceOffset = packReference.flatMap {
return $0.encodeToFlatBuffers(builder: &builder)
}
let maskDataOffset = maskData.flatMap { maskData -> Offset in
let start = TelegramCore_StickerMaskCoords.startStickerMaskCoords(&builder)
TelegramCore_StickerMaskCoords.add(n: maskData.n, &builder)
TelegramCore_StickerMaskCoords.add(x: Float32(maskData.x), &builder)
TelegramCore_StickerMaskCoords.add(y: Float32(maskData.y), &builder)
TelegramCore_StickerMaskCoords.add(zoom: Float32(maskData.zoom), &builder)
return TelegramCore_StickerMaskCoords.endStickerMaskCoords(&builder, start: start)
}
let start = TelegramCore_TelegramMediaFileAttribute_Sticker.startTelegramMediaFileAttribute_Sticker(&builder)
TelegramCore_TelegramMediaFileAttribute_Sticker.add(displayText: displayTextOffset, &builder)
if let packReferenceOffset {
TelegramCore_TelegramMediaFileAttribute_Sticker.add(packReference: packReferenceOffset, &builder)
}
if let maskDataOffset {
TelegramCore_TelegramMediaFileAttribute_Sticker.add(maskData: maskDataOffset, &builder)
}
offset = TelegramCore_TelegramMediaFileAttribute_Sticker.endTelegramMediaFileAttribute_Sticker(&builder, start: start)
case let .ImageSize(size):
valueType = .telegrammediafileattributeImagesize
let start = TelegramCore_TelegramMediaFileAttribute_ImageSize.startTelegramMediaFileAttribute_ImageSize(&builder)
TelegramCore_TelegramMediaFileAttribute_ImageSize.add(width: size.width, &builder)
TelegramCore_TelegramMediaFileAttribute_ImageSize.add(height: size.height, &builder)
offset = TelegramCore_TelegramMediaFileAttribute_ImageSize.endTelegramMediaFileAttribute_ImageSize(&builder, start: start)
case .Animated:
valueType = .telegrammediafileattributeAnimated
let start = TelegramCore_TelegramMediaFileAttribute_Animated.startTelegramMediaFileAttribute_Animated(&builder)
offset = TelegramCore_TelegramMediaFileAttribute_Animated.endTelegramMediaFileAttribute_Animated(&builder, start: start)
case let .Video(duration, size, flags, preloadSize, coverTime, videoCodec):
valueType = .telegrammediafileattributeVideo
let videoCodecOffset = videoCodec.flatMap { builder.create(string: $0) }
let start = TelegramCore_TelegramMediaFileAttribute_Video.startTelegramMediaFileAttribute_Video(&builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(duration: Float32(duration), &builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(width: size.width, &builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(height: size.height, &builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(flags: flags.rawValue, &builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(preloadSize: preloadSize ?? 0, &builder)
TelegramCore_TelegramMediaFileAttribute_Video.add(coverTime: Float32(coverTime ?? 0.0), &builder)
if let videoCodecOffset {
TelegramCore_TelegramMediaFileAttribute_Video.add(videoCodec: videoCodecOffset, &builder)}
offset = TelegramCore_TelegramMediaFileAttribute_Video.endTelegramMediaFileAttribute_Video(&builder, start: start)
case let .Audio(isVoice, duration, title, performer, waveform):
valueType = .telegrammediafileattributeAudio
let titleOffset = title.flatMap { builder.create(string: $0) }
let performerOffset = performer.flatMap { builder.create(string: $0) }
let waveformOffset = waveform.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaFileAttribute_Audio.startTelegramMediaFileAttribute_Audio(&builder)
TelegramCore_TelegramMediaFileAttribute_Audio.add(isVoice: isVoice, &builder)
TelegramCore_TelegramMediaFileAttribute_Audio.add(duration: Int32(duration), &builder)
if let titleOffset {
TelegramCore_TelegramMediaFileAttribute_Audio.add(title: titleOffset, &builder)
}
if let performerOffset {
TelegramCore_TelegramMediaFileAttribute_Audio.add(performer: performerOffset, &builder)
}
if let waveformOffset {
TelegramCore_TelegramMediaFileAttribute_Audio.addVectorOf(waveform: waveformOffset, &builder)
}
offset = TelegramCore_TelegramMediaFileAttribute_Audio.endTelegramMediaFileAttribute_Audio(&builder, start: start)
case .HasLinkedStickers:
valueType = .telegrammediafileattributeHaslinkedstickers
let start = TelegramCore_TelegramMediaFileAttribute_HasLinkedStickers.startTelegramMediaFileAttribute_HasLinkedStickers(&builder)
offset = TelegramCore_TelegramMediaFileAttribute_HasLinkedStickers.endTelegramMediaFileAttribute_HasLinkedStickers(&builder, start: start)
case .hintFileIsLarge:
valueType = .telegrammediafileattributeHintfileislarge
let start = TelegramCore_TelegramMediaFileAttribute_HintFileIsLarge.startTelegramMediaFileAttribute_HintFileIsLarge(&builder)
offset = TelegramCore_TelegramMediaFileAttribute_HintFileIsLarge.endTelegramMediaFileAttribute_HintFileIsLarge(&builder, start: start)
case .hintIsValidated:
valueType = .telegrammediafileattributeHintisvalidated
let start = TelegramCore_TelegramMediaFileAttribute_HintIsValidated.startTelegramMediaFileAttribute_HintIsValidated(&builder)
offset = TelegramCore_TelegramMediaFileAttribute_HintIsValidated.endTelegramMediaFileAttribute_HintIsValidated(&builder, start: start)
case .NoPremium:
valueType = .telegrammediafileattributeNopremium
let start = TelegramCore_TelegramMediaFileAttribute_NoPremium.startTelegramMediaFileAttribute_NoPremium(&builder)
offset = TelegramCore_TelegramMediaFileAttribute_NoPremium.endTelegramMediaFileAttribute_NoPremium(&builder, start: start)
case let .CustomEmoji(isPremium, isSingleColor, alt, packReference):
valueType = .telegrammediafileattributeCustomemoji
let altOffset = builder.create(string: alt)
let packReferenceOffset = packReference.flatMap {
return $0.encodeToFlatBuffers(builder: &builder)
}
let start = TelegramCore_TelegramMediaFileAttribute_CustomEmoji.startTelegramMediaFileAttribute_CustomEmoji(&builder)
TelegramCore_TelegramMediaFileAttribute_CustomEmoji.add(isPremium: isPremium, &builder)
TelegramCore_TelegramMediaFileAttribute_CustomEmoji.add(isSingleColor: isSingleColor, &builder)
TelegramCore_TelegramMediaFileAttribute_CustomEmoji.add(alt: altOffset, &builder)
if let packReferenceOffset {
TelegramCore_TelegramMediaFileAttribute_CustomEmoji.add(packReference: packReferenceOffset, &builder)
}
offset = TelegramCore_TelegramMediaFileAttribute_CustomEmoji.endTelegramMediaFileAttribute_CustomEmoji(&builder, start: start)
}
return TelegramCore_TelegramMediaFileAttribute.createTelegramMediaFileAttribute(&builder, valueType: valueType, valueOffset: offset)
}
}
public enum TelegramMediaFileReference: PostboxCoding, Equatable {
@ -422,6 +696,23 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
encoder.encodeObject(self.resource, forKey: "r")
}
public init(flatBuffersObject: TelegramCore_VideoThumbnail) throws {
self.dimensions = PixelDimensions(width: flatBuffersObject.width, height: flatBuffersObject.height)
self.resource = try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject.resource)
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let resourceOffset = TelegramMediaResource_serialize(resource: self.resource, flatBuffersBuilder: &builder)!
let start = TelegramCore_VideoThumbnail.startVideoThumbnail(&builder)
TelegramCore_VideoThumbnail.add(width: self.dimensions.width, &builder)
TelegramCore_VideoThumbnail.add(height: self.dimensions.height, &builder)
TelegramCore_VideoThumbnail.add(resource: resourceOffset, &builder)
return TelegramCore_VideoThumbnail.endVideoThumbnail(&builder, start: start)
}
public static func ==(lhs: VideoThumbnail, rhs: VideoThumbnail) -> Bool {
if lhs === rhs {
return true
@ -446,7 +737,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
public let mimeType: String
public let size: Int64?
public let attributes: [TelegramMediaFileAttribute]
public let alternativeRepresentations: [Media]
public let alternativeRepresentations: [TelegramMediaFile]
public let peerIds: [PeerId] = []
public var id: MediaId? {
@ -477,7 +768,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
mimeType: String,
size: Int64?,
attributes: [TelegramMediaFileAttribute],
alternativeRepresentations: [Media]
alternativeRepresentations: [TelegramMediaFile]
) {
self.fileId = fileId
self.partialReference = partialReference
@ -510,12 +801,20 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
}
self.attributes = decoder.decodeObjectArrayForKey("at")
if let altMedia = try? decoder.decodeObjectArrayWithCustomDecoderForKey("arep", decoder: { d in
return d.decodeRootObject() as! Media
return d.decodeRootObject()
}) {
self.alternativeRepresentations = altMedia
self.alternativeRepresentations = altMedia.compactMap { $0 as? TelegramMediaFile }
} else {
self.alternativeRepresentations = []
}
/*#if DEBUG
let fbData = self.encodeToFlatBuffersData()
var byteBuffer = ByteBuffer(data: fbData)
let flatBuffersObject: TelegramCore_TelegramMediaFile = try! getCheckedRoot(byteBuffer: &byteBuffer)
let fbObject = try! TelegramMediaFile(flatBuffersObject: flatBuffersObject)
assert(self == fbObject)
#endif*/
}
public func encode(_ encoder: PostboxEncoder) {
@ -580,6 +879,89 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
try container.encode(postboxEncoder.makeData(), forKey: .data)
}
public func encodeToFlatBuffersData() -> Data {
var builder = FlatBufferBuilder(initialSize: 1024)
let value = self.encodeToFlatBuffers(builder: &builder)
builder.finish(offset: value)
return builder.data
}
public init(flatBuffersObject: TelegramCore_TelegramMediaFile) throws {
self.fileId = MediaId(namespace: flatBuffersObject.fileId.namespace, id: flatBuffersObject.fileId.id)
self.partialReference = try flatBuffersObject.partialReference.flatMap { try PartialMediaReference(flatBuffersObject: $0 ) }
self.resource = try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject.resource)
self.previewRepresentations = try (0 ..< flatBuffersObject.previewRepresentationsCount).map { i in
return try TelegramMediaImageRepresentation(flatBuffersObject: flatBuffersObject.previewRepresentations(at: i)!)
}
self.videoThumbnails = try (0 ..< flatBuffersObject.videoThumbnailsCount).map { i in
return try VideoThumbnail(flatBuffersObject: flatBuffersObject.videoThumbnails(at: i)!)
}
self.videoCover = try flatBuffersObject.videoCover.flatMap { try TelegramMediaImage(flatBuffersObject: $0) }
self.immediateThumbnailData = flatBuffersObject.immediateThumbnailData.isEmpty ? nil : Data(flatBuffersObject.immediateThumbnailData)
self.mimeType = flatBuffersObject.mimeType
self.size = flatBuffersObject.size == Int64.min ? nil : flatBuffersObject.size
self.attributes = try (0 ..< flatBuffersObject.attributesCount).map { i in
return try TelegramMediaFileAttribute(flatBuffersObject: flatBuffersObject.attributes(at: i)!)
}
self.alternativeRepresentations = try (0 ..< flatBuffersObject.alternativeRepresentationsCount).map { i in
return try TelegramMediaFile(flatBuffersObject: flatBuffersObject.alternativeRepresentations(at: i)!)
}
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let partialReferenceOffset = self.partialReference.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let resourceOffset = TelegramMediaResource_serialize(resource: self.resource, flatBuffersBuilder: &builder)!
let previewRepresentationsOffsets = self.previewRepresentations.map { attribute in
return attribute.encodeToFlatBuffers(builder: &builder)
}
let previewRepresentationsOffset = builder.createVector(ofOffsets: previewRepresentationsOffsets, len: previewRepresentationsOffsets.count)
let videoThumbnailsOffsets = self.videoThumbnails.map { videoThumbnail in
return videoThumbnail.encodeToFlatBuffers(builder: &builder)
}
let videoThumbnailsOffset = builder.createVector(ofOffsets: videoThumbnailsOffsets, len: videoThumbnailsOffsets.count)
let videoCoverOffset = self.videoCover.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let immediateThumbnailDataOffset = self.immediateThumbnailData.flatMap { builder.createVector(bytes: $0) }
let mimeTypeOffset = builder.create(string: self.mimeType)
let attributesOffsets = self.attributes.map { attribute in
return attribute.encodeToFlatBuffers(builder: &builder)
}
let attributesOffset = builder.createVector(ofOffsets: attributesOffsets, len: attributesOffsets.count)
let alternativeRepresentationsOffsets = self.alternativeRepresentations.map { alternativeRepresentation in
return alternativeRepresentation.encodeToFlatBuffers(builder: &builder)
}
let alternativeRepresentationsOffset = builder.createVector(ofOffsets: alternativeRepresentationsOffsets, len: alternativeRepresentationsOffsets.count)
let start = TelegramCore_TelegramMediaFile.startTelegramMediaFile(&builder)
TelegramCore_TelegramMediaFile.add(fileId: TelegramCore_MediaId(namespace: self.fileId.namespace, id: self.fileId.id), &builder)
if let partialReferenceOffset {
TelegramCore_TelegramMediaFile.add(partialReference: partialReferenceOffset, &builder)
}
TelegramCore_TelegramMediaFile.add(resource: resourceOffset, &builder)
TelegramCore_TelegramMediaFile.addVectorOf(previewRepresentations: previewRepresentationsOffset, &builder)
TelegramCore_TelegramMediaFile.addVectorOf(videoThumbnails: videoThumbnailsOffset, &builder)
if let immediateThumbnailDataOffset {
TelegramCore_TelegramMediaFile.addVectorOf(immediateThumbnailData: immediateThumbnailDataOffset, &builder)
}
if let videoCoverOffset {
TelegramCore_TelegramMediaFile.add(videoCover: videoCoverOffset, &builder)
}
TelegramCore_TelegramMediaFile.add(mimeType: mimeTypeOffset, &builder)
TelegramCore_TelegramMediaFile.add(size: self.size ?? Int64.min, &builder)
TelegramCore_TelegramMediaFile.addVectorOf(attributes: attributesOffset, &builder)
TelegramCore_TelegramMediaFile.addVectorOf(alternativeRepresentations: alternativeRepresentationsOffset, &builder)
return TelegramCore_TelegramMediaFile.endTelegramMediaFile(&builder, start: start)
}
public var fileName: String? {
get {
for attribute in self.attributes {

View File

@ -1,5 +1,7 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
public enum TelegramMediaImageReferenceDecodingError: Error {
case generic
@ -54,6 +56,31 @@ public enum TelegramMediaImageReference: PostboxCoding, Equatable {
try container.encode(postboxEncoder.makeData(), forKey: .data)
}
public init(flatBuffersObject: TelegramCore_TelegramMediaImageReference) throws {
self = .cloud(
imageId: flatBuffersObject.imageId,
accessHash: flatBuffersObject.accessHash,
fileReference: flatBuffersObject.fileReference.isEmpty ? nil : Data(flatBuffersObject.fileReference)
)
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
switch self {
case let .cloud(imageId, accessHash, fileReference):
let fileReferenceOffset = fileReference.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaImageReference.startTelegramMediaImageReference(&builder)
TelegramCore_TelegramMediaImageReference.add(imageId: imageId, &builder)
TelegramCore_TelegramMediaImageReference.add(accessHash: accessHash, &builder)
if let fileReferenceOffset {
TelegramCore_TelegramMediaImageReference.addVectorOf(fileReference: fileReferenceOffset, &builder)
}
return TelegramCore_TelegramMediaImageReference.endTelegramMediaImageReference(&builder, start: start)
}
}
public static func ==(lhs: TelegramMediaImageReference, rhs: TelegramMediaImageReference) -> Bool {
switch lhs {
case let .cloud(imageId, accessHash, fileReference):
@ -99,7 +126,7 @@ public final class TelegramMediaImage: Media, Equatable, Codable {
public init(decoder: PostboxDecoder) {
self.dimensions = PixelDimensions(width: decoder.decodeInt32ForKey("w", orElse: 0), height: decoder.decodeInt32ForKey("h", orElse: 0))
self.resource = decoder.decodeObjectForKey("r") as! TelegramMediaResource
self.startTimestamp = decoder.decodeOptionalDoubleForKey("s")
self.startTimestamp = decoder.decodeOptionalDoubleForKey("s").flatMap({ Double(Float32($0)) })
}
public func encode(_ encoder: PostboxEncoder) {
@ -113,6 +140,29 @@ public final class TelegramMediaImage: Media, Equatable, Codable {
}
}
public init(flatBuffersObject: TelegramCore_VideoRepresentation) throws {
self.dimensions = PixelDimensions(width: flatBuffersObject.width, height: flatBuffersObject.height)
self.resource = try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject.resource)
if flatBuffersObject.startTimestamp != -1.0 {
self.startTimestamp = Double(flatBuffersObject.startTimestamp)
} else {
self.startTimestamp = nil
}
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let resourceOffset = TelegramMediaResource_serialize(resource: self.resource, flatBuffersBuilder: &builder)!
let start = TelegramCore_VideoRepresentation.startVideoRepresentation(&builder)
TelegramCore_VideoRepresentation.add(width: self.dimensions.width, &builder)
TelegramCore_VideoRepresentation.add(height: self.dimensions.height, &builder)
TelegramCore_VideoRepresentation.add(resource: resourceOffset, &builder)
TelegramCore_VideoRepresentation.add(startTimestamp: Float32(self.startTimestamp ?? -1.0), &builder)
return TelegramCore_VideoRepresentation.endVideoRepresentation(&builder, start: start)
}
public static func ==(lhs: VideoRepresentation, rhs: VideoRepresentation) -> Bool {
if lhs === rhs {
return true
@ -165,6 +215,52 @@ public final class TelegramMediaImage: Media, Equatable, Codable {
encoder.encodeInt32Array(self.backgroundColors, forKey: "b")
}
init(flatBuffersObject: TelegramCore_EmojiMarkup) throws {
switch flatBuffersObject.contentType {
case .emojimarkupContentEmoji:
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Emoji.self) else {
throw FlatBuffersError.missingRequiredField
}
self.content = .emoji(fileId: value.fileId)
case .emojimarkupContentSticker:
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Sticker.self) else {
throw FlatBuffersError.missingRequiredField
}
self.content = .sticker(packReference: try StickerPackReference(flatBuffersObject: value.packReference), fileId: value.fileId)
case .none_:
throw FlatBuffersError.missingRequiredField
}
self.backgroundColors = flatBuffersObject.backgroundColors
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let contentOffset: Offset
let contentType: TelegramCore_EmojiMarkup_Content
switch self.content {
case let .emoji(fileId):
contentType = .emojimarkupContentEmoji
let start = TelegramCore_EmojiMarkup_Content_Emoji.startEmojiMarkup_Content_Emoji(&builder)
TelegramCore_EmojiMarkup_Content_Emoji.add(fileId: fileId, &builder)
contentOffset = TelegramCore_EmojiMarkup_Content_Emoji.endEmojiMarkup_Content_Emoji(&builder, start: start)
case let .sticker(packReference, fileId):
contentType = .emojimarkupContentSticker
let packReferenceOffset = packReference.encodeToFlatBuffers(builder: &builder)
let start = TelegramCore_EmojiMarkup_Content_Sticker.startEmojiMarkup_Content_Sticker(&builder)
TelegramCore_EmojiMarkup_Content_Sticker.add(packReference: packReferenceOffset, &builder)
TelegramCore_EmojiMarkup_Content_Sticker.add(fileId: fileId, &builder)
contentOffset = TelegramCore_EmojiMarkup_Content_Sticker.endEmojiMarkup_Content_Sticker(&builder, start: start)
}
let backgroundColorsOffset = builder.createVector(self.backgroundColors)
let start = TelegramCore_EmojiMarkup.startEmojiMarkup(&builder)
TelegramCore_EmojiMarkup.add(contentType: contentType, &builder)
TelegramCore_EmojiMarkup.add(content: contentOffset, &builder)
TelegramCore_EmojiMarkup.addVectorOf(backgroundColors: backgroundColorsOffset, &builder)
return TelegramCore_EmojiMarkup.endEmojiMarkup(&builder, start: start)
}
public static func ==(lhs: EmojiMarkup, rhs: EmojiMarkup) -> Bool {
if lhs.content != rhs.content {
return false
@ -267,6 +363,59 @@ public final class TelegramMediaImage: Media, Equatable, Codable {
try container.encode(postboxEncoder.makeData(), forKey: .data)
}
public init(flatBuffersObject: TelegramCore_TelegramMediaImage) throws {
self.imageId = MediaId(namespace: flatBuffersObject.imageId.namespace, id: flatBuffersObject.imageId.id)
self.representations = try (0 ..< flatBuffersObject.representationsCount).map { i in
return try TelegramMediaImageRepresentation(flatBuffersObject: flatBuffersObject.representations(at: i)!)
}
self.videoRepresentations = try (0 ..< flatBuffersObject.videoRepresentationsCount).map { i in
return try TelegramMediaImage.VideoRepresentation(flatBuffersObject: flatBuffersObject.videoRepresentations(at: i)!)
}
self.immediateThumbnailData = flatBuffersObject.immediateThumbnailData.isEmpty ? nil : Data(flatBuffersObject.immediateThumbnailData)
self.emojiMarkup = try flatBuffersObject.emojiMarkup.map { try EmojiMarkup(flatBuffersObject: $0) }
self.reference = try flatBuffersObject.reference.map { try TelegramMediaImageReference(flatBuffersObject: $0) }
self.partialReference = try flatBuffersObject.partialReference.map { try PartialMediaReference(flatBuffersObject: $0) }
self.flags = TelegramMediaImageFlags(rawValue: flatBuffersObject.flags)
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let representationsOffsets = self.representations.map { item in
return item.encodeToFlatBuffers(builder: &builder)
}
let representationsOffset = builder.createVector(ofOffsets: representationsOffsets, len: representationsOffsets.count)
let videoRepresentationsOffsets = self.videoRepresentations.map { item in
return item.encodeToFlatBuffers(builder: &builder)
}
let videoRepresentationsOffset = builder.createVector(ofOffsets: videoRepresentationsOffsets, len: videoRepresentationsOffsets.count)
let immediateThumbnailDataOffset = self.immediateThumbnailData.flatMap { builder.createVector(bytes: $0) }
let emojiMarkupOffset = self.emojiMarkup.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let referenceOffset = self.reference.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let partialReferenceOffset = self.partialReference.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let start = TelegramCore_TelegramMediaImage.startTelegramMediaImage(&builder)
TelegramCore_TelegramMediaImage.add(imageId: TelegramCore_MediaId(namespace: self.imageId.namespace, id: self.imageId.id), &builder)
TelegramCore_TelegramMediaImage.addVectorOf(representations: representationsOffset, &builder)
TelegramCore_TelegramMediaImage.addVectorOf(videoRepresentations: videoRepresentationsOffset, &builder)
if let immediateThumbnailDataOffset {
TelegramCore_TelegramMediaImage.addVectorOf(immediateThumbnailData: immediateThumbnailDataOffset, &builder)
}
if let emojiMarkupOffset {
TelegramCore_TelegramMediaImage.add(emojiMarkup: emojiMarkupOffset, &builder)
}
if let referenceOffset {
TelegramCore_TelegramMediaImage.add(reference: referenceOffset, &builder)
}
if let partialReferenceOffset {
TelegramCore_TelegramMediaImage.add(partialReference: partialReferenceOffset, &builder)
}
TelegramCore_TelegramMediaImage.add(flags: self.flags.rawValue, &builder)
return TelegramCore_TelegramMediaImage.endTelegramMediaImage(&builder, start: start)
}
public func representationForDisplayAtSize(_ size: PixelDimensions) -> TelegramMediaImageRepresentation? {
if self.representations.count == 0 {
return nil
@ -417,6 +566,44 @@ public final class TelegramMediaImageRepresentation: PostboxCoding, Equatable, C
encoder.encodeInt32(self.typeHint.rawValue, forKey: "th")
}
public init(flatBuffersObject: TelegramCore_TelegramMediaImageRepresentation) throws {
self.dimensions = PixelDimensions(width: flatBuffersObject.width, height: flatBuffersObject.height)
self.resource = try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject.resource)
self.progressiveSizes = flatBuffersObject.progressiveSizes
self.immediateThumbnailData = flatBuffersObject.immediateThumbnailData.isEmpty ? nil : Data(flatBuffersObject.immediateThumbnailData)
self.hasVideo = flatBuffersObject.hasVideo
self.isPersonal = flatBuffersObject.isPersonal
switch flatBuffersObject.typeHint {
case .generic:
self.typeHint = .generic
case .animated:
self.typeHint = .animated
case .video:
self.typeHint = .video
}
}
func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let resourceOffset = TelegramMediaResource_serialize(resource: self.resource, flatBuffersBuilder: &builder)!
let progressiveSizesOffset = builder.createVector(self.progressiveSizes)
let immediateThumbnailDataOffset = self.immediateThumbnailData.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_TelegramMediaImageRepresentation.startTelegramMediaImageRepresentation(&builder)
TelegramCore_TelegramMediaImageRepresentation.add(width: self.dimensions.width, &builder)
TelegramCore_TelegramMediaImageRepresentation.add(height: self.dimensions.height, &builder)
TelegramCore_TelegramMediaImageRepresentation.add(resource: resourceOffset, &builder)
TelegramCore_TelegramMediaImageRepresentation.addVectorOf(progressiveSizes: progressiveSizesOffset, &builder)
if let immediateThumbnailDataOffset {
TelegramCore_TelegramMediaImageRepresentation.addVectorOf(immediateThumbnailData: immediateThumbnailDataOffset, &builder)
}
TelegramCore_TelegramMediaImageRepresentation.add(hasVideo: self.hasVideo, &builder)
TelegramCore_TelegramMediaImageRepresentation.add(isPersonal: self.isPersonal, &builder)
return TelegramCore_TelegramMediaImageRepresentation.endTelegramMediaImageRepresentation(&builder, start: start)
}
public var description: String {
return "(\(Int(dimensions.width))x\(Int(dimensions.height)))"
}

View File

@ -583,12 +583,10 @@ func _internal_reindexCacheInBackground(account: Account, lowImpact: Bool) -> Si
}
processResource(mediaMessages, file.resource, MediaResourceUserContentType(file: file))
for alternativeRepresentation in file.alternativeRepresentations {
if let alternativeRepresentation = alternativeRepresentation as? TelegramMediaFile {
for representation in alternativeRepresentation.previewRepresentations {
processResource(mediaMessages, representation.resource, MediaResourceUserContentType(file: file))
}
processResource(mediaMessages, alternativeRepresentation.resource, MediaResourceUserContentType(file: file))
for representation in alternativeRepresentation.previewRepresentations {
processResource(mediaMessages, representation.resource, MediaResourceUserContentType(file: file))
}
processResource(mediaMessages, alternativeRepresentation.resource, MediaResourceUserContentType(file: file))
}
} else if let webpage = media as? TelegramMediaWebpage {
if case let .Loaded(content) = webpage.content {

View File

@ -48,6 +48,8 @@ swift_library(
"//submodules/lottie-ios:Lottie",
"//submodules/TelegramUI/Components/Utils/GenerateStickerPlaceholderImage",
"//submodules/TelegramUIPreferences",
"//submodules/TelegramCore/FlatBuffers",
"//submodules/TelegramCore/FlatSerialization",
],
visibility = [
"//visibility:public",

View File

@ -7,6 +7,8 @@ import SwiftSignalKit
import AnimationCache
import MultiAnimationRenderer
import TelegramNotices
import FlatBuffers
import FlatSerialization
public extension EmojiPagerContentComponent {
private static func hasPremium(context: AccountContext, chatPeerId: EnginePeer.Id?, premiumIfSavedMessages: Bool) -> Signal<Bool, NoError> {
@ -1366,6 +1368,14 @@ public extension EmojiPagerContentComponent {
continue
}
#if DEBUG && false
let fbData = item.file.encodeToFlatBuffersData()
var byteBuffer = ByteBuffer(data: fbData)
let flatBuffersObject: TelegramCore_TelegramMediaFile = try! getCheckedRoot(byteBuffer: &byteBuffer)
let fbObject = try! TelegramMediaFile(flatBuffersObject: flatBuffersObject)
assert(item.file == fbObject)
#endif
var icon: EmojiPagerContentComponent.Item.Icon = .none
if [.reaction(onlyTop: false), .quickReaction].contains(subject), !hasPremium {
icon = .locked

View File

@ -986,6 +986,8 @@ extension ChatControllerImpl {
//effectiveCachedDataReady = .single(true)
effectiveCachedDataReady = self.cachedDataReady.get()
}
var measure_isFirstTime = true
let initTimestamp = self.initTimestamp
self.ready.set(combineLatest(queue: .mainQueue(),
self.chatDisplayNode.historyNode.historyState.get(),
self._chatLocationInfoReady.get(),
@ -997,7 +999,16 @@ extension ChatControllerImpl {
|> map { _, chatLocationInfoReady, cachedDataReady, _, wallpaperReady, presentationReady in
return chatLocationInfoReady && cachedDataReady && wallpaperReady && presentationReady
}
|> distinctUntilChanged)
|> distinctUntilChanged
|> beforeNext { value in
if measure_isFirstTime {
measure_isFirstTime = false
#if DEBUG
let deltaTime = (CFAbsoluteTimeGetCurrent() - initTimestamp) * 1000.0
print("Chat controller init to ready: \(deltaTime) ms")
#endif
}
})
if self.context.sharedContext.immediateExperimentalUISettings.crashOnLongQueries {
let _ = (self.ready.get()

View File

@ -627,6 +627,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var currentSendStarsUndoMessageId: EngineMessage.Id?
var currentSendStarsUndoCount: Int = 0
let initTimestamp: Double
public var alwaysShowSearchResultsAsList: Bool = false {
didSet {
self.presentationInterfaceState = self.presentationInterfaceState.updatedDisplayHistoryFilterAsList(self.alwaysShowSearchResultsAsList)
@ -675,6 +677,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
customChatNavigationStack: [EnginePeer.Id]? = nil,
params: ChatControllerParams? = nil
) {
self.initTimestamp = CFAbsoluteTimeGetCurrent()
let _ = ChatControllerCount.modify { value in
return value + 1
}

View File

@ -733,8 +733,13 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
public var isReady: Signal<Bool, NoError> {
return self._isReady.get()
}
private var didSetReady: Bool = false
private let initTimestamp: Double
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tag: HistoryViewInputTag?, source: ChatHistoryListSource, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles, rotated: Bool = false, isChatPreview: Bool, messageTransitionNode: @escaping () -> ChatMessageTransitionNodeImpl?) {
self.initTimestamp = CFAbsoluteTimeGetCurrent()
var tag = tag
if case .pinnedMessages = subject {
tag = .tag(.pinned)
@ -1698,6 +1703,8 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
}
|> distinctUntilChanged
let startTime = CFAbsoluteTimeGetCurrent()
var measure_isFirstTime = true
let messageViewQueue = Queue.mainQueue()
let historyViewTransitionDisposable = combineLatest(queue: messageViewQueue,
historyViewUpdate,
@ -1728,6 +1735,14 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
).startStrict(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, preferredStoryHighQuality, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, availableMessageEffects, savedMessageTags, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, translationState, maxReadStoryId, recommendedChannels, audioTranscriptionTrial, chatThemes, deviceContactsNumbers, contentSettings in
let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId, chatHasBots, allAdMessages) = promises
if measure_isFirstTime {
measure_isFirstTime = false
#if DEBUG
let deltaTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0
print("Chat load time: \(deltaTime) ms")
#endif
}
func applyHole() {
Queue.mainQueue().async {
if let strongSelf = self {
@ -4051,6 +4066,14 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
strongSelf.dequeueHistoryViewTransitions()
strongSelf._isReady.set(true)
if !strongSelf.didSetReady {
strongSelf.didSetReady = true
#if DEBUG
let deltaTime = (CFAbsoluteTimeGetCurrent() - strongSelf.initTimestamp) * 1000.0
print("Chat init to dequeue time: \(deltaTime) ms")
#endif
}
}
}

View File

@ -55,25 +55,24 @@ public final class HLSQualitySet {
public init?(baseFile: FileMediaReference, codecConfiguration: HLSCodecConfiguration) {
var qualityFiles: [Int: FileMediaReference] = [:]
for alternativeRepresentation in baseFile.media.alternativeRepresentations {
if let alternativeFile = alternativeRepresentation as? TelegramMediaFile {
for attribute in alternativeFile.attributes {
if case let .Video(_, size, _, _, _, videoCodec) = attribute {
if let videoCodec, NativeVideoContent.isVideoCodecSupported(videoCodec: videoCodec, isHardwareAv1Supported: codecConfiguration.isHardwareAv1Supported, isSoftwareAv1Supported: codecConfiguration.isSoftwareAv1Supported) {
let key = Int(min(size.width, size.height))
if let currentFile = qualityFiles[key] {
var currentCodec: String?
for attribute in currentFile.media.attributes {
if case let .Video(_, _, _, _, _, videoCodec) = attribute {
currentCodec = videoCodec
}
}
if let currentCodec, (currentCodec == "av1" || currentCodec == "av01") {
} else {
qualityFiles[key] = baseFile.withMedia(alternativeFile)
let alternativeFile = alternativeRepresentation
for attribute in alternativeFile.attributes {
if case let .Video(_, size, _, _, _, videoCodec) = attribute {
if let videoCodec, NativeVideoContent.isVideoCodecSupported(videoCodec: videoCodec, isHardwareAv1Supported: codecConfiguration.isHardwareAv1Supported, isSoftwareAv1Supported: codecConfiguration.isSoftwareAv1Supported) {
let key = Int(min(size.width, size.height))
if let currentFile = qualityFiles[key] {
var currentCodec: String?
for attribute in currentFile.media.attributes {
if case let .Video(_, _, _, _, _, videoCodec) = attribute {
currentCodec = videoCodec
}
}
if let currentCodec, (currentCodec == "av1" || currentCodec == "av01") {
} else {
qualityFiles[key] = baseFile.withMedia(alternativeFile)
}
} else {
qualityFiles[key] = baseFile.withMedia(alternativeFile)
}
}
}
@ -82,17 +81,16 @@ public final class HLSQualitySet {
var playlistFiles: [Int: FileMediaReference] = [:]
for alternativeRepresentation in baseFile.media.alternativeRepresentations {
if let alternativeFile = alternativeRepresentation as? TelegramMediaFile {
if alternativeFile.mimeType == "application/x-mpegurl" {
if let fileName = alternativeFile.fileName {
if fileName.hasPrefix("mtproto:") {
let fileIdString = String(fileName[fileName.index(fileName.startIndex, offsetBy: "mtproto:".count)...])
if let fileId = Int64(fileIdString) {
for (quality, file) in qualityFiles {
if file.media.fileId.id == fileId {
playlistFiles[quality] = baseFile.withMedia(alternativeFile)
break
}
let alternativeFile = alternativeRepresentation
if alternativeFile.mimeType == "application/x-mpegurl" {
if let fileName = alternativeFile.fileName {
if fileName.hasPrefix("mtproto:") {
let fileIdString = String(fileName[fileName.index(fileName.startIndex, offsetBy: "mtproto:".count)...])
if let fileId = Int64(fileIdString) {
for (quality, file) in qualityFiles {
if file.media.fileId.id == fileId {
playlistFiles[quality] = baseFile.withMedia(alternativeFile)
break
}
}
}

View File

@ -73,10 +73,8 @@ public final class NativeVideoContent: UniversalVideoContent {
public static func isHLSVideo(file: TelegramMediaFile) -> Bool {
for alternativeRepresentation in file.alternativeRepresentations {
if let alternativeFile = alternativeRepresentation as? TelegramMediaFile {
if alternativeFile.mimeType == "application/x-mpegurl" {
return true
}
if alternativeRepresentation.mimeType == "application/x-mpegurl" {
return true
}
}
return false