mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
c39fdb4463
2
.gitignore
vendored
2
.gitignore
vendored
@ -68,4 +68,4 @@ build-input/*
|
|||||||
submodules/OpusBinding/SharedHeaders/*
|
submodules/OpusBinding/SharedHeaders/*
|
||||||
submodules/FFMpegBinding/SharedHeaders/*
|
submodules/FFMpegBinding/SharedHeaders/*
|
||||||
submodules/OpenSSLEncryptionProvider/SharedHeaders/*
|
submodules/OpenSSLEncryptionProvider/SharedHeaders/*
|
||||||
|
buildServer.json
|
||||||
|
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "sweetpad-lldb",
|
||||||
|
"request": "attach",
|
||||||
|
"name": "Attach to running app (SweetPad)",
|
||||||
|
"preLaunchTask": "sweetpad: launch",
|
||||||
|
"codelldbAttributes": {
|
||||||
|
"initCommands": [
|
||||||
|
"command source ~/.lldbinit-Xcode"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"sweetpad.build.xcodeWorkspacePath": "Telegram/Telegram.xcodeproj/project.xcworkspace",
|
||||||
|
"lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB",
|
||||||
|
"lldb.launch.expressions": "native"
|
||||||
|
}
|
19
.vscode/tasks.json
vendored
Normal file
19
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "sweetpad",
|
||||||
|
"action": "launch",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$sweetpad-watch", // ! Required for debugging
|
||||||
|
"$sweetpad-xcodebuild-default",
|
||||||
|
"$sweetpad-xcbeautify-errors",
|
||||||
|
"$sweetpad-xcbeautify-warnings"
|
||||||
|
],
|
||||||
|
"label": "sweetpad: launch",
|
||||||
|
"detail": "Build and Launch the app",
|
||||||
|
"isBackground": true // ! Required for debugging
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -142,6 +142,8 @@ public protocol MediaManager: AnyObject {
|
|||||||
var universalVideoManager: UniversalVideoManager { get }
|
var universalVideoManager: UniversalVideoManager { get }
|
||||||
var overlayMediaManager: OverlayMediaManager { get }
|
var overlayMediaManager: OverlayMediaManager { get }
|
||||||
|
|
||||||
|
var currentPictureInPictureNode: AnyObject? { get set }
|
||||||
|
|
||||||
var globalMediaPlayerState: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> { get }
|
var globalMediaPlayerState: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> { get }
|
||||||
var musicMediaPlayerState: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> { get }
|
var musicMediaPlayerState: Signal<(Account, SharedMediaPlayerItemPlaybackStateOrLoading, MediaManagerPlayerType)?, NoError> { get }
|
||||||
var activeGlobalMediaPlayerAccountId: Signal<(AccountRecordId, Bool)?, NoError> { get }
|
var activeGlobalMediaPlayerAccountId: Signal<(AccountRecordId, Bool)?, NoError> { get }
|
||||||
|
@ -1287,7 +1287,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||||||
self.dismiss(forceAway: false)
|
self.dismiss(forceAway: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dismiss(forceAway: Bool) {
|
func dismiss(forceAway: Bool) {
|
||||||
var animatedOutNode = true
|
var animatedOutNode = true
|
||||||
var animatedOutInterface = false
|
var animatedOutInterface = false
|
||||||
|
|
||||||
@ -1403,12 +1403,19 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.galleryNode.beginCustomDismiss = { [weak self] simpleAnimation in
|
self.galleryNode.beginCustomDismiss = { [weak self] animationType in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.actionInteraction?.updateCanReadHistory(true)
|
strongSelf.actionInteraction?.updateCanReadHistory(true)
|
||||||
strongSelf._hiddenMedia.set(.single(nil))
|
strongSelf._hiddenMedia.set(.single(nil))
|
||||||
|
|
||||||
let animatedOutNode = !simpleAnimation
|
if let hiddenMediaManagerIndex = strongSelf.hiddenMediaManagerIndex {
|
||||||
|
strongSelf.hiddenMediaManagerIndex = nil
|
||||||
|
strongSelf.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch animationType {
|
||||||
|
case .default, .simpleAnimation:
|
||||||
|
let animatedOutNode = animationType != .simpleAnimation
|
||||||
|
|
||||||
if let chatController = strongSelf.baseNavigationController?.topViewController as? ChatController {
|
if let chatController = strongSelf.baseNavigationController?.topViewController as? ChatController {
|
||||||
chatController.updatePushedTransition(0.0, transition: .animated(duration: 0.45, curve: .customSpring(damping: 180.0, initialVelocity: 0.0)))
|
chatController.updatePushedTransition(0.0, transition: .animated(duration: 0.45, curve: .customSpring(damping: 180.0, initialVelocity: 0.0)))
|
||||||
@ -1416,19 +1423,31 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||||||
|
|
||||||
strongSelf.galleryNode.animateOut(animateContent: animatedOutNode, completion: {
|
strongSelf.galleryNode.animateOut(animateContent: animatedOutNode, completion: {
|
||||||
})
|
})
|
||||||
|
case .pip:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.galleryNode.completeCustomDismiss = { [weak self] isPictureInPicture in
|
self.galleryNode.completeCustomDismiss = { [weak self] isPictureInPicture in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex {
|
||||||
|
self.hiddenMediaManagerIndex = nil
|
||||||
|
self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||||
|
}
|
||||||
|
|
||||||
if isPictureInPicture {
|
if isPictureInPicture {
|
||||||
if let chatController = self?.baseNavigationController?.topViewController as? ChatController {
|
if let chatController = self.baseNavigationController?.topViewController as? ChatController {
|
||||||
chatController.updatePushedTransition(0.0, transition: .animated(duration: 0.45, curve: .customSpring(damping: 180.0, initialVelocity: 0.0)))
|
chatController.updatePushedTransition(0.0, transition: .animated(duration: 0.45, curve: .customSpring(damping: 180.0, initialVelocity: 0.0)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self?._hiddenMedia.set(.single(nil))
|
self._hiddenMedia.set(.single(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
self.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.galleryNode.controlsVisibilityChanged = { [weak self] visible in
|
self.galleryNode.controlsVisibilityChanged = { [weak self] visible in
|
||||||
@ -1666,6 +1685,22 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||||||
override public func viewDidAppear(_ animated: Bool) {
|
override public func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex {
|
||||||
|
self.hiddenMediaManagerIndex = nil
|
||||||
|
self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = self.context
|
||||||
|
let mediaManager = context.sharedContext.mediaManager
|
||||||
|
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(self._hiddenMedia.get()
|
||||||
|
|> map { messageIdAndMedia in
|
||||||
|
if let (messageId, media) = messageIdAndMedia {
|
||||||
|
return .chat(context.account.id, messageId, media)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
var nodeAnimatesItself = false
|
var nodeAnimatesItself = false
|
||||||
|
|
||||||
if let centralItemNode = self.galleryNode.pager.centralItemNode() {
|
if let centralItemNode = self.galleryNode.pager.centralItemNode() {
|
||||||
@ -1851,4 +1886,23 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||||||
keyShortcuts.append(contentsOf: itemNodeShortcuts)
|
keyShortcuts.append(contentsOf: itemNodeShortcuts)
|
||||||
return keyShortcuts
|
return keyShortcuts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func maybeExpandPIP(context: AccountContext, messageId: EngineMessage.Id) -> Bool {
|
||||||
|
guard let currentPictureInPictureNode = context.sharedContext.mediaManager.currentPictureInPictureNode as? UniversalVideoGalleryItemNode else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
guard let item = currentPictureInPictureNode.item else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
guard case let .message(message, _) = item.contentInfo else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if message.id != messageId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPictureInPictureNode.expandPIP()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,12 @@ import AccountContext
|
|||||||
import UndoUI
|
import UndoUI
|
||||||
|
|
||||||
open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate {
|
open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate {
|
||||||
|
public enum CustomDismissType {
|
||||||
|
case `default`
|
||||||
|
case simpleAnimation
|
||||||
|
case pip
|
||||||
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
|
||||||
public var statusBar: StatusBar?
|
public var statusBar: StatusBar?
|
||||||
@ -27,7 +33,7 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||||||
public var scrollView: UIScrollView
|
public var scrollView: UIScrollView
|
||||||
public var pager: GalleryPagerNode
|
public var pager: GalleryPagerNode
|
||||||
|
|
||||||
public var beginCustomDismiss: (Bool) -> Void = { _ in }
|
public var beginCustomDismiss: (GalleryControllerNode.CustomDismissType) -> Void = { _ in }
|
||||||
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
||||||
public var baseNavigationController: () -> NavigationController? = { return nil }
|
public var baseNavigationController: () -> NavigationController? = { return nil }
|
||||||
public var galleryController: () -> ViewController? = { return nil }
|
public var galleryController: () -> ViewController? = { return nil }
|
||||||
@ -128,9 +134,9 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pager.beginCustomDismiss = { [weak self] simpleAnimation in
|
self.pager.beginCustomDismiss = { [weak self] animationType in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.beginCustomDismiss(simpleAnimation)
|
strongSelf.beginCustomDismiss(animationType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ open class GalleryItemNode: ASDisplayNode {
|
|||||||
public var controlsVisibility: () -> Bool = { return true }
|
public var controlsVisibility: () -> Bool = { return true }
|
||||||
public var updateOrientation: (UIInterfaceOrientation) -> Void = { _ in }
|
public var updateOrientation: (UIInterfaceOrientation) -> Void = { _ in }
|
||||||
public var dismiss: () -> Void = { }
|
public var dismiss: () -> Void = { }
|
||||||
public var beginCustomDismiss: (Bool) -> Void = { _ in }
|
public var beginCustomDismiss: (GalleryControllerNode.CustomDismissType) -> Void = { _ in }
|
||||||
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
||||||
public var baseNavigationController: () -> NavigationController? = { return nil }
|
public var baseNavigationController: () -> NavigationController? = { return nil }
|
||||||
public var galleryController: () -> ViewController? = { return nil }
|
public var galleryController: () -> ViewController? = { return nil }
|
||||||
|
@ -117,7 +117,7 @@ public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGest
|
|||||||
public var controlsVisibility: () -> Bool = { return true }
|
public var controlsVisibility: () -> Bool = { return true }
|
||||||
public var updateOrientation: (UIInterfaceOrientation) -> Void = { _ in }
|
public var updateOrientation: (UIInterfaceOrientation) -> Void = { _ in }
|
||||||
public var dismiss: () -> Void = { }
|
public var dismiss: () -> Void = { }
|
||||||
public var beginCustomDismiss: (Bool) -> Void = { _ in }
|
public var beginCustomDismiss: (GalleryControllerNode.CustomDismissType) -> Void = { _ in }
|
||||||
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
||||||
public var baseNavigationController: () -> NavigationController? = { return nil }
|
public var baseNavigationController: () -> NavigationController? = { return nil }
|
||||||
public var galleryController: () -> ViewController? = { return nil }
|
public var galleryController: () -> ViewController? = { return nil }
|
||||||
|
@ -690,7 +690,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
if let message = self.message {
|
if let message = self.message {
|
||||||
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
||||||
if let self, let peer, let navigationController = self.baseNavigationController() {
|
if let self, let peer, let navigationController = self.baseNavigationController() {
|
||||||
self.beginCustomDismiss(true)
|
self.beginCustomDismiss(.simpleAnimation)
|
||||||
|
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false)))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false)))
|
||||||
|
|
||||||
@ -722,7 +722,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
if let peer, let message = self.message, canSendMessagesToPeer(peer._asPeer()) {
|
if let peer, let message = self.message, canSendMessagesToPeer(peer._asPeer()) {
|
||||||
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Conversation_ContextMenuReply, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Conversation_ContextMenuReply, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
||||||
if let self, let navigationController = self.baseNavigationController() {
|
if let self, let navigationController = self.baseNavigationController() {
|
||||||
self.beginCustomDismiss(true)
|
self.beginCustomDismiss(.simpleAnimation)
|
||||||
|
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: true)))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: true)))
|
||||||
|
|
||||||
|
@ -730,309 +730,6 @@ final class SettingsHeaderButton: HighlightableButtonNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
|
||||||
private final class PictureInPictureContentImpl: NSObject, PictureInPictureContent, AVPictureInPictureControllerDelegate {
|
|
||||||
private final class PlaybackDelegate: NSObject, AVPictureInPictureSampleBufferPlaybackDelegate {
|
|
||||||
private let node: UniversalVideoNode
|
|
||||||
private var statusDisposable: Disposable?
|
|
||||||
private var status: MediaPlayerStatus?
|
|
||||||
weak var pictureInPictureController: AVPictureInPictureController?
|
|
||||||
|
|
||||||
private var previousIsPlaying = false
|
|
||||||
init(node: UniversalVideoNode) {
|
|
||||||
self.node = node
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
var invalidatedStateOnce = false
|
|
||||||
self.statusDisposable = (self.node.status
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.status = status
|
|
||||||
if let status {
|
|
||||||
let isPlaying = status.status == .playing
|
|
||||||
if !invalidatedStateOnce {
|
|
||||||
invalidatedStateOnce = true
|
|
||||||
strongSelf.pictureInPictureController?.invalidatePlaybackState()
|
|
||||||
} else if strongSelf.previousIsPlaying != isPlaying {
|
|
||||||
strongSelf.previousIsPlaying = isPlaying
|
|
||||||
strongSelf.pictureInPictureController?.invalidatePlaybackState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).strict()
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.statusDisposable?.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, setPlaying playing: Bool) {
|
|
||||||
self.node.togglePlayPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerTimeRangeForPlayback(_ pictureInPictureController: AVPictureInPictureController) -> CMTimeRange {
|
|
||||||
guard let status = self.status else {
|
|
||||||
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)))
|
|
||||||
}
|
|
||||||
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: status.duration - status.timestamp, preferredTimescale: CMTimeScale(30.0)))
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerIsPlaybackPaused(_ pictureInPictureController: AVPictureInPictureController) -> Bool {
|
|
||||||
guard let status = self.status else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch status.status {
|
|
||||||
case .playing:
|
|
||||||
return false
|
|
||||||
case .buffering, .paused:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, didTransitionToRenderSize newRenderSize: CMVideoDimensions) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, skipByInterval skipInterval: CMTime, completion completionHandler: @escaping () -> Void) {
|
|
||||||
let node = self.node
|
|
||||||
let _ = (self.node.status
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak node] status in
|
|
||||||
if let node = node, let timestamp = status?.timestamp, let duration = status?.duration {
|
|
||||||
let nextTimestamp = timestamp + skipInterval.seconds
|
|
||||||
if nextTimestamp > duration {
|
|
||||||
node.seek(0.0)
|
|
||||||
node.pause()
|
|
||||||
} else {
|
|
||||||
node.seek(min(duration, nextTimestamp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
completionHandler()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerShouldProhibitBackgroundAudioPlayback(_ pictureInPictureController: AVPictureInPictureController) -> Bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private weak var overlayController: OverlayMediaController?
|
|
||||||
private weak var mediaManager: MediaManager?
|
|
||||||
private var pictureInPictureController: AVPictureInPictureController?
|
|
||||||
private var contentDelegate: PlaybackDelegate?
|
|
||||||
private let node: UniversalVideoNode
|
|
||||||
private let willBegin: (PictureInPictureContentImpl) -> Void
|
|
||||||
private let didEnd: (PictureInPictureContentImpl) -> Void
|
|
||||||
private let expand: (@escaping () -> Void) -> Void
|
|
||||||
private var pictureInPictureTimer: SwiftSignalKit.Timer?
|
|
||||||
private var didExpand: Bool = false
|
|
||||||
|
|
||||||
private var hiddenMediaManagerIndex: Int?
|
|
||||||
|
|
||||||
private var messageRemovedDisposable: Disposable?
|
|
||||||
|
|
||||||
private var isNativePictureInPictureActiveDisposable: Disposable?
|
|
||||||
|
|
||||||
init(context: AccountContext, overlayController: OverlayMediaController, mediaManager: MediaManager, accountId: AccountRecordId, hiddenMedia: (MessageId, Media)?, videoNode: UniversalVideoNode, canSkip: Bool, willBegin: @escaping (PictureInPictureContentImpl) -> Void, didEnd: @escaping (PictureInPictureContentImpl) -> Void, expand: @escaping (@escaping () -> Void) -> Void) {
|
|
||||||
self.overlayController = overlayController
|
|
||||||
self.mediaManager = mediaManager
|
|
||||||
self.node = videoNode
|
|
||||||
self.willBegin = willBegin
|
|
||||||
self.didEnd = didEnd
|
|
||||||
self.expand = expand
|
|
||||||
|
|
||||||
self.node.setCanPlaybackWithoutHierarchy(true)
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
if let videoLayer = videoNode.getVideoLayer() {
|
|
||||||
let contentDelegate = PlaybackDelegate(node: self.node)
|
|
||||||
self.contentDelegate = contentDelegate
|
|
||||||
|
|
||||||
let pictureInPictureController = AVPictureInPictureController(contentSource: AVPictureInPictureController.ContentSource(sampleBufferDisplayLayer: videoLayer, playbackDelegate: contentDelegate))
|
|
||||||
self.pictureInPictureController = pictureInPictureController
|
|
||||||
contentDelegate.pictureInPictureController = pictureInPictureController
|
|
||||||
|
|
||||||
pictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = false
|
|
||||||
pictureInPictureController.requiresLinearPlayback = !canSkip
|
|
||||||
pictureInPictureController.delegate = self
|
|
||||||
self.pictureInPictureController = pictureInPictureController
|
|
||||||
let timer = SwiftSignalKit.Timer(timeout: 0.005, repeat: true, completion: { [weak self] in
|
|
||||||
guard let strongSelf = self, let pictureInPictureController = strongSelf.pictureInPictureController else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if pictureInPictureController.isPictureInPicturePossible {
|
|
||||||
strongSelf.pictureInPictureTimer?.invalidate()
|
|
||||||
strongSelf.pictureInPictureTimer = nil
|
|
||||||
|
|
||||||
pictureInPictureController.startPictureInPicture()
|
|
||||||
}
|
|
||||||
}, queue: .mainQueue())
|
|
||||||
self.pictureInPictureTimer = timer
|
|
||||||
timer.start()
|
|
||||||
} else {
|
|
||||||
var currentIsNativePictureInPictureActive = false
|
|
||||||
self.isNativePictureInPictureActiveDisposable = (videoNode.isNativePictureInPictureActive
|
|
||||||
|> deliverOnMainQueue).startStrict(next: { [weak self] isNativePictureInPictureActive in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if currentIsNativePictureInPictureActive == isNativePictureInPictureActive {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
currentIsNativePictureInPictureActive = isNativePictureInPictureActive
|
|
||||||
|
|
||||||
if isNativePictureInPictureActive {
|
|
||||||
Queue.mainQueue().after(0.0, { [weak self] in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.willBegin(self)
|
|
||||||
|
|
||||||
if let overlayController = self.overlayController {
|
|
||||||
overlayController.setPictureInPictureContentHidden(content: self, isHidden: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.didEnd(self)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
self.expand { [weak self] in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.didExpand = true
|
|
||||||
|
|
||||||
if let overlayController = self.overlayController {
|
|
||||||
overlayController.setPictureInPictureContentHidden(content: self, isHidden: false)
|
|
||||||
self.node.alpha = 0.02
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let overlayController = self.overlayController else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
overlayController.removePictureInPictureContent(content: self)
|
|
||||||
self.node.canAttachContent = false
|
|
||||||
if self.didExpand {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.node.continuePlayingWithoutSound()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let _ = videoNode.enterNativePictureInPicture()
|
|
||||||
}
|
|
||||||
|
|
||||||
if let hiddenMedia = hiddenMedia {
|
|
||||||
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(Signal<(MessageId, Media)?, NoError>.single(hiddenMedia)
|
|
||||||
|> map { messageIdAndMedia in
|
|
||||||
if let (messageId, media) = messageIdAndMedia {
|
|
||||||
return .chat(accountId, messageId, media)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (messageId, _) = hiddenMedia {
|
|
||||||
self.messageRemovedDisposable = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
|
||||||
|> map { message -> Bool in
|
|
||||||
if let _ = message {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> filter { $0 }
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
overlayController.removePictureInPictureContent(content: strongSelf)
|
|
||||||
strongSelf.node.canAttachContent = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.messageRemovedDisposable?.dispose()
|
|
||||||
self.isNativePictureInPictureActiveDisposable?.dispose()
|
|
||||||
self.pictureInPictureTimer?.invalidate()
|
|
||||||
self.node.setCanPlaybackWithoutHierarchy(false)
|
|
||||||
|
|
||||||
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex, let mediaManager = self.mediaManager {
|
|
||||||
mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func invalidatePlaybackState() {
|
|
||||||
self.pictureInPictureController?.invalidatePlaybackState()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var videoNode: ASDisplayNode {
|
|
||||||
return self.node
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
||||||
Queue.mainQueue().after(0.1, { [weak self] in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.willBegin(strongSelf)
|
|
||||||
|
|
||||||
if let overlayController = strongSelf.overlayController {
|
|
||||||
overlayController.setPictureInPictureContentHidden(content: strongSelf, isHidden: true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
||||||
self.didEnd(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
|
|
||||||
print(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
||||||
guard let overlayController = self.overlayController else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
overlayController.removePictureInPictureContent(content: self)
|
|
||||||
self.node.canAttachContent = false
|
|
||||||
if self.didExpand {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.node.continuePlayingWithoutSound()
|
|
||||||
}
|
|
||||||
|
|
||||||
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
|
|
||||||
self.expand { [weak self] in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.didExpand = true
|
|
||||||
|
|
||||||
if let overlayController = strongSelf.overlayController {
|
|
||||||
overlayController.setPictureInPictureContentHidden(content: strongSelf, isHidden: false)
|
|
||||||
strongSelf.node.alpha = 0.02
|
|
||||||
}
|
|
||||||
|
|
||||||
completionHandler(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
@available(iOS 15.0, *)
|
||||||
private final class NativePictureInPictureContentImpl: NSObject, AVPictureInPictureControllerDelegate {
|
private final class NativePictureInPictureContentImpl: NSObject, AVPictureInPictureControllerDelegate {
|
||||||
private final class PlaybackDelegate: NSObject, AVPictureInPictureSampleBufferPlaybackDelegate {
|
private final class PlaybackDelegate: NSObject, AVPictureInPictureSampleBufferPlaybackDelegate {
|
||||||
@ -1079,7 +776,7 @@ private final class NativePictureInPictureContentImpl: NSObject, AVPictureInPict
|
|||||||
guard let status = self.status else {
|
guard let status = self.status else {
|
||||||
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)))
|
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)))
|
||||||
}
|
}
|
||||||
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: status.duration - status.timestamp, preferredTimescale: CMTimeScale(30.0)))
|
return CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(30.0)), duration: CMTime(seconds: status.duration, preferredTimescale: CMTimeScale(30.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pictureInPictureControllerIsPlaybackPaused(_ pictureInPictureController: AVPictureInPictureController) -> Bool {
|
public func pictureInPictureControllerIsPlaybackPaused(_ pictureInPictureController: AVPictureInPictureController) -> Bool {
|
||||||
@ -1230,13 +927,18 @@ private final class NativePictureInPictureContentImpl: NSObject, AVPictureInPict
|
|||||||
}
|
}
|
||||||
|
|
||||||
func invalidatePlaybackState() {
|
func invalidatePlaybackState() {
|
||||||
self.pictureInPictureController?.invalidatePlaybackState()
|
guard let pictureInPictureController = self.pictureInPictureController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pictureInPictureController.isPictureInPictureActive {
|
||||||
|
pictureInPictureController.invalidatePlaybackState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
public func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
||||||
self.node.setCanPlaybackWithoutHierarchy(true)
|
self.node.setCanPlaybackWithoutHierarchy(true)
|
||||||
|
|
||||||
if let hiddenMedia = self.hiddenMedia, let mediaManager = self.mediaManager {
|
if let hiddenMedia = self.hiddenMedia, let mediaManager = self.mediaManager, !"".isEmpty {
|
||||||
let accountId = self.accountId
|
let accountId = self.accountId
|
||||||
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(Signal<(MessageId, Media)?, NoError>.single(hiddenMedia)
|
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(Signal<(MessageId, Media)?, NoError>.single(hiddenMedia)
|
||||||
|> map { messageIdAndMedia in
|
|> map { messageIdAndMedia in
|
||||||
@ -1282,6 +984,14 @@ private final class NativePictureInPictureContentImpl: NSObject, AVPictureInPict
|
|||||||
completionHandler(true)
|
completionHandler(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func requestExpand() {
|
||||||
|
self.pictureInPictureController?.stopPictureInPicture()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func stop() {
|
||||||
|
self.pictureInPictureController?.stopPictureInPicture()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||||
@ -1331,7 +1041,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
|
|
||||||
private var requiresDownload = false
|
private var requiresDownload = false
|
||||||
|
|
||||||
private var item: UniversalVideoGalleryItem?
|
private(set) var item: UniversalVideoGalleryItem?
|
||||||
private var playbackRate: Double?
|
private var playbackRate: Double?
|
||||||
private var videoQuality: UniversalVideoContentVideoQuality = .auto
|
private var videoQuality: UniversalVideoContentVideoQuality = .auto
|
||||||
private let playbackRatePromise = ValuePromise<Double>()
|
private let playbackRatePromise = ValuePromise<Double>()
|
||||||
@ -2180,8 +1890,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
|
|
||||||
if let strongSelf = self, !isAnimated {
|
if let strongSelf = self, !isAnimated {
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
if let pictureInPictureContent = strongSelf.pictureInPictureContent as? PictureInPictureContentImpl {
|
if let nativePictureInPictureContent = strongSelf.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
|
||||||
pictureInPictureContent.invalidatePlaybackState()
|
nativePictureInPictureContent.invalidatePlaybackState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2358,6 +2068,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
if hadPreviousValue {
|
if hadPreviousValue {
|
||||||
videoNode.canAttachContent = isVisible
|
videoNode.canAttachContent = isVisible
|
||||||
if isVisible {
|
if isVisible {
|
||||||
|
if let currentPictureInPictureNode = self.context.sharedContext.mediaManager.currentPictureInPictureNode as? UniversalVideoGalleryItemNode, let currentItem = currentPictureInPictureNode.item, case let .message(currentMessage, _) = currentItem.contentInfo, case let .message(message, _) = item.contentInfo, currentMessage.id == message.id {
|
||||||
|
self.skipInitialPause = true
|
||||||
|
}
|
||||||
|
|
||||||
if self.skipInitialPause {
|
if self.skipInitialPause {
|
||||||
self.skipInitialPause = false
|
self.skipInitialPause = false
|
||||||
} else {
|
} else {
|
||||||
@ -2397,7 +2111,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func activateAsInitial() {
|
override func activateAsInitial() {
|
||||||
if let videoNode = self.videoNode, self.isCentral == true {
|
if let videoNode = self.videoNode, self.isCentral == true, !self.initiallyActivated {
|
||||||
self.initiallyActivated = true
|
self.initiallyActivated = true
|
||||||
|
|
||||||
var isAnimated = false
|
var isAnimated = false
|
||||||
@ -3117,7 +2831,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if customUnembedWhenPortrait(overlayNode) {
|
if customUnembedWhenPortrait(overlayNode) {
|
||||||
self.beginCustomDismiss(false)
|
self.beginCustomDismiss(.default)
|
||||||
self.statusNode.isHidden = true
|
self.statusNode.isHidden = true
|
||||||
self.animateOut(toOverlay: overlayNode, completion: { [weak self] in
|
self.animateOut(toOverlay: overlayNode, completion: { [weak self] in
|
||||||
self?.completeCustomDismiss(false)
|
self?.completeCustomDismiss(false)
|
||||||
@ -3181,9 +2895,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
guard let self, let controller = self.galleryController(), let navigationController = self.baseNavigationController() else {
|
guard let self, let controller = self.galleryController(), let navigationController = self.baseNavigationController() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.activePictureInPictureNavigationController = navigationController
|
self.activePictureInPictureNavigationController = navigationController
|
||||||
self.activePictureInPictureController = controller
|
self.activePictureInPictureController = controller
|
||||||
|
self.context.sharedContext.mediaManager.currentPictureInPictureNode = self
|
||||||
|
|
||||||
|
self.beginCustomDismiss(.pip)
|
||||||
controller.view.alpha = 0.0
|
controller.view.alpha = 0.0
|
||||||
controller.view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in
|
controller.view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in
|
||||||
self?.completeCustomDismiss(true)
|
self?.completeCustomDismiss(true)
|
||||||
@ -3201,6 +2918,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.context.sharedContext.mediaManager.currentPictureInPictureNode === self {
|
||||||
|
self.context.sharedContext.mediaManager.currentPictureInPictureNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
if let videoNode = self.videoNode {
|
if let videoNode = self.videoNode {
|
||||||
videoNode.setNativePictureInPictureIsActive(false)
|
videoNode.setNativePictureInPictureIsActive(false)
|
||||||
}
|
}
|
||||||
@ -3227,6 +2949,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
activePictureInPictureNavigationController.currentWindow?.present(activePictureInPictureController, on: .root, blockInteraction: false, completion: {
|
activePictureInPictureNavigationController.currentWindow?.present(activePictureInPictureController, on: .root, blockInteraction: false, completion: {
|
||||||
})
|
})
|
||||||
activePictureInPictureController.presentationArguments = previousPresentationArguments
|
activePictureInPictureController.presentationArguments = previousPresentationArguments
|
||||||
|
self.updateControlsVisibility(false)
|
||||||
|
|
||||||
activePictureInPictureController.view.alpha = 1.0
|
activePictureInPictureController.view.alpha = 1.0
|
||||||
activePictureInPictureController.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.35, completion: { _ in
|
activePictureInPictureController.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.35, completion: { _ in
|
||||||
@ -3240,6 +2963,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func pictureInPictureButtonPressed() {
|
@objc func pictureInPictureButtonPressed() {
|
||||||
|
if let currentPictureInPictureNode = self.context.sharedContext.mediaManager.currentPictureInPictureNode as? UniversalVideoGalleryItemNode, let currentItem = currentPictureInPictureNode.item, case let .message(currentMessage, _) = currentItem.contentInfo, case let .message(message, _) = self.item?.contentInfo, currentMessage.id == message.id {
|
||||||
|
if let controller = self.galleryController() as? GalleryController {
|
||||||
|
controller.dismiss(forceAway: true)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
|
if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
|
||||||
addAppLogEvent(postbox: self.context.account.postbox, type: "pip_btn", peerId: self.context.account.peerId)
|
addAppLogEvent(postbox: self.context.account.postbox, type: "pip_btn", peerId: self.context.account.peerId)
|
||||||
@ -3247,197 +2977,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isNativePictureInPictureSupported = false
|
|
||||||
switch self.item?.contentInfo {
|
|
||||||
case let .message(message, _):
|
|
||||||
for media in message.media {
|
|
||||||
if let media = media as? TelegramMediaFile, media.isVideo {
|
|
||||||
if message.id.namespace == Namespaces.Message.Cloud {
|
|
||||||
isNativePictureInPictureSupported = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let item = self.item, let videoNode = self.videoNode, let overlayController = self.context.sharedContext.mediaManager.overlayMediaManager.controller {
|
func expandPIP() {
|
||||||
videoNode.setContinuePlayingWithoutSoundOnLostAudioSession(false)
|
if #available(iOS 15.0, *) {
|
||||||
|
if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl {
|
||||||
let context = self.context
|
nativePictureInPictureContent.requestExpand()
|
||||||
let baseNavigationController = self.baseNavigationController()
|
|
||||||
let playbackRate = self.playbackRate
|
|
||||||
|
|
||||||
if #available(iOSApplicationExtension 15.0, iOS 15.0, *), AVPictureInPictureController.isPictureInPictureSupported(), isNativePictureInPictureSupported {
|
|
||||||
|
|
||||||
self.disablePictureInPicturePlaceholder = true
|
|
||||||
|
|
||||||
let overlayVideoNode = UniversalVideoNode(context: self.context, postbox: self.context.account.postbox, audioSession: self.context.sharedContext.mediaManager.audioSession, manager: self.context.sharedContext.mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .overlay)
|
|
||||||
let absoluteRect = videoNode.view.convert(videoNode.view.bounds, to: nil)
|
|
||||||
overlayVideoNode.frame = absoluteRect
|
|
||||||
overlayVideoNode.updateLayout(size: absoluteRect.size, transition: .immediate)
|
|
||||||
overlayVideoNode.canAttachContent = true
|
|
||||||
|
|
||||||
var hiddenMedia: (MessageId, Media)? = nil
|
|
||||||
switch item.contentInfo {
|
|
||||||
case let .message(message, _):
|
|
||||||
for media in message.media {
|
|
||||||
if let media = media as? TelegramMediaImage {
|
|
||||||
hiddenMedia = (message.id, media)
|
|
||||||
} else if let media = media as? TelegramMediaFile, media.isVideo {
|
|
||||||
hiddenMedia = (message.id, media)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = PictureInPictureContentImpl(context: self.context, overlayController: overlayController, mediaManager: self.context.sharedContext.mediaManager, accountId: self.context.account.id, hiddenMedia: hiddenMedia, videoNode: overlayVideoNode, canSkip: true, willBegin: { [weak self] content in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.beginCustomDismiss(true)
|
|
||||||
}, didEnd: { [weak self] _ in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.completeCustomDismiss(false)
|
|
||||||
}, expand: { [weak baseNavigationController] completion in
|
|
||||||
guard let contentInfo = item.contentInfo else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch contentInfo {
|
|
||||||
case let .message(message, _):
|
|
||||||
let gallery = GalleryController(context: context, source: .peerMessagesAtId(messageId: message.id, chatLocation: .peer(id: message.id.peerId), customTag: nil, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil)), playbackRate: playbackRate, replaceRootController: { [weak baseNavigationController] controller, ready in
|
|
||||||
if let baseNavigationController = baseNavigationController {
|
|
||||||
baseNavigationController.replaceTopController(controller, animated: false, ready: ready)
|
|
||||||
}
|
|
||||||
}, baseNavigationController: baseNavigationController)
|
|
||||||
gallery.temporaryDoNotWaitForReady = true
|
|
||||||
gallery.useSimpleAnimation = true
|
|
||||||
|
|
||||||
baseNavigationController?.view.endEditing(true)
|
|
||||||
|
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(gallery, in: .window(.root), with: GalleryControllerPresentationArguments(transitionArguments: { id, media in
|
|
||||||
return nil
|
|
||||||
}))
|
|
||||||
|
|
||||||
gallery.onDidAppear = {
|
|
||||||
completion()
|
|
||||||
}
|
|
||||||
case .webPage:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
self.pictureInPictureContent = content
|
|
||||||
|
|
||||||
self.context.sharedContext.mediaManager.overlayMediaManager.controller?.setPictureInPictureContent(content: content, absoluteRect: absoluteRect)
|
|
||||||
} else {
|
|
||||||
let context = self.context
|
|
||||||
let baseNavigationController = self.baseNavigationController()
|
|
||||||
let mediaManager = self.context.sharedContext.mediaManager
|
|
||||||
var expandImpl: (() -> Void)?
|
|
||||||
|
|
||||||
let shouldBeDismissed: Signal<Bool, NoError>
|
|
||||||
if let contentInfo = item.contentInfo, case let .message(message, _) = contentInfo {
|
|
||||||
shouldBeDismissed = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: message.id))
|
|
||||||
|> map { message -> Bool in
|
|
||||||
if let _ = message {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> distinctUntilChanged
|
|
||||||
} else {
|
|
||||||
shouldBeDismissed = .single(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
let overlayNode = OverlayUniversalVideoNode(context: self.context, postbox: self.context.account.postbox, audioSession: context.sharedContext.mediaManager.audioSession, manager: context.sharedContext.mediaManager.universalVideoManager, content: item.content, shouldBeDismissed: shouldBeDismissed, expand: {
|
|
||||||
expandImpl?()
|
|
||||||
}, close: { [weak mediaManager] in
|
|
||||||
mediaManager?.setOverlayVideoNode(nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
let playbackRate = self.playbackRate
|
|
||||||
|
|
||||||
expandImpl = { [weak overlayNode] in
|
|
||||||
guard let contentInfo = item.contentInfo, let overlayNode = overlayNode else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch contentInfo {
|
|
||||||
case let .message(message, messageIndex):
|
|
||||||
let source: GalleryControllerItemSource
|
|
||||||
if let _ = message.paidContent {
|
|
||||||
source = .standaloneMessage(message, messageIndex)
|
|
||||||
} else {
|
|
||||||
source = .peerMessagesAtId(messageId: message.id, chatLocation: .peer(id: message.id.peerId), customTag: nil, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
let gallery = GalleryController(context: context, source: source, playbackRate: playbackRate, replaceRootController: { controller, ready in
|
|
||||||
if let baseNavigationController = baseNavigationController {
|
|
||||||
baseNavigationController.replaceTopController(controller, animated: false, ready: ready)
|
|
||||||
}
|
|
||||||
}, baseNavigationController: baseNavigationController)
|
|
||||||
gallery.temporaryDoNotWaitForReady = true
|
|
||||||
|
|
||||||
baseNavigationController?.view.endEditing(true)
|
|
||||||
|
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(gallery, in: .window(.root), with: GalleryControllerPresentationArguments(transitionArguments: { [weak overlayNode] id, media in
|
|
||||||
if let overlayNode = overlayNode, let overlaySupernode = overlayNode.supernode {
|
|
||||||
return GalleryTransitionArguments(transitionNode: (overlayNode, overlayNode.bounds, { [weak overlayNode] in
|
|
||||||
return (overlayNode?.view.snapshotContentTree(), nil)
|
|
||||||
}), addToTransitionSurface: { [weak context, weak overlaySupernode, weak overlayNode] view in
|
|
||||||
guard let context = context, let overlayNode = overlayNode else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if context.sharedContext.mediaManager.hasOverlayVideoNode(overlayNode) {
|
|
||||||
overlaySupernode?.view.addSubview(view)
|
|
||||||
}
|
|
||||||
overlayNode.canAttachContent = false
|
|
||||||
})
|
|
||||||
} else if let info = context.sharedContext.mediaManager.galleryHiddenMediaManager.findTarget(messageId: id, media: media) {
|
|
||||||
return GalleryTransitionArguments(transitionNode: (info.1, info.1.bounds, {
|
|
||||||
return info.2()
|
|
||||||
}), addToTransitionSurface: info.0)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}))
|
|
||||||
case let .webPage(_, _, expandFromPip):
|
|
||||||
if let expandFromPip = expandFromPip, let baseNavigationController = baseNavigationController {
|
|
||||||
expandFromPip({ [weak overlayNode] in
|
|
||||||
if let overlayNode = overlayNode, let overlaySupernode = overlayNode.supernode {
|
|
||||||
return GalleryTransitionArguments(transitionNode: (overlayNode, overlayNode.bounds, { [weak overlayNode] in
|
|
||||||
return (overlayNode?.view.snapshotContentTree(), nil)
|
|
||||||
}), addToTransitionSurface: { [weak context, weak overlaySupernode, weak overlayNode] view in
|
|
||||||
guard let context = context, let overlayNode = overlayNode else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if context.sharedContext.mediaManager.hasOverlayVideoNode(overlayNode) {
|
|
||||||
overlaySupernode?.view.addSubview(view)
|
|
||||||
}
|
|
||||||
overlayNode.canAttachContent = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}, baseNavigationController, { [weak baseNavigationController] c, a in
|
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(c, in: .window(.root), with: a)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.sharedContext.mediaManager.setOverlayVideoNode(overlayNode)
|
|
||||||
if overlayNode.supernode != nil {
|
|
||||||
self.beginCustomDismiss(false)
|
|
||||||
self.statusNode.isHidden = true
|
|
||||||
self.animateOut(toOverlay: overlayNode, completion: { [weak self] in
|
|
||||||
self?.completeCustomDismiss(false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3997,7 +3542,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let navigationController = strongSelf.baseNavigationController() {
|
if let navigationController = strongSelf.baseNavigationController() {
|
||||||
strongSelf.beginCustomDismiss(true)
|
strongSelf.beginCustomDismiss(.simpleAnimation)
|
||||||
|
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false)))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false)))
|
||||||
|
|
||||||
@ -4050,7 +3595,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
if let peer, let (message, _, _) = strongSelf.contentInfo(), canSendMessagesToPeer(peer._asPeer()) {
|
if let peer, let (message, _, _) = strongSelf.contentInfo(), canSendMessagesToPeer(peer._asPeer()) {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuReply, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuReply, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.contextMenu.primaryColor)}, action: { [weak self] _, f in
|
||||||
if let self, let navigationController = self.baseNavigationController() {
|
if let self, let navigationController = self.baseNavigationController() {
|
||||||
self.beginCustomDismiss(true)
|
self.beginCustomDismiss(.simpleAnimation)
|
||||||
|
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: true)))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: true)))
|
||||||
|
|
||||||
|
@ -429,10 +429,6 @@ public final class FFMpegFileReader {
|
|||||||
if let stream = self.stream, Int(packet.streamIndex) == stream.info.index {
|
if let stream = self.stream, Int(packet.streamIndex) == stream.info.index {
|
||||||
let packetPts = packet.pts
|
let packetPts = packet.pts
|
||||||
|
|
||||||
/*if let focusedPart = self.focusedPart, packetPts >= focusedPart.endPts.value {
|
|
||||||
self.hasReadToEnd = true
|
|
||||||
}*/
|
|
||||||
|
|
||||||
let pts = CMTimeMake(value: packetPts, timescale: stream.info.timeScale)
|
let pts = CMTimeMake(value: packetPts, timescale: stream.info.timeScale)
|
||||||
let dts = CMTimeMake(value: packet.dts, timescale: stream.info.timeScale)
|
let dts = CMTimeMake(value: packet.dts, timescale: stream.info.timeScale)
|
||||||
|
|
||||||
@ -442,7 +438,7 @@ public final class FFMpegFileReader {
|
|||||||
if frameDuration != 0 {
|
if frameDuration != 0 {
|
||||||
duration = CMTimeMake(value: frameDuration * stream.info.timeBase, timescale: stream.info.timeScale)
|
duration = CMTimeMake(value: frameDuration * stream.info.timeBase, timescale: stream.info.timeScale)
|
||||||
} else {
|
} else {
|
||||||
duration = stream.info.fps
|
duration = CMTimeConvertScale(CMTimeMakeWithSeconds(1.0 / stream.info.fps.seconds, preferredTimescale: stream.info.timeScale), timescale: stream.info.timeScale, method: .quickTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame = MediaTrackDecodableFrame(type: .video, packet: packet, pts: pts, dts: dts, duration: duration)
|
let frame = MediaTrackDecodableFrame(type: .video, packet: packet, pts: pts, dts: dts, duration: duration)
|
||||||
|
@ -451,29 +451,48 @@ private func chatMessageImageFileThumbnailDatas(account: Account, userLocation:
|
|||||||
private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, fileReference: FileMediaReference, previewSourceFileReference: FileMediaReference?, thumbnailSize: Bool = false, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, forceThumbnail: Bool = false) -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> {
|
private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, fileReference: FileMediaReference, previewSourceFileReference: FileMediaReference?, thumbnailSize: Bool = false, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, forceThumbnail: Bool = false) -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> {
|
||||||
let fullSizeResource = fileReference.media.resource
|
let fullSizeResource = fileReference.media.resource
|
||||||
var reducedSizeResource: MediaResource?
|
var reducedSizeResource: MediaResource?
|
||||||
if let previewSourceFileReference, let videoThumbnail = previewSourceFileReference.media.videoThumbnails.first {
|
if let videoThumbnail = fileReference.media.videoThumbnails.first {
|
||||||
reducedSizeResource = videoThumbnail.resource
|
|
||||||
} else if let videoThumbnail = fileReference.media.videoThumbnails.first {
|
|
||||||
reducedSizeResource = videoThumbnail.resource
|
reducedSizeResource = videoThumbnail.resource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var previewSourceFullSizeResource: MediaResource?
|
||||||
|
if let previewSourceFileReference {
|
||||||
|
previewSourceFullSizeResource = previewSourceFileReference.media.resource
|
||||||
|
}
|
||||||
|
|
||||||
var thumbnailRepresentation: TelegramMediaImageRepresentation?
|
var thumbnailRepresentation: TelegramMediaImageRepresentation?
|
||||||
if let previewSourceFileReference {
|
|
||||||
thumbnailRepresentation = useLargeThumbnail ? largestImageRepresentation(previewSourceFileReference.media.previewRepresentations) : smallestImageRepresentation(previewSourceFileReference.media.previewRepresentations)
|
|
||||||
}
|
|
||||||
if thumbnailRepresentation == nil {
|
if thumbnailRepresentation == nil {
|
||||||
thumbnailRepresentation = useLargeThumbnail ? largestImageRepresentation(fileReference.media.previewRepresentations) : smallestImageRepresentation(fileReference.media.previewRepresentations)
|
thumbnailRepresentation = useLargeThumbnail ? largestImageRepresentation(fileReference.media.previewRepresentations) : smallestImageRepresentation(fileReference.media.previewRepresentations)
|
||||||
}
|
}
|
||||||
|
|
||||||
let thumbnailResource = thumbnailRepresentation?.resource
|
let thumbnailResource = thumbnailRepresentation?.resource
|
||||||
|
|
||||||
|
let maybePreviewSourceFullSize: Signal<MediaResourceData, NoError>
|
||||||
|
if let previewSourceFullSizeResource {
|
||||||
|
maybePreviewSourceFullSize = postbox.mediaBox.cachedResourceRepresentation(previewSourceFullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: false, attemptSynchronously: synchronousLoad)
|
||||||
|
} else {
|
||||||
|
maybePreviewSourceFullSize = .single(MediaResourceData(path: "", offset: 0, size: 0, complete: false))
|
||||||
|
}
|
||||||
|
|
||||||
let maybeFullSize = postbox.mediaBox.cachedResourceRepresentation(fullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: false, attemptSynchronously: synchronousLoad)
|
let maybeFullSize = postbox.mediaBox.cachedResourceRepresentation(fullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: false, attemptSynchronously: synchronousLoad)
|
||||||
|
|
||||||
let fetchedFullSize = postbox.mediaBox.cachedResourceRepresentation(fullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: true, attemptSynchronously: synchronousLoad)
|
let fetchedFullSize = postbox.mediaBox.cachedResourceRepresentation(fullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: true, attemptSynchronously: synchronousLoad)
|
||||||
var fetchedReducedSize: Signal<MediaResourceData, NoError> = .single(MediaResourceData(path: "", offset: 0, size: 0, complete: false))
|
var fetchedReducedSize: Signal<MediaResourceData, NoError> = .single(MediaResourceData(path: "", offset: 0, size: 0, complete: false))
|
||||||
if let reducedSizeResource = reducedSizeResource {
|
if let reducedSizeResource = reducedSizeResource {
|
||||||
fetchedReducedSize = postbox.mediaBox.cachedResourceRepresentation(reducedSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: true, attemptSynchronously: synchronousLoad)
|
fetchedReducedSize = postbox.mediaBox.cachedResourceRepresentation(reducedSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: true, attemptSynchronously: synchronousLoad)
|
||||||
}
|
}
|
||||||
|
|
||||||
let signal = maybeFullSize
|
let signal = combineLatest(
|
||||||
|
maybePreviewSourceFullSize,
|
||||||
|
maybeFullSize
|
||||||
|
)
|
||||||
|
|> map { maybePreviewSourceFullSize, maybeFullSize -> MediaResourceData in
|
||||||
|
if maybePreviewSourceFullSize.complete {
|
||||||
|
return maybePreviewSourceFullSize
|
||||||
|
} else {
|
||||||
|
return maybeFullSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { maybeData -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> in
|
|> mapToSignal { maybeData -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> in
|
||||||
if maybeData.complete && !forceThumbnail {
|
if maybeData.complete && !forceThumbnail {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct MediaId: Hashable, PostboxCoding, CustomStringConvertible, Codable {
|
public struct MediaId: Hashable, Comparable, PostboxCoding, CustomStringConvertible, Codable {
|
||||||
public typealias Namespace = Int32
|
public typealias Namespace = Int32
|
||||||
public typealias Id = Int64
|
public typealias Id = Int64
|
||||||
|
|
||||||
@ -39,6 +39,14 @@ public struct MediaId: Hashable, PostboxCoding, CustomStringConvertible, Codable
|
|||||||
encoder.encodeInt64(self.id, forKey: "i")
|
encoder.encodeInt64(self.id, forKey: "i")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func <(lhs: MediaId, rhs: MediaId) -> Bool {
|
||||||
|
if lhs.namespace != rhs.namespace {
|
||||||
|
return lhs.namespace < rhs.namespace
|
||||||
|
} else {
|
||||||
|
return lhs.id < rhs.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func encodeToBuffer(_ buffer: WriteBuffer) {
|
public func encodeToBuffer(_ buffer: WriteBuffer) {
|
||||||
var namespace = self.namespace
|
var namespace = self.namespace
|
||||||
var id = self.id
|
var id = self.id
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
include "InstantPageBlock.fbs";
|
||||||
|
include "MediaId.fbs";
|
||||||
|
include "Media.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table InstantPage {
|
||||||
|
blocks:[InstantPageBlock] (id: 0, required);
|
||||||
|
media:[Media] (id: 1, required);
|
||||||
|
isComplete:bool (id: 2);
|
||||||
|
rtl:bool (id: 3);
|
||||||
|
url:string (id: 4, required);
|
||||||
|
views:int32 (id: 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type InstantPage;
|
@ -0,0 +1,235 @@
|
|||||||
|
include "RichText.fbs";
|
||||||
|
include "MediaId.fbs";
|
||||||
|
include "TelegramChannel.fbs";
|
||||||
|
include "PixelDimensions.fbs";
|
||||||
|
include "RichText.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
union InstantPageBlock_Value {
|
||||||
|
InstantPageBlock_Unsupported,
|
||||||
|
InstantPageBlock_Title,
|
||||||
|
InstantPageBlock_Subtitle,
|
||||||
|
InstantPageBlock_AuthorDate,
|
||||||
|
InstantPageBlock_Header,
|
||||||
|
InstantPageBlock_Subheader,
|
||||||
|
InstantPageBlock_Paragraph,
|
||||||
|
InstantPageBlock_Preformatted,
|
||||||
|
InstantPageBlock_Footer,
|
||||||
|
InstantPageBlock_Divider,
|
||||||
|
InstantPageBlock_Anchor,
|
||||||
|
InstantPageBlock_List,
|
||||||
|
InstantPageBlock_BlockQuote,
|
||||||
|
InstantPageBlock_PullQuote,
|
||||||
|
InstantPageBlock_Image,
|
||||||
|
InstantPageBlock_Video,
|
||||||
|
InstantPageBlock_Audio,
|
||||||
|
InstantPageBlock_Cover,
|
||||||
|
InstantPageBlock_WebEmbed,
|
||||||
|
InstantPageBlock_PostEmbed,
|
||||||
|
InstantPageBlock_Collage,
|
||||||
|
InstantPageBlock_Slideshow,
|
||||||
|
InstantPageBlock_ChannelBanner,
|
||||||
|
InstantPageBlock_Kicker,
|
||||||
|
InstantPageBlock_Table,
|
||||||
|
InstantPageBlock_Details,
|
||||||
|
InstantPageBlock_RelatedArticles,
|
||||||
|
InstantPageBlock_Map
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock {
|
||||||
|
value:InstantPageBlock_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Unsupported {}
|
||||||
|
|
||||||
|
table InstantPageBlock_Title {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Subtitle {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_AuthorDate {
|
||||||
|
author:RichText (id: 0, required);
|
||||||
|
date:int32 (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Header {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Subheader {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Paragraph {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Preformatted {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Footer {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Divider {}
|
||||||
|
|
||||||
|
table InstantPageBlock_Anchor {
|
||||||
|
name:string (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_List {
|
||||||
|
items:[InstantPageListItem] (id: 0, required);
|
||||||
|
ordered:bool (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_BlockQuote {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
caption:RichText (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_PullQuote {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
caption:RichText (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Image {
|
||||||
|
id:MediaId (id: 0, required);
|
||||||
|
caption:InstantPageCaption (id: 1, required);
|
||||||
|
url:string (id: 2);
|
||||||
|
webpageId:MediaId (id: 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Video {
|
||||||
|
id:MediaId (id: 0, required);
|
||||||
|
caption:InstantPageCaption (id: 1, required);
|
||||||
|
autoplay:bool (id: 2);
|
||||||
|
loop:bool (id: 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Audio {
|
||||||
|
id:MediaId (id: 0, required);
|
||||||
|
caption:InstantPageCaption (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Cover {
|
||||||
|
block:InstantPageBlock (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_WebEmbed {
|
||||||
|
url:string (id: 0);
|
||||||
|
html:string (id: 1);
|
||||||
|
dimensions:PixelDimensions (id: 2);
|
||||||
|
caption:InstantPageCaption (id: 3, required);
|
||||||
|
stretchToWidth:bool (id: 4);
|
||||||
|
allowScrolling:bool (id: 5);
|
||||||
|
coverId:MediaId (id: 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_PostEmbed {
|
||||||
|
url:string (id: 0, required);
|
||||||
|
webpageId:MediaId (id: 1);
|
||||||
|
avatarId:MediaId (id: 2);
|
||||||
|
author:string (id: 3, required);
|
||||||
|
date:int32 (id: 4);
|
||||||
|
blocks:[InstantPageBlock] (id: 5, required);
|
||||||
|
caption:InstantPageCaption (id: 6, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Collage {
|
||||||
|
items:[InstantPageBlock] (id: 0, required);
|
||||||
|
caption:InstantPageCaption (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Slideshow {
|
||||||
|
items:[InstantPageBlock] (id: 0, required);
|
||||||
|
caption:InstantPageCaption (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_ChannelBanner {
|
||||||
|
channel:TelegramChannel (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Kicker {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Table {
|
||||||
|
title:RichText (id: 0, required);
|
||||||
|
rows:[InstantPageTableRow] (id: 1, required);
|
||||||
|
bordered:bool (id: 2);
|
||||||
|
striped:bool (id: 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Details {
|
||||||
|
title:RichText (id: 0, required);
|
||||||
|
blocks:[InstantPageBlock] (id: 1, required);
|
||||||
|
expanded:bool (id: 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_RelatedArticles {
|
||||||
|
title:RichText (id: 0, required);
|
||||||
|
articles:[InstantPageRelatedArticle] (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageBlock_Map {
|
||||||
|
latitude:float64 (id: 0);
|
||||||
|
longitude:float64 (id: 1);
|
||||||
|
zoom:int32 (id: 2);
|
||||||
|
dimensions:PixelDimensions (id: 3, required);
|
||||||
|
caption:InstantPageCaption (id: 4, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageCaption {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
credit:RichText (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
union InstantPageListItem_Value {
|
||||||
|
InstantPageListItem_Text,
|
||||||
|
InstantPageListItem_Blocks,
|
||||||
|
InstantPageListItem_Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageListItem {
|
||||||
|
value:InstantPageListItem_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageListItem_Text {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
number:string (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageListItem_Blocks {
|
||||||
|
blocks:[InstantPageBlock] (id: 0, required);
|
||||||
|
number:string (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageListItem_Unknown {}
|
||||||
|
|
||||||
|
table InstantPageTableCell {
|
||||||
|
text:RichText (id: 0);
|
||||||
|
header:bool (id: 1);
|
||||||
|
alignment:int32 (id: 2);
|
||||||
|
verticalAlignment:int32 (id: 3);
|
||||||
|
colspan:int32 (id: 4);
|
||||||
|
rowspan:int32 (id: 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageTableRow {
|
||||||
|
cells:[InstantPageTableCell] (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table InstantPageRelatedArticle {
|
||||||
|
url:string (id: 0, required);
|
||||||
|
webpageId:MediaId (id: 1, required);
|
||||||
|
title:string (id: 2);
|
||||||
|
description:string (id: 3);
|
||||||
|
photoId:MediaId (id: 4);
|
||||||
|
author:string (id: 5);
|
||||||
|
date:int32 (id: 6);
|
||||||
|
}
|
23
submodules/TelegramCore/FlatSerialization/Models/Media.fbs
Normal file
23
submodules/TelegramCore/FlatSerialization/Models/Media.fbs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
include "MediaId.fbs";
|
||||||
|
include "TelegramMediaFile.fbs";
|
||||||
|
include "TelegramMediaImage.fbs";
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
union Media_Value {
|
||||||
|
Media_TelegramMediaFile,
|
||||||
|
Media_TelegramMediaImage
|
||||||
|
}
|
||||||
|
|
||||||
|
table Media {
|
||||||
|
value:Media_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table Media_TelegramMediaFile {
|
||||||
|
file:TelegramMediaFile (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table Media_TelegramMediaImage {
|
||||||
|
image:TelegramMediaImage (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type Media;
|
@ -0,0 +1,5 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
struct OptionalBool {
|
||||||
|
value:bool (id: 0);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table RestrictionRule {
|
||||||
|
platform:string (id: 0, required);
|
||||||
|
reason:string (id: 1, required);
|
||||||
|
text:string (id: 2, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table PeerAccessRestrictionInfo {
|
||||||
|
rules:[RestrictionRule] (id: 0, required);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table PeerEmojiStatusContentEmoji {
|
||||||
|
fileId:int64 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table PeerEmojiStatusContentStarGift {
|
||||||
|
id:int64 (id: 0);
|
||||||
|
fileId:int64 (id: 1);
|
||||||
|
title:string (id: 2, required);
|
||||||
|
slug:string (id: 3, required);
|
||||||
|
patternFileId:int64 (id: 4);
|
||||||
|
innerColor:int32 (id: 5);
|
||||||
|
outerColor:int32 (id: 6);
|
||||||
|
patternColor:int32 (id: 7);
|
||||||
|
textColor:int32 (id: 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
union PeerEmojiStatusContent_Value {
|
||||||
|
PeerEmojiStatusContentEmoji,
|
||||||
|
PeerEmojiStatusContentStarGift
|
||||||
|
}
|
||||||
|
|
||||||
|
table PeerEmojiStatusContent {
|
||||||
|
value:PeerEmojiStatusContent_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table PeerEmojiStatus {
|
||||||
|
content:PeerEmojiStatusContent (id: 0, required);
|
||||||
|
expirationDate:int32 (id: 1);
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table PeerNameColor {
|
||||||
|
value:int32 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type PeerNameColor;
|
@ -0,0 +1,95 @@
|
|||||||
|
include "MediaId.fbs";
|
||||||
|
include "PixelDimensions.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
union RichText_Value {
|
||||||
|
RichText_Empty,
|
||||||
|
RichText_Plain,
|
||||||
|
RichText_Bold,
|
||||||
|
RichText_Italic,
|
||||||
|
RichText_Underline,
|
||||||
|
RichText_Strikethrough,
|
||||||
|
RichText_Fixed,
|
||||||
|
RichText_Url,
|
||||||
|
RichText_Email,
|
||||||
|
RichText_Concat,
|
||||||
|
RichText_Subscript,
|
||||||
|
RichText_Superscript,
|
||||||
|
RichText_Marked,
|
||||||
|
RichText_Phone,
|
||||||
|
RichText_Image,
|
||||||
|
RichText_Anchor
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText {
|
||||||
|
value:RichText_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Empty {}
|
||||||
|
|
||||||
|
table RichText_Plain {
|
||||||
|
text:string (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Bold {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Italic {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Underline {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Strikethrough {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Fixed {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Url {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
url:string (id: 1, required);
|
||||||
|
webpageId:MediaId (id: 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Email {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
email:string (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Concat {
|
||||||
|
texts:[RichText] (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Subscript {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Superscript {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Marked {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Phone {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
phone:string (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Image {
|
||||||
|
id:MediaId (id: 0, required);
|
||||||
|
dimensions:PixelDimensions (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table RichText_Anchor {
|
||||||
|
text:RichText (id: 0, required);
|
||||||
|
name:string (id: 1, required);
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table StarsAmount {
|
||||||
|
value:int64 (id: 0);
|
||||||
|
nanos:int32 (id: 1);
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
include "PeerId.fbs";
|
||||||
|
include "TelegramPeerAccessHash.fbs";
|
||||||
|
include "TelegramMediaImageRepresentation.fbs";
|
||||||
|
include "PeerAccessRestrictionInfo.fbs";
|
||||||
|
include "TelegramChatAdminRights.fbs";
|
||||||
|
include "TelegramChatBannedRights.fbs";
|
||||||
|
include "TelegramPeerUsername.fbs";
|
||||||
|
include "Optional.fbs";
|
||||||
|
include "PeerNameColor.fbs";
|
||||||
|
include "PeerEmojiStatus.fbs";
|
||||||
|
include "StarsAmount.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramChannelInfo_Broadcast {
|
||||||
|
flags:int32 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramChannelInfo_Group {
|
||||||
|
flags:int32 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
union TelegramChannelInfo_Value {
|
||||||
|
TelegramChannelInfo_Broadcast,
|
||||||
|
TelegramChannelInfo_Group
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramChannelInfo {
|
||||||
|
value:TelegramChannelInfo_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramChannel {
|
||||||
|
id:PeerId (id: 0, required);
|
||||||
|
accessHash:TelegramPeerAccessHash (id: 1);
|
||||||
|
title:string (id: 2, required);
|
||||||
|
username:string (id: 3);
|
||||||
|
photo:[TelegramMediaImageRepresentation] (id: 4);
|
||||||
|
creationDate:int32 (id: 5);
|
||||||
|
version:int32 (id: 6);
|
||||||
|
participationStatus:int32 (id: 7);
|
||||||
|
info:TelegramChannelInfo (id: 8, required);
|
||||||
|
flags:int32 (id: 9);
|
||||||
|
restrictionInfo:PeerAccessRestrictionInfo (id: 10);
|
||||||
|
adminRights:TelegramChatAdminRights (id: 11);
|
||||||
|
bannedRights:TelegramChatBannedRights (id: 12);
|
||||||
|
defaultBannedRights:TelegramChatBannedRights (id: 13);
|
||||||
|
usernames:[TelegramPeerUsername] (id: 14);
|
||||||
|
storiesHidden:OptionalBool (id: 15);
|
||||||
|
nameColor:PeerNameColor (id: 16);
|
||||||
|
backgroundEmojiId:int64 (id: 17);
|
||||||
|
profileColor:PeerNameColor (id: 18);
|
||||||
|
profileBackgroundEmojiId:int64 (id: 19);
|
||||||
|
emojiStatus:PeerEmojiStatus (id: 20);
|
||||||
|
approximateBoostLevel:int32 (id: 21);
|
||||||
|
subscriptionUntilDate:int32 (id: 22);
|
||||||
|
verificationIconFileId:int64 (id: 23);
|
||||||
|
sendPaidMessageStars:StarsAmount (id: 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type TelegramChannel;
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramChatAdminRights {
|
||||||
|
rights:int32 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type TelegramChatAdminRights;
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramChatBannedRights {
|
||||||
|
flags:int32 (id: 0);
|
||||||
|
untilDate:int32 (id: 1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
include "PeerId.fbs";
|
||||||
|
include "TelegramMediaImageRepresentation.fbs";
|
||||||
|
include "TelegramChatAdminRights.fbs";
|
||||||
|
include "TelegramChatBannedRights.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramGroupRole_Creator {
|
||||||
|
rank:string (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramGroupRole_Admin {
|
||||||
|
rights:TelegramChatAdminRights (id: 0, required);
|
||||||
|
rank:string (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramGroupRole_Member {}
|
||||||
|
|
||||||
|
union TelegramGroupRole_Value {
|
||||||
|
TelegramGroupRole_Creator,
|
||||||
|
TelegramGroupRole_Admin,
|
||||||
|
TelegramGroupRole_Member
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramGroupRole {
|
||||||
|
value:TelegramGroupRole_Value (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramGroupToChannelMigrationReference {
|
||||||
|
peerId:int64 (id: 0);
|
||||||
|
accessHash:int64 (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramGroup {
|
||||||
|
id:PeerId (id: 0, required);
|
||||||
|
title:string (id: 1, required);
|
||||||
|
photo:[TelegramMediaImageRepresentation] (id: 2, required);
|
||||||
|
participantCount:int32 (id: 3);
|
||||||
|
role:TelegramGroupRole (id: 4, required);
|
||||||
|
membership:int32 (id: 5);
|
||||||
|
flags:int32 (id: 6);
|
||||||
|
defaultBannedRights:TelegramChatBannedRights (id: 7);
|
||||||
|
migrationReference:TelegramGroupToChannelMigrationReference (id: 8);
|
||||||
|
creationDate:int32 (id: 9);
|
||||||
|
version:int32 (id: 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type TelegramGroup;
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramPeerAccessHash_Personal {
|
||||||
|
accessHash:int64 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramPeerAccessHash_GenericPublic {
|
||||||
|
accessHash:int64 (id: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
union TelegramPeerAccessHash_Value {
|
||||||
|
TelegramPeerAccessHash_Personal,
|
||||||
|
TelegramPeerAccessHash_GenericPublic
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramPeerAccessHash {
|
||||||
|
value:TelegramPeerAccessHash_Value (id: 1, required);
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table TelegramPeerUsername {
|
||||||
|
flags:int32 (id: 0);
|
||||||
|
username:string (id: 1, required);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type TelegramPeerUsername;
|
@ -0,0 +1,40 @@
|
|||||||
|
include "PeerId.fbs";
|
||||||
|
include "TelegramPeerAccessHash.fbs";
|
||||||
|
include "TelegramMediaImageRepresentation.fbs";
|
||||||
|
include "PeerAccessRestrictionInfo.fbs";
|
||||||
|
include "PeerEmojiStatus.fbs";
|
||||||
|
include "TelegramPeerUsername.fbs";
|
||||||
|
include "PeerNameColor.fbs";
|
||||||
|
include "Optional.fbs";
|
||||||
|
include "StarsAmount.fbs";
|
||||||
|
|
||||||
|
namespace TelegramCore;
|
||||||
|
|
||||||
|
table BotUserInfo {
|
||||||
|
flags:int32 (id: 0);
|
||||||
|
inlinePlaceholder:string (id: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table TelegramUser {
|
||||||
|
id:PeerId (id: 0, required);
|
||||||
|
accessHash:TelegramPeerAccessHash (id: 1);
|
||||||
|
firstName:string (id: 2);
|
||||||
|
lastName:string (id: 3);
|
||||||
|
username:string (id: 4);
|
||||||
|
phone:string (id: 5);
|
||||||
|
photo:[TelegramMediaImageRepresentation] (id: 6, required);
|
||||||
|
botInfo:BotUserInfo (id: 7);
|
||||||
|
restrictionInfo:PeerAccessRestrictionInfo (id: 8);
|
||||||
|
flags:int32 (id: 9);
|
||||||
|
emojiStatus:PeerEmojiStatus (id: 10);
|
||||||
|
usernames:[TelegramPeerUsername] (id: 11);
|
||||||
|
storiesHidden:OptionalBool (id: 12);
|
||||||
|
nameColor:PeerNameColor (id: 13);
|
||||||
|
backgroundEmojiId:int64 (id: 14);
|
||||||
|
profileColor:PeerNameColor (id: 15);
|
||||||
|
profileBackgroundEmojiId:int64 (id: 16);
|
||||||
|
subscriberCount:int32 (id: 17);
|
||||||
|
verificationIconFileId:int64 (id: 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type TelegramUser;
|
@ -1,7 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Postbox
|
import Postbox
|
||||||
|
|
||||||
|
|
||||||
public enum TelegramChannelPermission {
|
public enum TelegramChannelPermission {
|
||||||
case sendText
|
case sendText
|
||||||
case sendPhoto
|
case sendPhoto
|
||||||
|
@ -160,7 +160,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let staticIconData = try container.decodeIfPresent(Data.self, forKey: .staticIconData) {
|
if let staticIconData = try container.decodeIfPresent(Data.self, forKey: .staticIconData) {
|
||||||
var byteBuffer = ByteBuffer(data: staticIconData)
|
var byteBuffer = ByteBuffer(data: staticIconData)
|
||||||
self.staticIcon = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, staticIconData)
|
self.staticIcon = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, staticIconData)
|
||||||
} else {
|
} else {
|
||||||
let staticIconData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon)
|
let staticIconData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon)
|
||||||
self.staticIcon = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data))))
|
self.staticIcon = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data))))
|
||||||
@ -168,7 +168,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let appearAnimationData = try container.decodeIfPresent(Data.self, forKey: .appearAnimationData) {
|
if let appearAnimationData = try container.decodeIfPresent(Data.self, forKey: .appearAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: appearAnimationData)
|
var byteBuffer = ByteBuffer(data: appearAnimationData)
|
||||||
self.appearAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, appearAnimationData)
|
self.appearAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, appearAnimationData)
|
||||||
} else {
|
} else {
|
||||||
let appearAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .appearAnimation)
|
let appearAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .appearAnimation)
|
||||||
self.appearAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: appearAnimationData.data))))
|
self.appearAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: appearAnimationData.data))))
|
||||||
@ -176,7 +176,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let selectAnimationData = try container.decodeIfPresent(Data.self, forKey: .selectAnimationData) {
|
if let selectAnimationData = try container.decodeIfPresent(Data.self, forKey: .selectAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: selectAnimationData)
|
var byteBuffer = ByteBuffer(data: selectAnimationData)
|
||||||
self.selectAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, selectAnimationData)
|
self.selectAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, selectAnimationData)
|
||||||
} else {
|
} else {
|
||||||
let selectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .selectAnimation)
|
let selectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .selectAnimation)
|
||||||
self.selectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: selectAnimationData.data))))
|
self.selectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: selectAnimationData.data))))
|
||||||
@ -184,7 +184,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let activateAnimationData = try container.decodeIfPresent(Data.self, forKey: .activateAnimationData) {
|
if let activateAnimationData = try container.decodeIfPresent(Data.self, forKey: .activateAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: activateAnimationData)
|
var byteBuffer = ByteBuffer(data: activateAnimationData)
|
||||||
self.activateAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, activateAnimationData)
|
self.activateAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, activateAnimationData)
|
||||||
} else {
|
} else {
|
||||||
let activateAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .activateAnimation)
|
let activateAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .activateAnimation)
|
||||||
self.activateAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: activateAnimationData.data))))
|
self.activateAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: activateAnimationData.data))))
|
||||||
@ -192,7 +192,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let effectAnimationData = try container.decodeIfPresent(Data.self, forKey: .effectAnimationData) {
|
if let effectAnimationData = try container.decodeIfPresent(Data.self, forKey: .effectAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: effectAnimationData)
|
var byteBuffer = ByteBuffer(data: effectAnimationData)
|
||||||
self.effectAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, effectAnimationData)
|
self.effectAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, effectAnimationData)
|
||||||
} else {
|
} else {
|
||||||
let effectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation)
|
let effectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation)
|
||||||
self.effectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data))))
|
self.effectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data))))
|
||||||
@ -200,7 +200,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let aroundAnimationData = try container.decodeIfPresent(Data.self, forKey: .aroundAnimationData) {
|
if let aroundAnimationData = try container.decodeIfPresent(Data.self, forKey: .aroundAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: aroundAnimationData)
|
var byteBuffer = ByteBuffer(data: aroundAnimationData)
|
||||||
self.aroundAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, aroundAnimationData)
|
self.aroundAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, aroundAnimationData)
|
||||||
} else if let aroundAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .aroundAnimation) {
|
} else if let aroundAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .aroundAnimation) {
|
||||||
self.aroundAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: aroundAnimationData.data))))
|
self.aroundAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: aroundAnimationData.data))))
|
||||||
} else {
|
} else {
|
||||||
@ -209,7 +209,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
|
|
||||||
if let centerAnimationData = try container.decodeIfPresent(Data.self, forKey: .centerAnimationData) {
|
if let centerAnimationData = try container.decodeIfPresent(Data.self, forKey: .centerAnimationData) {
|
||||||
var byteBuffer = ByteBuffer(data: centerAnimationData)
|
var byteBuffer = ByteBuffer(data: centerAnimationData)
|
||||||
self.centerAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, centerAnimationData)
|
self.centerAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, centerAnimationData)
|
||||||
} else if let centerAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .centerAnimation) {
|
} else if let centerAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .centerAnimation) {
|
||||||
self.centerAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: centerAnimationData.data))))
|
self.centerAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: centerAnimationData.data))))
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,6 +2,8 @@ import Foundation
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public enum CachedPeerAutoremoveTimeout: Equatable, PostboxCoding {
|
public enum CachedPeerAutoremoveTimeout: Equatable, PostboxCoding {
|
||||||
public struct Value: Equatable, PostboxCoding {
|
public struct Value: Equatable, PostboxCoding {
|
||||||
@ -261,6 +263,16 @@ public enum PeerNameColor: Hashable {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_PeerNameColor) throws {
|
||||||
|
self.init(rawValue: flatBuffersObject.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let start = TelegramCore_PeerNameColor.startPeerNameColor(&builder)
|
||||||
|
TelegramCore_PeerNameColor.add(value: self.rawValue, &builder)
|
||||||
|
return TelegramCore_PeerNameColor.endPeerNameColor(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PeerEmojiStatus: Equatable, Codable {
|
public struct PeerEmojiStatus: Equatable, Codable {
|
||||||
@ -320,6 +332,68 @@ public struct PeerEmojiStatus: Equatable, Codable {
|
|||||||
try container.encode(textColor, forKey: .textColor)
|
try container.encode(textColor, forKey: .textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_PeerEmojiStatusContent) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .peeremojistatuscontentemoji:
|
||||||
|
guard let emoji = flatBuffersObject.value(type: TelegramCore_PeerEmojiStatusContentEmoji.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .emoji(fileId: emoji.fileId)
|
||||||
|
|
||||||
|
case .peeremojistatuscontentstargift:
|
||||||
|
guard let starGift = flatBuffersObject.value(type: TelegramCore_PeerEmojiStatusContentStarGift.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .starGift(
|
||||||
|
id: starGift.id,
|
||||||
|
fileId: starGift.fileId,
|
||||||
|
title: starGift.title,
|
||||||
|
slug: starGift.slug,
|
||||||
|
patternFileId: starGift.patternFileId,
|
||||||
|
innerColor: starGift.innerColor,
|
||||||
|
outerColor: starGift.outerColor,
|
||||||
|
patternColor: starGift.patternColor,
|
||||||
|
textColor: starGift.textColor
|
||||||
|
)
|
||||||
|
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_PeerEmojiStatusContent_Value
|
||||||
|
let valueOffset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case let .emoji(fileId):
|
||||||
|
valueType = .peeremojistatuscontentemoji
|
||||||
|
let start = TelegramCore_PeerEmojiStatusContentEmoji.startPeerEmojiStatusContentEmoji(&builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentEmoji.add(fileId: fileId, &builder)
|
||||||
|
valueOffset = TelegramCore_PeerEmojiStatusContentEmoji.endPeerEmojiStatusContentEmoji(&builder, start: start)
|
||||||
|
case let .starGift(id, fileId, title, slug, patternFileId, innerColor, outerColor, patternColor, textColor):
|
||||||
|
valueType = .peeremojistatuscontentstargift
|
||||||
|
let titleOffset = builder.create(string: title)
|
||||||
|
let slugOffset = builder.create(string: slug)
|
||||||
|
let start = TelegramCore_PeerEmojiStatusContentStarGift.startPeerEmojiStatusContentStarGift(&builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(id: id, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(fileId: fileId, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(title: titleOffset, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(slug: slugOffset, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(patternFileId: patternFileId, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(innerColor: innerColor, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(outerColor: outerColor, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(patternColor: patternColor, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContentStarGift.add(textColor: textColor, &builder)
|
||||||
|
valueOffset = TelegramCore_PeerEmojiStatusContentStarGift.endPeerEmojiStatusContentStarGift(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = TelegramCore_PeerEmojiStatusContent.startPeerEmojiStatusContent(&builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContent.add(valueType: valueType, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatusContent.add(value: valueOffset, &builder)
|
||||||
|
return TelegramCore_PeerEmojiStatusContent.endPeerEmojiStatusContent(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public var content: Content
|
public var content: Content
|
||||||
public var expirationDate: Int32?
|
public var expirationDate: Int32?
|
||||||
@ -348,6 +422,20 @@ public struct PeerEmojiStatus: Equatable, Codable {
|
|||||||
try container.encode(self.content, forKey: .content)
|
try container.encode(self.content, forKey: .content)
|
||||||
try container.encodeIfPresent(self.expirationDate, forKey: .expirationDate)
|
try container.encodeIfPresent(self.expirationDate, forKey: .expirationDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_PeerEmojiStatus) throws {
|
||||||
|
self.content = try Content(flatBuffersObject: flatBuffersObject.content)
|
||||||
|
self.expirationDate = flatBuffersObject.expirationDate == Int32.min ? nil : flatBuffersObject.expirationDate
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let contentOffset = self.content.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let start = TelegramCore_PeerEmojiStatus.startPeerEmojiStatus(&builder)
|
||||||
|
TelegramCore_PeerEmojiStatus.add(content: contentOffset, &builder)
|
||||||
|
TelegramCore_PeerEmojiStatus.add(expirationDate: self.expirationDate ?? Int32.min, &builder)
|
||||||
|
return TelegramCore_PeerEmojiStatus.endPeerEmojiStatus(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PeerEmojiStatus {
|
extension PeerEmojiStatus {
|
||||||
|
@ -961,7 +961,7 @@ public final class WallpaperDataResource: TelegramMediaResource {
|
|||||||
|
|
||||||
public func TelegramMediaResource_parse(flatBuffersData data: Data) throws -> TelegramMediaResource {
|
public func TelegramMediaResource_parse(flatBuffersData data: Data) throws -> TelegramMediaResource {
|
||||||
var byteBuffer = ByteBuffer(data: data)
|
var byteBuffer = ByteBuffer(data: data)
|
||||||
let flatBuffersObject: TelegramCore_TelegramMediaResource = getRoot(byteBuffer: &byteBuffer)
|
let flatBuffersObject: TelegramCore_TelegramMediaResource = FlatBuffers_getRoot(byteBuffer: &byteBuffer)
|
||||||
|
|
||||||
return try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject)
|
return try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject)
|
||||||
}
|
}
|
||||||
@ -970,7 +970,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
switch flatBuffersObject.valueType {
|
switch flatBuffersObject.valueType {
|
||||||
case .telegrammediaresourceCloudfilemediaresource:
|
case .telegrammediaresourceCloudfilemediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudFileMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudFileMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return CloudFileMediaResource(
|
return CloudFileMediaResource(
|
||||||
datacenterId: Int(value.datacenterId),
|
datacenterId: Int(value.datacenterId),
|
||||||
@ -982,7 +982,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceClouddocumentsizemediaresource:
|
case .telegrammediaresourceClouddocumentsizemediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return CloudDocumentSizeMediaResource(
|
return CloudDocumentSizeMediaResource(
|
||||||
datacenterId: value.datacenterId,
|
datacenterId: value.datacenterId,
|
||||||
@ -993,7 +993,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceCloudphotosizemediaresource:
|
case .telegrammediaresourceCloudphotosizemediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return CloudPhotoSizeMediaResource(
|
return CloudPhotoSizeMediaResource(
|
||||||
datacenterId: value.datacenterId,
|
datacenterId: value.datacenterId,
|
||||||
@ -1005,7 +1005,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceCloudpeerphotosizemediaresource:
|
case .telegrammediaresourceCloudpeerphotosizemediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudPeerPhotoSizeMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
let sizeSpec: CloudPeerPhotoSizeSpec
|
let sizeSpec: CloudPeerPhotoSizeSpec
|
||||||
switch value.sizeSpec {
|
switch value.sizeSpec {
|
||||||
@ -1023,7 +1023,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceCloudstickerpackthumbnailmediaresource:
|
case .telegrammediaresourceCloudstickerpackthumbnailmediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudStickerPackThumbnailMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return CloudStickerPackThumbnailMediaResource(
|
return CloudStickerPackThumbnailMediaResource(
|
||||||
datacenterId: value.datacenterId,
|
datacenterId: value.datacenterId,
|
||||||
@ -1033,7 +1033,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceClouddocumentmediaresource:
|
case .telegrammediaresourceClouddocumentmediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_CloudDocumentMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return CloudDocumentMediaResource(
|
return CloudDocumentMediaResource(
|
||||||
datacenterId: Int(value.datacenterId),
|
datacenterId: Int(value.datacenterId),
|
||||||
@ -1045,7 +1045,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
)
|
)
|
||||||
case .telegrammediaresourceLocalfilemediaresource:
|
case .telegrammediaresourceLocalfilemediaresource:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_LocalFileMediaResource.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaResource_LocalFileMediaResource.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
return LocalFileMediaResource(
|
return LocalFileMediaResource(
|
||||||
fileId: value.fileId,
|
fileId: value.fileId,
|
||||||
@ -1053,7 +1053,7 @@ public func TelegramMediaResource_parse(flatBuffersObject: TelegramCore_Telegram
|
|||||||
isSecretRelated: value.isSecretRelated
|
isSecretRelated: value.isSecretRelated
|
||||||
)
|
)
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,9 +1094,10 @@ public func TelegramMediaResource_serialize(resource: TelegramMediaResource, fla
|
|||||||
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceClouddocumentsizemediaresource, valueOffset: offset)
|
return TelegramCore_TelegramMediaResource.createTelegramMediaResource(&builder, valueType: .telegrammediaresourceClouddocumentsizemediaresource, valueOffset: offset)
|
||||||
case let resource as CloudPhotoSizeMediaResource:
|
case let resource as CloudPhotoSizeMediaResource:
|
||||||
let sizeSpecOffset = builder.create(string: resource.sizeSpec)
|
let sizeSpecOffset = builder.create(string: resource.sizeSpec)
|
||||||
let start = TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.startTelegramMediaResource_CloudPhotoSizeMediaResource(&builder)
|
|
||||||
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
|
let fileReferenceOffset = resource.fileReference.flatMap { builder.createVector(bytes: $0) }
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.startTelegramMediaResource_CloudPhotoSizeMediaResource(&builder)
|
||||||
|
|
||||||
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
|
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(datacenterId: Int32(resource.datacenterId), &builder)
|
||||||
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(photoId: resource.photoId, &builder)
|
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(photoId: resource.photoId, &builder)
|
||||||
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(accessHash: resource.accessHash, &builder)
|
TelegramCore_TelegramMediaResource_CloudPhotoSizeMediaResource.add(accessHash: resource.accessHash, &builder)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import Foundation
|
||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
private enum InstantPageBlockType: Int32 {
|
private enum InstantPageBlockType: Int32 {
|
||||||
case unsupported = 0
|
case unsupported = 0
|
||||||
@ -512,6 +515,395 @@ public indirect enum InstantPageBlock: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageBlock) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .instantpageblockUnsupported:
|
||||||
|
self = .unsupported
|
||||||
|
case .instantpageblockTitle:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Title.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .title(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockSubtitle:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Subtitle.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .subtitle(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockAuthordate:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_AuthorDate.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .authorDate(author: try RichText(flatBuffersObject: value.author), date: value.date)
|
||||||
|
case .instantpageblockHeader:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Header.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .header(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockSubheader:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Subheader.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .subheader(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockParagraph:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Paragraph.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .paragraph(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockPreformatted:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Preformatted.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .preformatted(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockFooter:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Footer.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .footer(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockDivider:
|
||||||
|
self = .divider
|
||||||
|
case .instantpageblockAnchor:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Anchor.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .anchor(value.name)
|
||||||
|
case .instantpageblockList:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_List.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .list(items: try (0 ..< value.itemsCount).map { try InstantPageListItem(flatBuffersObject: value.items(at: $0)!) }, ordered: value.ordered)
|
||||||
|
case .instantpageblockBlockquote:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_BlockQuote.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .blockQuote(text: try RichText(flatBuffersObject: value.text), caption: try RichText(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockPullquote:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_PullQuote.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .pullQuote(text: try RichText(flatBuffersObject: value.text), caption: try RichText(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockImage:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Image.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .image(id: MediaId(value.id), caption: try InstantPageCaption(flatBuffersObject: value.caption), url: value.url, webpageId: value.webpageId.flatMap(MediaId.init))
|
||||||
|
case .instantpageblockVideo:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Video.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .video(id: MediaId(value.id), caption: try InstantPageCaption(flatBuffersObject: value.caption), autoplay: value.autoplay, loop: value.loop)
|
||||||
|
case .instantpageblockAudio:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Audio.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .audio(id: MediaId(value.id), caption: try InstantPageCaption(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockCover:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Cover.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .cover(try InstantPageBlock(flatBuffersObject: value.block))
|
||||||
|
case .instantpageblockWebembed:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_WebEmbed.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .webEmbed(url: value.url, html: value.html, dimensions: value.dimensions.flatMap(PixelDimensions.init), caption: try InstantPageCaption(flatBuffersObject: value.caption), stretchToWidth: value.stretchToWidth, allowScrolling: value.allowScrolling, coverId: value.coverId.flatMap(MediaId.init))
|
||||||
|
case .instantpageblockPostembed:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_PostEmbed.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .postEmbed(url: value.url, webpageId: value.webpageId.flatMap(MediaId.init), avatarId: value.avatarId.flatMap(MediaId.init), author: value.author, date: value.date, blocks: try (0 ..< value.blocksCount).map { try InstantPageBlock(flatBuffersObject: value.blocks(at: $0)!) }, caption: try InstantPageCaption(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockCollage:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Collage.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .collage(items: try (0 ..< value.itemsCount).map { try InstantPageBlock(flatBuffersObject: value.items(at: $0)!) }, caption: try InstantPageCaption(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockSlideshow:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Slideshow.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .slideshow(items: try (0 ..< value.itemsCount).map { try InstantPageBlock(flatBuffersObject: value.items(at: $0)!) }, caption: try InstantPageCaption(flatBuffersObject: value.caption))
|
||||||
|
case .instantpageblockChannelbanner:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_ChannelBanner.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
let channel = try value.channel.flatMap { try TelegramChannel(flatBuffersObject: $0) }
|
||||||
|
self = .channelBanner(channel)
|
||||||
|
case .instantpageblockKicker:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Kicker.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .kicker(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .instantpageblockTable:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Table.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .table(title: try RichText(flatBuffersObject: value.title), rows: try (0 ..< value.rowsCount).map { try InstantPageTableRow(flatBuffersObject: value.rows(at: $0)!) }, bordered: value.bordered, striped: value.striped)
|
||||||
|
case .instantpageblockDetails:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Details.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .details(title: try RichText(flatBuffersObject: value.title), blocks: try (0 ..< value.blocksCount).map { try InstantPageBlock(flatBuffersObject: value.blocks(at: $0)!) }, expanded: value.expanded)
|
||||||
|
case .instantpageblockRelatedarticles:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_RelatedArticles.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .relatedArticles(title: try RichText(flatBuffersObject: value.title), articles: try (0 ..< value.articlesCount).map { try InstantPageRelatedArticle(flatBuffersObject: value.articles(at: $0)!) })
|
||||||
|
case .instantpageblockMap:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_InstantPageBlock_Map.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .map(latitude: value.latitude, longitude: value.longitude, zoom: value.zoom, dimensions: PixelDimensions(value.dimensions), caption: try InstantPageCaption(flatBuffersObject: value.caption))
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_InstantPageBlock_Value
|
||||||
|
let offset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case .unsupported:
|
||||||
|
valueType = .instantpageblockUnsupported
|
||||||
|
let start = TelegramCore_InstantPageBlock_Unsupported.startInstantPageBlock_Unsupported(&builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Unsupported.endInstantPageBlock_Unsupported(&builder, start: start)
|
||||||
|
case let .title(text):
|
||||||
|
valueType = .instantpageblockTitle
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Title.startInstantPageBlock_Title(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Title.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Title.endInstantPageBlock_Title(&builder, start: start)
|
||||||
|
case let .subtitle(text):
|
||||||
|
valueType = .instantpageblockSubtitle
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Subtitle.startInstantPageBlock_Subtitle(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Subtitle.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Subtitle.endInstantPageBlock_Subtitle(&builder, start: start)
|
||||||
|
case let .authorDate(author, date):
|
||||||
|
valueType = .instantpageblockAuthordate
|
||||||
|
let authorOffset = author.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_AuthorDate.startInstantPageBlock_AuthorDate(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_AuthorDate.add(author: authorOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_AuthorDate.add(date: date, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_AuthorDate.endInstantPageBlock_AuthorDate(&builder, start: start)
|
||||||
|
case let .header(text):
|
||||||
|
valueType = .instantpageblockHeader
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Header.startInstantPageBlock_Header(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Header.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Header.endInstantPageBlock_Header(&builder, start: start)
|
||||||
|
case let .subheader(text):
|
||||||
|
valueType = .instantpageblockSubheader
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Subheader.startInstantPageBlock_Subheader(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Subheader.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Subheader.endInstantPageBlock_Subheader(&builder, start: start)
|
||||||
|
case let .paragraph(text):
|
||||||
|
valueType = .instantpageblockParagraph
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Paragraph.startInstantPageBlock_Paragraph(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Paragraph.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Paragraph.endInstantPageBlock_Paragraph(&builder, start: start)
|
||||||
|
case let .preformatted(text):
|
||||||
|
valueType = .instantpageblockPreformatted
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Preformatted.startInstantPageBlock_Preformatted(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Preformatted.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Preformatted.endInstantPageBlock_Preformatted(&builder, start: start)
|
||||||
|
case let .footer(text):
|
||||||
|
valueType = .instantpageblockFooter
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Footer.startInstantPageBlock_Footer(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Footer.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Footer.endInstantPageBlock_Footer(&builder, start: start)
|
||||||
|
case .divider:
|
||||||
|
valueType = .instantpageblockDivider
|
||||||
|
let start = TelegramCore_InstantPageBlock_Divider.startInstantPageBlock_Divider(&builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Divider.endInstantPageBlock_Divider(&builder, start: start)
|
||||||
|
case let .anchor(name):
|
||||||
|
valueType = .instantpageblockAnchor
|
||||||
|
let nameOffset = builder.create(string: name)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Anchor.startInstantPageBlock_Anchor(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Anchor.add(name: nameOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Anchor.endInstantPageBlock_Anchor(&builder, start: start)
|
||||||
|
case let .list(items, ordered):
|
||||||
|
valueType = .instantpageblockList
|
||||||
|
let itemsOffsets = items.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let itemsOffset = builder.createVector(ofOffsets: itemsOffsets, len: itemsOffsets.count)
|
||||||
|
let start = TelegramCore_InstantPageBlock_List.startInstantPageBlock_List(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_List.addVectorOf(items: itemsOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_List.add(ordered: ordered, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_List.endInstantPageBlock_List(&builder, start: start)
|
||||||
|
case let .blockQuote(text, caption):
|
||||||
|
valueType = .instantpageblockBlockquote
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_BlockQuote.startInstantPageBlock_BlockQuote(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_BlockQuote.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_BlockQuote.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_BlockQuote.endInstantPageBlock_BlockQuote(&builder, start: start)
|
||||||
|
case let .pullQuote(text, caption):
|
||||||
|
valueType = .instantpageblockPullquote
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_PullQuote.startInstantPageBlock_PullQuote(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_PullQuote.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_PullQuote.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_PullQuote.endInstantPageBlock_PullQuote(&builder, start: start)
|
||||||
|
case let .image(id, caption, url, webpageId):
|
||||||
|
valueType = .instantpageblockImage
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let urlOffset = url.flatMap { builder.create(string: $0) }
|
||||||
|
let start = TelegramCore_InstantPageBlock_Image.startInstantPageBlock_Image(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Image.add(id: id.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Image.add(caption: captionOffset, &builder)
|
||||||
|
if let urlOffset {
|
||||||
|
TelegramCore_InstantPageBlock_Image.add(url: urlOffset, &builder)
|
||||||
|
}
|
||||||
|
if let webpageId {
|
||||||
|
TelegramCore_InstantPageBlock_Image.add(webpageId: webpageId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_InstantPageBlock_Image.endInstantPageBlock_Image(&builder, start: start)
|
||||||
|
case let .video(id, caption, autoplay, loop):
|
||||||
|
valueType = .instantpageblockVideo
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Video.startInstantPageBlock_Video(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Video.add(id: id.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Video.add(caption: captionOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Video.add(autoplay: autoplay, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Video.add(loop: loop, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Video.endInstantPageBlock_Video(&builder, start: start)
|
||||||
|
case let .audio(id, caption):
|
||||||
|
valueType = .instantpageblockAudio
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Audio.startInstantPageBlock_Audio(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Audio.add(id: id.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Audio.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Audio.endInstantPageBlock_Audio(&builder, start: start)
|
||||||
|
case let .cover(block):
|
||||||
|
valueType = .instantpageblockCover
|
||||||
|
let blockOffset = block.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Cover.startInstantPageBlock_Cover(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Cover.add(block: blockOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Cover.endInstantPageBlock_Cover(&builder, start: start)
|
||||||
|
case let .webEmbed(url, html, dimensions, caption, stretchToWidth, allowScrolling, coverId):
|
||||||
|
valueType = .instantpageblockWebembed
|
||||||
|
let urlOffset = url.flatMap { builder.create(string: $0) }
|
||||||
|
let htmlOffset = html.flatMap { builder.create(string: $0) }
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_WebEmbed.startInstantPageBlock_WebEmbed(&builder)
|
||||||
|
if let urlOffset {
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(url: urlOffset, &builder)
|
||||||
|
}
|
||||||
|
if let htmlOffset {
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(html: htmlOffset, &builder)
|
||||||
|
}
|
||||||
|
if let dimensions {
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(dimensions: dimensions.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(caption: captionOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(stretchToWidth: stretchToWidth, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(allowScrolling: allowScrolling, &builder)
|
||||||
|
if let coverId {
|
||||||
|
TelegramCore_InstantPageBlock_WebEmbed.add(coverId: coverId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_InstantPageBlock_WebEmbed.endInstantPageBlock_WebEmbed(&builder, start: start)
|
||||||
|
case let .postEmbed(url, webpageId, avatarId, author, date, blocks, caption):
|
||||||
|
valueType = .instantpageblockPostembed
|
||||||
|
let urlOffset = builder.create(string: url)
|
||||||
|
let authorOffset = builder.create(string: author)
|
||||||
|
let blocksOffsets = blocks.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let blocksOffset = builder.createVector(ofOffsets: blocksOffsets, len: blocksOffsets.count)
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_PostEmbed.startInstantPageBlock_PostEmbed(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(url: urlOffset, &builder)
|
||||||
|
if let webpageId {
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(webpageId: webpageId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
if let avatarId {
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(avatarId: avatarId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(author: authorOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(date: date, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.addVectorOf(blocks: blocksOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_PostEmbed.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_PostEmbed.endInstantPageBlock_PostEmbed(&builder, start: start)
|
||||||
|
case let .collage(items, caption):
|
||||||
|
valueType = .instantpageblockCollage
|
||||||
|
let itemsOffsets = items.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let itemsOffset = builder.createVector(ofOffsets: itemsOffsets, len: itemsOffsets.count)
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Collage.startInstantPageBlock_Collage(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Collage.addVectorOf(items: itemsOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Collage.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Collage.endInstantPageBlock_Collage(&builder, start: start)
|
||||||
|
case let .slideshow(items, caption):
|
||||||
|
valueType = .instantpageblockSlideshow
|
||||||
|
let itemsOffsets = items.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let itemsOffset = builder.createVector(ofOffsets: itemsOffsets, len: itemsOffsets.count)
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Slideshow.startInstantPageBlock_Slideshow(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Slideshow.addVectorOf(items: itemsOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Slideshow.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Slideshow.endInstantPageBlock_Slideshow(&builder, start: start)
|
||||||
|
case let .channelBanner(channel):
|
||||||
|
valueType = .instantpageblockChannelbanner
|
||||||
|
let channelOffset = channel.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let start = TelegramCore_InstantPageBlock_ChannelBanner.startInstantPageBlock_ChannelBanner(&builder)
|
||||||
|
if let channelOffset {
|
||||||
|
TelegramCore_InstantPageBlock_ChannelBanner.add(channel: channelOffset, &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_InstantPageBlock_ChannelBanner.endInstantPageBlock_ChannelBanner(&builder, start: start)
|
||||||
|
case let .kicker(text):
|
||||||
|
valueType = .instantpageblockKicker
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Kicker.startInstantPageBlock_Kicker(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Kicker.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Kicker.endInstantPageBlock_Kicker(&builder, start: start)
|
||||||
|
case let .table(title, rows, bordered, striped):
|
||||||
|
valueType = .instantpageblockTable
|
||||||
|
let titleOffset = title.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let rowsOffsets = rows.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let rowsOffset = builder.createVector(ofOffsets: rowsOffsets, len: rowsOffsets.count)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Table.startInstantPageBlock_Table(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Table.add(title: titleOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Table.addVectorOf(rows: rowsOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Table.add(bordered: bordered, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Table.add(striped: striped, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Table.endInstantPageBlock_Table(&builder, start: start)
|
||||||
|
case let .details(title, blocks, expanded):
|
||||||
|
valueType = .instantpageblockDetails
|
||||||
|
let titleOffset = title.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let blocksOffsets = blocks.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let blocksOffset = builder.createVector(ofOffsets: blocksOffsets, len: blocksOffsets.count)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Details.startInstantPageBlock_Details(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Details.add(title: titleOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Details.addVectorOf(blocks: blocksOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Details.add(expanded: expanded, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Details.endInstantPageBlock_Details(&builder, start: start)
|
||||||
|
case let .relatedArticles(title, articles):
|
||||||
|
valueType = .instantpageblockRelatedarticles
|
||||||
|
let titleOffset = title.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let articlesOffsets = articles.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let articlesOffset = builder.createVector(ofOffsets: articlesOffsets, len: articlesOffsets.count)
|
||||||
|
let start = TelegramCore_InstantPageBlock_RelatedArticles.startInstantPageBlock_RelatedArticles(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_RelatedArticles.add(title: titleOffset, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_RelatedArticles.addVectorOf(articles: articlesOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_RelatedArticles.endInstantPageBlock_RelatedArticles(&builder, start: start)
|
||||||
|
case let .map(latitude, longitude, zoom, dimensions, caption):
|
||||||
|
valueType = .instantpageblockMap
|
||||||
|
let captionOffset = caption.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageBlock_Map.startInstantPageBlock_Map(&builder)
|
||||||
|
TelegramCore_InstantPageBlock_Map.add(latitude: latitude, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Map.add(longitude: longitude, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Map.add(zoom: zoom, &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Map.add(dimensions: dimensions.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_InstantPageBlock_Map.add(caption: captionOffset, &builder)
|
||||||
|
offset = TelegramCore_InstantPageBlock_Map.endInstantPageBlock_Map(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TelegramCore_InstantPageBlock.createInstantPageBlock(&builder, valueType: valueType, valueOffset: offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class InstantPageCaption: PostboxCoding, Equatable {
|
public final class InstantPageCaption: PostboxCoding, Equatable {
|
||||||
@ -542,6 +934,21 @@ public final class InstantPageCaption: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageCaption) throws {
|
||||||
|
self.text = try RichText(flatBuffersObject: flatBuffersObject.text)
|
||||||
|
self.credit = try RichText(flatBuffersObject: flatBuffersObject.credit)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let textOffset = self.text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let creditOffset = self.credit.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_InstantPageCaption.startInstantPageCaption(&builder)
|
||||||
|
TelegramCore_InstantPageCaption.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_InstantPageCaption.add(credit: creditOffset, &builder)
|
||||||
|
let offset = TelegramCore_InstantPageCaption.endInstantPageCaption(&builder, start: start)
|
||||||
|
return offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum InstantPageListItemType: Int32 {
|
private enum InstantPageListItemType: Int32 {
|
||||||
@ -611,6 +1018,69 @@ public indirect enum InstantPageListItem: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageListItem) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .instantpagelistitemText:
|
||||||
|
guard let textValue = flatBuffersObject.value(type: TelegramCore_InstantPageListItem_Text.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .text(try RichText(flatBuffersObject: textValue.text), textValue.number)
|
||||||
|
|
||||||
|
case .instantpagelistitemBlocks:
|
||||||
|
guard let blocksValue = flatBuffersObject.value(type: TelegramCore_InstantPageListItem_Blocks.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
let blocks = try (0 ..< blocksValue.blocksCount).map { i in
|
||||||
|
return try InstantPageBlock(flatBuffersObject: blocksValue.blocks(at: i)!)
|
||||||
|
}
|
||||||
|
self = .blocks(blocks, blocksValue.number)
|
||||||
|
case .instantpagelistitemUnknown:
|
||||||
|
self = .unknown
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_InstantPageListItem_Value
|
||||||
|
let offset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case let .text(text, number):
|
||||||
|
valueType = .instantpagelistitemText
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let numberOffset = number.map { builder.create(string: $0) } ?? Offset()
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageListItem_Text.startInstantPageListItem_Text(&builder)
|
||||||
|
TelegramCore_InstantPageListItem_Text.add(text: textOffset, &builder)
|
||||||
|
if let _ = number {
|
||||||
|
TelegramCore_InstantPageListItem_Text.add(number: numberOffset, &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_InstantPageListItem_Text.endInstantPageListItem_Text(&builder, start: start)
|
||||||
|
case let .blocks(blocks, number):
|
||||||
|
valueType = .instantpagelistitemBlocks
|
||||||
|
let blocksOffsets = blocks.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let blocksOffset = builder.createVector(ofOffsets: blocksOffsets, len: blocksOffsets.count)
|
||||||
|
let numberOffset = number.map { builder.create(string: $0) } ?? Offset()
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageListItem_Blocks.startInstantPageListItem_Blocks(&builder)
|
||||||
|
TelegramCore_InstantPageListItem_Blocks.addVectorOf(blocks: blocksOffset, &builder)
|
||||||
|
if let _ = number {
|
||||||
|
TelegramCore_InstantPageListItem_Blocks.add(number: numberOffset, &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_InstantPageListItem_Blocks.endInstantPageListItem_Blocks(&builder, start: start)
|
||||||
|
case .unknown:
|
||||||
|
valueType = .instantpagelistitemUnknown
|
||||||
|
let start = TelegramCore_InstantPageListItem_Unknown.startInstantPageListItem_Unknown(&builder)
|
||||||
|
offset = TelegramCore_InstantPageListItem_Unknown.endInstantPageListItem_Unknown(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageListItem.startInstantPageListItem(&builder)
|
||||||
|
TelegramCore_InstantPageListItem.add(valueType: valueType, &builder)
|
||||||
|
TelegramCore_InstantPageListItem.add(value: offset, &builder)
|
||||||
|
return TelegramCore_InstantPageListItem.endInstantPageListItem(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TableHorizontalAlignment: Int32 {
|
public enum TableHorizontalAlignment: Int32 {
|
||||||
@ -685,6 +1155,30 @@ public final class InstantPageTableCell: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageTableCell) throws {
|
||||||
|
self.text = try flatBuffersObject.text.map { try RichText(flatBuffersObject: $0) }
|
||||||
|
self.header = flatBuffersObject.header
|
||||||
|
self.alignment = TableHorizontalAlignment(rawValue: flatBuffersObject.alignment) ?? .left
|
||||||
|
self.verticalAlignment = TableVerticalAlignment(rawValue: flatBuffersObject.verticalAlignment) ?? .top
|
||||||
|
self.colspan = flatBuffersObject.colspan
|
||||||
|
self.rowspan = flatBuffersObject.rowspan
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let textOffset = text.map { $0.encodeToFlatBuffers(builder: &builder) } ?? Offset()
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageTableCell.startInstantPageTableCell(&builder)
|
||||||
|
if let _ = text {
|
||||||
|
TelegramCore_InstantPageTableCell.add(text: textOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_InstantPageTableCell.add(header: header, &builder)
|
||||||
|
TelegramCore_InstantPageTableCell.add(alignment: alignment.rawValue, &builder)
|
||||||
|
TelegramCore_InstantPageTableCell.add(verticalAlignment: verticalAlignment.rawValue, &builder)
|
||||||
|
TelegramCore_InstantPageTableCell.add(colspan: colspan, &builder)
|
||||||
|
TelegramCore_InstantPageTableCell.add(rowspan: rowspan, &builder)
|
||||||
|
return TelegramCore_InstantPageTableCell.endInstantPageTableCell(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class InstantPageTableRow: PostboxCoding, Equatable {
|
public final class InstantPageTableRow: PostboxCoding, Equatable {
|
||||||
@ -705,6 +1199,21 @@ public final class InstantPageTableRow: PostboxCoding, Equatable {
|
|||||||
public static func ==(lhs: InstantPageTableRow, rhs: InstantPageTableRow) -> Bool {
|
public static func ==(lhs: InstantPageTableRow, rhs: InstantPageTableRow) -> Bool {
|
||||||
return lhs.cells == rhs.cells
|
return lhs.cells == rhs.cells
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageTableRow) throws {
|
||||||
|
self.cells = try (0 ..< flatBuffersObject.cellsCount).map { i in
|
||||||
|
return try InstantPageTableCell(flatBuffersObject: flatBuffersObject.cells(at: i)!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let cellsOffsets = cells.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let cellsOffset = builder.createVector(ofOffsets: cellsOffsets, len: cellsOffsets.count)
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageTableRow.startInstantPageTableRow(&builder)
|
||||||
|
TelegramCore_InstantPageTableRow.addVectorOf(cells: cellsOffset, &builder)
|
||||||
|
return TelegramCore_InstantPageTableRow.endInstantPageTableRow(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class InstantPageRelatedArticle: PostboxCoding, Equatable {
|
public final class InstantPageRelatedArticle: PostboxCoding, Equatable {
|
||||||
@ -801,6 +1310,45 @@ public final class InstantPageRelatedArticle: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPageRelatedArticle) throws {
|
||||||
|
self.url = flatBuffersObject.url
|
||||||
|
self.webpageId = MediaId(flatBuffersObject.webpageId)
|
||||||
|
self.title = flatBuffersObject.title
|
||||||
|
self.description = flatBuffersObject.description
|
||||||
|
self.photoId = flatBuffersObject.photoId.flatMap(MediaId.init)
|
||||||
|
self.author = flatBuffersObject.author
|
||||||
|
self.date = flatBuffersObject.date == Int32.min ? nil : flatBuffersObject.date
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let urlOffset = builder.create(string: url)
|
||||||
|
let titleOffset = title.map { builder.create(string: $0) }
|
||||||
|
let descriptionOffset = description.map { builder.create(string: $0) }
|
||||||
|
let authorOffset = author.map { builder.create(string: $0) }
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPageRelatedArticle.startInstantPageRelatedArticle(&builder)
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(url: urlOffset, &builder)
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(webpageId: webpageId.asFlatBuffersObject(), &builder)
|
||||||
|
if let titleOffset {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(title: titleOffset, &builder)
|
||||||
|
}
|
||||||
|
if let descriptionOffset {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(description: descriptionOffset, &builder)
|
||||||
|
}
|
||||||
|
if let photoId {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(photoId: photoId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
if let authorOffset {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(author: authorOffset, &builder)
|
||||||
|
}
|
||||||
|
if let date {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(date: date, &builder)
|
||||||
|
} else {
|
||||||
|
TelegramCore_InstantPageRelatedArticle.add(date: Int32.min, &builder)
|
||||||
|
}
|
||||||
|
return TelegramCore_InstantPageRelatedArticle.endInstantPageRelatedArticle(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class MediaDictionary: PostboxCoding {
|
private final class MediaDictionary: PostboxCoding {
|
||||||
@ -862,6 +1410,17 @@ public final class InstantPage: PostboxCoding, Equatable {
|
|||||||
self.rtl = decoder.decodeInt32ForKey("r", orElse: 0) != 0
|
self.rtl = decoder.decodeInt32ForKey("r", orElse: 0) != 0
|
||||||
self.url = decoder.decodeStringForKey("url", orElse: "")
|
self.url = decoder.decodeStringForKey("url", orElse: "")
|
||||||
self.views = decoder.decodeOptionalInt32ForKey("v")
|
self.views = decoder.decodeOptionalInt32ForKey("v")
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
var builder = FlatBufferBuilder(initialSize: 1024)
|
||||||
|
let offset = self.encodeToFlatBuffers(builder: &builder)
|
||||||
|
builder.finish(offset: offset)
|
||||||
|
let serializedData = builder.data
|
||||||
|
var byteBuffer = ByteBuffer(data: serializedData)
|
||||||
|
let deserializedValue = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_InstantPage
|
||||||
|
let parsedValue = try! InstantPage(flatBuffersObject: deserializedValue)
|
||||||
|
assert(self == parsedValue)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@ -908,4 +1467,119 @@ public final class InstantPage: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_InstantPage) throws {
|
||||||
|
self.blocks = try (0 ..< flatBuffersObject.blocksCount).map { i in
|
||||||
|
return try InstantPageBlock(flatBuffersObject: flatBuffersObject.blocks(at: i)!)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:release support other media types
|
||||||
|
var media: [MediaId: Media] = [:]
|
||||||
|
for i in 0 ..< flatBuffersObject.mediaCount {
|
||||||
|
let mediaItem = flatBuffersObject.media(at: i)!
|
||||||
|
switch mediaItem.valueType {
|
||||||
|
case .mediaTelegrammediafile:
|
||||||
|
guard let value = mediaItem.value(type: TelegramCore_Media_TelegramMediaFile.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
let parsedMedia = try TelegramMediaFile(flatBuffersObject: value.file)
|
||||||
|
media[parsedMedia.fileId] = parsedMedia
|
||||||
|
case .mediaTelegrammediaimage:
|
||||||
|
guard let value = mediaItem.value(type: TelegramCore_Media_TelegramMediaImage.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
let parsedMedia = try TelegramMediaImage(flatBuffersObject: value.image)
|
||||||
|
media[parsedMedia.imageId] = parsedMedia
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.media = media
|
||||||
|
|
||||||
|
self.isComplete = flatBuffersObject.isComplete
|
||||||
|
self.rtl = flatBuffersObject.rtl
|
||||||
|
self.url = flatBuffersObject.url
|
||||||
|
self.views = flatBuffersObject.views == Int32.min ? nil : flatBuffersObject.views
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let blocksOffsets = self.blocks.map { block in
|
||||||
|
return block.encodeToFlatBuffers(builder: &builder)
|
||||||
|
}
|
||||||
|
let blocksOffset = builder.createVector(ofOffsets: blocksOffsets, len: blocksOffsets.count)
|
||||||
|
|
||||||
|
var mediaOffsets: [Offset] = []
|
||||||
|
for (_, media) in self.media.sorted(by: { $0.key < $1.key }) {
|
||||||
|
switch media {
|
||||||
|
case let file as TelegramMediaFile:
|
||||||
|
let fileOffset = file.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_Media_TelegramMediaFile.startMedia_TelegramMediaFile(&builder)
|
||||||
|
TelegramCore_Media_TelegramMediaFile.add(file: fileOffset, &builder)
|
||||||
|
let offset = TelegramCore_Media_TelegramMediaFile.endMedia_TelegramMediaFile(&builder, start: start)
|
||||||
|
mediaOffsets.append(TelegramCore_Media.createMedia(&builder, valueType: .mediaTelegrammediafile, valueOffset: offset))
|
||||||
|
case let image as TelegramMediaImage:
|
||||||
|
let imageOffset = image.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_Media_TelegramMediaImage.startMedia_TelegramMediaImage(&builder)
|
||||||
|
TelegramCore_Media_TelegramMediaImage.add(image: imageOffset, &builder)
|
||||||
|
let offset = TelegramCore_Media_TelegramMediaImage.endMedia_TelegramMediaImage(&builder, start: start)
|
||||||
|
mediaOffsets.append(TelegramCore_Media.createMedia(&builder, valueType: .mediaTelegrammediaimage, valueOffset: offset))
|
||||||
|
default:
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mediaOffset = builder.createVector(ofOffsets: mediaOffsets, len: mediaOffsets.count)
|
||||||
|
|
||||||
|
let urlOffset = builder.create(string: self.url)
|
||||||
|
|
||||||
|
let start = TelegramCore_InstantPage.startInstantPage(&builder)
|
||||||
|
|
||||||
|
TelegramCore_InstantPage.addVectorOf(blocks: blocksOffset, &builder)
|
||||||
|
TelegramCore_InstantPage.addVectorOf(media: mediaOffset, &builder)
|
||||||
|
TelegramCore_InstantPage.add(isComplete: self.isComplete, &builder)
|
||||||
|
TelegramCore_InstantPage.add(rtl: self.rtl, &builder)
|
||||||
|
TelegramCore_InstantPage.add(url: urlOffset, &builder)
|
||||||
|
TelegramCore_InstantPage.add(views: self.views ?? Int32.min, &builder)
|
||||||
|
|
||||||
|
return TelegramCore_InstantPage.endInstantPage(&builder, start: start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension InstantPage {
|
||||||
|
struct Accessor: Equatable {
|
||||||
|
let _wrappedInstantPage: InstantPage?
|
||||||
|
let _wrapped: TelegramCore_InstantPage?
|
||||||
|
let _wrappedData: Data?
|
||||||
|
|
||||||
|
public init(_ wrapped: TelegramCore_InstantPage, _ _wrappedData: Data) {
|
||||||
|
self._wrapped = wrapped
|
||||||
|
self._wrappedData = _wrappedData
|
||||||
|
self._wrappedInstantPage = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ wrapped: InstantPage) {
|
||||||
|
self._wrapped = nil
|
||||||
|
self._wrappedData = nil
|
||||||
|
self._wrappedInstantPage = wrapped
|
||||||
|
}
|
||||||
|
|
||||||
|
public func _parse() -> InstantPage {
|
||||||
|
if let _wrappedInstantPage = self._wrappedInstantPage {
|
||||||
|
return _wrappedInstantPage
|
||||||
|
} else {
|
||||||
|
return try! InstantPage(flatBuffersObject: self._wrapped!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: InstantPage.Accessor, rhs: InstantPage.Accessor) -> Bool {
|
||||||
|
if let lhsWrappedInstantPage = lhs._wrappedInstantPage, let rhsWrappedInstantPage = rhs._wrappedInstantPage {
|
||||||
|
return lhsWrappedInstantPage === rhsWrappedInstantPage
|
||||||
|
} else if let lhsWrappedData = lhs._wrappedData, let rhsWrappedData = rhs._wrappedData {
|
||||||
|
return lhsWrappedData == rhsWrappedData
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
return lhs._parse() == rhs._parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public extension PartialMediaReference {
|
|||||||
switch flatBuffersObject.valueType {
|
switch flatBuffersObject.valueType {
|
||||||
case .partialmediareferenceMessage:
|
case .partialmediareferenceMessage:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_Message.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_Message.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
if let message = value.message {
|
if let message = value.message {
|
||||||
self = .message(message: try MessageReference(flatBuffersObject: message))
|
self = .message(message: try MessageReference(flatBuffersObject: message))
|
||||||
@ -88,7 +88,7 @@ public extension PartialMediaReference {
|
|||||||
}
|
}
|
||||||
case .partialmediareferenceWebpage:
|
case .partialmediareferenceWebpage:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_WebPage.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_WebPage.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
if let webPage = value.webPage {
|
if let webPage = value.webPage {
|
||||||
self = .webPage(webPage: try WebpageReference(flatBuffersObject: webPage))
|
self = .webPage(webPage: try WebpageReference(flatBuffersObject: webPage))
|
||||||
@ -97,7 +97,7 @@ public extension PartialMediaReference {
|
|||||||
}
|
}
|
||||||
case .partialmediareferenceStickerpack:
|
case .partialmediareferenceStickerpack:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_StickerPack.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PartialMediaReference_StickerPack.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .stickerPack(stickerPack: try StickerPackReference(flatBuffersObject: value.stickerPack))
|
self = .stickerPack(stickerPack: try StickerPackReference(flatBuffersObject: value.stickerPack))
|
||||||
case .partialmediareferenceSavedgif:
|
case .partialmediareferenceSavedgif:
|
||||||
@ -107,7 +107,7 @@ public extension PartialMediaReference {
|
|||||||
case .partialmediareferenceRecentsticker:
|
case .partialmediareferenceRecentsticker:
|
||||||
self = .recentSticker
|
self = .recentSticker
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public enum TelegramPeerAccessHash: Hashable {
|
public enum TelegramPeerAccessHash: Hashable {
|
||||||
case personal(Int64)
|
case personal(Int64)
|
||||||
@ -12,4 +14,44 @@ public enum TelegramPeerAccessHash: Hashable {
|
|||||||
return genericPublic
|
return genericPublic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramPeerAccessHash) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .telegrampeeraccesshashPersonal:
|
||||||
|
guard let personal = flatBuffersObject.value(type: TelegramCore_TelegramPeerAccessHash_Personal.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .personal(personal.accessHash)
|
||||||
|
case .telegrampeeraccesshashGenericpublic:
|
||||||
|
guard let genericPublic = flatBuffersObject.value(type: TelegramCore_TelegramPeerAccessHash_GenericPublic.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .genericPublic(genericPublic.accessHash)
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_TelegramPeerAccessHash_Value
|
||||||
|
let valueOffset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case let .personal(accessHash):
|
||||||
|
valueType = .telegrampeeraccesshashPersonal
|
||||||
|
let start = TelegramCore_TelegramPeerAccessHash_Personal.startTelegramPeerAccessHash_Personal(&builder)
|
||||||
|
TelegramCore_TelegramPeerAccessHash_Personal.add(accessHash: accessHash, &builder)
|
||||||
|
valueOffset = TelegramCore_TelegramPeerAccessHash_Personal.endTelegramPeerAccessHash_Personal(&builder, start: start)
|
||||||
|
case let .genericPublic(accessHash):
|
||||||
|
valueType = .telegrampeeraccesshashGenericpublic
|
||||||
|
let start = TelegramCore_TelegramPeerAccessHash_GenericPublic.startTelegramPeerAccessHash_GenericPublic(&builder)
|
||||||
|
TelegramCore_TelegramPeerAccessHash_GenericPublic.add(accessHash: accessHash, &builder)
|
||||||
|
valueOffset = TelegramCore_TelegramPeerAccessHash_GenericPublic.endTelegramPeerAccessHash_GenericPublic(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramPeerAccessHash.startTelegramPeerAccessHash(&builder)
|
||||||
|
TelegramCore_TelegramPeerAccessHash.add(valueType: valueType, &builder)
|
||||||
|
TelegramCore_TelegramPeerAccessHash.add(value: valueOffset, &builder)
|
||||||
|
return TelegramCore_TelegramPeerAccessHash.endTelegramPeerAccessHash(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public final class RestrictionRule: PostboxCoding, Equatable {
|
public final class RestrictionRule: PostboxCoding, Equatable {
|
||||||
public let platform: String
|
public let platform: String
|
||||||
@ -41,6 +43,24 @@ public final class RestrictionRule: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_RestrictionRule) throws {
|
||||||
|
self.platform = flatBuffersObject.platform
|
||||||
|
self.reason = flatBuffersObject.reason
|
||||||
|
self.text = flatBuffersObject.text
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let platformOffset = builder.create(string: self.platform)
|
||||||
|
let reasonOffset = builder.create(string: self.reason)
|
||||||
|
let textOffset = builder.create(string: self.text)
|
||||||
|
|
||||||
|
let start = TelegramCore_RestrictionRule.startRestrictionRule(&builder)
|
||||||
|
TelegramCore_RestrictionRule.add(platform: platformOffset, &builder)
|
||||||
|
TelegramCore_RestrictionRule.add(reason: reasonOffset, &builder)
|
||||||
|
TelegramCore_RestrictionRule.add(text: textOffset, &builder)
|
||||||
|
return TelegramCore_RestrictionRule.endRestrictionRule(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class PeerAccessRestrictionInfo: PostboxCoding, Equatable {
|
public final class PeerAccessRestrictionInfo: PostboxCoding, Equatable {
|
||||||
@ -65,4 +85,17 @@ public final class PeerAccessRestrictionInfo: PostboxCoding, Equatable {
|
|||||||
public static func ==(lhs: PeerAccessRestrictionInfo, rhs: PeerAccessRestrictionInfo) -> Bool {
|
public static func ==(lhs: PeerAccessRestrictionInfo, rhs: PeerAccessRestrictionInfo) -> Bool {
|
||||||
return lhs.rules == rhs.rules
|
return lhs.rules == rhs.rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_PeerAccessRestrictionInfo) throws {
|
||||||
|
self.rules = try (0 ..< flatBuffersObject.rulesCount).map { try RestrictionRule(flatBuffersObject: flatBuffersObject.rules(at: $0)!) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let rulesOffsets = self.rules.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let rulesOffset = builder.createVector(ofOffsets: rulesOffsets, len: rulesOffsets.count)
|
||||||
|
|
||||||
|
let start = TelegramCore_PeerAccessRestrictionInfo.startPeerAccessRestrictionInfo(&builder)
|
||||||
|
TelegramCore_PeerAccessRestrictionInfo.addVectorOf(rules: rulesOffset, &builder)
|
||||||
|
return TelegramCore_PeerAccessRestrictionInfo.endPeerAccessRestrictionInfo(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,21 +80,21 @@ public enum PeerReference: PostboxCoding, Hashable, Equatable {
|
|||||||
switch flatBuffersObject.valueType {
|
switch flatBuffersObject.valueType {
|
||||||
case .peerreferenceUser:
|
case .peerreferenceUser:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_User.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_User.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .user(id: value.id, accessHash: value.accessHash)
|
self = .user(id: value.id, accessHash: value.accessHash)
|
||||||
case .peerreferenceGroup:
|
case .peerreferenceGroup:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Group.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Group.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .group(id: value.id)
|
self = .group(id: value.id)
|
||||||
case .peerreferenceChannel:
|
case .peerreferenceChannel:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Channel.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_PeerReference_Channel.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .channel(id: value.id, accessHash: value.accessHash)
|
self = .channel(id: value.id, accessHash: value.accessHash)
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public final class RecentMediaItem: Codable, Equatable {
|
|||||||
if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "md") {
|
if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "md") {
|
||||||
self.serializedFile = serializedFileData
|
self.serializedFile = serializedFileData
|
||||||
var byteBuffer = ByteBuffer(data: serializedFileData)
|
var byteBuffer = ByteBuffer(data: serializedFileData)
|
||||||
self.media = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
self.media = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
||||||
} else {
|
} else {
|
||||||
let mediaData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m")
|
let mediaData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m")
|
||||||
let media = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))
|
let media = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))
|
||||||
@ -282,7 +282,7 @@ public final class RecentReactionItem: Codable, Equatable {
|
|||||||
|
|
||||||
if let mediaData = try container.decodeIfPresent(Data.self, forKey: "md") {
|
if let mediaData = try container.decodeIfPresent(Data.self, forKey: "md") {
|
||||||
var byteBuffer = ByteBuffer(data: mediaData)
|
var byteBuffer = ByteBuffer(data: mediaData)
|
||||||
let file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, mediaData)
|
let file = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, mediaData)
|
||||||
self.content = .custom(file)
|
self.content = .custom(file)
|
||||||
} else if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") {
|
} else if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") {
|
||||||
self.content = .custom(TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))))
|
self.content = .custom(TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))))
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
private enum RichTextTypes: Int32 {
|
private enum RichTextTypes: Int32 {
|
||||||
case empty = 0
|
case empty = 0
|
||||||
@ -292,3 +294,208 @@ public extension RichText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RichText {
|
||||||
|
public init(flatBuffersObject: TelegramCore_RichText) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .richtextEmpty:
|
||||||
|
self = .empty
|
||||||
|
case .richtextPlain:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Plain.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .plain(value.text)
|
||||||
|
case .richtextBold:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Bold.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .bold(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextItalic:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Italic.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .italic(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextUnderline:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Underline.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .underline(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextStrikethrough:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Strikethrough.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .strikethrough(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextFixed:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Fixed.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .fixed(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextUrl:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Url.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .url(text: try RichText(flatBuffersObject: value.text), url: value.url, webpageId: value.webpageId.flatMap { MediaId($0) })
|
||||||
|
case .richtextEmail:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Email.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .email(text: try RichText(flatBuffersObject: value.text),
|
||||||
|
email: value.email)
|
||||||
|
case .richtextConcat:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Concat.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .concat(try (0..<value.textsCount).map { try RichText(flatBuffersObject: value.texts(at: $0)!) })
|
||||||
|
case .richtextSubscript:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Subscript.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .subscript(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextSuperscript:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Superscript.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .superscript(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextMarked:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Marked.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .marked(try RichText(flatBuffersObject: value.text))
|
||||||
|
case .richtextPhone:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Phone.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .phone(text: try RichText(flatBuffersObject: value.text),
|
||||||
|
phone: value.phone)
|
||||||
|
case .richtextImage:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Image.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .image(id: MediaId(value.id), dimensions: PixelDimensions(value.dimensions))
|
||||||
|
case .richtextAnchor:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_RichText_Anchor.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .anchor(text: try RichText(flatBuffersObject: value.text),
|
||||||
|
name: value.name)
|
||||||
|
case .none_:
|
||||||
|
self = .empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_RichText_Value
|
||||||
|
let offset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case .empty:
|
||||||
|
valueType = .richtextEmpty
|
||||||
|
let start = TelegramCore_RichText_Empty.startRichText_Empty(&builder)
|
||||||
|
offset = TelegramCore_RichText_Empty.endRichText_Empty(&builder, start: start)
|
||||||
|
case let .plain(text):
|
||||||
|
valueType = .richtextPlain
|
||||||
|
let textOffset = builder.create(string: text)
|
||||||
|
let start = TelegramCore_RichText_Plain.startRichText_Plain(&builder)
|
||||||
|
TelegramCore_RichText_Plain.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Plain.endRichText_Plain(&builder, start: start)
|
||||||
|
case let .bold(text):
|
||||||
|
valueType = .richtextBold
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Bold.startRichText_Bold(&builder)
|
||||||
|
TelegramCore_RichText_Bold.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Bold.endRichText_Bold(&builder, start: start)
|
||||||
|
case let .italic(text):
|
||||||
|
valueType = .richtextItalic
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Italic.startRichText_Italic(&builder)
|
||||||
|
TelegramCore_RichText_Italic.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Italic.endRichText_Italic(&builder, start: start)
|
||||||
|
case let .underline(text):
|
||||||
|
valueType = .richtextUnderline
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Underline.startRichText_Underline(&builder)
|
||||||
|
TelegramCore_RichText_Underline.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Underline.endRichText_Underline(&builder, start: start)
|
||||||
|
case let .strikethrough(text):
|
||||||
|
valueType = .richtextStrikethrough
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Strikethrough.startRichText_Strikethrough(&builder)
|
||||||
|
TelegramCore_RichText_Strikethrough.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Strikethrough.endRichText_Strikethrough(&builder, start: start)
|
||||||
|
case let .fixed(text):
|
||||||
|
valueType = .richtextFixed
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Fixed.startRichText_Fixed(&builder)
|
||||||
|
TelegramCore_RichText_Fixed.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Fixed.endRichText_Fixed(&builder, start: start)
|
||||||
|
case let .url(text, url, webpageId):
|
||||||
|
valueType = .richtextUrl
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let urlOffset = builder.create(string: url)
|
||||||
|
let start = TelegramCore_RichText_Url.startRichText_Url(&builder)
|
||||||
|
TelegramCore_RichText_Url.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_RichText_Url.add(url: urlOffset, &builder)
|
||||||
|
if let webpageId {
|
||||||
|
TelegramCore_RichText_Url.add(webpageId: webpageId.asFlatBuffersObject(), &builder)
|
||||||
|
}
|
||||||
|
offset = TelegramCore_RichText_Url.endRichText_Url(&builder, start: start)
|
||||||
|
case let .email(text, email):
|
||||||
|
valueType = .richtextEmail
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let emailOffset = builder.create(string: email)
|
||||||
|
let start = TelegramCore_RichText_Email.startRichText_Email(&builder)
|
||||||
|
TelegramCore_RichText_Email.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_RichText_Email.add(email: emailOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Email.endRichText_Email(&builder, start: start)
|
||||||
|
case let .concat(texts):
|
||||||
|
valueType = .richtextConcat
|
||||||
|
let textsOffsets = texts.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let textsOffset = builder.createVector(ofOffsets: textsOffsets, len: textsOffsets.count)
|
||||||
|
let start = TelegramCore_RichText_Concat.startRichText_Concat(&builder)
|
||||||
|
TelegramCore_RichText_Concat.addVectorOf(texts: textsOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Concat.endRichText_Concat(&builder, start: start)
|
||||||
|
case let .subscript(text):
|
||||||
|
valueType = .richtextSubscript
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Subscript.startRichText_Subscript(&builder)
|
||||||
|
TelegramCore_RichText_Subscript.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Subscript.endRichText_Subscript(&builder, start: start)
|
||||||
|
case let .superscript(text):
|
||||||
|
valueType = .richtextSuperscript
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Superscript.startRichText_Superscript(&builder)
|
||||||
|
TelegramCore_RichText_Superscript.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Superscript.endRichText_Superscript(&builder, start: start)
|
||||||
|
case let .marked(text):
|
||||||
|
valueType = .richtextMarked
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let start = TelegramCore_RichText_Marked.startRichText_Marked(&builder)
|
||||||
|
TelegramCore_RichText_Marked.add(text: textOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Marked.endRichText_Marked(&builder, start: start)
|
||||||
|
case let .phone(text, phone):
|
||||||
|
valueType = .richtextPhone
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let phoneOffset = builder.create(string: phone)
|
||||||
|
let start = TelegramCore_RichText_Phone.startRichText_Phone(&builder)
|
||||||
|
TelegramCore_RichText_Phone.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_RichText_Phone.add(phone: phoneOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Phone.endRichText_Phone(&builder, start: start)
|
||||||
|
case let .image(id, dimensions):
|
||||||
|
valueType = .richtextImage
|
||||||
|
let start = TelegramCore_RichText_Image.startRichText_Image(&builder)
|
||||||
|
TelegramCore_RichText_Image.add(id: id.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_RichText_Image.add(dimensions: dimensions.asFlatBuffersObject(), &builder)
|
||||||
|
offset = TelegramCore_RichText_Image.endRichText_Image(&builder, start: start)
|
||||||
|
case let .anchor(text, name):
|
||||||
|
valueType = .richtextAnchor
|
||||||
|
let textOffset = text.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let nameOffset = builder.create(string: name)
|
||||||
|
let start = TelegramCore_RichText_Anchor.startRichText_Anchor(&builder)
|
||||||
|
TelegramCore_RichText_Anchor.add(text: textOffset, &builder)
|
||||||
|
TelegramCore_RichText_Anchor.add(name: nameOffset, &builder)
|
||||||
|
offset = TelegramCore_RichText_Anchor.endRichText_Anchor(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TelegramCore_RichText.createRichText(&builder, valueType: valueType, valueOffset: offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ public final class SavedStickerItem: Codable, Equatable {
|
|||||||
|
|
||||||
if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "fd") {
|
if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "fd") {
|
||||||
var byteBuffer = ByteBuffer(data: serializedFileData)
|
var byteBuffer = ByteBuffer(data: serializedFileData)
|
||||||
self.file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
self.file = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
||||||
} else {
|
} else {
|
||||||
let file = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: (try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "f")).data)))
|
let file = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: (try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "f")).data)))
|
||||||
self.file = TelegramMediaFile.Accessor(file)
|
self.file = TelegramMediaFile.Accessor(file)
|
||||||
|
@ -18,7 +18,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
|
|||||||
self.index = index
|
self.index = index
|
||||||
|
|
||||||
var byteBuffer = ByteBuffer(data: serializedFile)
|
var byteBuffer = ByteBuffer(data: serializedFile)
|
||||||
let accessor = getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile
|
let accessor = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile
|
||||||
self.file = TelegramMediaFile.Accessor(accessor, serializedFile)
|
self.file = TelegramMediaFile.Accessor(accessor, serializedFile)
|
||||||
|
|
||||||
self.indexKeys = indexKeys
|
self.indexKeys = indexKeys
|
||||||
@ -29,7 +29,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
|
|||||||
|
|
||||||
if let serializedFileData = decoder.decodeDataForKey("fd") {
|
if let serializedFileData = decoder.decodeDataForKey("fd") {
|
||||||
var byteBuffer = ByteBuffer(data: serializedFileData)
|
var byteBuffer = ByteBuffer(data: serializedFileData)
|
||||||
self.file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
self.file = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData)
|
||||||
} else {
|
} else {
|
||||||
let file = decoder.decodeObjectForKey("f") as! TelegramMediaFile
|
let file = decoder.decodeObjectForKey("f") as! TelegramMediaFile
|
||||||
self.file = TelegramMediaFile.Accessor(file)
|
self.file = TelegramMediaFile.Accessor(file)
|
||||||
|
@ -1,22 +1,13 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public enum TelegramChannelParticipationStatus {
|
public enum TelegramChannelParticipationStatus: Int32 {
|
||||||
case member
|
case member = 0
|
||||||
case left
|
case left = 1
|
||||||
case kicked
|
case kicked = 2
|
||||||
|
|
||||||
fileprivate var rawValue: Int32 {
|
public init(rawValue: Int32) {
|
||||||
switch self {
|
|
||||||
case .member:
|
|
||||||
return 0
|
|
||||||
case .left:
|
|
||||||
return 1
|
|
||||||
case .kicked:
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate init(rawValue: Int32) {
|
|
||||||
switch rawValue {
|
switch rawValue {
|
||||||
case 0:
|
case 0:
|
||||||
self = .member
|
self = .member
|
||||||
@ -48,6 +39,7 @@ public struct TelegramChannelBroadcastFlags: OptionSet {
|
|||||||
|
|
||||||
public struct TelegramChannelBroadcastInfo: Equatable {
|
public struct TelegramChannelBroadcastInfo: Equatable {
|
||||||
public let flags: TelegramChannelBroadcastFlags
|
public let flags: TelegramChannelBroadcastFlags
|
||||||
|
|
||||||
public init(flags: TelegramChannelBroadcastFlags) {
|
public init(flags: TelegramChannelBroadcastFlags) {
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
}
|
}
|
||||||
@ -124,6 +116,46 @@ public enum TelegramChannelInfo: Equatable {
|
|||||||
return .group(TelegramChannelGroupInfo(flags: TelegramChannelGroupFlags(rawValue: decoder.decodeInt32ForKey("i.f", orElse: 0))))
|
return .group(TelegramChannelGroupInfo(flags: TelegramChannelGroupFlags(rawValue: decoder.decodeInt32ForKey("i.f", orElse: 0))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramChannelInfo) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .telegramchannelinfoBroadcast:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramChannelInfo_Broadcast.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .broadcast(TelegramChannelBroadcastInfo(flags: TelegramChannelBroadcastFlags(rawValue: value.flags)))
|
||||||
|
case .telegramchannelinfoGroup:
|
||||||
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramChannelInfo_Group.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .group(TelegramChannelGroupInfo(flags: TelegramChannelGroupFlags(rawValue: value.flags)))
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueType: TelegramCore_TelegramChannelInfo_Value
|
||||||
|
let valueOffset: Offset
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case let .broadcast(info):
|
||||||
|
valueType = .telegramchannelinfoBroadcast
|
||||||
|
let start = TelegramCore_TelegramChannelInfo_Broadcast.startTelegramChannelInfo_Broadcast(&builder)
|
||||||
|
TelegramCore_TelegramChannelInfo_Broadcast.add(flags: info.flags.rawValue, &builder)
|
||||||
|
valueOffset = TelegramCore_TelegramChannelInfo_Broadcast.endTelegramChannelInfo_Broadcast(&builder, start: start)
|
||||||
|
case let .group(info):
|
||||||
|
valueType = .telegramchannelinfoGroup
|
||||||
|
let start = TelegramCore_TelegramChannelInfo_Group.startTelegramChannelInfo_Group(&builder)
|
||||||
|
TelegramCore_TelegramChannelInfo_Group.add(flags: info.flags.rawValue, &builder)
|
||||||
|
valueOffset = TelegramCore_TelegramChannelInfo_Group.endTelegramChannelInfo_Group(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramChannelInfo.startTelegramChannelInfo(&builder)
|
||||||
|
TelegramCore_TelegramChannelInfo.add(valueType: valueType, &builder)
|
||||||
|
TelegramCore_TelegramChannelInfo.add(value: valueOffset, &builder)
|
||||||
|
return TelegramCore_TelegramChannelInfo.endTelegramChannelInfo(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TelegramChannelFlags: OptionSet {
|
public struct TelegramChannelFlags: OptionSet {
|
||||||
@ -314,6 +346,17 @@ public final class TelegramChannel: Peer, Equatable {
|
|||||||
self.subscriptionUntilDate = decoder.decodeOptionalInt32ForKey("sud")
|
self.subscriptionUntilDate = decoder.decodeOptionalInt32ForKey("sud")
|
||||||
self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid")
|
self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid")
|
||||||
self.sendPaidMessageStars = decoder.decodeCodable(StarsAmount.self, forKey: "sendPaidMessageStars")
|
self.sendPaidMessageStars = decoder.decodeCodable(StarsAmount.self, forKey: "sendPaidMessageStars")
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
var builder = FlatBufferBuilder(initialSize: 1024)
|
||||||
|
let offset = self.encodeToFlatBuffers(builder: &builder)
|
||||||
|
builder.finish(offset: offset)
|
||||||
|
let serializedData = builder.data
|
||||||
|
var byteBuffer = ByteBuffer(data: serializedData)
|
||||||
|
let deserializedValue = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramChannel
|
||||||
|
let parsedValue = try! TelegramChannel(flatBuffersObject: deserializedValue)
|
||||||
|
assert(self == parsedValue)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@ -544,4 +587,116 @@ public final class TelegramChannel: Peer, Equatable {
|
|||||||
public func withUpdatedVerificationIconFileId(_ verificationIconFileId: Int64?) -> TelegramChannel {
|
public func withUpdatedVerificationIconFileId(_ verificationIconFileId: Int64?) -> TelegramChannel {
|
||||||
return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, emojiStatus: self.emojiStatus, approximateBoostLevel: self.approximateBoostLevel, subscriptionUntilDate: self.subscriptionUntilDate, verificationIconFileId: verificationIconFileId, sendPaidMessageStars: self.sendPaidMessageStars)
|
return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, emojiStatus: self.emojiStatus, approximateBoostLevel: self.approximateBoostLevel, subscriptionUntilDate: self.subscriptionUntilDate, verificationIconFileId: verificationIconFileId, sendPaidMessageStars: self.sendPaidMessageStars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramChannel) throws {
|
||||||
|
self.id = PeerId(flatBuffersObject.id)
|
||||||
|
self.accessHash = try flatBuffersObject.accessHash.flatMap(TelegramPeerAccessHash.init)
|
||||||
|
self.title = flatBuffersObject.title
|
||||||
|
self.username = flatBuffersObject.username
|
||||||
|
self.photo = try (0 ..< flatBuffersObject.photoCount).map { try TelegramMediaImageRepresentation(flatBuffersObject: flatBuffersObject.photo(at: $0)!) }
|
||||||
|
self.creationDate = flatBuffersObject.creationDate
|
||||||
|
self.version = flatBuffersObject.version
|
||||||
|
self.participationStatus = TelegramChannelParticipationStatus(rawValue: flatBuffersObject.participationStatus)
|
||||||
|
|
||||||
|
guard let infoObj = flatBuffersObject.info else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self.info = try TelegramChannelInfo(flatBuffersObject: infoObj)
|
||||||
|
|
||||||
|
self.flags = TelegramChannelFlags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.restrictionInfo = try flatBuffersObject.restrictionInfo.flatMap { try PeerAccessRestrictionInfo(flatBuffersObject: $0) }
|
||||||
|
self.adminRights = try flatBuffersObject.adminRights.flatMap { try TelegramChatAdminRights(flatBuffersObject: $0) }
|
||||||
|
self.bannedRights = try flatBuffersObject.bannedRights.flatMap { try TelegramChatBannedRights(flatBuffersObject: $0) }
|
||||||
|
self.defaultBannedRights = try flatBuffersObject.defaultBannedRights.map { try TelegramChatBannedRights(flatBuffersObject: $0) }
|
||||||
|
self.usernames = try (0 ..< flatBuffersObject.usernamesCount).map { try TelegramPeerUsername(flatBuffersObject: flatBuffersObject.usernames(at: $0)!) }
|
||||||
|
self.storiesHidden = flatBuffersObject.storiesHidden?.value
|
||||||
|
self.nameColor = try flatBuffersObject.nameColor.flatMap(PeerNameColor.init(flatBuffersObject:))
|
||||||
|
self.backgroundEmojiId = flatBuffersObject.backgroundEmojiId == Int64.min ? nil : flatBuffersObject.backgroundEmojiId
|
||||||
|
self.profileColor = try flatBuffersObject.profileColor.flatMap(PeerNameColor.init)
|
||||||
|
self.profileBackgroundEmojiId = flatBuffersObject.profileBackgroundEmojiId == Int64.min ? nil : flatBuffersObject.profileBackgroundEmojiId
|
||||||
|
self.emojiStatus = try flatBuffersObject.emojiStatus.flatMap { try PeerEmojiStatus(flatBuffersObject: $0) }
|
||||||
|
self.approximateBoostLevel = flatBuffersObject.approximateBoostLevel == Int32.min ? nil : flatBuffersObject.approximateBoostLevel
|
||||||
|
self.subscriptionUntilDate = flatBuffersObject.subscriptionUntilDate == Int32.min ? nil : flatBuffersObject.subscriptionUntilDate
|
||||||
|
self.verificationIconFileId = flatBuffersObject.verificationIconFileId == Int64.min ? nil : flatBuffersObject.verificationIconFileId
|
||||||
|
self.sendPaidMessageStars = try flatBuffersObject.sendPaidMessageStars.flatMap { try StarsAmount(flatBuffersObject: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let accessHashOffset = self.accessHash.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
|
||||||
|
let photoOffsets = self.photo.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let photoOffset = builder.createVector(ofOffsets: photoOffsets, len: photoOffsets.count)
|
||||||
|
|
||||||
|
let usernamesOffsets = self.usernames.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let usernamesOffset = builder.createVector(ofOffsets: usernamesOffsets, len: usernamesOffsets.count)
|
||||||
|
|
||||||
|
let titleOffset = builder.create(string: self.title)
|
||||||
|
let usernameOffset = self.username.map { builder.create(string: $0) }
|
||||||
|
let nameColorOffset = self.nameColor.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let profileColorOffset = self.profileColor.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
|
||||||
|
let infoOffset = self.info.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let restrictionInfoOffset = self.restrictionInfo?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let adminRightsOffset = self.adminRights?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let bannedRightsOffset = self.bannedRights?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let defaultBannedRightsOffset = self.defaultBannedRights?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let emojiStatusOffset = self.emojiStatus?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let sendPaidMessageStarsOffset = self.sendPaidMessageStars?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramChannel.startTelegramChannel(&builder)
|
||||||
|
|
||||||
|
TelegramCore_TelegramChannel.add(id: self.id.asFlatBuffersObject(), &builder)
|
||||||
|
if let accessHashOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(accessHash: accessHashOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramChannel.add(title: titleOffset, &builder)
|
||||||
|
if let usernameOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(username: usernameOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramChannel.addVectorOf(photo: photoOffset, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(creationDate: self.creationDate, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(version: self.version, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(participationStatus: self.participationStatus.rawValue, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(info: infoOffset, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(flags: self.flags.rawValue, &builder)
|
||||||
|
|
||||||
|
if let restrictionInfoOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(restrictionInfo: restrictionInfoOffset, &builder)
|
||||||
|
}
|
||||||
|
if let adminRightsOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(adminRights: adminRightsOffset, &builder)
|
||||||
|
}
|
||||||
|
if let bannedRightsOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(bannedRights: bannedRightsOffset, &builder)
|
||||||
|
}
|
||||||
|
if let defaultBannedRightsOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(defaultBannedRights: defaultBannedRightsOffset, &builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramCore_TelegramChannel.addVectorOf(usernames: usernamesOffset, &builder)
|
||||||
|
|
||||||
|
if let storiesHidden = self.storiesHidden {
|
||||||
|
TelegramCore_TelegramChannel.add(storiesHidden: TelegramCore_OptionalBool(value: storiesHidden), &builder)
|
||||||
|
}
|
||||||
|
if let nameColorOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(nameColor: nameColorOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramChannel.add(backgroundEmojiId: self.backgroundEmojiId ?? Int64.min, &builder)
|
||||||
|
if let profileColorOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(profileColor: profileColorOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramChannel.add(profileBackgroundEmojiId: self.profileBackgroundEmojiId ?? Int64.min, &builder)
|
||||||
|
if let emojiStatusOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(emojiStatus: emojiStatusOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramChannel.add(approximateBoostLevel: self.approximateBoostLevel ?? Int32.min, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(subscriptionUntilDate: self.subscriptionUntilDate ?? Int32.min, &builder)
|
||||||
|
TelegramCore_TelegramChannel.add(verificationIconFileId: self.verificationIconFileId ?? Int64.min, &builder)
|
||||||
|
if let sendPaidMessageStarsOffset {
|
||||||
|
TelegramCore_TelegramChannel.add(sendPaidMessageStars: sendPaidMessageStarsOffset, &builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TelegramCore_TelegramChannel.endTelegramChannel(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public struct TelegramChatAdminRightsFlags: OptionSet, Hashable {
|
public struct TelegramChatAdminRightsFlags: OptionSet, Hashable {
|
||||||
public var rawValue: Int32
|
public var rawValue: Int32
|
||||||
@ -124,4 +126,14 @@ public struct TelegramChatAdminRights: PostboxCoding, Codable, Equatable {
|
|||||||
public static func ==(lhs: TelegramChatAdminRights, rhs: TelegramChatAdminRights) -> Bool {
|
public static func ==(lhs: TelegramChatAdminRights, rhs: TelegramChatAdminRights) -> Bool {
|
||||||
return lhs.rights == rhs.rights
|
return lhs.rights == rhs.rights
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramChatAdminRights) throws {
|
||||||
|
self.rights = TelegramChatAdminRightsFlags(rawValue: flatBuffersObject.rights)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let start = TelegramCore_TelegramChatAdminRights.startTelegramChatAdminRights(&builder)
|
||||||
|
TelegramCore_TelegramChatAdminRights.add(rights: self.rights.rawValue, &builder)
|
||||||
|
return TelegramCore_TelegramChatAdminRights.endTelegramChatAdminRights(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public struct TelegramChatBannedRightsFlags: OptionSet, Hashable {
|
public struct TelegramChatBannedRightsFlags: OptionSet, Hashable {
|
||||||
public var rawValue: Int32
|
public var rawValue: Int32
|
||||||
@ -54,4 +56,16 @@ public struct TelegramChatBannedRights: PostboxCoding, Equatable {
|
|||||||
public static func ==(lhs: TelegramChatBannedRights, rhs: TelegramChatBannedRights) -> Bool {
|
public static func ==(lhs: TelegramChatBannedRights, rhs: TelegramChatBannedRights) -> Bool {
|
||||||
return lhs.flags == rhs.flags && lhs.untilDate == rhs.untilDate
|
return lhs.flags == rhs.flags && lhs.untilDate == rhs.untilDate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramChatBannedRights) throws {
|
||||||
|
self.flags = TelegramChatBannedRightsFlags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.untilDate = flatBuffersObject.untilDate
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let start = TelegramCore_TelegramChatBannedRights.startTelegramChatBannedRights(&builder)
|
||||||
|
TelegramCore_TelegramChatBannedRights.add(flags: self.flags.rawValue, &builder)
|
||||||
|
TelegramCore_TelegramChatBannedRights.add(untilDate: self.untilDate, &builder)
|
||||||
|
return TelegramCore_TelegramChatBannedRights.endTelegramChatBannedRights(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public enum TelegramGroupRole: Equatable, PostboxCoding {
|
public enum TelegramGroupRole: Equatable, PostboxCoding {
|
||||||
case creator(rank: String?)
|
case creator(rank: String?)
|
||||||
@ -40,6 +42,61 @@ public enum TelegramGroupRole: Equatable, PostboxCoding {
|
|||||||
encoder.encodeInt32(2, forKey: "_v")
|
encoder.encodeInt32(2, forKey: "_v")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramGroupRole) throws {
|
||||||
|
switch flatBuffersObject.valueType {
|
||||||
|
case .telegramgrouproleCreator:
|
||||||
|
guard let creator = flatBuffersObject.value(type: TelegramCore_TelegramGroupRole_Creator.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .creator(rank: creator.rank)
|
||||||
|
case .telegramgrouproleAdmin:
|
||||||
|
guard let admin = flatBuffersObject.value(type: TelegramCore_TelegramGroupRole_Admin.self) else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self = .admin(try TelegramChatAdminRights(flatBuffersObject: admin.rights), rank: admin.rank)
|
||||||
|
case .telegramgrouproleMember:
|
||||||
|
self = .member
|
||||||
|
case .none_:
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let valueOffset: Offset
|
||||||
|
let valueType: TelegramCore_TelegramGroupRole_Value
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case let .creator(rank):
|
||||||
|
let rankOffset = rank.map { builder.create(string: $0) }
|
||||||
|
let start = TelegramCore_TelegramGroupRole_Creator.startTelegramGroupRole_Creator(&builder)
|
||||||
|
if let rankOffset {
|
||||||
|
TelegramCore_TelegramGroupRole_Creator.add(rank: rankOffset, &builder)
|
||||||
|
}
|
||||||
|
valueOffset = TelegramCore_TelegramGroupRole_Creator.endTelegramGroupRole_Creator(&builder, start: start)
|
||||||
|
valueType = .telegramgrouproleCreator
|
||||||
|
case let .admin(rights, rank):
|
||||||
|
let rankOffset = rank.map { builder.create(string: $0) }
|
||||||
|
let rightsOffset = rights.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramGroupRole_Admin.startTelegramGroupRole_Admin(&builder)
|
||||||
|
TelegramCore_TelegramGroupRole_Admin.add(rights: rightsOffset, &builder)
|
||||||
|
if let rankOffset {
|
||||||
|
TelegramCore_TelegramGroupRole_Admin.add(rank: rankOffset, &builder)
|
||||||
|
}
|
||||||
|
valueOffset = TelegramCore_TelegramGroupRole_Admin.endTelegramGroupRole_Admin(&builder, start: start)
|
||||||
|
valueType = .telegramgrouproleAdmin
|
||||||
|
case .member:
|
||||||
|
let start = TelegramCore_TelegramGroupRole_Member.startTelegramGroupRole_Member(&builder)
|
||||||
|
valueOffset = TelegramCore_TelegramGroupRole_Member.endTelegramGroupRole_Member(&builder, start: start)
|
||||||
|
valueType = .telegramgrouproleMember
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramGroupRole.startTelegramGroupRole(&builder)
|
||||||
|
TelegramCore_TelegramGroupRole.add(value: valueOffset, &builder)
|
||||||
|
TelegramCore_TelegramGroupRole.add(valueType: valueType, &builder)
|
||||||
|
return TelegramCore_TelegramGroupRole.endTelegramGroupRole(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TelegramGroupMembership: Int32 {
|
public enum TelegramGroupMembership: Int32 {
|
||||||
@ -73,6 +130,18 @@ public struct TelegramGroupToChannelMigrationReference: Equatable {
|
|||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.accessHash = accessHash
|
self.accessHash = accessHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramGroupToChannelMigrationReference) throws {
|
||||||
|
self.peerId = PeerId(flatBuffersObject.peerId)
|
||||||
|
self.accessHash = flatBuffersObject.accessHash
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let start = TelegramCore_TelegramGroupToChannelMigrationReference.startTelegramGroupToChannelMigrationReference(&builder)
|
||||||
|
TelegramCore_TelegramGroupToChannelMigrationReference.add(peerId: self.peerId.toInt64(), &builder)
|
||||||
|
TelegramCore_TelegramGroupToChannelMigrationReference.add(accessHash: self.accessHash, &builder)
|
||||||
|
return TelegramCore_TelegramGroupToChannelMigrationReference.endTelegramGroupToChannelMigrationReference(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class TelegramGroup: Peer, Equatable {
|
public final class TelegramGroup: Peer, Equatable {
|
||||||
@ -137,6 +206,17 @@ public final class TelegramGroup: Peer, Equatable {
|
|||||||
}
|
}
|
||||||
self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0)
|
self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||||
self.version = Int(decoder.decodeInt32ForKey("v", orElse: 0))
|
self.version = Int(decoder.decodeInt32ForKey("v", orElse: 0))
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
var builder = FlatBufferBuilder(initialSize: 1024)
|
||||||
|
let offset = self.encodeToFlatBuffers(builder: &builder)
|
||||||
|
builder.finish(offset: offset)
|
||||||
|
let serializedData = builder.data
|
||||||
|
var byteBuffer = ByteBuffer(data: serializedData)
|
||||||
|
let deserializedValue = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramGroup
|
||||||
|
let parsedValue = try! TelegramGroup(flatBuffersObject: deserializedValue)
|
||||||
|
assert(self == parsedValue)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@ -163,6 +243,65 @@ public final class TelegramGroup: Peer, Equatable {
|
|||||||
encoder.encodeInt32(Int32(self.version), forKey: "v")
|
encoder.encodeInt32(Int32(self.version), forKey: "v")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramGroup) throws {
|
||||||
|
self.id = PeerId(flatBuffersObject.id)
|
||||||
|
self.title = flatBuffersObject.title
|
||||||
|
self.photo = try (0 ..< flatBuffersObject.photoCount).map { try TelegramMediaImageRepresentation(flatBuffersObject: flatBuffersObject.photo(at: $0)!) }
|
||||||
|
self.participantCount = Int(flatBuffersObject.participantCount)
|
||||||
|
|
||||||
|
guard let role = flatBuffersObject.role else {
|
||||||
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
|
}
|
||||||
|
self.role = try TelegramGroupRole(flatBuffersObject: role)
|
||||||
|
|
||||||
|
self.membership = TelegramGroupMembership(rawValue: flatBuffersObject.membership)!
|
||||||
|
self.flags = TelegramGroupFlags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.defaultBannedRights = try flatBuffersObject.defaultBannedRights.flatMap { try TelegramChatBannedRights(flatBuffersObject: $0) }
|
||||||
|
|
||||||
|
if let migrationReference = flatBuffersObject.migrationReference {
|
||||||
|
self.migrationReference = try TelegramGroupToChannelMigrationReference(flatBuffersObject: migrationReference)
|
||||||
|
} else {
|
||||||
|
self.migrationReference = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.creationDate = flatBuffersObject.creationDate
|
||||||
|
self.version = Int(flatBuffersObject.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let titleOffset = builder.create(string: self.title)
|
||||||
|
|
||||||
|
let photoOffsets = self.photo.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let photoOffset = builder.createVector(ofOffsets: photoOffsets, len: photoOffsets.count)
|
||||||
|
|
||||||
|
let roleOffset = self.role.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let defaultBannedRightsOffset = self.defaultBannedRights?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let migrationReferenceOffset = self.migrationReference?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramGroup.startTelegramGroup(&builder)
|
||||||
|
|
||||||
|
TelegramCore_TelegramGroup.add(id: self.id.asFlatBuffersObject(), &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(title: titleOffset, &builder)
|
||||||
|
TelegramCore_TelegramGroup.addVectorOf(photo: photoOffset, &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(participantCount: Int32(self.participantCount), &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(role: roleOffset, &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(membership: self.membership.rawValue, &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(flags: self.flags.rawValue, &builder)
|
||||||
|
|
||||||
|
if let defaultBannedRightsOffset {
|
||||||
|
TelegramCore_TelegramGroup.add(defaultBannedRights: defaultBannedRightsOffset, &builder)
|
||||||
|
}
|
||||||
|
if let migrationReferenceOffset {
|
||||||
|
TelegramCore_TelegramGroup.add(migrationReference: migrationReferenceOffset, &builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramCore_TelegramGroup.add(creationDate: self.creationDate, &builder)
|
||||||
|
TelegramCore_TelegramGroup.add(version: Int32(self.version), &builder)
|
||||||
|
|
||||||
|
return TelegramCore_TelegramGroup.endTelegramGroup(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
public func isEqual(_ other: Peer) -> Bool {
|
public func isEqual(_ other: Peer) -> Bool {
|
||||||
if let other = other as? TelegramGroup {
|
if let other = other as? TelegramGroup {
|
||||||
return self == other
|
return self == other
|
||||||
|
@ -15,11 +15,6 @@ private let typeHintIsValidated: Int32 = 8
|
|||||||
private let typeNoPremium: Int32 = 9
|
private let typeNoPremium: Int32 = 9
|
||||||
private let typeCustomEmoji: Int32 = 10
|
private let typeCustomEmoji: Int32 = 10
|
||||||
|
|
||||||
enum FlatBuffersError: Error {
|
|
||||||
case missingRequiredField
|
|
||||||
case invalidUnionType
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
|
public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
|
||||||
case id(id: Int64, accessHash: Int64)
|
case id(id: Int64, accessHash: Int64)
|
||||||
case name(String)
|
case name(String)
|
||||||
@ -131,19 +126,19 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
|
|||||||
switch flatBuffersObject.valueType {
|
switch flatBuffersObject.valueType {
|
||||||
case .stickerpackreferenceId:
|
case .stickerpackreferenceId:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Id.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Id.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .id(id: value.id, accessHash: value.accessHash)
|
self = .id(id: value.id, accessHash: value.accessHash)
|
||||||
case .stickerpackreferenceName:
|
case .stickerpackreferenceName:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Name.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Name.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .name(value.name)
|
self = .name(value.name)
|
||||||
case .stickerpackreferenceAnimatedemoji:
|
case .stickerpackreferenceAnimatedemoji:
|
||||||
self = .animatedEmoji
|
self = .animatedEmoji
|
||||||
case .stickerpackreferenceDice:
|
case .stickerpackreferenceDice:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Dice.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_StickerPackReference_Dice.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .dice(value.emoji)
|
self = .dice(value.emoji)
|
||||||
case .stickerpackreferenceAnimatedemojianimations:
|
case .stickerpackreferenceAnimatedemojianimations:
|
||||||
@ -159,7 +154,7 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable {
|
|||||||
case .stickerpackreferenceIconchannelstatusemoji:
|
case .stickerpackreferenceIconchannelstatusemoji:
|
||||||
self = .iconChannelStatusEmoji
|
self = .iconChannelStatusEmoji
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +470,7 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
|
|||||||
|
|
||||||
init(flatBuffersData data: Data) throws {
|
init(flatBuffersData data: Data) throws {
|
||||||
var byteBuffer = ByteBuffer(data: data)
|
var byteBuffer = ByteBuffer(data: data)
|
||||||
let flatBuffersObject: TelegramCore_TelegramMediaFileAttribute = getRoot(byteBuffer: &byteBuffer)
|
let flatBuffersObject: TelegramCore_TelegramMediaFileAttribute = FlatBuffers_getRoot(byteBuffer: &byteBuffer)
|
||||||
try self.init(flatBuffersObject: flatBuffersObject)
|
try self.init(flatBuffersObject: flatBuffersObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,29 +478,29 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
|
|||||||
switch flatBuffersObject.valueType {
|
switch flatBuffersObject.valueType {
|
||||||
case .telegrammediafileattributeFilename:
|
case .telegrammediafileattributeFilename:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_FileName.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_FileName.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .FileName(fileName: value.fileName)
|
self = .FileName(fileName: value.fileName)
|
||||||
case .telegrammediafileattributeSticker:
|
case .telegrammediafileattributeSticker:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Sticker.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Sticker.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .Sticker(displayText: value.displayText, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }), maskData: value.maskData.flatMap({ StickerMaskCoords(flatBuffersObject: $0) }))
|
self = .Sticker(displayText: value.displayText, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }), maskData: value.maskData.flatMap({ StickerMaskCoords(flatBuffersObject: $0) }))
|
||||||
case .telegrammediafileattributeImagesize:
|
case .telegrammediafileattributeImagesize:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_ImageSize.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_ImageSize.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .ImageSize(size: PixelDimensions(width: value.width, height: value.height))
|
self = .ImageSize(size: PixelDimensions(width: value.width, height: value.height))
|
||||||
case .telegrammediafileattributeAnimated:
|
case .telegrammediafileattributeAnimated:
|
||||||
self = .Animated
|
self = .Animated
|
||||||
case .telegrammediafileattributeVideo:
|
case .telegrammediafileattributeVideo:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
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)
|
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:
|
case .telegrammediafileattributeAudio:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Audio.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_Audio.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .Audio(isVoice: value.isVoice, duration: Int(value.duration), title: value.title, performer: value.performer, waveform: value.waveform.isEmpty ? nil : Data(value.waveform))
|
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:
|
case .telegrammediafileattributeHaslinkedstickers:
|
||||||
@ -517,10 +512,10 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable {
|
|||||||
case .telegrammediafileattributeNopremium:
|
case .telegrammediafileattributeNopremium:
|
||||||
self = .NoPremium
|
self = .NoPremium
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
case .telegrammediafileattributeCustomemoji:
|
case .telegrammediafileattributeCustomemoji:
|
||||||
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) else {
|
guard let value = flatBuffersObject.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self = .CustomEmoji(isPremium: value.isPremium, isSingleColor: value.isSingleColor, alt: value.alt, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }))
|
self = .CustomEmoji(isPremium: value.isPremium, isSingleColor: value.isSingleColor, alt: value.alt, packReference: try value.packReference.flatMap({ try StickerPackReference(flatBuffersObject: $0) }))
|
||||||
}
|
}
|
||||||
|
@ -219,16 +219,16 @@ public final class TelegramMediaImage: Media, Equatable, Codable {
|
|||||||
switch flatBuffersObject.contentType {
|
switch flatBuffersObject.contentType {
|
||||||
case .emojimarkupContentEmoji:
|
case .emojimarkupContentEmoji:
|
||||||
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Emoji.self) else {
|
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Emoji.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self.content = .emoji(fileId: value.fileId)
|
self.content = .emoji(fileId: value.fileId)
|
||||||
case .emojimarkupContentSticker:
|
case .emojimarkupContentSticker:
|
||||||
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Sticker.self) else {
|
guard let value = flatBuffersObject.content(type: TelegramCore_EmojiMarkup_Content_Sticker.self) else {
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
self.content = .sticker(packReference: try StickerPackReference(flatBuffersObject: value.packReference), fileId: value.fileId)
|
self.content = .sticker(packReference: try StickerPackReference(flatBuffersObject: value.packReference), fileId: value.fileId)
|
||||||
case .none_:
|
case .none_:
|
||||||
throw FlatBuffersError.missingRequiredField
|
throw FlatBuffersError.missingRequiredField(file: #file, line: #line)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backgroundColors = flatBuffersObject.backgroundColors
|
self.backgroundColors = flatBuffersObject.backgroundColors
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Postbox
|
import Postbox
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public struct UserInfoFlags: OptionSet {
|
public struct UserInfoFlags: OptionSet {
|
||||||
public var rawValue: Int32
|
public var rawValue: Int32
|
||||||
@ -64,6 +66,22 @@ public struct BotUserInfo: PostboxCoding, Equatable {
|
|||||||
encoder.encodeNil(forKey: "ip")
|
encoder.encodeNil(forKey: "ip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_BotUserInfo) throws {
|
||||||
|
self.flags = BotUserInfoFlags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.inlinePlaceholder = flatBuffersObject.inlinePlaceholder
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let inlinePlaceholderOffset = self.inlinePlaceholder.map { builder.create(string: $0) }
|
||||||
|
|
||||||
|
let start = TelegramCore_BotUserInfo.startBotUserInfo(&builder)
|
||||||
|
TelegramCore_BotUserInfo.add(flags: self.flags.rawValue, &builder)
|
||||||
|
if let inlinePlaceholderOffset {
|
||||||
|
TelegramCore_BotUserInfo.add(inlinePlaceholder: inlinePlaceholderOffset, &builder)
|
||||||
|
}
|
||||||
|
return TelegramCore_BotUserInfo.endBotUserInfo(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TelegramPeerUsername: PostboxCoding, Equatable {
|
public struct TelegramPeerUsername: PostboxCoding, Equatable {
|
||||||
@ -99,6 +117,20 @@ public struct TelegramPeerUsername: PostboxCoding, Equatable {
|
|||||||
encoder.encodeInt32(self.flags.rawValue, forKey: "f")
|
encoder.encodeInt32(self.flags.rawValue, forKey: "f")
|
||||||
encoder.encodeString(self.username, forKey: "un")
|
encoder.encodeString(self.username, forKey: "un")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramPeerUsername) throws {
|
||||||
|
self.flags = Flags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.username = flatBuffersObject.username
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let usernameOffset = builder.create(string: self.username)
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramPeerUsername.startTelegramPeerUsername(&builder)
|
||||||
|
TelegramCore_TelegramPeerUsername.add(flags: self.flags.rawValue, &builder)
|
||||||
|
TelegramCore_TelegramPeerUsername.add(username: usernameOffset, &builder)
|
||||||
|
return TelegramCore_TelegramPeerUsername.endTelegramPeerUsername(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PeerVerification: Codable, Equatable {
|
public struct PeerVerification: Codable, Equatable {
|
||||||
@ -298,6 +330,17 @@ public final class TelegramUser: Peer, Equatable {
|
|||||||
self.profileBackgroundEmojiId = decoder.decodeOptionalInt64ForKey("pgem")
|
self.profileBackgroundEmojiId = decoder.decodeOptionalInt64ForKey("pgem")
|
||||||
self.subscriberCount = decoder.decodeOptionalInt32ForKey("ssc")
|
self.subscriberCount = decoder.decodeOptionalInt32ForKey("ssc")
|
||||||
self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid")
|
self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid")
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
var builder = FlatBufferBuilder(initialSize: 1024)
|
||||||
|
let offset = self.encodeToFlatBuffers(builder: &builder)
|
||||||
|
builder.finish(offset: offset)
|
||||||
|
let serializedData = builder.data
|
||||||
|
var byteBuffer = ByteBuffer(data: serializedData)
|
||||||
|
let deserializedValue = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramUser
|
||||||
|
let parsedValue = try! TelegramUser(flatBuffersObject: deserializedValue)
|
||||||
|
assert(self == parsedValue)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@ -516,4 +559,95 @@ public final class TelegramUser: Peer, Equatable {
|
|||||||
public func withUpdatedProfileBackgroundEmojiId(_ profileBackgroundEmojiId: Int64?) -> TelegramUser {
|
public func withUpdatedProfileBackgroundEmojiId(_ profileBackgroundEmojiId: Int64?) -> TelegramUser {
|
||||||
return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: self.subscriberCount, verificationIconFileId: self.verificationIconFileId)
|
return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: self.subscriberCount, verificationIconFileId: self.verificationIconFileId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_TelegramUser) throws {
|
||||||
|
self.id = PeerId(flatBuffersObject.id)
|
||||||
|
self.accessHash = try flatBuffersObject.accessHash.flatMap(TelegramPeerAccessHash.init)
|
||||||
|
self.firstName = flatBuffersObject.firstName
|
||||||
|
self.lastName = flatBuffersObject.lastName
|
||||||
|
self.username = flatBuffersObject.username
|
||||||
|
self.phone = flatBuffersObject.phone
|
||||||
|
self.photo = try (0 ..< flatBuffersObject.photoCount).map { try TelegramMediaImageRepresentation(flatBuffersObject: flatBuffersObject.photo(at: $0)!) }
|
||||||
|
self.botInfo = try flatBuffersObject.botInfo.flatMap { try BotUserInfo(flatBuffersObject: $0) }
|
||||||
|
self.restrictionInfo = try flatBuffersObject.restrictionInfo.flatMap { try PeerAccessRestrictionInfo(flatBuffersObject: $0) }
|
||||||
|
self.flags = UserInfoFlags(rawValue: flatBuffersObject.flags)
|
||||||
|
self.emojiStatus = try flatBuffersObject.emojiStatus.flatMap { try PeerEmojiStatus(flatBuffersObject: $0) }
|
||||||
|
self.usernames = try (0 ..< flatBuffersObject.usernamesCount).map { try TelegramPeerUsername(flatBuffersObject: flatBuffersObject.usernames(at: $0)!) }
|
||||||
|
self.storiesHidden = flatBuffersObject.storiesHidden?.value
|
||||||
|
self.nameColor = try flatBuffersObject.nameColor.flatMap(PeerNameColor.init)
|
||||||
|
self.backgroundEmojiId = flatBuffersObject.backgroundEmojiId == Int64.min ? nil : flatBuffersObject.backgroundEmojiId
|
||||||
|
self.profileColor = try flatBuffersObject.profileColor.flatMap(PeerNameColor.init)
|
||||||
|
self.profileBackgroundEmojiId = flatBuffersObject.profileBackgroundEmojiId == Int64.min ? nil : flatBuffersObject.profileBackgroundEmojiId
|
||||||
|
self.subscriberCount = flatBuffersObject.subscriberCount == Int32.min ? nil : flatBuffersObject.subscriberCount
|
||||||
|
self.verificationIconFileId = flatBuffersObject.verificationIconFileId == Int64.min ? nil : flatBuffersObject.verificationIconFileId
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let accessHashOffset = self.accessHash.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
|
||||||
|
let firstNameOffset = self.firstName.map { builder.create(string: $0) }
|
||||||
|
let lastNameOffset = self.lastName.map { builder.create(string: $0) }
|
||||||
|
let usernameOffset = self.username.map { builder.create(string: $0) }
|
||||||
|
let phoneOffset = self.phone.map { builder.create(string: $0) }
|
||||||
|
|
||||||
|
let photoOffsets = self.photo.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let photoOffset = builder.createVector(ofOffsets: photoOffsets, len: photoOffsets.count)
|
||||||
|
|
||||||
|
let botInfoOffset = self.botInfo?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
let restrictionInfoOffset = self.restrictionInfo?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let usernamesOffsets = self.usernames.map { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let usernamesOffset = builder.createVector(ofOffsets: usernamesOffsets, len: usernamesOffsets.count)
|
||||||
|
|
||||||
|
let nameColorOffset = self.nameColor.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let profileColorOffset = self.profileColor.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
|
||||||
|
let emojiStatusOffset = self.emojiStatus?.encodeToFlatBuffers(builder: &builder)
|
||||||
|
|
||||||
|
let start = TelegramCore_TelegramUser.startTelegramUser(&builder)
|
||||||
|
|
||||||
|
TelegramCore_TelegramUser.add(id: self.id.asFlatBuffersObject(), &builder)
|
||||||
|
if let accessHashOffset {
|
||||||
|
TelegramCore_TelegramUser.add(accessHash: accessHashOffset, &builder)
|
||||||
|
}
|
||||||
|
if let firstNameOffset {
|
||||||
|
TelegramCore_TelegramUser.add(firstName: firstNameOffset, &builder)
|
||||||
|
}
|
||||||
|
if let lastNameOffset {
|
||||||
|
TelegramCore_TelegramUser.add(lastName: lastNameOffset, &builder)
|
||||||
|
}
|
||||||
|
if let usernameOffset {
|
||||||
|
TelegramCore_TelegramUser.add(username: usernameOffset, &builder)
|
||||||
|
}
|
||||||
|
if let phoneOffset {
|
||||||
|
TelegramCore_TelegramUser.add(phone: phoneOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramUser.addVectorOf(photo: photoOffset, &builder)
|
||||||
|
if let botInfoOffset {
|
||||||
|
TelegramCore_TelegramUser.add(botInfo: botInfoOffset, &builder)
|
||||||
|
}
|
||||||
|
if let restrictionInfoOffset {
|
||||||
|
TelegramCore_TelegramUser.add(restrictionInfo: restrictionInfoOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramUser.add(flags: self.flags.rawValue, &builder)
|
||||||
|
if let emojiStatusOffset {
|
||||||
|
TelegramCore_TelegramUser.add(emojiStatus: emojiStatusOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramUser.addVectorOf(usernames: usernamesOffset, &builder)
|
||||||
|
|
||||||
|
if let storiesHidden = self.storiesHidden {
|
||||||
|
TelegramCore_TelegramUser.add(storiesHidden: TelegramCore_OptionalBool(value: storiesHidden), &builder)
|
||||||
|
}
|
||||||
|
if let nameColorOffset {
|
||||||
|
TelegramCore_TelegramUser.add(nameColor: nameColorOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramUser.add(backgroundEmojiId: self.backgroundEmojiId ?? Int64.min, &builder)
|
||||||
|
if let profileColorOffset {
|
||||||
|
TelegramCore_TelegramUser.add(profileColor: profileColorOffset, &builder)
|
||||||
|
}
|
||||||
|
TelegramCore_TelegramUser.add(profileBackgroundEmojiId: self.profileBackgroundEmojiId ?? Int64.min, &builder)
|
||||||
|
TelegramCore_TelegramUser.add(subscriberCount: self.subscriberCount ?? Int32.min, &builder)
|
||||||
|
TelegramCore_TelegramUser.add(verificationIconFileId: self.verificationIconFileId ?? Int64.min, &builder)
|
||||||
|
|
||||||
|
return TelegramCore_TelegramUser.endTelegramUser(&builder, start: start)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ import Postbox
|
|||||||
import MtProtoKit
|
import MtProtoKit
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
|
||||||
public struct StarsTopUpOption: Equatable, Codable {
|
public struct StarsTopUpOption: Equatable, Codable {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
@ -280,6 +282,18 @@ public struct StarsAmount: Equatable, Comparable, Hashable, Codable, CustomStrin
|
|||||||
self.nanos = nanos
|
self.nanos = nanos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(flatBuffersObject: TelegramCore_StarsAmount) throws {
|
||||||
|
self.value = flatBuffersObject.value
|
||||||
|
self.nanos = flatBuffersObject.nanos
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
|
||||||
|
let start = TelegramCore_StarsAmount.startStarsAmount(&builder)
|
||||||
|
TelegramCore_StarsAmount.add(value: self.value, &builder)
|
||||||
|
TelegramCore_StarsAmount.add(nanos: self.nanos, &builder)
|
||||||
|
return TelegramCore_StarsAmount.endStarsAmount(&builder, start: start)
|
||||||
|
}
|
||||||
|
|
||||||
public var stringValue: String {
|
public var stringValue: String {
|
||||||
return totalValue.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", totalValue) : String(format: "%.02f", totalValue)
|
return totalValue.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", totalValue) : String(format: "%.02f", totalValue)
|
||||||
}
|
}
|
||||||
|
54
submodules/TelegramCore/Sources/Utils/FlatBuffersUtils.swift
Normal file
54
submodules/TelegramCore/Sources/Utils/FlatBuffersUtils.swift
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import Foundation
|
||||||
|
import FlatBuffers
|
||||||
|
import FlatSerialization
|
||||||
|
import Postbox
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
public func FlatBuffers_getRoot<T: FlatBufferObject & Verifiable>(
|
||||||
|
byteBuffer: inout ByteBuffer,
|
||||||
|
fileId: String? = nil,
|
||||||
|
options: VerifierOptions = .init()
|
||||||
|
) -> T {
|
||||||
|
return try! getCheckedRoot(byteBuffer: &byteBuffer, fileId: fileId, options: options)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
@inline(__always)
|
||||||
|
public func FlatBuffers_getRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffer) -> T {
|
||||||
|
return getRoot(byteBuffer: &byteBuffer)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public enum FlatBuffersError: Error {
|
||||||
|
case missingRequiredField(file: String, line: Int)
|
||||||
|
case invalidUnionType
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension PeerId {
|
||||||
|
init(_ id: TelegramCore_PeerId) {
|
||||||
|
self.init(namespace: PeerId.Namespace._internalFromInt32Value(id.namespace), id: PeerId.Id._internalFromInt64Value(id.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asFlatBuffersObject() -> TelegramCore_PeerId {
|
||||||
|
return TelegramCore_PeerId(namespace: self.namespace._internalGetInt32Value(), id: self.id._internalGetInt64Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension MediaId {
|
||||||
|
init(_ id: TelegramCore_MediaId) {
|
||||||
|
self.init(namespace: id.namespace, id: id.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asFlatBuffersObject() -> TelegramCore_MediaId {
|
||||||
|
return TelegramCore_MediaId(namespace: self.namespace, id: self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension PixelDimensions {
|
||||||
|
init(_ dimensions: TelegramCore_PixelDimensions) {
|
||||||
|
self.init(width: dimensions.width, height: dimensions.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asFlatBuffersObject() -> TelegramCore_PixelDimensions {
|
||||||
|
return TelegramCore_PixelDimensions(width: self.width, height: self.height)
|
||||||
|
}
|
||||||
|
}
|
22
submodules/TelegramUI/Components/BatchVideoRendering/BUILD
Normal file
22
submodules/TelegramUI/Components/BatchVideoRendering/BUILD
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "BatchVideoRendering",
|
||||||
|
module_name = "BatchVideoRendering",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/MediaPlayer:UniversalMediaPlayer",
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/TelegramCore",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
@ -0,0 +1,341 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import Display
|
||||||
|
import UniversalMediaPlayer
|
||||||
|
import AccountContext
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramCore
|
||||||
|
import CoreMedia
|
||||||
|
|
||||||
|
public protocol BatchVideoRenderingContextTarget: AnyObject {
|
||||||
|
var batchVideoRenderingTargetState: BatchVideoRenderingContext.TargetState? { get set }
|
||||||
|
|
||||||
|
func setSampleBuffer(sampleBuffer: CMSampleBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class BatchVideoRenderingContext {
|
||||||
|
public typealias Target = BatchVideoRenderingContextTarget
|
||||||
|
|
||||||
|
public final class TargetHandle {
|
||||||
|
private weak var context: BatchVideoRenderingContext?
|
||||||
|
private let id: Int
|
||||||
|
|
||||||
|
init(context: BatchVideoRenderingContext, id: Int) {
|
||||||
|
self.context = context
|
||||||
|
self.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.context?.targetRemoved(id: self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class TargetState {
|
||||||
|
var currentFrameExpirationTimestamp: Double?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ReadingContext {
|
||||||
|
let dataPath: String
|
||||||
|
|
||||||
|
var isFailed: Bool = false
|
||||||
|
var reader: FFMpegFileReader?
|
||||||
|
|
||||||
|
init(dataPath: String) {
|
||||||
|
self.dataPath = dataPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func advance() -> CMSampleBuffer? {
|
||||||
|
outer: while true {
|
||||||
|
if self.isFailed {
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
if self.reader == nil {
|
||||||
|
let reader = FFMpegFileReader(
|
||||||
|
source: .file(self.dataPath),
|
||||||
|
useHardwareAcceleration: false,
|
||||||
|
selectedStream: .mediaType(.video),
|
||||||
|
seek: nil,
|
||||||
|
maxReadablePts: nil
|
||||||
|
)
|
||||||
|
if reader == nil {
|
||||||
|
self.isFailed = true
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
self.reader = reader
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let reader = self.reader else {
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
|
||||||
|
switch reader.readFrame() {
|
||||||
|
case let .frame(frame):
|
||||||
|
return createSampleBuffer(fromSampleBuffer: frame.sampleBuffer, withTimeOffset: .zero, duration: nil, displayImmediately: true)
|
||||||
|
case .error:
|
||||||
|
self.isFailed = true
|
||||||
|
break outer
|
||||||
|
case .endOfStream:
|
||||||
|
self.reader = nil
|
||||||
|
case .waitingForMoreData:
|
||||||
|
self.isFailed = true
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class TargetContext {
|
||||||
|
weak var target: Target?
|
||||||
|
let file: TelegramMediaFile
|
||||||
|
let userLocation: MediaResourceUserLocation
|
||||||
|
|
||||||
|
var readingContext: QueueLocalObject<ReadingContext>?
|
||||||
|
var fetchDisposable: Disposable?
|
||||||
|
var dataDisposable: Disposable?
|
||||||
|
var dataPath: String?
|
||||||
|
|
||||||
|
init(
|
||||||
|
target: Target,
|
||||||
|
file: TelegramMediaFile,
|
||||||
|
userLocation: MediaResourceUserLocation
|
||||||
|
) {
|
||||||
|
self.target = target
|
||||||
|
self.file = file
|
||||||
|
self.userLocation = userLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.fetchDisposable?.dispose()
|
||||||
|
self.dataDisposable?.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static let sharedQueue = Queue(name: "BatchVideoRenderingContext", qos: .default)
|
||||||
|
|
||||||
|
private let context: AccountContext
|
||||||
|
|
||||||
|
private var targetContexts: [Int: TargetContext] = [:]
|
||||||
|
private var nextId: Int = 0
|
||||||
|
|
||||||
|
private var isRendering: Bool = false
|
||||||
|
private var displayLink: SharedDisplayLinkDriver.Link?
|
||||||
|
|
||||||
|
public init(context: AccountContext) {
|
||||||
|
self.context = context
|
||||||
|
}
|
||||||
|
|
||||||
|
public func add(target: Target, file: TelegramMediaFile, userLocation: MediaResourceUserLocation) -> TargetHandle {
|
||||||
|
let id = self.nextId
|
||||||
|
self.nextId += 1
|
||||||
|
|
||||||
|
self.targetContexts[id] = TargetContext(
|
||||||
|
target: target,
|
||||||
|
file: file,
|
||||||
|
userLocation: userLocation
|
||||||
|
)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
return TargetHandle(context: self, id: id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func targetRemoved(id: Int) {
|
||||||
|
if self.targetContexts.removeValue(forKey: id) != nil {
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func update() {
|
||||||
|
var removeIds: [Int] = []
|
||||||
|
for (id, targetContext) in self.targetContexts {
|
||||||
|
if targetContext.target != nil {
|
||||||
|
if targetContext.fetchDisposable == nil {
|
||||||
|
//TODO:release pass resource reference
|
||||||
|
targetContext.fetchDisposable = fetchedMediaResource(
|
||||||
|
mediaBox: self.context.account.postbox.mediaBox,
|
||||||
|
userLocation: targetContext.userLocation,
|
||||||
|
userContentType: .sticker,
|
||||||
|
reference: .media(media: .standalone(media: targetContext.file), resource: targetContext.file.resource)
|
||||||
|
).startStrict()
|
||||||
|
}
|
||||||
|
if targetContext.dataDisposable == nil {
|
||||||
|
targetContext.dataDisposable = (self.context.account.postbox.mediaBox.resourceData(targetContext.file.resource)
|
||||||
|
|> deliverOnMainQueue).startStrict(next: { [weak self, weak targetContext] data in
|
||||||
|
guard let self, let targetContext else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if data.complete && targetContext.dataPath == nil {
|
||||||
|
targetContext.dataPath = data.path
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if targetContext.readingContext == nil, let dataPath = targetContext.dataPath {
|
||||||
|
targetContext.readingContext = QueueLocalObject(queue: BatchVideoRenderingContext.sharedQueue, generate: {
|
||||||
|
return ReadingContext(dataPath: dataPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeIds.append(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for id in removeIds {
|
||||||
|
self.targetContexts.removeValue(forKey: id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.targetContexts.isEmpty {
|
||||||
|
if self.displayLink == nil {
|
||||||
|
self.displayLink = SharedDisplayLinkDriver.shared.add { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.updateRendering()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.displayLink = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateRendering() {
|
||||||
|
if self.isRendering {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let timestamp = CACurrentMediaTime()
|
||||||
|
|
||||||
|
var removeIds: [Int] = []
|
||||||
|
var renderIds: [Int] = []
|
||||||
|
for (id, targetContext) in self.targetContexts {
|
||||||
|
guard let target = targetContext.target else {
|
||||||
|
removeIds.append(id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let targetState: TargetState
|
||||||
|
if let current = target.batchVideoRenderingTargetState {
|
||||||
|
targetState = current
|
||||||
|
} else {
|
||||||
|
targetState = TargetState()
|
||||||
|
target.batchVideoRenderingTargetState = targetState
|
||||||
|
}
|
||||||
|
|
||||||
|
if let currentFrameExpirationTimestamp = targetState.currentFrameExpirationTimestamp {
|
||||||
|
if timestamp >= currentFrameExpirationTimestamp {
|
||||||
|
renderIds.append(id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderIds.append(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in removeIds {
|
||||||
|
self.targetContexts.removeValue(forKey: id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !renderIds.isEmpty {
|
||||||
|
self.isRendering = true
|
||||||
|
|
||||||
|
var readingContexts: [Int: QueueLocalObject<ReadingContext>] = [:]
|
||||||
|
for id in renderIds {
|
||||||
|
guard let targetContext = self.targetContexts[id] else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if let readingContext = targetContext.readingContext {
|
||||||
|
readingContexts[id] = readingContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BatchVideoRenderingContext.sharedQueue.async { [weak self] in
|
||||||
|
var sampleBuffers: [Int: CMSampleBuffer?] = [:]
|
||||||
|
for (id, readingContext) in readingContexts {
|
||||||
|
guard let readingContext = readingContext.unsafeGet() else {
|
||||||
|
sampleBuffers[id] = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if let sampleBuffer = readingContext.advance() {
|
||||||
|
sampleBuffers[id] = sampleBuffer
|
||||||
|
} else {
|
||||||
|
sampleBuffers[id] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isRendering = false
|
||||||
|
|
||||||
|
for (id, sampleBuffer) in sampleBuffers {
|
||||||
|
guard let targetContext = self.targetContexts[id], let target = targetContext.target, let targetState = target.batchVideoRenderingTargetState else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let sampleBuffer {
|
||||||
|
target.setSampleBuffer(sampleBuffer: sampleBuffer)
|
||||||
|
if let targetState = target.batchVideoRenderingTargetState {
|
||||||
|
targetState.currentFrameExpirationTimestamp = CACurrentMediaTime() + CMSampleBufferGetDuration(sampleBuffer).seconds
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetState.currentFrameExpirationTimestamp = CACurrentMediaTime() + 1.0 / 30.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.targetContexts.isEmpty {
|
||||||
|
if self.displayLink == nil {
|
||||||
|
self.displayLink = SharedDisplayLinkDriver.shared.add { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.updateRendering()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.displayLink = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createSampleBuffer(fromSampleBuffer sampleBuffer: CMSampleBuffer, withTimeOffset timeOffset: CMTime, duration: CMTime?, displayImmediately: Bool) -> CMSampleBuffer? {
|
||||||
|
var itemCount: CMItemCount = 0
|
||||||
|
var status = CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, entryCount: 0, arrayToFill: nil, entriesNeededOut: &itemCount)
|
||||||
|
if status != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var timingInfo = [CMSampleTimingInfo](repeating: CMSampleTimingInfo(duration: CMTimeMake(value: 0, timescale: 0), presentationTimeStamp: CMTimeMake(value: 0, timescale: 0), decodeTimeStamp: CMTimeMake(value: 0, timescale: 0)), count: itemCount)
|
||||||
|
status = CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, entryCount: itemCount, arrayToFill: &timingInfo, entriesNeededOut: &itemCount)
|
||||||
|
if status != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let dur = duration {
|
||||||
|
for i in 0 ..< itemCount {
|
||||||
|
timingInfo[i].decodeTimeStamp = CMTimeAdd(timingInfo[i].decodeTimeStamp, timeOffset)
|
||||||
|
timingInfo[i].presentationTimeStamp = CMTimeAdd(timingInfo[i].presentationTimeStamp, timeOffset)
|
||||||
|
timingInfo[i].duration = dur
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i in 0 ..< itemCount {
|
||||||
|
timingInfo[i].decodeTimeStamp = CMTimeAdd(timingInfo[i].decodeTimeStamp, timeOffset)
|
||||||
|
timingInfo[i].presentationTimeStamp = CMTimeAdd(timingInfo[i].presentationTimeStamp, timeOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleBufferOffset: CMSampleBuffer?
|
||||||
|
CMSampleBufferCreateCopyWithNewTiming(allocator: kCFAllocatorDefault, sampleBuffer: sampleBuffer, sampleTimingEntryCount: itemCount, sampleTimingArray: &timingInfo, sampleBufferOut: &sampleBufferOffset)
|
||||||
|
guard let sampleBufferOffset else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if displayImmediately {
|
||||||
|
let attachments: NSArray = CMSampleBufferGetSampleAttachmentsArray(sampleBufferOffset, createIfNecessary: true)! as NSArray
|
||||||
|
let dict: NSMutableDictionary = attachments[0] as! NSMutableDictionary
|
||||||
|
dict[kCMSampleAttachmentKey_DisplayImmediately as NSString] = true as NSNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampleBufferOffset
|
||||||
|
}
|
@ -530,6 +530,11 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
private var appliedHlsInlinePlaybackRange: Range<Int64>?
|
private var appliedHlsInlinePlaybackRange: Range<Int64>?
|
||||||
private var hlsInlinePlaybackRangeDisposable: Disposable?
|
private var hlsInlinePlaybackRangeDisposable: Disposable?
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
private var testDeferHLSMedia: Bool = true
|
||||||
|
private var deferHLSMediaTimer: Foundation.Timer?
|
||||||
|
#endif
|
||||||
|
|
||||||
override public init() {
|
override public init() {
|
||||||
self.pinchContainerNode = PinchSourceContainerNode()
|
self.pinchContainerNode = PinchSourceContainerNode()
|
||||||
|
|
||||||
@ -864,9 +869,36 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
let hlsInlinePlaybackRange = self.hlsInlinePlaybackRange
|
let hlsInlinePlaybackRange = self.hlsInlinePlaybackRange
|
||||||
let appliedHlsInlinePlaybackRange = self.appliedHlsInlinePlaybackRange
|
let appliedHlsInlinePlaybackRange = self.appliedHlsInlinePlaybackRange
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
let testDeferHLSMedia = self.testDeferHLSMedia
|
||||||
|
#endif
|
||||||
|
|
||||||
return { [weak self] context, presentationData, dateTimeFormat, message, associatedData, attributes, media, mediaIndex, dateAndStatus, automaticDownload, peerType, peerId, sizeCalculation, layoutConstants, contentMode, presentationContext in
|
return { [weak self] context, presentationData, dateTimeFormat, message, associatedData, attributes, media, mediaIndex, dateAndStatus, automaticDownload, peerType, peerId, sizeCalculation, layoutConstants, contentMode, presentationContext in
|
||||||
let _ = peerType
|
let _ = peerType
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
var media = media
|
||||||
|
var maybeRestoreHLSMedia = false
|
||||||
|
if testDeferHLSMedia {
|
||||||
|
if let file = media as? TelegramMediaFile, !file.alternativeRepresentations.isEmpty {
|
||||||
|
maybeRestoreHLSMedia = true
|
||||||
|
media = TelegramMediaFile(
|
||||||
|
fileId: file.fileId,
|
||||||
|
partialReference: file.partialReference,
|
||||||
|
resource: file.resource,
|
||||||
|
previewRepresentations: file.previewRepresentations,
|
||||||
|
videoThumbnails: file.videoThumbnails,
|
||||||
|
videoCover: file.videoCover,
|
||||||
|
immediateThumbnailData: file.immediateThumbnailData,
|
||||||
|
mimeType: file.mimeType,
|
||||||
|
size: file.size,
|
||||||
|
attributes: file.attributes,
|
||||||
|
alternativeRepresentations: []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var useInlineHLS = true
|
var useInlineHLS = true
|
||||||
var displayInlineScrubber = true
|
var displayInlineScrubber = true
|
||||||
var startFromSavedPosition = true
|
var startFromSavedPosition = true
|
||||||
@ -882,13 +914,6 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#if DEBUG
|
|
||||||
if "".isEmpty {
|
|
||||||
displayInlineScrubber = false
|
|
||||||
startFromSavedPosition = false
|
|
||||||
}
|
|
||||||
#endif*/
|
|
||||||
|
|
||||||
var nativeSize: CGSize
|
var nativeSize: CGSize
|
||||||
|
|
||||||
let isSecretMedia = message.containsSecretMedia
|
let isSecretMedia = message.containsSecretMedia
|
||||||
@ -1823,6 +1848,18 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
strongSelf.preferredStoryHighQuality = associatedData.preferredStoryHighQuality
|
strongSelf.preferredStoryHighQuality = associatedData.preferredStoryHighQuality
|
||||||
strongSelf.showSensitiveContent = associatedData.showSensitiveContent
|
strongSelf.showSensitiveContent = associatedData.showSensitiveContent
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
if strongSelf.testDeferHLSMedia && maybeRestoreHLSMedia && strongSelf.deferHLSMediaTimer == nil {
|
||||||
|
strongSelf.deferHLSMediaTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { [weak strongSelf] _ in
|
||||||
|
guard let strongSelf else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.testDeferHLSMedia = false
|
||||||
|
strongSelf.requestInlineUpdate?()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if let previousArguments = strongSelf.currentImageArguments {
|
if let previousArguments = strongSelf.currentImageArguments {
|
||||||
if previousArguments.imageSize == arguments.imageSize {
|
if previousArguments.imageSize == arguments.imageSize {
|
||||||
strongSelf.pinchContainerNode.frame = imageFrame
|
strongSelf.pinchContainerNode.frame = imageFrame
|
||||||
|
@ -50,6 +50,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUIPreferences",
|
"//submodules/TelegramUIPreferences",
|
||||||
"//submodules/TelegramCore/FlatBuffers",
|
"//submodules/TelegramCore/FlatBuffers",
|
||||||
"//submodules/TelegramCore/FlatSerialization",
|
"//submodules/TelegramCore/FlatSerialization",
|
||||||
|
"//submodules/TelegramUI/Components/BatchVideoRendering",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -19,18 +19,20 @@ import SoftwareVideo
|
|||||||
import AVFoundation
|
import AVFoundation
|
||||||
import PhotoResources
|
import PhotoResources
|
||||||
import ShimmerEffect
|
import ShimmerEffect
|
||||||
|
import BatchVideoRendering
|
||||||
|
|
||||||
private class GifVideoLayer: AVSampleBufferDisplayLayer {
|
private class GifVideoLayer: AVSampleBufferDisplayLayer, BatchVideoRenderingContext.Target {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
private let batchVideoContext: BatchVideoRenderingContext
|
||||||
private let userLocation: MediaResourceUserLocation
|
private let userLocation: MediaResourceUserLocation
|
||||||
private let file: TelegramMediaFile?
|
private let file: TelegramMediaFile?
|
||||||
|
|
||||||
private var frameManager: SoftwareVideoLayerFrameManager?
|
private var batchVideoTargetHandle: BatchVideoRenderingContext.TargetHandle?
|
||||||
|
var batchVideoRenderingTargetState: BatchVideoRenderingContext.TargetState?
|
||||||
|
|
||||||
private var thumbnailDisposable: Disposable?
|
private var thumbnailDisposable: Disposable?
|
||||||
|
|
||||||
private var playbackTimestamp: Double = 0.0
|
private var isReadyToRender: Bool = false
|
||||||
private var playbackTimer: SwiftSignalKit.Timer?
|
|
||||||
|
|
||||||
var started: (() -> Void)?
|
var started: (() -> Void)?
|
||||||
|
|
||||||
@ -39,28 +41,13 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer {
|
|||||||
if self.shouldBeAnimating == oldValue {
|
if self.shouldBeAnimating == oldValue {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.updateShouldBeRendering()
|
||||||
if self.shouldBeAnimating {
|
|
||||||
self.playbackTimer?.invalidate()
|
|
||||||
let startTimestamp = self.playbackTimestamp + CFAbsoluteTimeGetCurrent()
|
|
||||||
self.playbackTimer = SwiftSignalKit.Timer(timeout: 1.0 / 30.0, repeat: true, completion: { [weak self] in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let timestamp = CFAbsoluteTimeGetCurrent() - startTimestamp
|
|
||||||
strongSelf.frameManager?.tick(timestamp: timestamp)
|
|
||||||
strongSelf.playbackTimestamp = timestamp
|
|
||||||
}, queue: .mainQueue())
|
|
||||||
self.playbackTimer?.start()
|
|
||||||
} else {
|
|
||||||
self.playbackTimer?.invalidate()
|
|
||||||
self.playbackTimer = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(context: AccountContext, userLocation: MediaResourceUserLocation, file: TelegramMediaFile?, synchronousLoad: Bool) {
|
init(context: AccountContext, batchVideoContext: BatchVideoRenderingContext, userLocation: MediaResourceUserLocation, file: TelegramMediaFile?, synchronousLoad: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.batchVideoContext = batchVideoContext
|
||||||
self.userLocation = userLocation
|
self.userLocation = userLocation
|
||||||
self.file = file
|
self.file = file
|
||||||
|
|
||||||
@ -102,6 +89,7 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.context = layer.context
|
self.context = layer.context
|
||||||
|
self.batchVideoContext = layer.batchVideoContext
|
||||||
self.userLocation = layer.userLocation
|
self.userLocation = layer.userLocation
|
||||||
self.file = layer.file
|
self.file = layer.file
|
||||||
|
|
||||||
@ -117,18 +105,28 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func setupVideo() {
|
private func setupVideo() {
|
||||||
guard let file = self.file else {
|
self.isReadyToRender = true
|
||||||
return
|
self.updateShouldBeRendering()
|
||||||
}
|
}
|
||||||
let frameManager = SoftwareVideoLayerFrameManager(account: self.context.account, userLocation: self.userLocation, userContentType: .other, fileReference: .savedGif(media: file), layerHolder: nil, layer: self)
|
|
||||||
self.frameManager = frameManager
|
private func updateShouldBeRendering() {
|
||||||
frameManager.started = { [weak self] in
|
let shouldBeRendering = self.shouldBeAnimating && self.isReadyToRender
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
if shouldBeRendering, let file = self.file {
|
||||||
|
if self.batchVideoTargetHandle == nil {
|
||||||
|
self.batchVideoTargetHandle = self.batchVideoContext.add(target: self, file: file, userLocation: self.userLocation)
|
||||||
}
|
}
|
||||||
let _ = strongSelf
|
} else {
|
||||||
|
self.batchVideoTargetHandle = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSampleBuffer(sampleBuffer: CMSampleBuffer) {
|
||||||
|
if #available(iOS 17.0, *) {
|
||||||
|
self.sampleBufferRenderer.enqueue(sampleBuffer)
|
||||||
|
} else {
|
||||||
|
self.enqueue(sampleBuffer)
|
||||||
}
|
}
|
||||||
frameManager.start()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +380,7 @@ public final class GifPagerContentComponent: Component {
|
|||||||
init(
|
init(
|
||||||
item: Item?,
|
item: Item?,
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
|
batchVideoContext: BatchVideoRenderingContext,
|
||||||
groupId: String,
|
groupId: String,
|
||||||
attemptSynchronousLoad: Bool,
|
attemptSynchronousLoad: Bool,
|
||||||
onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void
|
onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void
|
||||||
@ -389,7 +388,7 @@ public final class GifPagerContentComponent: Component {
|
|||||||
self.item = item
|
self.item = item
|
||||||
self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder
|
self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder
|
||||||
|
|
||||||
super.init(context: context, userLocation: .other, file: item?.file.media, synchronousLoad: attemptSynchronousLoad)
|
super.init(context: context, batchVideoContext: batchVideoContext, userLocation: .other, file: item?.file.media, synchronousLoad: attemptSynchronousLoad)
|
||||||
|
|
||||||
if item == nil {
|
if item == nil {
|
||||||
self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0)
|
self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0)
|
||||||
@ -594,6 +593,7 @@ public final class GifPagerContentComponent: Component {
|
|||||||
private var pagerEnvironment: PagerComponentChildEnvironment?
|
private var pagerEnvironment: PagerComponentChildEnvironment?
|
||||||
private var theme: PresentationTheme?
|
private var theme: PresentationTheme?
|
||||||
private var itemLayout: ItemLayout?
|
private var itemLayout: ItemLayout?
|
||||||
|
private var batchVideoContext: BatchVideoRenderingContext?
|
||||||
|
|
||||||
private var currentLoadMoreToken: String?
|
private var currentLoadMoreToken: String?
|
||||||
|
|
||||||
@ -833,6 +833,14 @@ public final class GifPagerContentComponent: Component {
|
|||||||
searchInset += itemLayout.searchHeight
|
searchInset += itemLayout.searchHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let batchVideoContext: BatchVideoRenderingContext
|
||||||
|
if let current = self.batchVideoContext {
|
||||||
|
batchVideoContext = current
|
||||||
|
} else {
|
||||||
|
batchVideoContext = BatchVideoRenderingContext(context: component.context)
|
||||||
|
self.batchVideoContext = batchVideoContext
|
||||||
|
}
|
||||||
|
|
||||||
if let itemRange = itemLayout.visibleItems(for: self.scrollView.bounds) {
|
if let itemRange = itemLayout.visibleItems(for: self.scrollView.bounds) {
|
||||||
for index in itemRange.lowerBound ..< itemRange.upperBound {
|
for index in itemRange.lowerBound ..< itemRange.upperBound {
|
||||||
var item: Item?
|
var item: Item?
|
||||||
@ -869,6 +877,7 @@ public final class GifPagerContentComponent: Component {
|
|||||||
itemLayer = ItemLayer(
|
itemLayer = ItemLayer(
|
||||||
item: item,
|
item: item,
|
||||||
context: component.context,
|
context: component.context,
|
||||||
|
batchVideoContext: batchVideoContext,
|
||||||
groupId: "savedGif",
|
groupId: "savedGif",
|
||||||
attemptSynchronousLoad: attemptSynchronousLoads,
|
attemptSynchronousLoad: attemptSynchronousLoads,
|
||||||
onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in
|
onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in
|
||||||
|
@ -118,21 +118,6 @@ final class GalleryHiddenMediaManagerImpl: GalleryHiddenMediaManager {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
return index
|
return index
|
||||||
|
|
||||||
/*let index = self.sourcesDisposables.add((signal |> deliverOnMainQueue).start(next: { [weak self] id in
|
|
||||||
if let strongSelf = self {
|
|
||||||
if id != state?.0 {
|
|
||||||
if let (previousId, previousIndex) = state {
|
|
||||||
strongSelf.removeHiddenMedia(id: previousId, index: previousIndex)
|
|
||||||
state = nil
|
|
||||||
}
|
|
||||||
if let id = id {
|
|
||||||
state = (id, strongSelf.addHiddenMedia(id: id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
return index*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeSource(_ index: Int) {
|
func removeSource(_ index: Int) {
|
||||||
|
@ -58,6 +58,8 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public weak var currentPictureInPictureNode: AnyObject?
|
||||||
|
|
||||||
private let queue = Queue.mainQueue()
|
private let queue = Queue.mainQueue()
|
||||||
|
|
||||||
private let accountManager: AccountManager<TelegramAccountManagerTypes>
|
private let accountManager: AccountManager<TelegramAccountManagerTypes>
|
||||||
|
@ -318,6 +318,11 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
})
|
})
|
||||||
case let .gallery(gallery):
|
case let .gallery(gallery):
|
||||||
params.dismissInput()
|
params.dismissInput()
|
||||||
|
|
||||||
|
if GalleryController.maybeExpandPIP(context: params.context, messageId: params.message.id) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
let _ = (gallery
|
let _ = (gallery
|
||||||
|> deliverOnMainQueue).startStandalone(next: { gallery in
|
|> deliverOnMainQueue).startStandalone(next: { gallery in
|
||||||
gallery.centralItemUpdated = { messageId in
|
gallery.centralItemUpdated = { messageId in
|
||||||
|
@ -1105,7 +1105,7 @@ final class HLSVideoJSNativeContentNode: ASDisplayNode, UniversalVideoContentNod
|
|||||||
|
|
||||||
let thumbnailVideoReference = HLSVideoContent.minimizedHLSQuality(file: fileReference, codecConfiguration: self.codecConfiguration)?.file ?? fileReference
|
let thumbnailVideoReference = HLSVideoContent.minimizedHLSQuality(file: fileReference, codecConfiguration: self.codecConfiguration)?.file ?? fileReference
|
||||||
|
|
||||||
self.imageNode.setSignal(internalMediaGridMessageVideo(postbox: postbox, userLocation: userLocation, videoReference: thumbnailVideoReference, previewSourceFileReference: nil, imageReference: nil, onlyFullSize: onlyFullSizeThumbnail, useLargeThumbnail: useLargeThumbnail, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail || fileReference.media.isInstantVideo) |> map { [weak self] getSize, getData in
|
self.imageNode.setSignal(internalMediaGridMessageVideo(postbox: postbox, userLocation: userLocation, videoReference: thumbnailVideoReference, previewSourceFileReference: fileReference, imageReference: nil, onlyFullSize: onlyFullSizeThumbnail, useLargeThumbnail: useLargeThumbnail, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail || fileReference.media.isInstantVideo) |> map { [weak self] getSize, getData in
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
if let strongSelf = self, strongSelf.dimensions == nil {
|
if let strongSelf = self, strongSelf.dimensions == nil {
|
||||||
if let dimensions = getSize() {
|
if let dimensions = getSize() {
|
||||||
|
@ -678,8 +678,11 @@ private:
|
|||||||
|
|
||||||
- (void)setTone:(CallAudioTone * _Nullable)tone {
|
- (void)setTone:(CallAudioTone * _Nullable)tone {
|
||||||
_audioDeviceModule->perform([tone](tgcalls::SharedAudioDeviceModule *audioDeviceModule) {
|
_audioDeviceModule->perform([tone](tgcalls::SharedAudioDeviceModule *audioDeviceModule) {
|
||||||
//audioDeviceModule->audioDeviceModule()->setTone([tone asTone]);
|
#ifdef WEBRTC_IOS
|
||||||
//TODO:implement
|
WrappedAudioDeviceModuleIOS *deviceModule = (WrappedAudioDeviceModuleIOS *)audioDeviceModule->audioDeviceModule().get();
|
||||||
|
webrtc::tgcalls_ios_adm::AudioDeviceModuleIOS *deviceModule_iOS = (webrtc::tgcalls_ios_adm::AudioDeviceModuleIOS *)deviceModule->WrappedInstance().get();
|
||||||
|
deviceModule_iOS->setTone([tone asTone]);
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b07cb07fb9bcb97f745e74c27f8751e8bef1dfb3
|
Subproject commit d50eeeb40ce6a2d36d505bcaf0b5f4e5ed473f22
|
Loading…
x
Reference in New Issue
Block a user