mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge branches 'master' and 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
ab0ec36112
87 changed files with 942 additions and 867 deletions
|
|
@ -1070,7 +1070,7 @@ private final class NotificationServiceHandler {
|
|||
if let resource = fetchResource {
|
||||
if let _ = strongSelf.stateManager?.postbox.mediaBox.completedResourcePath(resource) {
|
||||
} else {
|
||||
let intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int(Int32.max), MediaBoxFetchPriority.maximum)])
|
||||
let intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int64.max, MediaBoxFetchPriority.maximum)])
|
||||
fetchMediaSignal = Signal { subscriber in
|
||||
let collectedData = Atomic<Data>(value: Data())
|
||||
return standaloneMultipartFetch(
|
||||
|
|
@ -1121,7 +1121,7 @@ private final class NotificationServiceHandler {
|
|||
if let path = strongSelf.stateManager?.postbox.mediaBox.completedResourcePath(resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
|
||||
fetchNotificationSoundSignal = .single(data)
|
||||
} else {
|
||||
let intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int(Int32.max), MediaBoxFetchPriority.maximum)])
|
||||
let intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int64.max, MediaBoxFetchPriority.maximum)])
|
||||
fetchNotificationSoundSignal = Signal { subscriber in
|
||||
let collectedData = Atomic<Data>(value: Data())
|
||||
return standaloneMultipartFetch(
|
||||
|
|
|
|||
|
|
@ -46,15 +46,15 @@ public func messageMediaFileCancelInteractiveFetch(context: AccountContext, mess
|
|||
context.fetchManager.cancelInteractiveFetches(category: fetchCategoryForFile(file), location: .chat(messageId.peerId), locationKey: .messageId(messageId), resource: file.resource)
|
||||
}
|
||||
|
||||
public func messageMediaImageInteractiveFetched(context: AccountContext, message: Message, image: TelegramMediaImage, resource: MediaResource, range: Range<Int>? = nil, userInitiated: Bool = true, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Void, NoError> {
|
||||
public func messageMediaImageInteractiveFetched(context: AccountContext, message: Message, image: TelegramMediaImage, resource: MediaResource, range: Range<Int64>? = nil, userInitiated: Bool = true, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Void, NoError> {
|
||||
return messageMediaImageInteractiveFetched(fetchManager: context.fetchManager, messageId: message.id, messageReference: MessageReference(message), image: image, resource: resource, range: range, userInitiated: userInitiated, priority: .userInitiated, storeToDownloadsPeerType: storeToDownloadsPeerType)
|
||||
}
|
||||
|
||||
public func messageMediaImageInteractiveFetched(fetchManager: FetchManager, messageId: MessageId, messageReference: MessageReference, image: TelegramMediaImage, resource: MediaResource, range: Range<Int>? = nil, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Void, NoError> {
|
||||
public func messageMediaImageInteractiveFetched(fetchManager: FetchManager, messageId: MessageId, messageReference: MessageReference, image: TelegramMediaImage, resource: MediaResource, range: Range<Int64>? = nil, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Void, NoError> {
|
||||
let mediaReference = AnyMediaReference.message(message: messageReference, media: image)
|
||||
let ranges: IndexSet
|
||||
if let range = range {
|
||||
ranges = IndexSet(integersIn: range)
|
||||
ranges = IndexSet(integersIn: Int(range.lowerBound) ..< Int(range.upperBound))
|
||||
} else {
|
||||
ranges = FetchCompleteRange
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ public protocol UniversalVideoManager: AnyObject {
|
|||
func addPlaybackCompleted(id: AnyHashable, _ f: @escaping () -> Void) -> Int
|
||||
func removePlaybackCompleted(id: AnyHashable, index: Int)
|
||||
func statusSignal(content: UniversalVideoContent) -> Signal<MediaPlayerStatus?, NoError>
|
||||
func bufferingStatusSignal(content: UniversalVideoContent) -> Signal<(IndexSet, Int)?, NoError>
|
||||
func bufferingStatusSignal(content: UniversalVideoContent) -> Signal<(IndexSet, Int64)?, NoError>
|
||||
}
|
||||
|
||||
public enum AudioRecordingState: Equatable {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import AVFoundation
|
|||
public protocol UniversalVideoContentNode: AnyObject {
|
||||
var ready: Signal<Void, NoError> { get }
|
||||
var status: Signal<MediaPlayerStatus, NoError> { get }
|
||||
var bufferingStatus: Signal<(IndexSet, Int)?, NoError> { get }
|
||||
var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> { get }
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition)
|
||||
|
||||
|
|
@ -105,8 +105,8 @@ public final class UniversalVideoNode: ASDisplayNode {
|
|||
return self._status.get()
|
||||
}
|
||||
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int)?>()
|
||||
public var bufferingStatus: Signal<(IndexSet, Int)?, NoError> {
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int64)?>()
|
||||
public var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> {
|
||||
return self._bufferingStatus.get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ private final class ImportManager {
|
|||
}
|
||||
|
||||
enum State {
|
||||
case progress(totalBytes: Int, totalUploadedBytes: Int, totalMediaBytes: Int, totalUploadedMediaBytes: Int)
|
||||
case progress(totalBytes: Int64, totalUploadedBytes: Int64, totalMediaBytes: Int64, totalUploadedMediaBytes: Int64)
|
||||
case error(ImportError)
|
||||
case done
|
||||
}
|
||||
|
|
@ -74,11 +74,11 @@ private final class ImportManager {
|
|||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private let totalBytes: Int
|
||||
private let totalMediaBytes: Int
|
||||
private let mainFileSize: Int
|
||||
private let totalBytes: Int64
|
||||
private let totalMediaBytes: Int64
|
||||
private let mainFileSize: Int64
|
||||
private var pendingEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]
|
||||
private var entryProgress: [String: (Int, Int)] = [:]
|
||||
private var entryProgress: [String: (Int64, Int64)] = [:]
|
||||
private var activeEntries: [String: Disposable] = [:]
|
||||
|
||||
private var stateValue: State {
|
||||
|
|
@ -99,10 +99,10 @@ private final class ImportManager {
|
|||
|
||||
self.mainFileSize = fileSize(mainFile.path) ?? 0
|
||||
|
||||
var totalMediaBytes = 0
|
||||
var totalMediaBytes: Int64 = 0
|
||||
for entry in self.entries {
|
||||
self.entryProgress[entry.1] = (Int(entry.0.uncompressedSize), 0)
|
||||
totalMediaBytes += Int(entry.0.uncompressedSize)
|
||||
self.entryProgress[entry.1] = (Int64(entry.0.uncompressedSize), 0)
|
||||
totalMediaBytes += Int64(entry.0.uncompressedSize)
|
||||
}
|
||||
self.totalBytes = self.mainFileSize + totalMediaBytes
|
||||
self.totalMediaBytes = totalMediaBytes
|
||||
|
|
@ -155,7 +155,7 @@ private final class ImportManager {
|
|||
return
|
||||
}
|
||||
|
||||
var totalUploadedMediaBytes = 0
|
||||
var totalUploadedMediaBytes: Int64 = 0
|
||||
for (_, entrySizes) in self.entryProgress {
|
||||
totalUploadedMediaBytes += entrySizes.1
|
||||
}
|
||||
|
|
@ -278,7 +278,7 @@ private final class ImportManager {
|
|||
return
|
||||
}
|
||||
if let (size, _) = strongSelf.entryProgress[entry.1] {
|
||||
strongSelf.entryProgress[entry.1] = (size, Int(progress * Float(entry.0.uncompressedSize)))
|
||||
strongSelf.entryProgress[entry.1] = (size, Int64(progress * Float(entry.0.uncompressedSize)))
|
||||
strongSelf.updateProgress()
|
||||
}
|
||||
}, error: { [weak self] error in
|
||||
|
|
@ -321,7 +321,7 @@ public final class ChatImportActivityScreen: ViewController {
|
|||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
private let totalBytes: Int
|
||||
private let totalBytes: Int64
|
||||
private var state: ImportManager.State
|
||||
|
||||
private var videoNode: UniversalVideoNode?
|
||||
|
|
@ -329,7 +329,7 @@ public final class ChatImportActivityScreen: ViewController {
|
|||
|
||||
fileprivate var remainingAnimationSeconds: Double?
|
||||
|
||||
init(controller: ChatImportActivityScreen, context: AccountContext, totalBytes: Int, totalMediaBytes: Int) {
|
||||
init(controller: ChatImportActivityScreen, context: AccountContext, totalBytes: Int64, totalMediaBytes: Int64) {
|
||||
self.controller = controller
|
||||
self.context = context
|
||||
self.totalBytes = totalBytes
|
||||
|
|
@ -727,8 +727,8 @@ public final class ChatImportActivityScreen: ViewController {
|
|||
fileprivate var peerId: PeerId
|
||||
private let archivePath: String?
|
||||
private let mainEntry: TempBoxFile
|
||||
private let totalBytes: Int
|
||||
private let totalMediaBytes: Int
|
||||
private let totalBytes: Int64
|
||||
private let totalMediaBytes: Int64
|
||||
private let otherEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]
|
||||
|
||||
private var importManager: ImportManager?
|
||||
|
|
@ -759,9 +759,9 @@ public final class ChatImportActivityScreen: ViewController {
|
|||
|
||||
let mainEntrySize = fileSize(self.mainEntry.path) ?? 0
|
||||
|
||||
var totalMediaBytes = 0
|
||||
var totalMediaBytes: Int64 = 0
|
||||
for entry in self.otherEntries {
|
||||
totalMediaBytes += Int(entry.0.uncompressedSize)
|
||||
totalMediaBytes += Int64(entry.0.uncompressedSize)
|
||||
}
|
||||
self.totalBytes = mainEntrySize + totalMediaBytes
|
||||
self.totalMediaBytes = totalMediaBytes
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
var totalBytes = 0.0
|
||||
var totalProgressInBytes = 0.0
|
||||
for (entry, progress) in entries {
|
||||
var size = 1024 * 1024 * 1024
|
||||
var size: Int64 = 1024 * 1024 * 1024
|
||||
if let sizeValue = entry.resourceReference.resource.size {
|
||||
size = sizeValue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,14 @@ final class ChatListSearchInteraction {
|
|||
let clearRecentSearch: () -> Void
|
||||
let addContact: (String) -> Void
|
||||
let toggleMessageSelection: (EngineMessage.Id, Bool) -> Void
|
||||
let messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int, isFirstInList: Bool)?) -> Void)
|
||||
let messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)
|
||||
let mediaMessageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void)
|
||||
let peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?
|
||||
let present: (ViewController, Any?) -> Void
|
||||
let dismissInput: () -> Void
|
||||
let getSelectedMessageIds: () -> Set<EngineMessage.Id>?
|
||||
|
||||
init(openPeer: @escaping (EnginePeer, EnginePeer?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EnginePeer, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?) {
|
||||
init(openPeer: @escaping (EnginePeer, EnginePeer?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EnginePeer, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?) {
|
||||
self.openPeer = openPeer
|
||||
self.openDisabledPeer = openDisabledPeer
|
||||
self.openMessage = openMessage
|
||||
|
|
@ -771,7 +771,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
let _ = self.paneContainerNode.scrollToTop()
|
||||
}
|
||||
|
||||
private func messageContextAction(_ message: EngineMessage, node: ASDisplayNode?, rect: CGRect?, gesture anyRecognizer: UIGestureRecognizer?, paneKey: ChatListSearchPaneKey, downloadResource: (id: String, size: Int, isFirstInList: Bool)?) {
|
||||
private func messageContextAction(_ message: EngineMessage, node: ASDisplayNode?, rect: CGRect?, gesture anyRecognizer: UIGestureRecognizer?, paneKey: ChatListSearchPaneKey, downloadResource: (id: String, size: Int64, isFirstInList: Bool)?) {
|
||||
guard let node = node as? ContextExtractedContentContainingNode else {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder)
|
||||
case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType)
|
||||
case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType)
|
||||
case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int, isFirstInList: Bool)?, MessageSection, Bool)
|
||||
case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool)
|
||||
case addContact(String, PresentationTheme, PresentationStrings)
|
||||
|
||||
public var stableId: ChatListSearchEntryStableId {
|
||||
|
|
@ -418,7 +418,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
}
|
||||
}
|
||||
|
||||
public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem {
|
||||
public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder):
|
||||
let primaryPeer: EnginePeer
|
||||
|
|
@ -720,7 +720,7 @@ private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [
|
|||
return ChatListSearchContainerRecentTransition(deletions: deletions, insertions: insertions, updates: updates)
|
||||
}
|
||||
|
||||
public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, animated: Bool, context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ChatListSearchContainerTransition {
|
||||
public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, animated: Bool, context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ChatListSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
|
|
@ -1149,7 +1149,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
}
|
||||
}
|
||||
|
||||
var resource: (id: String, size: Int, isFirstInList: Bool)?
|
||||
var resource: (id: String, size: Int64, isFirstInList: Bool)?
|
||||
if let resourceValue = findMediaResourceById(message: item.message, resourceId: item.resourceId), let size = resourceValue.size {
|
||||
resource = (resourceValue.id.stringRepresentation, size, entries.isEmpty)
|
||||
}
|
||||
|
|
@ -1784,7 +1784,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
return
|
||||
}
|
||||
|
||||
var fetchResourceId: (id: String, size: Int, isFirstInList: Bool)?
|
||||
var fetchResourceId: (id: String, size: Int64, isFirstInList: Bool)?
|
||||
for entry in currentEntries {
|
||||
switch entry {
|
||||
case let .message(m, _, _, _, _, _, _, _, resource, _, _):
|
||||
|
|
|
|||
|
|
@ -274,10 +274,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||
TempBox.shared.dispose(tempZip)
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: gzippedData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(gzippedData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: gzippedData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
@ -354,10 +354,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||
}
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: logData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(logData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: logData.count, attributes: [.FileName(fileName: "Log-iOS-Short.txt")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(logData.count), attributes: [.FileName(fileName: "Log-iOS-Short.txt")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
@ -440,10 +440,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||
TempBox.shared.dispose(tempZip)
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: gzippedData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(gzippedData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: gzippedData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
@ -524,10 +524,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||
TempBox.shared.dispose(tempZip)
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: gzippedData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(gzippedData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: gzippedData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
@ -608,10 +608,10 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||
TempBox.shared.dispose(tempZip)
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: gzippedData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(gzippedData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: gzippedData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
@ -1234,10 +1234,10 @@ public func triggerDebugSendLogsUI(context: AccountContext, additionalInfo: Stri
|
|||
TempBox.shared.dispose(tempZip)
|
||||
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: gzippedData.count, isSecretRelated: false)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(gzippedData.count), isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: gzippedData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ public final class DirectMediaImageCache {
|
|||
return self.account.postbox.mediaBox.cachedRepresentationPathForId(resourceId.stringRepresentation, representationId: representationId, keepDuration: .general)
|
||||
}
|
||||
|
||||
private func getLoadSignal(width: Int, resource: MediaResourceReference, resourceSizeLimit: Int) -> Signal<UIImage?, NoError>? {
|
||||
private func getLoadSignal(width: Int, resource: MediaResourceReference, resourceSizeLimit: Int64) -> Signal<UIImage?, NoError>? {
|
||||
return Signal { subscriber in
|
||||
let cachePath = self.getCachePath(resourceId: resource.resource.id, imageType: .square(width: width))
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ public final class DirectMediaImageCache {
|
|||
).start()
|
||||
|
||||
let dataSignal: Signal<Data?, NoError>
|
||||
if resourceSizeLimit < Int(Int32.max) {
|
||||
if resourceSizeLimit < Int(Int64.max) {
|
||||
dataSignal = self.account.postbox.mediaBox.resourceData(resource.resource, size: resourceSizeLimit, in: 0 ..< resourceSizeLimit)
|
||||
|> map { data, _ -> Data? in
|
||||
return data
|
||||
|
|
@ -239,44 +239,44 @@ public final class DirectMediaImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
private func getProgressiveSize(mediaReference: AnyMediaReference, width: Int, representations: [TelegramMediaImageRepresentation]) -> (resource: MediaResourceReference, size: Int)? {
|
||||
private func getProgressiveSize(mediaReference: AnyMediaReference, width: Int, representations: [TelegramMediaImageRepresentation]) -> (resource: MediaResourceReference, size: Int64)? {
|
||||
if let representation = representations.first(where: { !$0.progressiveSizes.isEmpty }) {
|
||||
let selectedSize: Int32
|
||||
let selectedSize: Int64
|
||||
let progressiveSizes = representation.progressiveSizes
|
||||
if progressiveSizes.count > 0 && width <= 64 {
|
||||
selectedSize = progressiveSizes[0]
|
||||
selectedSize = Int64(progressiveSizes[0])
|
||||
} else if progressiveSizes.count > 2 && width <= 160 {
|
||||
selectedSize = progressiveSizes[2]
|
||||
selectedSize = Int64(progressiveSizes[2])
|
||||
} else if progressiveSizes.count > 4 && width <= 400 {
|
||||
selectedSize = progressiveSizes[4]
|
||||
selectedSize = Int64(progressiveSizes[4])
|
||||
} else {
|
||||
selectedSize = Int32.max
|
||||
selectedSize = Int64.max
|
||||
}
|
||||
return (mediaReference.resourceReference(representation.resource), Int(selectedSize))
|
||||
return (mediaReference.resourceReference(representation.resource), selectedSize)
|
||||
} else {
|
||||
for representation in representations.sorted(by: { $0.dimensions.width < $1.dimensions.width }) {
|
||||
if Int(Float(representation.dimensions.width) * 1.2) >= width {
|
||||
return (mediaReference.resourceReference(representation.resource), Int(Int32.max))
|
||||
return (mediaReference.resourceReference(representation.resource), Int64.max)
|
||||
}
|
||||
}
|
||||
if let representation = representations.last {
|
||||
return (mediaReference.resourceReference(representation.resource), Int(Int32.max))
|
||||
return (mediaReference.resourceReference(representation.resource), Int64.max)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func getResource(message: Message, image: TelegramMediaImage, width: Int) -> (resource: MediaResourceReference, size: Int)? {
|
||||
private func getResource(message: Message, image: TelegramMediaImage, width: Int) -> (resource: MediaResourceReference, size: Int64)? {
|
||||
return self.getProgressiveSize(mediaReference: MediaReference.message(message: MessageReference(message), media: image).abstract, width: width, representations: image.representations)
|
||||
}
|
||||
|
||||
private func getResource(message: Message, file: TelegramMediaFile, width: Int) -> (resource: MediaResourceReference, size: Int)? {
|
||||
private func getResource(message: Message, file: TelegramMediaFile, width: Int) -> (resource: MediaResourceReference, size: Int64)? {
|
||||
return self.getProgressiveSize(mediaReference: MediaReference.message(message: MessageReference(message), media: file).abstract, width: width, representations: file.previewRepresentations)
|
||||
}
|
||||
|
||||
private func getImageSynchronous(message: Message, media: Media, width: Int, possibleWidths: [Int]) -> GetMediaResult? {
|
||||
var immediateThumbnailData: Data?
|
||||
var resource: (resource: MediaResourceReference, size: Int)?
|
||||
var resource: (resource: MediaResourceReference, size: Int64)?
|
||||
if let image = media as? TelegramMediaImage {
|
||||
immediateThumbnailData = image.immediateThumbnailData
|
||||
resource = self.getResource(message: message, image: image, width: width)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ private final class FetchManagerLocationEntry {
|
|||
var combinedRanges: IndexSet {
|
||||
var result = IndexSet()
|
||||
if self.userInitiated {
|
||||
result.insert(integersIn: 0 ..< Int(Int32.max))
|
||||
result.insert(integersIn: 0 ..< Int(Int64.max))
|
||||
} else {
|
||||
for range in self.ranges.copyItems() {
|
||||
result.formUnion(range)
|
||||
|
|
@ -220,13 +220,13 @@ private final class FetchManagerCategoryContext {
|
|||
activeContext.ranges = ranges
|
||||
let entryCompleted = self.entryCompleted
|
||||
let storeManager = self.storeManager
|
||||
let parsedRanges: [(Range<Int>, MediaBoxFetchPriority)]?
|
||||
if ranges.count == 1 && ranges.min() == 0 && ranges.max() == Int(Int32.max) {
|
||||
let parsedRanges: [(Range<Int64>, MediaBoxFetchPriority)]?
|
||||
if ranges.count == 1 && ranges.min() == 0 && ranges.max() == Int(Int64.max) {
|
||||
parsedRanges = nil
|
||||
} else {
|
||||
var resultRanges: [(Range<Int>, MediaBoxFetchPriority)] = []
|
||||
var resultRanges: [(Range<Int64>, MediaBoxFetchPriority)] = []
|
||||
for range in ranges.rangeView {
|
||||
resultRanges.append((range, .default))
|
||||
resultRanges.append((Int64(range.lowerBound) ..< Int64(range.upperBound), .default))
|
||||
}
|
||||
parsedRanges = resultRanges
|
||||
}
|
||||
|
|
@ -302,14 +302,14 @@ private final class FetchManagerCategoryContext {
|
|||
if let entry = self.entries[topEntryId] {
|
||||
let ranges = entry.combinedRanges
|
||||
|
||||
let parsedRanges: [(Range<Int>, MediaBoxFetchPriority)]?
|
||||
let parsedRanges: [(Range<Int64>, MediaBoxFetchPriority)]?
|
||||
|
||||
var count = 0
|
||||
var isCompleteRange = false
|
||||
var isVideoPreload = false
|
||||
for range in ranges.rangeView {
|
||||
count += 1
|
||||
if range.lowerBound == 0 && range.upperBound == Int(Int32.max) {
|
||||
if range.lowerBound == 0 && range.upperBound == Int(Int64.max) {
|
||||
isCompleteRange = true
|
||||
}
|
||||
}
|
||||
|
|
@ -321,9 +321,9 @@ private final class FetchManagerCategoryContext {
|
|||
if count == 1 && isCompleteRange {
|
||||
parsedRanges = nil
|
||||
} else {
|
||||
var resultRanges: [(Range<Int>, MediaBoxFetchPriority)] = []
|
||||
var resultRanges: [(Range<Int64>, MediaBoxFetchPriority)] = []
|
||||
for range in ranges.rangeView {
|
||||
resultRanges.append((range, .default))
|
||||
resultRanges.append((Int64(range.lowerBound) ..< Int64(range.upperBound), .default))
|
||||
}
|
||||
parsedRanges = resultRanges
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,11 +255,11 @@ final class ChatVideoGalleryItemScrubberView: UIView {
|
|||
}))
|
||||
}
|
||||
|
||||
func setBufferingStatusSignal(_ status: Signal<(IndexSet, Int)?, NoError>?) {
|
||||
func setBufferingStatusSignal(_ status: Signal<(IndexSet, Int64)?, NoError>?) {
|
||||
self.scrubberNode.bufferingStatus = status
|
||||
}
|
||||
|
||||
func setFetchStatusSignal(_ fetchStatus: Signal<MediaResourceStatus, NoError>?, strings: PresentationStrings, decimalSeparator: String, fileSize: Int?) {
|
||||
func setFetchStatusSignal(_ fetchStatus: Signal<MediaResourceStatus, NoError>?, strings: PresentationStrings, decimalSeparator: String, fileSize: Int64?) {
|
||||
let formatting = DataSizeStringFormatting(strings: strings, decimalSeparator: decimalSeparator)
|
||||
if let fileSize = fileSize {
|
||||
if let fetchStatus = fetchStatus {
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ public final class LegacyLiveUploadInterface: VideoConversionWatcher, TGLiveUplo
|
|||
|
||||
let result = strongSelf.dataValue.modify { dataValue in
|
||||
if let dataValue = dataValue, dataValue.complete {
|
||||
return MediaResourceData(path: path, offset: 0, size: size, complete: true)
|
||||
return MediaResourceData(path: path, offset: 0, size: Int64(size), complete: true)
|
||||
} else {
|
||||
return MediaResourceData(path: path, offset: 0, size: size, complete: false)
|
||||
return MediaResourceData(path: path, offset: 0, size: Int64(size), complete: false)
|
||||
}
|
||||
}
|
||||
if let result = result {
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public func fetchPhotoLibraryResource(localIdentifier: String) -> Signal<MediaRe
|
|||
#if DEBUG
|
||||
print("compression completion \((CACurrentMediaTime() - startTime) * 1000.0) ms")
|
||||
#endif
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
subscriber.putCompletion()
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ public final class VideoLibraryMediaResource: TelegramMediaResource {
|
|||
public let localIdentifier: String
|
||||
public let conversion: VideoLibraryMediaResourceConversion
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public var headerSize: Int32 {
|
||||
return 32 * 1024
|
||||
}
|
||||
|
|
@ -148,6 +152,10 @@ public struct LocalFileVideoMediaResourceId {
|
|||
}
|
||||
|
||||
public final class LocalFileVideoMediaResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public let randomId: Int64
|
||||
public let path: String
|
||||
public let adjustments: VideoMediaResourceAdjustments?
|
||||
|
|
@ -209,6 +217,10 @@ public struct PhotoLibraryMediaResourceId {
|
|||
}
|
||||
|
||||
public class PhotoLibraryMediaResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public let localIdentifier: String
|
||||
public let uniqueId: Int64
|
||||
|
||||
|
|
@ -253,6 +265,10 @@ public struct LocalFileGifMediaResourceId {
|
|||
}
|
||||
|
||||
public final class LocalFileGifMediaResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public let randomId: Int64
|
||||
public let path: String
|
||||
|
||||
|
|
@ -302,6 +318,10 @@ public struct BundleResourceId {
|
|||
}
|
||||
|
||||
public class BundleResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public let nameHash: Int64
|
||||
public let path: String
|
||||
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ public final class ManagedFile {
|
|||
ftruncate(self.fd, count)
|
||||
}
|
||||
|
||||
public func getSize() -> Int? {
|
||||
public func getSize() -> Int64? {
|
||||
if let queue = self.queue {
|
||||
assert(queue.isCurrent())
|
||||
}
|
||||
var value = stat()
|
||||
if fstat(self.fd, &value) == 0 {
|
||||
return Int(value.st_size)
|
||||
return value.st_size
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,14 +71,14 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
print("maxOffset \(maxOffset)")
|
||||
#endif*/
|
||||
|
||||
let resourceSize: Int = resourceReference.resource.size ?? Int(Int32.max - 1)
|
||||
let readCount = max(0, min(resourceSize - context.readingOffset, Int(bufferSize)))
|
||||
let requestRange: Range<Int> = context.readingOffset ..< (context.readingOffset + readCount)
|
||||
let resourceSize: Int64 = resourceReference.resource.size ?? (Int64.max - 1)
|
||||
let readCount = max(0, min(resourceSize - context.readingOffset, Int64(bufferSize)))
|
||||
let requestRange: Range<Int64> = context.readingOffset ..< (context.readingOffset + readCount)
|
||||
|
||||
assert(readCount < 16 * 1024 * 1024)
|
||||
|
||||
if let maximumFetchSize = context.maximumFetchSize {
|
||||
context.touchedRanges.insert(integersIn: requestRange)
|
||||
context.touchedRanges.insert(integersIn: Int(requestRange.lowerBound) ..< Int(requestRange.upperBound))
|
||||
var totalCount = 0
|
||||
for range in context.touchedRanges.rangeView {
|
||||
totalCount += range.count
|
||||
|
|
@ -95,7 +95,7 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
if readCount == 0 {
|
||||
fetchedData = Data()
|
||||
} else {
|
||||
if let tempFilePath = context.tempFilePath, let fileData = (try? Data(contentsOf: URL(fileURLWithPath: tempFilePath), options: .mappedRead))?.subdata(in: requestRange) {
|
||||
if let tempFilePath = context.tempFilePath, let fileData = (try? Data(contentsOf: URL(fileURLWithPath: tempFilePath), options: .mappedRead))?.subdata(in: Int(requestRange.lowerBound) ..< Int(requestRange.upperBound)) {
|
||||
fetchedData = fileData
|
||||
} else {
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
|
|
@ -124,15 +124,15 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
let fd = open(tempFilePath, O_RDONLY, S_IRUSR)
|
||||
if fd >= 0 {
|
||||
let readingOffset = context.readingOffset
|
||||
let readCount = max(0, min(fileSize - readingOffset, Int(bufferSize)))
|
||||
let readCount = max(0, min(fileSize - readingOffset, Int64(bufferSize)))
|
||||
let range = readingOffset ..< (readingOffset + readCount)
|
||||
assert(readCount < 16 * 1024 * 1024)
|
||||
|
||||
lseek(fd, off_t(range.lowerBound), SEEK_SET)
|
||||
var data = Data(count: readCount)
|
||||
var data = Data(count: Int(readCount))
|
||||
data.withUnsafeMutableBytes { bytes -> Void in
|
||||
precondition(bytes.baseAddress != nil)
|
||||
let readBytes = read(fd, bytes.baseAddress, readCount)
|
||||
let readBytes = read(fd, bytes.baseAddress, Int(readCount))
|
||||
precondition(readBytes <= readCount)
|
||||
}
|
||||
fetchedData = data
|
||||
|
|
@ -146,7 +146,7 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
var completedRequest = false
|
||||
let disposable = data.start(next: { next in
|
||||
if next.complete {
|
||||
let readCount = max(0, min(next.size - readingOffset, Int(bufferSize)))
|
||||
let readCount = max(0, min(next.size - readingOffset, Int64(bufferSize)))
|
||||
let range = readingOffset ..< (readingOffset + readCount)
|
||||
|
||||
assert(readCount < 16 * 1024 * 1024)
|
||||
|
|
@ -154,10 +154,10 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
let fd = open(next.path, O_RDONLY, S_IRUSR)
|
||||
if fd >= 0 {
|
||||
lseek(fd, off_t(range.lowerBound), SEEK_SET)
|
||||
var data = Data(count: readCount)
|
||||
var data = Data(count: Int(readCount))
|
||||
data.withUnsafeMutableBytes { bytes -> Void in
|
||||
precondition(bytes.baseAddress != nil)
|
||||
let readBytes = read(fd, bytes.baseAddress, readCount)
|
||||
let readBytes = read(fd, bytes.baseAddress, Int(readCount))
|
||||
assert(readBytes <= readCount)
|
||||
precondition(readBytes <= readCount)
|
||||
}
|
||||
|
|
@ -181,10 +181,10 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
assert(fetchedData.count <= readCount)
|
||||
fetchedData.withUnsafeBytes { bytes -> Void in
|
||||
precondition(bytes.baseAddress != nil)
|
||||
memcpy(buffer, bytes.baseAddress, min(fetchedData.count, readCount))
|
||||
memcpy(buffer, bytes.baseAddress, min(fetchedData.count, Int(readCount)))
|
||||
}
|
||||
fetchedCount = Int32(fetchedData.count)
|
||||
context.readingOffset += Int(fetchedCount)
|
||||
context.readingOffset += Int64(fetchedCount)
|
||||
}
|
||||
|
||||
if context.closed {
|
||||
|
|
@ -202,7 +202,7 @@ private func seekCallback(userData: UnsafeMutableRawPointer?, offset: Int64, whe
|
|||
|
||||
var result: Int64 = offset
|
||||
|
||||
let resourceSize: Int
|
||||
let resourceSize: Int64
|
||||
if let size = resourceReference.resource.size {
|
||||
resourceSize = size
|
||||
} else {
|
||||
|
|
@ -210,14 +210,14 @@ private func seekCallback(userData: UnsafeMutableRawPointer?, offset: Int64, whe
|
|||
if let tempFilePath = context.tempFilePath, let fileSize = fileSize(tempFilePath) {
|
||||
resourceSize = fileSize
|
||||
} else {
|
||||
var resultSize: Int = Int(Int32.max - 1)
|
||||
var resultSize: Int64 = Int64.max - 1
|
||||
let data = postbox.mediaBox.resourceData(resourceReference.resource, pathExtension: nil, option: .complete(waitUntilFetchStatus: false))
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
let _ = context.currentSemaphore.swap(semaphore)
|
||||
var completedRequest = false
|
||||
let disposable = data.start(next: { next in
|
||||
if next.complete {
|
||||
resultSize = Int(next.size)
|
||||
resultSize = next.size
|
||||
completedRequest = true
|
||||
semaphore.signal()
|
||||
}
|
||||
|
|
@ -232,14 +232,14 @@ private func seekCallback(userData: UnsafeMutableRawPointer?, offset: Int64, whe
|
|||
resourceSize = resultSize
|
||||
}
|
||||
} else {
|
||||
resourceSize = Int(Int32.max - 1)
|
||||
resourceSize = Int64.max - 1
|
||||
}
|
||||
}
|
||||
|
||||
if (whence & FFMPEG_AVSEEK_SIZE) != 0 {
|
||||
result = Int64(resourceSize == Int(Int32.max - 1) ? 0 : resourceSize)
|
||||
} else {
|
||||
context.readingOffset = Int(min(Int64(resourceSize), offset))
|
||||
context.readingOffset = min(Int64(resourceSize), offset)
|
||||
|
||||
if context.readingOffset != context.requestedDataOffset {
|
||||
context.requestedDataOffset = context.readingOffset
|
||||
|
|
@ -249,7 +249,7 @@ private func seekCallback(userData: UnsafeMutableRawPointer?, offset: Int64, whe
|
|||
} else {
|
||||
if streamable {
|
||||
if context.tempFilePath == nil {
|
||||
let fetchRange: Range<Int> = context.readingOffset ..< Int(Int32.max)
|
||||
let fetchRange: Range<Int64> = context.readingOffset ..< Int64.max
|
||||
context.fetchedDataDisposable.set(fetchedMediaResource(mediaBox: postbox.mediaBox, reference: resourceReference, range: (fetchRange, .elevated), statsCategory: statsCategory, preferBackgroundReferenceRevalidation: streamable).start())
|
||||
}
|
||||
} else if !context.requestedCompleteFetch && context.fetchAutomatically {
|
||||
|
|
@ -282,9 +282,9 @@ final class FFMpegMediaFrameSourceContext: NSObject {
|
|||
fileprivate var statsCategory: MediaResourceStatsCategory?
|
||||
|
||||
private let ioBufferSize = 1 * 1024
|
||||
fileprivate var readingOffset = 0
|
||||
fileprivate var readingOffset: Int64 = 0
|
||||
|
||||
fileprivate var requestedDataOffset: Int?
|
||||
fileprivate var requestedDataOffset: Int64?
|
||||
fileprivate let fetchedDataDisposable = MetaDisposable()
|
||||
fileprivate let keepDataDisposable = MetaDisposable()
|
||||
fileprivate let fetchedFullDataDisposable = MetaDisposable()
|
||||
|
|
@ -342,7 +342,7 @@ final class FFMpegMediaFrameSourceContext: NSObject {
|
|||
|
||||
if streamable {
|
||||
if self.tempFilePath == nil {
|
||||
self.fetchedDataDisposable.set(fetchedMediaResource(mediaBox: postbox.mediaBox, reference: resourceReference, range: (0 ..< Int(Int32.max), .elevated), statsCategory: self.statsCategory ?? .generic, preferBackgroundReferenceRevalidation: streamable).start())
|
||||
self.fetchedDataDisposable.set(fetchedMediaResource(mediaBox: postbox.mediaBox, reference: resourceReference, range: (0 ..< Int64.max, .elevated), statsCategory: self.statsCategory ?? .generic, preferBackgroundReferenceRevalidation: streamable).start())
|
||||
}
|
||||
} else if !self.requestedCompleteFetch && self.fetchAutomatically {
|
||||
self.requestedCompleteFetch = true
|
||||
|
|
@ -449,7 +449,7 @@ final class FFMpegMediaFrameSourceContext: NSObject {
|
|||
|
||||
if streamable {
|
||||
if self.tempFilePath == nil {
|
||||
self.fetchedFullDataDisposable.set(fetchedMediaResource(mediaBox: postbox.mediaBox, reference: resourceReference, range: (0 ..< Int(Int32.max), .default), statsCategory: self.statsCategory ?? .generic, preferBackgroundReferenceRevalidation: streamable).start())
|
||||
self.fetchedFullDataDisposable.set(fetchedMediaResource(mediaBox: postbox.mediaBox, reference: resourceReference, range: (0 ..< Int64.max, .default), statsCategory: self.statsCategory ?? .generic, preferBackgroundReferenceRevalidation: streamable).start())
|
||||
}
|
||||
self.requestedCompleteFetch = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ private final class MediaPlayerScrubbingBufferingNode: ASDisplayNode {
|
|||
private let containerNode: ASDisplayNode
|
||||
private let foregroundNode: ASImageNode
|
||||
|
||||
private var ranges: (IndexSet, Int)?
|
||||
private var ranges: (IndexSet, Int64)?
|
||||
|
||||
init(color: UIColor, lineCap: MediaPlayerScrubbingNodeCap, lineHeight: CGFloat) {
|
||||
self.color = color
|
||||
|
|
@ -239,7 +239,7 @@ private final class MediaPlayerScrubbingBufferingNode: ASDisplayNode {
|
|||
self.addSubnode(self.containerNode)
|
||||
}
|
||||
|
||||
func updateStatus(_ ranges: IndexSet, _ size: Int) {
|
||||
func updateStatus(_ ranges: IndexSet, _ size: Int64) {
|
||||
self.ranges = (ranges, size)
|
||||
if !self.bounds.width.isZero {
|
||||
self.updateLayout(size: self.bounds.size, transition: .animated(duration: 0.15, curve: .easeInOut))
|
||||
|
|
@ -358,9 +358,9 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
private var bufferingStatusDisposable: Disposable?
|
||||
private var bufferingStatusValuePromise = Promise<(IndexSet, Int)?>()
|
||||
private var bufferingStatusValuePromise = Promise<(IndexSet, Int64)?>()
|
||||
|
||||
public var bufferingStatus: Signal<(IndexSet, Int)?, NoError>? {
|
||||
public var bufferingStatus: Signal<(IndexSet, Int64)?, NoError>? {
|
||||
didSet {
|
||||
if let bufferingStatus = self.bufferingStatus {
|
||||
self.bufferingStatusValuePromise.set(bufferingStatus)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
|
||||
let data: Signal<(Data, Bool), NoError>
|
||||
|
||||
let readCount = min(256 * 1024, Int(bufferSize))
|
||||
let requestRange: Range<Int> = context.readingOffset ..< (context.readingOffset + readCount)
|
||||
let readCount = min(256 * 1024, Int64(bufferSize))
|
||||
let requestRange: Range<Int64> = context.readingOffset ..< (context.readingOffset + readCount)
|
||||
|
||||
context.currentNumberOfReads += 1
|
||||
context.currentReadBytes += readCount
|
||||
|
|
@ -59,7 +59,7 @@ private func readPacketCallback(userData: UnsafeMutableRawPointer?, buffer: Unsa
|
|||
memcpy(buffer, bytes, fetchedData.count)
|
||||
}
|
||||
let fetchedCount = Int32(fetchedData.count)
|
||||
context.readingOffset += Int(fetchedCount)
|
||||
context.readingOffset += Int64(fetchedCount)
|
||||
return fetchedCount
|
||||
} else {
|
||||
return 0
|
||||
|
|
@ -71,7 +71,7 @@ private func seekCallback(userData: UnsafeMutableRawPointer?, offset: Int64, whe
|
|||
if (whence & FFMPEG_AVSEEK_SIZE) != 0 {
|
||||
return Int64(context.size)
|
||||
} else {
|
||||
context.readingOffset = Int(offset)
|
||||
context.readingOffset = offset
|
||||
return offset
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ private final class SoftwareVideoStream {
|
|||
private final class UniversalSoftwareVideoSourceImpl {
|
||||
fileprivate let mediaBox: MediaBox
|
||||
fileprivate let fileReference: FileMediaReference
|
||||
fileprivate let size: Int
|
||||
fileprivate let size: Int64
|
||||
fileprivate let automaticallyFetchHeader: Bool
|
||||
|
||||
fileprivate let state: ValuePromise<UniversalSoftwareVideoSourceState>
|
||||
|
|
@ -108,12 +108,12 @@ private final class UniversalSoftwareVideoSourceImpl {
|
|||
fileprivate var avFormatContext: FFMpegAVFormatContext!
|
||||
fileprivate var videoStream: SoftwareVideoStream!
|
||||
|
||||
fileprivate var readingOffset: Int = 0
|
||||
fileprivate var readingOffset: Int64 = 0
|
||||
|
||||
fileprivate var cancelRead: Signal<Bool, NoError>
|
||||
fileprivate var requiredDataIsNotLocallyAvailable: (() -> Void)?
|
||||
fileprivate var currentNumberOfReads: Int = 0
|
||||
fileprivate var currentReadBytes: Int = 0
|
||||
fileprivate var currentReadBytes: Int64 = 0
|
||||
|
||||
init?(mediaBox: MediaBox, fileReference: FileMediaReference, state: ValuePromise<UniversalSoftwareVideoSourceState>, cancelInitialization: Signal<Bool, NoError>, automaticallyFetchHeader: Bool, hintVP9: Bool = false) {
|
||||
guard let size = fileReference.media.size else {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ public class SecureIdLocalImageResource: TelegramMediaResource {
|
|||
public let localId: Int64
|
||||
public let source: TelegramMediaResource
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init(localId: Int64, source: TelegramMediaResource) {
|
||||
self.localId = localId
|
||||
self.source = source
|
||||
|
|
@ -61,7 +65,7 @@ public func fetchSecureIdLocalImageResource(postbox: Postbox, resource: SecureId
|
|||
|
||||
subscriber.putNext(.reset)
|
||||
|
||||
let fetch = fetchResource(resource.source, .single([(0 ..< Int.max, .default)]), nil)
|
||||
let fetch = fetchResource(resource.source, .single([(0 ..< Int64.max, .default)]), nil)
|
||||
let buffer = Atomic<Buffer>(value: Buffer())
|
||||
let disposable = fetch.start(next: { result in
|
||||
switch result {
|
||||
|
|
@ -106,19 +110,19 @@ public func fetchSecureIdLocalImageResource(postbox: Postbox, resource: SecureId
|
|||
guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
|
||||
return
|
||||
}
|
||||
data.copyBytes(to: bytes, from: range)
|
||||
data.copyBytes(to: bytes, from: Int(range.lowerBound) ..< Int(range.upperBound))
|
||||
}
|
||||
}
|
||||
case let .dataPart(resourceOffset, data, range, _):
|
||||
let _ = buffer.with { buffer in
|
||||
if buffer.data.count < resourceOffset + range.count {
|
||||
buffer.data.count = resourceOffset + range.count
|
||||
if buffer.data.count < Int(resourceOffset) + range.count {
|
||||
buffer.data.count = Int(resourceOffset) + range.count
|
||||
}
|
||||
buffer.data.withUnsafeMutableBytes { buffer -> Void in
|
||||
guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
|
||||
return
|
||||
}
|
||||
data.copyBytes(to: bytes.advanced(by: resourceOffset), from: range)
|
||||
data.copyBytes(to: bytes.advanced(by: Int(resourceOffset)), from: Int(range.lowerBound) ..< Int(range.upperBound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +135,7 @@ public func fetchSecureIdLocalImageResource(postbox: Postbox, resource: SecureId
|
|||
context.setBlendMode(.copy)
|
||||
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
||||
}, scale: 1.0), let scaledData = scaledImage.jpegData(compressionQuality: 0.6) {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: scaledData, range: 0 ..< scaledData.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: scaledData, range: 0 ..< Int64(scaledData.count), complete: true))
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ private let progressiveRangeMap: [(Int, [Int])] = [
|
|||
(Int(Int32.max), [2, 3, 4])
|
||||
]
|
||||
|
||||
public func representationFetchRangeForDisplayAtSize(representation: TelegramMediaImageRepresentation, dimension: Int?) -> Range<Int>? {
|
||||
public func representationFetchRangeForDisplayAtSize(representation: TelegramMediaImageRepresentation, dimension: Int?) -> Range<Int64>? {
|
||||
if representation.progressiveSizes.count > 1, let dimension = dimension {
|
||||
var largestByteSize = Int(representation.progressiveSizes[0])
|
||||
var largestByteSize = Int64(representation.progressiveSizes[0])
|
||||
for (maxDimension, byteSizes) in progressiveRangeMap {
|
||||
largestByteSize = Int(representation.progressiveSizes[min(representation.progressiveSizes.count - 1, byteSizes.last!)])
|
||||
largestByteSize = Int64(representation.progressiveSizes[min(representation.progressiveSizes.count - 1, byteSizes.last!)])
|
||||
if maxDimension >= dimension {
|
||||
break
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ public func chatMessagePhotoDatas(postbox: Postbox, photoReference: ImageMediaRe
|
|||
if let progressiveRepresentation = progressiveImageRepresentation(photoReference.media.representations), progressiveRepresentation.progressiveSizes.count > 1 {
|
||||
enum SizeSource {
|
||||
case miniThumbnail(data: Data)
|
||||
case image(size: Int)
|
||||
case image(size: Int64)
|
||||
}
|
||||
|
||||
var sources: [SizeSource] = []
|
||||
|
|
@ -70,7 +70,7 @@ public func chatMessagePhotoDatas(postbox: Postbox, photoReference: ImageMediaRe
|
|||
if progressiveRepresentation.progressiveSizes.count - 1 < sizeIndex {
|
||||
return nil
|
||||
}
|
||||
return .image(size: Int(progressiveRepresentation.progressiveSizes[sizeIndex]))
|
||||
return .image(size: Int64(progressiveRepresentation.progressiveSizes[sizeIndex]))
|
||||
})
|
||||
largestByteSize = Int(progressiveRepresentation.progressiveSizes[min(progressiveRepresentation.progressiveSizes.count - 1, byteSizes.last!)])
|
||||
if maxDimension >= Int(fullRepresentationSize.width) {
|
||||
|
|
@ -78,7 +78,7 @@ public func chatMessagePhotoDatas(postbox: Postbox, photoReference: ImageMediaRe
|
|||
}
|
||||
}
|
||||
if sources.isEmpty {
|
||||
sources.append(.image(size: largestByteSize))
|
||||
sources.append(.image(size: Int64(largestByteSize)))
|
||||
}
|
||||
if let miniThumbnail = photoReference.media.immediateThumbnailData.flatMap(decodeTinyThumbnail) {
|
||||
sources.insert(.miniThumbnail(data: miniThumbnail), at: 0)
|
||||
|
|
@ -90,7 +90,7 @@ public func chatMessagePhotoDatas(postbox: Postbox, photoReference: ImageMediaRe
|
|||
case let .miniThumbnail(data):
|
||||
return .single((source, data))
|
||||
case let .image(size):
|
||||
return postbox.mediaBox.resourceData(progressiveRepresentation.resource, size: Int(progressiveRepresentation.progressiveSizes.last!), in: 0 ..< size, mode: .incremental, notifyAboutIncomplete: true, attemptSynchronously: synchronousLoad)
|
||||
return postbox.mediaBox.resourceData(progressiveRepresentation.resource, size: Int64(progressiveRepresentation.progressiveSizes.last!), in: 0 ..< size, mode: .incremental, notifyAboutIncomplete: true, attemptSynchronously: synchronousLoad)
|
||||
|> map { (data, _) -> (SizeSource, Data?) in
|
||||
return (source, data)
|
||||
}
|
||||
|
|
@ -127,9 +127,9 @@ public func chatMessagePhotoDatas(postbox: Postbox, photoReference: ImageMediaRe
|
|||
})
|
||||
var fetchDisposable: Disposable?
|
||||
if autoFetchFullSize {
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: postbox.mediaBox, reference: photoReference.resourceReference(progressiveRepresentation.resource), range: (0 ..< largestByteSize, .default), statsCategory: .image).start()
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: postbox.mediaBox, reference: photoReference.resourceReference(progressiveRepresentation.resource), range: (0 ..< Int64(largestByteSize), .default), statsCategory: .image).start()
|
||||
} else if useMiniThumbnailIfAvailable {
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: postbox.mediaBox, reference: photoReference.resourceReference(progressiveRepresentation.resource), range: (0 ..< thumbnailByteSize, .default), statsCategory: .image).start()
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: postbox.mediaBox, reference: photoReference.resourceReference(progressiveRepresentation.resource), range: (0 ..< Int64(thumbnailByteSize), .default), statsCategory: .image).start()
|
||||
}
|
||||
|
||||
return ActionDisposable {
|
||||
|
|
@ -1671,7 +1671,7 @@ public func chatMessagePhotoStatus(context: AccountContext, messageId: MessageId
|
|||
context.account.postbox.mediaBox.resourceRangesStatus(largestRepresentation.resource)
|
||||
)
|
||||
|> map { status, rangeStatus -> MediaResourceStatus in
|
||||
if rangeStatus.contains(integersIn: range) {
|
||||
if rangeStatus.contains(integersIn: Int(range.lowerBound) ..< Int(range.upperBound)) {
|
||||
return .Local
|
||||
}
|
||||
|
||||
|
|
@ -1708,39 +1708,11 @@ public func standaloneChatMessagePhotoInteractiveFetched(account: Account, photo
|
|||
|
||||
public func chatMessagePhotoInteractiveFetched(context: AccountContext, photoReference: ImageMediaReference, displayAtSize: Int?, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Never, NoError> {
|
||||
if let largestRepresentation = largestRepresentationForPhoto(photoReference.media) {
|
||||
var fetchRange: (Range<Int>, MediaBoxFetchPriority)?
|
||||
var fetchRange: (Range<Int64>, MediaBoxFetchPriority)?
|
||||
if let displayAtSize = displayAtSize, let range = representationFetchRangeForDisplayAtSize(representation: largestRepresentation, dimension: displayAtSize) {
|
||||
fetchRange = (range, .default)
|
||||
}
|
||||
|
||||
/*switch photoReference {
|
||||
case let .message(message, _):
|
||||
if let id = message.id {
|
||||
let ranges: IndexSet
|
||||
if let (range, _) = fetchRange {
|
||||
ranges = IndexSet(integersIn: range)
|
||||
} else {
|
||||
ranges = IndexSet(integersIn: 0 ..< Int(Int32.max) as Range<Int>)
|
||||
}
|
||||
return context.fetchManager.interactivelyFetched(
|
||||
category: .image,
|
||||
location: .chat(id.peerId),
|
||||
locationKey: .messageId(id),
|
||||
mediaReference: photoReference.abstract,
|
||||
resourceReference: photoReference.resourceReference(largestRepresentation.resource),
|
||||
ranges: ranges,
|
||||
statsCategory: .image,
|
||||
elevatedPriority: false,
|
||||
userInitiated: false,
|
||||
priority: .userInitiated,
|
||||
storeToDownloadsPeerType: nil
|
||||
)
|
||||
|> ignoreValues
|
||||
}
|
||||
default:
|
||||
break
|
||||
}*/
|
||||
|
||||
return fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: photoReference.resourceReference(largestRepresentation.resource), range: fetchRange, statsCategory: .image, reportResultStatus: true)
|
||||
|> mapToSignal { type -> Signal<FetchResourceSourceType, FetchResourceError> in
|
||||
if case .remote = type, let peerType = storeToDownloadsPeerType {
|
||||
|
|
@ -2294,7 +2266,7 @@ public func svgIconImageFile(account: Account, fileReference: FileMediaReference
|
|||
} else {
|
||||
data = Signal { subscriber in
|
||||
if let url = getAppBundle().url(forResource: "durgerking", withExtension: "placeholder"), let data = try? Data(contentsOf: url, options: .mappedRead) {
|
||||
subscriber.putNext(MediaResourceData(path: url.path, offset: 0, size: data.count, complete: true))
|
||||
subscriber.putNext(MediaResourceData(path: url.path, offset: 0, size: Int64(data.count), complete: true))
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return EmptyDisposable
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import Foundation
|
||||
|
||||
public func fileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int? {
|
||||
public func fileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? {
|
||||
if useTotalFileAllocatedSize {
|
||||
let url = URL(fileURLWithPath: path)
|
||||
if let values = (try? url.resourceValues(forKeys: Set([.isRegularFileKey, .totalFileAllocatedSizeKey]))) {
|
||||
if values.isRegularFile ?? false {
|
||||
if let fileSize = values.totalFileAllocatedSize {
|
||||
return fileSize
|
||||
return Int64(fileSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ public func fileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) ->
|
|||
|
||||
var value = stat()
|
||||
if stat(path, &value) == 0 {
|
||||
return Int(value.st_size)
|
||||
return value.st_size
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ private struct ResourceStorePaths {
|
|||
|
||||
public struct MediaResourceData {
|
||||
public let path: String
|
||||
public let offset: Int
|
||||
public let size: Int
|
||||
public let offset: Int64
|
||||
public let size: Int64
|
||||
public let complete: Bool
|
||||
|
||||
public init(path: String, offset: Int, size: Int, complete: Bool) {
|
||||
public init(path: String, offset: Int64, size: Int64, complete: Bool) {
|
||||
self.path = path
|
||||
self.offset = offset
|
||||
self.size = size
|
||||
|
|
@ -71,10 +71,10 @@ public enum MediaBoxFetchPriority: Int32 {
|
|||
}
|
||||
|
||||
public enum MediaResourceDataFetchResult {
|
||||
case dataPart(resourceOffset: Int, data: Data, range: Range<Int>, complete: Bool)
|
||||
case resourceSizeUpdated(Int)
|
||||
case dataPart(resourceOffset: Int64, data: Data, range: Range<Int64>, complete: Bool)
|
||||
case resourceSizeUpdated(Int64)
|
||||
case progressUpdated(Float)
|
||||
case replaceHeader(data: Data, range: Range<Int>)
|
||||
case replaceHeader(data: Data, range: Range<Int64>)
|
||||
case moveLocalFile(path: String)
|
||||
case moveTempFile(file: TempBoxFile)
|
||||
case copyLocalItem(MediaResourceDataFetchCopyLocalItem)
|
||||
|
|
@ -153,9 +153,9 @@ public final class MediaBox {
|
|||
private var fileContexts: [MediaResourceId: MediaBoxFileContext] = [:]
|
||||
private var keepResourceContexts: [MediaResourceId: MediaBoxKeepResourceContext] = [:]
|
||||
|
||||
private var wrappedFetchResource = Promise<(MediaResource, Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>>()
|
||||
private var wrappedFetchResource = Promise<(MediaResource, Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>>()
|
||||
|
||||
public var fetchResource: ((MediaResource, Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>)? {
|
||||
public var fetchResource: ((MediaResource, Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>)? {
|
||||
didSet {
|
||||
if let fetchResource = self.fetchResource {
|
||||
wrappedFetchResource.set(.single(fetchResource))
|
||||
|
|
@ -318,7 +318,7 @@ public final class MediaBox {
|
|||
return self.resourceStatus(resource.id, resourceSize: resource.size, approximateSynchronousValue: approximateSynchronousValue)
|
||||
}
|
||||
|
||||
public func resourceStatus(_ resourceId: MediaResourceId, resourceSize: Int?, approximateSynchronousValue: Bool = false) -> Signal<MediaResourceStatus, NoError> {
|
||||
public func resourceStatus(_ resourceId: MediaResourceId, resourceSize: Int64?, approximateSynchronousValue: Bool = false) -> Signal<MediaResourceStatus, NoError> {
|
||||
let signal = Signal<MediaResourceStatus, NoError> { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ public final class MediaBox {
|
|||
}
|
||||
}
|
||||
}
|
||||
}, size: resourceSize.flatMap(Int32.init))
|
||||
}, size: resourceSize)
|
||||
statusUpdateDisposable.set(ActionDisposable {
|
||||
statusDisposable.dispose()
|
||||
releaseContext()
|
||||
|
|
@ -487,7 +487,7 @@ public final class MediaBox {
|
|||
case let .incremental(waitUntilFetchStatus):
|
||||
waitUntilAfterInitialFetch = waitUntilFetchStatus
|
||||
}
|
||||
let dataDisposable = fileContext.data(range: 0 ..< Int32.max, waitUntilAfterInitialFetch: waitUntilAfterInitialFetch, next: { value in
|
||||
let dataDisposable = fileContext.data(range: 0 ..< Int64.max, waitUntilAfterInitialFetch: waitUntilAfterInitialFetch, next: { value in
|
||||
self.dataQueue.async {
|
||||
if value.complete {
|
||||
if let pathExtension = pathExtension {
|
||||
|
|
@ -564,7 +564,7 @@ public final class MediaBox {
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchedResourceData(_ resource: MediaResource, in range: Range<Int>, priority: MediaBoxFetchPriority = .default, parameters: MediaResourceFetchParameters?) -> Signal<Void, FetchResourceError> {
|
||||
public func fetchedResourceData(_ resource: MediaResource, in range: Range<Int64>, priority: MediaBoxFetchPriority = .default, parameters: MediaResourceFetchParameters?) -> Signal<Void, FetchResourceError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
|
|
@ -580,7 +580,7 @@ public final class MediaBox {
|
|||
}
|
||||
|
||||
let fetchResource = self.wrappedFetchResource.get()
|
||||
let fetchedDisposable = fileContext.fetched(range: Int32(range.lowerBound) ..< Int32(range.upperBound), priority: priority, fetch: { intervals in
|
||||
let fetchedDisposable = fileContext.fetched(range: range.lowerBound ..< range.upperBound, priority: priority, fetch: { intervals in
|
||||
return fetchResource
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
|> mapToSignal { fetch in
|
||||
|
|
@ -602,11 +602,11 @@ public final class MediaBox {
|
|||
}
|
||||
}
|
||||
|
||||
public func resourceData(_ resource: MediaResource, size: Int, in range: Range<Int>, mode: ResourceDataRangeMode = .complete, notifyAboutIncomplete: Bool = false, attemptSynchronously: Bool = false) -> Signal<(Data, Bool), NoError> {
|
||||
public func resourceData(_ resource: MediaResource, size: Int64, in range: Range<Int64>, mode: ResourceDataRangeMode = .complete, notifyAboutIncomplete: Bool = false, attemptSynchronously: Bool = false) -> Signal<(Data, Bool), NoError> {
|
||||
return self.resourceData(id: resource.id, size: size, in: range, mode: mode, notifyAboutIncomplete: notifyAboutIncomplete, attemptSynchronously: attemptSynchronously)
|
||||
}
|
||||
|
||||
public func resourceData(id: MediaResourceId, size: Int, in range: Range<Int>, mode: ResourceDataRangeMode = .complete, notifyAboutIncomplete: Bool = false, attemptSynchronously: Bool = false) -> Signal<(Data, Bool), NoError> {
|
||||
public func resourceData(id: MediaResourceId, size: Int64, in range: Range<Int64>, mode: ResourceDataRangeMode = .complete, notifyAboutIncomplete: Bool = false, attemptSynchronously: Bool = false) -> Signal<(Data, Bool), NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
|
|
@ -622,8 +622,8 @@ public final class MediaBox {
|
|||
let clippedLowerBound = min(completeSize, max(0, range.lowerBound))
|
||||
let clippedUpperBound = min(completeSize, max(0, range.upperBound))
|
||||
if clippedLowerBound < clippedUpperBound {
|
||||
file.seek(position: Int64(clippedLowerBound))
|
||||
let data = file.readData(count: clippedUpperBound)
|
||||
file.seek(position: clippedLowerBound)
|
||||
let data = file.readData(count: Int(clippedUpperBound - clippedLowerBound))
|
||||
subscriber.putNext((data, true))
|
||||
} else {
|
||||
subscriber.putNext((Data(), isComplete: true))
|
||||
|
|
@ -631,7 +631,7 @@ public final class MediaBox {
|
|||
subscriber.putCompletion()
|
||||
return EmptyDisposable
|
||||
} else {
|
||||
if let data = MediaBoxPartialFile.extractPartialData(path: paths.partial, metaPath: paths.partial + ".meta", range: Int32(range.lowerBound) ..< Int32(range.upperBound)) {
|
||||
if let data = MediaBoxPartialFile.extractPartialData(path: paths.partial, metaPath: paths.partial + ".meta", range: range) {
|
||||
subscriber.putNext((data, true))
|
||||
subscriber.putCompletion()
|
||||
return EmptyDisposable
|
||||
|
|
@ -646,8 +646,6 @@ public final class MediaBox {
|
|||
return
|
||||
}
|
||||
|
||||
let range = Int32(range.lowerBound) ..< Int32(range.upperBound)
|
||||
|
||||
let dataDisposable = fileContext.data(range: range, waitUntilAfterInitialFetch: false, next: { result in
|
||||
if let file = ManagedFile(queue: self.dataQueue, path: result.path, mode: .read), let fileSize = file.getSize() {
|
||||
if result.complete {
|
||||
|
|
@ -658,7 +656,7 @@ public final class MediaBox {
|
|||
subscriber.putCompletion()
|
||||
} else if clippedUpperBound <= fileSize {
|
||||
file.seek(position: Int64(clippedLowerBound))
|
||||
let resultData = file.readData(count: clippedUpperBound - clippedLowerBound)
|
||||
let resultData = file.readData(count: Int(clippedUpperBound - clippedLowerBound))
|
||||
subscriber.putNext((resultData, true))
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import Crc32
|
|||
import ManagedFile
|
||||
|
||||
private final class MediaBoxFileMap {
|
||||
fileprivate(set) var sum: Int32
|
||||
fileprivate(set) var sum: Int64
|
||||
private(set) var ranges: IndexSet
|
||||
private(set) var truncationSize: Int32?
|
||||
private(set) var truncationSize: Int64?
|
||||
private(set) var progress: Float?
|
||||
|
||||
init() {
|
||||
|
|
@ -21,74 +21,146 @@ private final class MediaBoxFileMap {
|
|||
return nil
|
||||
}
|
||||
|
||||
var crc: UInt32 = 0
|
||||
var count: Int32 = 0
|
||||
var sum: Int32 = 0
|
||||
var ranges: IndexSet = IndexSet()
|
||||
|
||||
guard fd.read(&crc, 4) == 4 else {
|
||||
return nil
|
||||
}
|
||||
guard fd.read(&count, 4) == 4 else {
|
||||
var firstUInt32: UInt32 = 0
|
||||
guard fd.read(&firstUInt32, 4) == 4 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 || length < 4 + 4 + count * 2 * 4 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var truncationSizeValue: Int32 = 0
|
||||
|
||||
var data = Data(count: Int(4 + count * 2 * 4))
|
||||
let dataCount = data.count
|
||||
if !(data.withUnsafeMutableBytes { rawBytes -> Bool in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
if firstUInt32 == 0x7bac1487 {
|
||||
var crc: UInt32 = 0
|
||||
guard fd.read(&crc, 4) == 4 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var count: Int32 = 0
|
||||
var sum: Int64 = 0
|
||||
var ranges: IndexSet = IndexSet()
|
||||
|
||||
guard fd.read(&count, 4) == 4 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 || length < 4 + 4 + 4 + 8 + count * 2 * 8 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var truncationSizeValue: Int32 = 0
|
||||
|
||||
var data = Data(count: Int(8 + count * 2 * 8))
|
||||
let dataCount = data.count
|
||||
if !(data.withUnsafeMutableBytes { rawBytes -> Bool in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
|
||||
guard fd.read(bytes, dataCount) == dataCount else {
|
||||
return false
|
||||
}
|
||||
|
||||
memcpy(&truncationSizeValue, bytes, 4)
|
||||
|
||||
let calculatedCrc = Crc32(bytes, Int32(dataCount))
|
||||
if calculatedCrc != crc {
|
||||
return false
|
||||
}
|
||||
|
||||
var offset = 4
|
||||
for _ in 0 ..< count {
|
||||
var intervalOffset: Int32 = 0
|
||||
var intervalLength: Int32 = 0
|
||||
memcpy(&intervalOffset, bytes.advanced(by: offset), 4)
|
||||
memcpy(&intervalLength, bytes.advanced(by: offset + 4), 4)
|
||||
offset += 8
|
||||
guard fd.read(bytes, dataCount) == dataCount else {
|
||||
return false
|
||||
}
|
||||
|
||||
ranges.insert(integersIn: Int(intervalOffset) ..< Int(intervalOffset + intervalLength))
|
||||
memcpy(&truncationSizeValue, bytes, 8)
|
||||
|
||||
sum += intervalLength
|
||||
let calculatedCrc = Crc32(bytes, Int32(dataCount))
|
||||
if calculatedCrc != crc {
|
||||
return false
|
||||
}
|
||||
|
||||
var offset = 8
|
||||
for _ in 0 ..< count {
|
||||
var intervalOffset: Int64 = 0
|
||||
var intervalLength: Int64 = 0
|
||||
memcpy(&intervalOffset, bytes.advanced(by: offset), 8)
|
||||
memcpy(&intervalLength, bytes.advanced(by: offset + 8), 8)
|
||||
offset += 8 * 2
|
||||
|
||||
ranges.insert(integersIn: Int(intervalOffset) ..< Int(intervalOffset + intervalLength))
|
||||
|
||||
sum += intervalLength
|
||||
}
|
||||
|
||||
return true
|
||||
}) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return true
|
||||
}) {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.sum = sum
|
||||
self.ranges = ranges
|
||||
if truncationSizeValue == -1 {
|
||||
self.truncationSize = nil
|
||||
self.sum = sum
|
||||
self.ranges = ranges
|
||||
if truncationSizeValue == -1 {
|
||||
self.truncationSize = nil
|
||||
} else {
|
||||
self.truncationSize = Int64(truncationSizeValue)
|
||||
}
|
||||
} else {
|
||||
self.truncationSize = truncationSizeValue
|
||||
let crc: UInt32 = firstUInt32
|
||||
var count: Int32 = 0
|
||||
var sum: Int32 = 0
|
||||
var ranges: IndexSet = IndexSet()
|
||||
|
||||
guard fd.read(&count, 4) == 4 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if count < 0 || length < 4 + 4 + count * 2 * 4 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var truncationSizeValue: Int32 = 0
|
||||
|
||||
var data = Data(count: Int(4 + count * 2 * 4))
|
||||
let dataCount = data.count
|
||||
if !(data.withUnsafeMutableBytes { rawBytes -> Bool in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
|
||||
guard fd.read(bytes, dataCount) == dataCount else {
|
||||
return false
|
||||
}
|
||||
|
||||
memcpy(&truncationSizeValue, bytes, 4)
|
||||
|
||||
let calculatedCrc = Crc32(bytes, Int32(dataCount))
|
||||
if calculatedCrc != crc {
|
||||
return false
|
||||
}
|
||||
|
||||
var offset = 4
|
||||
for _ in 0 ..< count {
|
||||
var intervalOffset: Int32 = 0
|
||||
var intervalLength: Int32 = 0
|
||||
memcpy(&intervalOffset, bytes.advanced(by: offset), 4)
|
||||
memcpy(&intervalLength, bytes.advanced(by: offset + 4), 4)
|
||||
offset += 8
|
||||
|
||||
ranges.insert(integersIn: Int(intervalOffset) ..< Int(intervalOffset + intervalLength))
|
||||
|
||||
sum += intervalLength
|
||||
}
|
||||
|
||||
return true
|
||||
}) {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.sum = Int64(sum)
|
||||
self.ranges = ranges
|
||||
if truncationSizeValue == -1 {
|
||||
self.truncationSize = nil
|
||||
} else {
|
||||
self.truncationSize = Int64(truncationSizeValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func serialize(to file: ManagedFile) {
|
||||
file.seek(position: 0)
|
||||
let buffer = WriteBuffer()
|
||||
var magic: UInt32 = 0x7bac1487
|
||||
buffer.write(&magic, offset: 0, length: 4)
|
||||
|
||||
var zero: Int32 = 0
|
||||
buffer.write(&zero, offset: 0, length: 4)
|
||||
|
||||
|
|
@ -96,29 +168,29 @@ private final class MediaBoxFileMap {
|
|||
var count: Int32 = Int32(rangeView.count)
|
||||
buffer.write(&count, offset: 0, length: 4)
|
||||
|
||||
var truncationSizeValue: Int32 = self.truncationSize ?? -1
|
||||
buffer.write(&truncationSizeValue, offset: 0, length: 4)
|
||||
var truncationSizeValue: Int64 = self.truncationSize ?? -1
|
||||
buffer.write(&truncationSizeValue, offset: 0, length: 8)
|
||||
|
||||
for range in rangeView {
|
||||
var intervalOffset = Int32(range.lowerBound)
|
||||
var intervalLength = Int32(range.count)
|
||||
buffer.write(&intervalOffset, offset: 0, length: 4)
|
||||
buffer.write(&intervalLength, offset: 0, length: 4)
|
||||
buffer.write(&intervalOffset, offset: 0, length: 8)
|
||||
buffer.write(&intervalLength, offset: 0, length: 8)
|
||||
}
|
||||
var crc: UInt32 = Crc32(buffer.memory.advanced(by: 4 * 2), Int32(buffer.length - 4 * 2))
|
||||
memcpy(buffer.memory, &crc, 4)
|
||||
var crc: UInt32 = Crc32(buffer.memory.advanced(by: 4 + 4 + 4), Int32(buffer.length - (4 + 4 + 4)))
|
||||
memcpy(buffer.memory.advanced(by: 4), &crc, 4)
|
||||
let written = file.write(buffer.memory, count: buffer.length)
|
||||
assert(written == buffer.length)
|
||||
}
|
||||
|
||||
fileprivate func fill(_ range: Range<Int32>) {
|
||||
fileprivate func fill(_ range: Range<Int64>) {
|
||||
let intRange: Range<Int> = Int(range.lowerBound) ..< Int(range.upperBound)
|
||||
let previousCount = self.ranges.count(in: intRange)
|
||||
self.ranges.insert(integersIn: intRange)
|
||||
self.sum += Int32(range.count - previousCount)
|
||||
self.sum += Int64(range.count - previousCount)
|
||||
}
|
||||
|
||||
fileprivate func truncate(_ size: Int32) {
|
||||
fileprivate func truncate(_ size: Int64) {
|
||||
self.truncationSize = size
|
||||
}
|
||||
fileprivate func progressUpdated(_ progress: Float) {
|
||||
|
|
@ -132,7 +204,7 @@ private final class MediaBoxFileMap {
|
|||
self.progress = nil
|
||||
}
|
||||
|
||||
fileprivate func contains(_ range: Range<Int32>) -> Range<Int32>? {
|
||||
fileprivate func contains(_ range: Range<Int64>) -> Range<Int64>? {
|
||||
let maxValue: Int
|
||||
if let truncationSize = self.truncationSize {
|
||||
maxValue = Int(truncationSize)
|
||||
|
|
@ -141,7 +213,7 @@ private final class MediaBoxFileMap {
|
|||
}
|
||||
let intRange: Range<Int> = Int(range.lowerBound) ..< min(maxValue, Int(range.upperBound))
|
||||
if self.ranges.contains(integersIn: intRange) {
|
||||
return Int32(intRange.lowerBound) ..< Int32(intRange.upperBound)
|
||||
return Int64(intRange.lowerBound) ..< Int64(intRange.upperBound)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -149,11 +221,11 @@ private final class MediaBoxFileMap {
|
|||
}
|
||||
|
||||
private class MediaBoxPartialFileDataRequest {
|
||||
let range: Range<Int32>
|
||||
let range: Range<Int64>
|
||||
var waitingUntilAfterInitialFetch: Bool
|
||||
let completion: (MediaResourceData) -> Void
|
||||
|
||||
init(range: Range<Int32>, waitingUntilAfterInitialFetch: Bool, completion: @escaping (MediaResourceData) -> Void) {
|
||||
init(range: Range<Int64>, waitingUntilAfterInitialFetch: Bool, completion: @escaping (MediaResourceData) -> Void) {
|
||||
self.range = range
|
||||
self.waitingUntilAfterInitialFetch = waitingUntilAfterInitialFetch
|
||||
self.completion = completion
|
||||
|
|
@ -165,21 +237,21 @@ final class MediaBoxPartialFile {
|
|||
private let path: String
|
||||
private let metaPath: String
|
||||
private let completePath: String
|
||||
private let completed: (Int32) -> Void
|
||||
private let completed: (Int64) -> Void
|
||||
private let metadataFd: ManagedFile
|
||||
private let fd: ManagedFile
|
||||
fileprivate let fileMap: MediaBoxFileMap
|
||||
private var dataRequests = Bag<MediaBoxPartialFileDataRequest>()
|
||||
private let missingRanges: MediaBoxFileMissingRanges
|
||||
private let rangeStatusRequests = Bag<((IndexSet) -> Void, () -> Void)>()
|
||||
private let statusRequests = Bag<((MediaResourceStatus) -> Void, Int32?)>()
|
||||
private let statusRequests = Bag<((MediaResourceStatus) -> Void, Int64?)>()
|
||||
|
||||
private let fullRangeRequests = Bag<Disposable>()
|
||||
|
||||
private var currentFetch: (Promise<[(Range<Int>, MediaBoxFetchPriority)]>, Disposable)?
|
||||
private var currentFetch: (Promise<[(Range<Int64>, MediaBoxFetchPriority)]>, Disposable)?
|
||||
private var processedAtLeastOneFetch: Bool = false
|
||||
|
||||
init?(queue: Queue, path: String, metaPath: String, completePath: String, completed: @escaping (Int32) -> Void) {
|
||||
init?(queue: Queue, path: String, metaPath: String, completePath: String, completed: @escaping (Int64) -> Void) {
|
||||
assert(queue.isCurrent())
|
||||
if let metadataFd = ManagedFile(queue: queue, path: metaPath, mode: .readwrite), let fd = ManagedFile(queue: queue, path: path, mode: .readwrite) {
|
||||
self.queue = queue
|
||||
|
|
@ -217,7 +289,7 @@ final class MediaBoxPartialFile {
|
|||
self.currentFetch?.1.dispose()
|
||||
}
|
||||
|
||||
static func extractPartialData(path: String, metaPath: String, range: Range<Int32>) -> Data? {
|
||||
static func extractPartialData(path: String, metaPath: String, range: Range<Int64>) -> Data? {
|
||||
guard let metadataFd = ManagedFile(queue: nil, path: metaPath, mode: .read) else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -234,7 +306,7 @@ final class MediaBoxPartialFile {
|
|||
return fd.readData(count: Int(clippedRange.upperBound - clippedRange.lowerBound))
|
||||
}
|
||||
|
||||
var storedSize: Int32 {
|
||||
var storedSize: Int64 {
|
||||
assert(self.queue.isCurrent())
|
||||
return self.fileMap.sum
|
||||
}
|
||||
|
|
@ -246,7 +318,7 @@ final class MediaBoxPartialFile {
|
|||
self.fileMap.serialize(to: self.metadataFd)
|
||||
|
||||
for request in self.dataRequests.copyItems() {
|
||||
request.completion(MediaResourceData(path: self.path, offset: Int(request.range.lowerBound), size: 0, complete: false))
|
||||
request.completion(MediaResourceData(path: self.path, offset: request.range.lowerBound, size: 0, complete: false))
|
||||
}
|
||||
|
||||
if let updatedRanges = self.missingRanges.reset(fileMap: self.fileMap) {
|
||||
|
|
@ -283,7 +355,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
|
||||
for request in self.dataRequests.copyItems() {
|
||||
request.completion(MediaResourceData(path: self.completePath, offset: Int(request.range.lowerBound), size: max(0, size - Int(request.range.lowerBound)), complete: true))
|
||||
request.completion(MediaResourceData(path: self.completePath, offset: request.range.lowerBound, size: max(0, size - request.range.lowerBound), complete: true))
|
||||
}
|
||||
self.dataRequests.removeAll()
|
||||
|
||||
|
|
@ -325,7 +397,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
|
||||
for request in self.dataRequests.copyItems() {
|
||||
request.completion(MediaResourceData(path: self.completePath, offset: Int(request.range.lowerBound), size: max(0, size - Int(request.range.lowerBound)), complete: true))
|
||||
request.completion(MediaResourceData(path: self.completePath, offset: request.range.lowerBound, size: max(0, size - request.range.lowerBound), complete: true))
|
||||
}
|
||||
self.dataRequests.removeAll()
|
||||
|
||||
|
|
@ -334,17 +406,17 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
self.statusRequests.removeAll()
|
||||
|
||||
self.completed(Int32(size))
|
||||
self.completed(size)
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func truncate(_ size: Int32) {
|
||||
func truncate(_ size: Int64) {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
let range: Range<Int32> = size ..< Int32.max
|
||||
let range: Range<Int64> = size ..< Int64.max
|
||||
|
||||
self.fileMap.truncate(size)
|
||||
self.fileMap.serialize(to: self.metadataFd)
|
||||
|
|
@ -359,24 +431,24 @@ final class MediaBoxPartialFile {
|
|||
self.updateStatuses()
|
||||
}
|
||||
|
||||
func write(offset: Int32, data: Data, dataRange: Range<Int>) {
|
||||
func write(offset: Int64, data: Data, dataRange: Range<Int64>) {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
self.fd.seek(position: Int64(offset))
|
||||
self.fd.seek(position: offset)
|
||||
let written = data.withUnsafeBytes { rawBytes -> Int in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
|
||||
return self.fd.write(bytes.advanced(by: dataRange.lowerBound), count: dataRange.count)
|
||||
return self.fd.write(bytes.advanced(by: Int(dataRange.lowerBound)), count: dataRange.count)
|
||||
}
|
||||
assert(written == dataRange.count)
|
||||
let range: Range<Int32> = offset ..< (offset + Int32(dataRange.count))
|
||||
let range: Range<Int64> = offset ..< (offset + Int64(dataRange.count))
|
||||
self.fileMap.fill(range)
|
||||
self.fileMap.serialize(to: self.metadataFd)
|
||||
|
||||
self.checkDataRequestsAfterFill(range: range)
|
||||
}
|
||||
|
||||
func checkDataRequestsAfterFill(range: Range<Int32>) {
|
||||
func checkDataRequestsAfterFill(range: Range<Int64>) {
|
||||
var removeIndices: [(Int, MediaBoxPartialFileDataRequest)] = []
|
||||
for (index, request) in self.dataRequests.copyItemsWithIndices() {
|
||||
if request.range.overlaps(range) {
|
||||
|
|
@ -402,7 +474,7 @@ final class MediaBoxPartialFile {
|
|||
if let truncationSize = self.fileMap.truncationSize, truncationSize < maxValue {
|
||||
maxValue = truncationSize
|
||||
}
|
||||
request.completion(MediaResourceData(path: self.path, offset: Int(request.range.lowerBound), size: Int(maxValue) - Int(request.range.lowerBound), complete: true))
|
||||
request.completion(MediaResourceData(path: self.path, offset: request.range.lowerBound, size: maxValue - request.range.lowerBound, complete: true))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +523,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
func read(range: Range<Int32>) -> Data? {
|
||||
func read(range: Range<Int64>) -> Data? {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
if let actualRange = self.fileMap.contains(range) {
|
||||
|
|
@ -472,11 +544,11 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
func data(range: Range<Int32>, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable {
|
||||
func data(range: Range<Int64>, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
if let actualRange = self.fileMap.contains(range) {
|
||||
next(MediaResourceData(path: self.path, offset: Int(actualRange.lowerBound), size: actualRange.count, complete: true))
|
||||
next(MediaResourceData(path: self.path, offset: actualRange.lowerBound, size: Int64(actualRange.count), complete: true))
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +556,7 @@ final class MediaBoxPartialFile {
|
|||
if waitUntilAfterInitialFetch && !self.processedAtLeastOneFetch {
|
||||
waitingUntilAfterInitialFetch = true
|
||||
} else {
|
||||
next(MediaResourceData(path: self.path, offset: Int(range.lowerBound), size: 0, complete: false))
|
||||
next(MediaResourceData(path: self.path, offset: range.lowerBound, size: 0, complete: false))
|
||||
}
|
||||
|
||||
let index = self.dataRequests.add(MediaBoxPartialFileDataRequest(range: range, waitingUntilAfterInitialFetch: waitingUntilAfterInitialFetch, completion: { data in
|
||||
|
|
@ -501,7 +573,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
func fetched(range: Range<Int32>, priority: MediaBoxFetchPriority, fetch: @escaping (Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
func fetched(range: Range<Int64>, priority: MediaBoxFetchPriority, fetch: @escaping (Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
if let _ = self.fileMap.contains(range) {
|
||||
|
|
@ -528,14 +600,14 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
func fetchedFullRange(fetch: @escaping (Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
func fetchedFullRange(fetch: @escaping (Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
let queue = self.queue
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
let index = self.fullRangeRequests.add(disposable)
|
||||
self.updateStatuses()
|
||||
|
||||
disposable.set(self.fetched(range: 0 ..< Int32.max, priority: .default, fetch: fetch, error: { e in
|
||||
disposable.set(self.fetched(range: 0 ..< Int64.max, priority: .default, fetch: fetch, error: { e in
|
||||
error(e)
|
||||
}, completed: { [weak self] in
|
||||
queue.async {
|
||||
|
|
@ -599,7 +671,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
private func immediateStatus(size: Int32?) -> MediaResourceStatus {
|
||||
private func immediateStatus(size: Int64?) -> MediaResourceStatus {
|
||||
let status: MediaResourceStatus
|
||||
if self.fullRangeRequests.isEmpty && self.currentFetch == nil {
|
||||
if let truncationSize = self.fileMap.truncationSize, self.fileMap.sum == truncationSize {
|
||||
|
|
@ -629,7 +701,7 @@ final class MediaBoxPartialFile {
|
|||
return status
|
||||
}
|
||||
|
||||
func status(next: @escaping (MediaResourceStatus) -> Void, completed: @escaping () -> Void, size: Int32?) -> Disposable {
|
||||
func status(next: @escaping (MediaResourceStatus) -> Void, completed: @escaping () -> Void, size: Int64?) -> Disposable {
|
||||
let index = self.statusRequests.add((next, size))
|
||||
|
||||
let value = self.immediateStatus(size: size)
|
||||
|
|
@ -649,7 +721,7 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
}
|
||||
|
||||
private func updateRequestRanges(_ intervals: [(Range<Int>, MediaBoxFetchPriority)], fetch: ((Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>)?) {
|
||||
private func updateRequestRanges(_ intervals: [(Range<Int64>, MediaBoxFetchPriority)], fetch: ((Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>)?) {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
#if DEBUG
|
||||
|
|
@ -667,7 +739,7 @@ final class MediaBoxPartialFile {
|
|||
if let (promise, _) = self.currentFetch {
|
||||
promise.set(.single(intervals))
|
||||
} else if let fetch = fetch {
|
||||
let promise = Promise<[(Range<Int>, MediaBoxFetchPriority)]>()
|
||||
let promise = Promise<[(Range<Int64>, MediaBoxFetchPriority)]>()
|
||||
let disposable = MetaDisposable()
|
||||
self.currentFetch = (promise, disposable)
|
||||
self.updateStatuses()
|
||||
|
|
@ -680,15 +752,15 @@ final class MediaBoxPartialFile {
|
|||
strongSelf.reset()
|
||||
}
|
||||
case let .resourceSizeUpdated(size):
|
||||
strongSelf.truncate(Int32(size))
|
||||
strongSelf.truncate(size)
|
||||
case let .dataPart(resourceOffset, data, range, complete):
|
||||
if !data.isEmpty {
|
||||
strongSelf.write(offset: Int32(resourceOffset), data: data, dataRange: range)
|
||||
strongSelf.write(offset: resourceOffset, data: data, dataRange: range)
|
||||
}
|
||||
if complete {
|
||||
if let maxOffset = strongSelf.fileMap.ranges.rangeView.reversed().first?.upperBound {
|
||||
let maxValue = max(resourceOffset + range.count, maxOffset)
|
||||
strongSelf.truncate(Int32(maxValue))
|
||||
let maxValue = max(resourceOffset + Int64(range.count), Int64(maxOffset))
|
||||
strongSelf.truncate(maxValue)
|
||||
}
|
||||
}
|
||||
case let .replaceHeader(data, range):
|
||||
|
|
@ -710,9 +782,9 @@ final class MediaBoxPartialFile {
|
|||
request.waitingUntilAfterInitialFetch = false
|
||||
|
||||
if let actualRange = strongSelf.fileMap.contains(request.range) {
|
||||
request.completion(MediaResourceData(path: strongSelf.path, offset: Int(actualRange.lowerBound), size: actualRange.count, complete: true))
|
||||
request.completion(MediaResourceData(path: strongSelf.path, offset: actualRange.lowerBound, size: Int64(actualRange.count), complete: true))
|
||||
} else {
|
||||
request.completion(MediaResourceData(path: strongSelf.path, offset: Int(request.range.lowerBound), size: 0, complete: false))
|
||||
request.completion(MediaResourceData(path: strongSelf.path, offset: request.range.lowerBound, size: 0, complete: false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -733,13 +805,13 @@ final class MediaBoxPartialFile {
|
|||
}
|
||||
|
||||
private final class MediaBoxFileMissingRange {
|
||||
var range: Range<Int32>
|
||||
var range: Range<Int64>
|
||||
let priority: MediaBoxFetchPriority
|
||||
var remainingRanges: IndexSet
|
||||
let error: (MediaResourceDataFetchError) -> Void
|
||||
let completion: () -> Void
|
||||
|
||||
init(range: Range<Int32>, priority: MediaBoxFetchPriority, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) {
|
||||
init(range: Range<Int64>, priority: MediaBoxFetchPriority, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) {
|
||||
self.range = range
|
||||
self.priority = priority
|
||||
let intRange: Range<Int> = Int(range.lowerBound) ..< Int(range.upperBound)
|
||||
|
|
@ -761,11 +833,11 @@ private final class MediaBoxFileMissingRanges {
|
|||
return errorsAndCompletions
|
||||
}
|
||||
|
||||
func reset(fileMap: MediaBoxFileMap) -> [(Range<Int>, MediaBoxFetchPriority)]? {
|
||||
func reset(fileMap: MediaBoxFileMap) -> [(Range<Int64>, MediaBoxFetchPriority)]? {
|
||||
return self.update(fileMap: fileMap)
|
||||
}
|
||||
|
||||
private func missingRequestedIntervals() -> [(Range<Int>, MediaBoxFetchPriority)] {
|
||||
private func missingRequestedIntervals() -> [(Range<Int64>, MediaBoxFetchPriority)] {
|
||||
var intervalsByPriority: [MediaBoxFetchPriority: IndexSet] = [:]
|
||||
var remainingIntervals = IndexSet()
|
||||
for item in self.requestedRanges.copyItems() {
|
||||
|
|
@ -780,14 +852,14 @@ private final class MediaBoxFileMissingRanges {
|
|||
}
|
||||
}
|
||||
|
||||
var result: [(Range<Int>, MediaBoxFetchPriority)] = []
|
||||
var result: [(Range<Int64>, MediaBoxFetchPriority)] = []
|
||||
|
||||
for priority in intervalsByPriority.keys.sorted(by: { $0.rawValue > $1.rawValue }) {
|
||||
let currentIntervals = intervalsByPriority[priority]!.intersection(remainingIntervals)
|
||||
remainingIntervals.subtract(currentIntervals)
|
||||
for range in currentIntervals.rangeView {
|
||||
if !range.isEmpty {
|
||||
result.append((range, priority))
|
||||
result.append((Int64(range.lowerBound) ..< Int64(range.upperBound), priority))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -795,7 +867,7 @@ private final class MediaBoxFileMissingRanges {
|
|||
return result
|
||||
}
|
||||
|
||||
func fill(_ range: Range<Int32>) -> ([(Range<Int>, MediaBoxFetchPriority)], [() -> Void])? {
|
||||
func fill(_ range: Range<Int64>) -> ([(Range<Int64>, MediaBoxFetchPriority)], [() -> Void])? {
|
||||
let intRange: Range<Int> = Int(range.lowerBound) ..< Int(range.upperBound)
|
||||
if self.missingRangesFlattened.intersects(integersIn: intRange) {
|
||||
self.missingRangesFlattened.remove(integersIn: intRange)
|
||||
|
|
@ -820,18 +892,18 @@ private final class MediaBoxFileMissingRanges {
|
|||
}
|
||||
}
|
||||
|
||||
func addRequest(fileMap: MediaBoxFileMap, range: Range<Int32>, priority: MediaBoxFetchPriority, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) -> (Int, [(Range<Int>, MediaBoxFetchPriority)]?) {
|
||||
func addRequest(fileMap: MediaBoxFileMap, range: Range<Int64>, priority: MediaBoxFetchPriority, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) -> (Int, [(Range<Int64>, MediaBoxFetchPriority)]?) {
|
||||
let index = self.requestedRanges.add(MediaBoxFileMissingRange(range: range, priority: priority, error: error, completion: completion))
|
||||
|
||||
return (index, self.update(fileMap: fileMap))
|
||||
}
|
||||
|
||||
func removeRequest(fileMap: MediaBoxFileMap, index: Int) -> [(Range<Int>, MediaBoxFetchPriority)]? {
|
||||
func removeRequest(fileMap: MediaBoxFileMap, index: Int) -> [(Range<Int64>, MediaBoxFetchPriority)]? {
|
||||
self.requestedRanges.remove(index)
|
||||
return self.update(fileMap: fileMap)
|
||||
}
|
||||
|
||||
private func update(fileMap: MediaBoxFileMap) -> [(Range<Int>, MediaBoxFetchPriority)]? {
|
||||
private func update(fileMap: MediaBoxFileMap) -> [(Range<Int64>, MediaBoxFetchPriority)]? {
|
||||
var byPriority: [MediaBoxFetchPriority: IndexSet] = [:]
|
||||
var flattened = IndexSet()
|
||||
for item in self.requestedRanges.copyItems() {
|
||||
|
|
@ -857,7 +929,7 @@ private final class MediaBoxFileMissingRanges {
|
|||
}
|
||||
|
||||
private enum MediaBoxFileContent {
|
||||
case complete(String, Int)
|
||||
case complete(String, Int64)
|
||||
case partial(MediaBoxPartialFile)
|
||||
}
|
||||
|
||||
|
|
@ -883,7 +955,7 @@ final class MediaBoxFileContext {
|
|||
self.partialPath = partialPath
|
||||
self.metaPath = metaPath
|
||||
|
||||
var completeImpl: ((Int32) -> Void)?
|
||||
var completeImpl: ((Int64) -> Void)?
|
||||
if let size = fileSize(path) {
|
||||
self.content = .complete(path, size)
|
||||
} else if let file = MediaBoxPartialFile(queue: queue, path: partialPath, metaPath: metaPath, completePath: path, completed: { size in
|
||||
|
|
@ -893,7 +965,7 @@ final class MediaBoxFileContext {
|
|||
completeImpl = { [weak self] size in
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.content = .complete(path, Int(size))
|
||||
strongSelf.content = .complete(path, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -914,35 +986,35 @@ final class MediaBoxFileContext {
|
|||
self.references.remove(index)
|
||||
}
|
||||
|
||||
func data(range: Range<Int32>, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable {
|
||||
func data(range: Range<Int64>, waitUntilAfterInitialFetch: Bool, next: @escaping (MediaResourceData) -> Void) -> Disposable {
|
||||
switch self.content {
|
||||
case let .complete(path, size):
|
||||
var lowerBound = range.lowerBound
|
||||
if lowerBound < 0 {
|
||||
lowerBound = 0
|
||||
}
|
||||
if lowerBound > Int(size) {
|
||||
lowerBound = Int32(clamping: size)
|
||||
if lowerBound > size {
|
||||
lowerBound = size
|
||||
}
|
||||
var upperBound = range.upperBound
|
||||
if upperBound < 0 {
|
||||
upperBound = 0
|
||||
}
|
||||
if upperBound > Int(size) {
|
||||
upperBound = Int32(clamping: size)
|
||||
if upperBound > size {
|
||||
upperBound = size
|
||||
}
|
||||
if upperBound < lowerBound {
|
||||
upperBound = lowerBound
|
||||
}
|
||||
|
||||
next(MediaResourceData(path: path, offset: Int(lowerBound), size: Int(upperBound - lowerBound), complete: true))
|
||||
next(MediaResourceData(path: path, offset: lowerBound, size: upperBound - lowerBound, complete: true))
|
||||
return EmptyDisposable
|
||||
case let .partial(file):
|
||||
return file.data(range: range, waitUntilAfterInitialFetch: waitUntilAfterInitialFetch, next: next)
|
||||
}
|
||||
}
|
||||
|
||||
func fetched(range: Range<Int32>, priority: MediaBoxFetchPriority, fetch: @escaping (Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
func fetched(range: Range<Int64>, priority: MediaBoxFetchPriority, fetch: @escaping (Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
switch self.content {
|
||||
case .complete:
|
||||
return EmptyDisposable
|
||||
|
|
@ -951,7 +1023,7 @@ final class MediaBoxFileContext {
|
|||
}
|
||||
}
|
||||
|
||||
func fetchedFullRange(fetch: @escaping (Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
func fetchedFullRange(fetch: @escaping (Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, error: @escaping (MediaResourceDataFetchError) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
switch self.content {
|
||||
case .complete:
|
||||
return EmptyDisposable
|
||||
|
|
@ -972,7 +1044,7 @@ final class MediaBoxFileContext {
|
|||
func rangeStatus(next: @escaping (IndexSet) -> Void, completed: @escaping () -> Void) -> Disposable {
|
||||
switch self.content {
|
||||
case let .complete(_, size):
|
||||
next(IndexSet(integersIn: 0 ..< size))
|
||||
next(IndexSet(integersIn: 0 ..< Int(size)))
|
||||
completed()
|
||||
return EmptyDisposable
|
||||
case let .partial(file):
|
||||
|
|
@ -980,7 +1052,7 @@ final class MediaBoxFileContext {
|
|||
}
|
||||
}
|
||||
|
||||
func status(next: @escaping (MediaResourceStatus) -> Void, completed: @escaping () -> Void, size: Int32?) -> Disposable {
|
||||
func status(next: @escaping (MediaResourceStatus) -> Void, completed: @escaping () -> Void, size: Int64?) -> Disposable {
|
||||
switch self.content {
|
||||
case .complete:
|
||||
next(.Local)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public struct MediaResourceId: Equatable, Hashable {
|
|||
|
||||
public protocol MediaResource {
|
||||
var id: MediaResourceId { get }
|
||||
var size: Int? { get }
|
||||
var size: Int64? { get }
|
||||
var streamable: Bool { get }
|
||||
var headerSize: Int32 { get }
|
||||
|
||||
|
|
@ -18,10 +18,6 @@ public protocol MediaResource {
|
|||
}
|
||||
|
||||
public extension MediaResource {
|
||||
var size: Int? {
|
||||
return nil
|
||||
}
|
||||
|
||||
var streamable: Bool {
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ private struct AutomaticDownloadPeers {
|
|||
let otherPrivate: Bool
|
||||
let groups: Bool
|
||||
let channels: Bool
|
||||
let size: Int32?
|
||||
let size: Int64?
|
||||
|
||||
init(category: MediaAutoDownloadCategory) {
|
||||
self.contacts = category.contacts
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ private enum AutomaticDownloadPeerType {
|
|||
|
||||
private final class AutodownloadMediaCategoryControllerArguments {
|
||||
let togglePeer: (AutomaticDownloadPeerType) -> Void
|
||||
let adjustSize: (Int32) -> Void
|
||||
let adjustSize: (Int64) -> Void
|
||||
let toggleVideoPreload: () -> Void
|
||||
|
||||
init(togglePeer: @escaping (AutomaticDownloadPeerType) -> Void, adjustSize: @escaping (Int32) -> Void, toggleVideoPreload: @escaping () -> Void) {
|
||||
init(togglePeer: @escaping (AutomaticDownloadPeerType) -> Void, adjustSize: @escaping (Int64) -> Void, toggleVideoPreload: @escaping () -> Void) {
|
||||
self.togglePeer = togglePeer
|
||||
self.adjustSize = adjustSize
|
||||
self.toggleVideoPreload = toggleVideoPreload
|
||||
|
|
@ -70,7 +70,7 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry {
|
|||
case peerChannels(PresentationTheme, String, Bool)
|
||||
|
||||
case sizeHeader(PresentationTheme, String)
|
||||
case sizeItem(PresentationTheme, PresentationStrings, String, String, Int32)
|
||||
case sizeItem(PresentationTheme, PresentationStrings, String, String, Int64)
|
||||
case sizePreload(PresentationTheme, String, Bool, Bool)
|
||||
case sizePreloadInfo(PresentationTheme, String)
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ private func autodownloadMediaCategoryControllerEntries(presentationData: Presen
|
|||
let categories = effectiveAutodownloadCategories(settings: settings, networkType: connectionType.automaticDownloadNetworkType)
|
||||
|
||||
let peers: AutomaticDownloadPeers
|
||||
let size: Int32
|
||||
let size: Int64
|
||||
let predownload: Bool
|
||||
|
||||
switch category {
|
||||
|
|
@ -270,7 +270,7 @@ private func autodownloadMediaCategoryControllerEntries(presentationData: Presen
|
|||
}
|
||||
|
||||
let sizeText: String
|
||||
if size == Int32.max {
|
||||
if size == Int64.max {
|
||||
sizeText = autodownloadDataSizeString(1536 * 1024 * 1024, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
|
||||
} else {
|
||||
sizeText = autodownloadDataSizeString(Int64(size), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import LegacyComponents
|
|||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
|
||||
private let autodownloadSizeValues: [(CGFloat, Int32)] = [
|
||||
private let autodownloadSizeValues: [(CGFloat, Int64)] = [
|
||||
(0.000, 512 * 1024),
|
||||
(0.257, 1024 * 1024),
|
||||
(0.520, 10 * 1024 * 1024),
|
||||
|
|
@ -17,7 +17,7 @@ private let autodownloadSizeValues: [(CGFloat, Int32)] = [
|
|||
(1.000, 1536 * 1024 * 1024)
|
||||
]
|
||||
|
||||
private func sliderValue(for size: Int32) -> CGFloat {
|
||||
private func sliderValue(for size: Int64) -> CGFloat {
|
||||
for i in 1 ..< autodownloadSizeValues.count {
|
||||
let (previousValue, previousValueSize) = autodownloadSizeValues[i - 1]
|
||||
let (value, valueSize) = autodownloadSizeValues[i]
|
||||
|
|
@ -32,13 +32,13 @@ private func sliderValue(for size: Int32) -> CGFloat {
|
|||
return 0.0
|
||||
}
|
||||
|
||||
private func sizeValue(for sliderValue: CGFloat) -> Int32 {
|
||||
private func sizeValue(for sliderValue: CGFloat) -> Int64 {
|
||||
for i in 1 ..< autodownloadSizeValues.count {
|
||||
let (previousValue, previousValueSize) = autodownloadSizeValues[i - 1]
|
||||
let (value, valueSize) = autodownloadSizeValues[i]
|
||||
if value > sliderValue {
|
||||
let delta = (sliderValue - previousValue) / (value - previousValue) * CGFloat(valueSize - previousValueSize)
|
||||
return previousValueSize + Int32(delta)
|
||||
return previousValueSize + Int64(delta)
|
||||
} else if previousValue == sliderValue {
|
||||
return previousValueSize
|
||||
} else if value == sliderValue || i == autodownloadSizeValues.count - 1 {
|
||||
|
|
@ -53,11 +53,11 @@ final class AutodownloadSizeLimitItem: ListViewItem, ItemListItem {
|
|||
let strings: PresentationStrings
|
||||
let decimalSeparator: String
|
||||
let text: String
|
||||
let value: Int32
|
||||
let value: Int64
|
||||
let sectionId: ItemListSectionId
|
||||
let updated: (Int32) -> Void
|
||||
let updated: (Int64) -> Void
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, decimalSeparator: String, text: String, value: Int32, sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, decimalSeparator: String, text: String, value: Int64, sectionId: ItemListSectionId, updated: @escaping (Int64) -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.decimalSeparator = decimalSeparator
|
||||
|
|
@ -299,4 +299,3 @@ private final class AutodownloadSizeLimitItemNode: ListViewItemNode {
|
|||
self.item?.updated(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -426,20 +426,20 @@ private func stringForUseLessDataSetting(_ dataSaving: VoiceCallDataSaving, stri
|
|||
}
|
||||
}
|
||||
|
||||
private func stringForAutoDownloadTypes(strings: PresentationStrings, decimalSeparator: String, photo: Bool, videoSize: Int32?, fileSize: Int32?) -> String {
|
||||
private func stringForAutoDownloadTypes(strings: PresentationStrings, decimalSeparator: String, photo: Bool, videoSize: Int64?, fileSize: Int64?) -> String {
|
||||
var types: [String] = []
|
||||
if photo && videoSize == nil {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypePhoto)
|
||||
}
|
||||
if let videoSize = videoSize {
|
||||
if photo {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeMedia(autodownloadDataSizeString(Int64(videoSize), decimalSeparator: decimalSeparator)).string)
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeMedia(autodownloadDataSizeString(videoSize, decimalSeparator: decimalSeparator)).string)
|
||||
} else {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(Int64(videoSize), decimalSeparator: decimalSeparator)).string)
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(videoSize, decimalSeparator: decimalSeparator)).string)
|
||||
}
|
||||
}
|
||||
if let fileSize = fileSize {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(Int64(fileSize), decimalSeparator: decimalSeparator)).string)
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(fileSize, decimalSeparator: decimalSeparator)).string)
|
||||
}
|
||||
|
||||
if types.isEmpty {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-247016673] = { return Api.AttachMenuPeerType.parse_attachMenuPeerTypePM($0) }
|
||||
dict[2104224014] = { return Api.AttachMenuPeerType.parse_attachMenuPeerTypeSameBotPM($0) }
|
||||
dict[-1392388579] = { return Api.Authorization.parse_authorization($0) }
|
||||
dict[-532532493] = { return Api.AutoDownloadSettings.parse_autoDownloadSettings($0) }
|
||||
dict[-1896171181] = { return Api.AutoDownloadSettings.parse_autoDownloadSettings($0) }
|
||||
dict[-1065882623] = { return Api.AvailableReaction.parse_availableReaction($0) }
|
||||
dict[-177732982] = { return Api.BankCardOpenUrl.parse_bankCardOpenUrl($0) }
|
||||
dict[1527845466] = { return Api.BaseTheme.parse_baseThemeArctic($0) }
|
||||
|
|
@ -177,7 +177,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[2004110666] = { return Api.DialogFilterSuggested.parse_dialogFilterSuggested($0) }
|
||||
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
|
||||
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
|
||||
dict[512177195] = { return Api.Document.parse_document($0) }
|
||||
dict[-1881881384] = { return Api.Document.parse_document($0) }
|
||||
dict[922273905] = { return Api.Document.parse_documentEmpty($0) }
|
||||
dict[297109817] = { return Api.DocumentAttribute.parse_documentAttributeAnimated($0) }
|
||||
dict[-1739392570] = { return Api.DocumentAttribute.parse_documentAttributeAudio($0) }
|
||||
|
|
@ -198,14 +198,14 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1417756512] = { return Api.EncryptedChat.parse_encryptedChatEmpty($0) }
|
||||
dict[1223809356] = { return Api.EncryptedChat.parse_encryptedChatRequested($0) }
|
||||
dict[1722964307] = { return Api.EncryptedChat.parse_encryptedChatWaiting($0) }
|
||||
dict[1248893260] = { return Api.EncryptedFile.parse_encryptedFile($0) }
|
||||
dict[-1476358952] = { return Api.EncryptedFile.parse_encryptedFile($0) }
|
||||
dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) }
|
||||
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
|
||||
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
|
||||
dict[179611673] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
|
||||
dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) }
|
||||
dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) }
|
||||
dict[1648543603] = { return Api.FileHash.parse_fileHash($0) }
|
||||
dict[-207944868] = { return Api.FileHash.parse_fileHash($0) }
|
||||
dict[-11252123] = { return Api.Folder.parse_folder($0) }
|
||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||
dict[-1107729093] = { return Api.Game.parse_game($0) }
|
||||
|
|
@ -557,7 +557,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[1471006352] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonHangup($0) }
|
||||
dict[-2048646399] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonMissed($0) }
|
||||
dict[-58224696] = { return Api.PhoneCallProtocol.parse_phoneCallProtocol($0) }
|
||||
dict[-1655957568] = { return Api.PhoneConnection.parse_phoneConnection($0) }
|
||||
dict[-1665063993] = { return Api.PhoneConnection.parse_phoneConnection($0) }
|
||||
dict[1667228533] = { return Api.PhoneConnection.parse_phoneConnectionWebrtc($0) }
|
||||
dict[-82216347] = { return Api.Photo.parse_photo($0) }
|
||||
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
|
||||
|
|
@ -632,7 +632,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[2137295719] = { return Api.SearchResultsPosition.parse_searchResultPosition($0) }
|
||||
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
|
||||
dict[-1964327229] = { return Api.SecureData.parse_secureData($0) }
|
||||
dict[-534283678] = { return Api.SecureFile.parse_secureFile($0) }
|
||||
dict[2097791614] = { return Api.SecureFile.parse_secureFile($0) }
|
||||
dict[1679398724] = { return Api.SecureFile.parse_secureFileEmpty($0) }
|
||||
dict[-1141711456] = { return Api.SecurePasswordKdfAlgo.parse_securePasswordKdfAlgoPBKDF2HMACSHA512iter100000($0) }
|
||||
dict[-2042159726] = { return Api.SecurePasswordKdfAlgo.parse_securePasswordKdfAlgoSHA512($0) }
|
||||
|
|
|
|||
|
|
@ -472,18 +472,18 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum AutoDownloadSettings: TypeConstructorDescription {
|
||||
case autoDownloadSettings(flags: Int32, photoSizeMax: Int32, videoSizeMax: Int32, fileSizeMax: Int32, videoUploadMaxbitrate: Int32)
|
||||
case autoDownloadSettings(flags: Int32, photoSizeMax: Int32, videoSizeMax: Int64, fileSizeMax: Int64, videoUploadMaxbitrate: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .autoDownloadSettings(let flags, let photoSizeMax, let videoSizeMax, let fileSizeMax, let videoUploadMaxbitrate):
|
||||
if boxed {
|
||||
buffer.appendInt32(-532532493)
|
||||
buffer.appendInt32(-1896171181)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(photoSizeMax, buffer: buffer, boxed: false)
|
||||
serializeInt32(videoSizeMax, buffer: buffer, boxed: false)
|
||||
serializeInt32(fileSizeMax, buffer: buffer, boxed: false)
|
||||
serializeInt64(videoSizeMax, buffer: buffer, boxed: false)
|
||||
serializeInt64(fileSizeMax, buffer: buffer, boxed: false)
|
||||
serializeInt32(videoUploadMaxbitrate, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
|
|
@ -501,10 +501,10 @@ public extension Api {
|
|||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int64?
|
||||
_4 = reader.readInt64()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
|
|
|
|||
|
|
@ -1130,15 +1130,16 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum PhoneConnection: TypeConstructorDescription {
|
||||
case phoneConnection(id: Int64, ip: String, ipv6: String, port: Int32, peerTag: Buffer)
|
||||
case phoneConnection(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, peerTag: Buffer)
|
||||
case phoneConnectionWebrtc(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, username: String, password: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .phoneConnection(let id, let ip, let ipv6, let port, let peerTag):
|
||||
case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1655957568)
|
||||
buffer.appendInt32(-1665063993)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeString(ip, buffer: buffer, boxed: false)
|
||||
serializeString(ipv6, buffer: buffer, boxed: false)
|
||||
|
|
@ -1162,31 +1163,34 @@ public extension Api {
|
|||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .phoneConnection(let id, let ip, let ipv6, let port, let peerTag):
|
||||
return ("phoneConnection", [("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("peerTag", String(describing: peerTag))])
|
||||
case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag):
|
||||
return ("phoneConnection", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("peerTag", String(describing: peerTag))])
|
||||
case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password):
|
||||
return ("phoneConnectionWebrtc", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("username", String(describing: username)), ("password", String(describing: password))])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_phoneConnection(_ reader: BufferReader) -> PhoneConnection? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Buffer?
|
||||
_5 = parseBytes(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Buffer?
|
||||
_6 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.PhoneConnection.phoneConnection(id: _1!, ip: _2!, ipv6: _3!, port: _4!, peerTag: _5!)
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.PhoneConnection.phoneConnection(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, peerTag: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -180,18 +180,18 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum SecureFile: TypeConstructorDescription {
|
||||
case secureFile(id: Int64, accessHash: Int64, size: Int32, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer)
|
||||
case secureFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer)
|
||||
case secureFileEmpty
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret):
|
||||
if boxed {
|
||||
buffer.appendInt32(-534283678)
|
||||
buffer.appendInt32(2097791614)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(size, buffer: buffer, boxed: false)
|
||||
serializeInt64(size, buffer: buffer, boxed: false)
|
||||
serializeInt32(dcId, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeBytes(fileHash, buffer: buffer, boxed: false)
|
||||
|
|
@ -220,8 +220,8 @@ public extension Api {
|
|||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
|
|
|
|||
|
|
@ -565,11 +565,11 @@ public extension Api.functions.account {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.account {
|
||||
static func initTakeoutSession(flags: Int32, fileMaxSize: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.Takeout>) {
|
||||
static func initTakeoutSession(flags: Int32, fileMaxSize: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.Takeout>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-262453244)
|
||||
buffer.appendInt32(-1896617296)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(fileMaxSize!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 5) != 0 {serializeInt64(fileMaxSize!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "account.initTakeoutSession", parameters: [("flags", String(describing: flags)), ("fileMaxSize", String(describing: fileMaxSize))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Takeout? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.account.Takeout?
|
||||
|
|
@ -4032,11 +4032,11 @@ public extension Api.functions.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getDocumentByHash(sha256: Buffer, size: Int32, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Document>) {
|
||||
static func getDocumentByHash(sha256: Buffer, size: Int64, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Document>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(864953444)
|
||||
buffer.appendInt32(-1309538785)
|
||||
serializeBytes(sha256, buffer: buffer, boxed: false)
|
||||
serializeInt32(size, buffer: buffer, boxed: false)
|
||||
serializeInt64(size, buffer: buffer, boxed: false)
|
||||
serializeString(mimeType, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getDocumentByHash", parameters: [("sha256", String(describing: sha256)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in
|
||||
let reader = BufferReader(buffer)
|
||||
|
|
@ -7171,11 +7171,11 @@ public extension Api.functions.updates {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.upload {
|
||||
static func getCdnFile(fileToken: Buffer, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.upload.CdnFile>) {
|
||||
static func getCdnFile(fileToken: Buffer, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.upload.CdnFile>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(536919235)
|
||||
buffer.appendInt32(962554330)
|
||||
serializeBytes(fileToken, buffer: buffer, boxed: false)
|
||||
serializeInt32(offset, buffer: buffer, boxed: false)
|
||||
serializeInt64(offset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "upload.getCdnFile", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.CdnFile? in
|
||||
let reader = BufferReader(buffer)
|
||||
|
|
@ -7188,11 +7188,11 @@ public extension Api.functions.upload {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.upload {
|
||||
static func getCdnFileHashes(fileToken: Buffer, offset: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) {
|
||||
static func getCdnFileHashes(fileToken: Buffer, offset: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1302676017)
|
||||
buffer.appendInt32(-1847836879)
|
||||
serializeBytes(fileToken, buffer: buffer, boxed: false)
|
||||
serializeInt32(offset, buffer: buffer, boxed: false)
|
||||
serializeInt64(offset, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "upload.getCdnFileHashes", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Api.FileHash]?
|
||||
|
|
@ -7204,12 +7204,12 @@ public extension Api.functions.upload {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.upload {
|
||||
static func getFile(flags: Int32, location: Api.InputFileLocation, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.upload.File>) {
|
||||
static func getFile(flags: Int32, location: Api.InputFileLocation, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.upload.File>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1319462148)
|
||||
buffer.appendInt32(-1101843010)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
location.serialize(buffer, true)
|
||||
serializeInt32(offset, buffer: buffer, boxed: false)
|
||||
serializeInt64(offset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "upload.getFile", parameters: [("flags", String(describing: flags)), ("location", String(describing: location)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.File? in
|
||||
let reader = BufferReader(buffer)
|
||||
|
|
|
|||
|
|
@ -1074,14 +1074,14 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum Document: TypeConstructorDescription {
|
||||
case document(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, mimeType: String, size: Int32, thumbs: [Api.PhotoSize]?, videoThumbs: [Api.VideoSize]?, dcId: Int32, attributes: [Api.DocumentAttribute])
|
||||
case document(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, mimeType: String, size: Int64, thumbs: [Api.PhotoSize]?, videoThumbs: [Api.VideoSize]?, dcId: Int32, attributes: [Api.DocumentAttribute])
|
||||
case documentEmpty(id: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .document(let flags, let id, let accessHash, let fileReference, let date, let mimeType, let size, let thumbs, let videoThumbs, let dcId, let attributes):
|
||||
if boxed {
|
||||
buffer.appendInt32(512177195)
|
||||
buffer.appendInt32(-1881881384)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
|
|
@ -1089,7 +1089,7 @@ public extension Api {
|
|||
serializeBytes(fileReference, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeString(mimeType, buffer: buffer, boxed: false)
|
||||
serializeInt32(size, buffer: buffer, boxed: false)
|
||||
serializeInt64(size, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(thumbs!.count))
|
||||
for item in thumbs! {
|
||||
|
|
@ -1138,8 +1138,8 @@ public extension Api {
|
|||
_5 = reader.readInt32()
|
||||
var _6: String?
|
||||
_6 = parseString(reader)
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
var _7: Int64?
|
||||
_7 = reader.readInt64()
|
||||
var _8: [Api.PhotoSize]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self)
|
||||
|
|
|
|||
|
|
@ -390,18 +390,18 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum EncryptedFile: TypeConstructorDescription {
|
||||
case encryptedFile(id: Int64, accessHash: Int64, size: Int32, dcId: Int32, keyFingerprint: Int32)
|
||||
case encryptedFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, keyFingerprint: Int32)
|
||||
case encryptedFileEmpty
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .encryptedFile(let id, let accessHash, let size, let dcId, let keyFingerprint):
|
||||
if boxed {
|
||||
buffer.appendInt32(1248893260)
|
||||
buffer.appendInt32(-1476358952)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
serializeInt32(size, buffer: buffer, boxed: false)
|
||||
serializeInt64(size, buffer: buffer, boxed: false)
|
||||
serializeInt32(dcId, buffer: buffer, boxed: false)
|
||||
serializeInt32(keyFingerprint, buffer: buffer, boxed: false)
|
||||
break
|
||||
|
|
@ -428,8 +428,8 @@ public extension Api {
|
|||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
|
|
@ -664,15 +664,15 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
enum FileHash: TypeConstructorDescription {
|
||||
case fileHash(offset: Int32, limit: Int32, hash: Buffer)
|
||||
case fileHash(offset: Int64, limit: Int32, hash: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .fileHash(let offset, let limit, let hash):
|
||||
if boxed {
|
||||
buffer.appendInt32(1648543603)
|
||||
buffer.appendInt32(-207944868)
|
||||
}
|
||||
serializeInt32(offset, buffer: buffer, boxed: false)
|
||||
serializeInt64(offset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
serializeBytes(hash, buffer: buffer, boxed: false)
|
||||
break
|
||||
|
|
@ -687,8 +687,8 @@ public extension Api {
|
|||
}
|
||||
|
||||
public static func parse_fileHash(_ reader: BufferReader) -> FileHash? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Buffer?
|
||||
|
|
|
|||
|
|
@ -661,11 +661,11 @@ public enum AccountNetworkState: Equatable {
|
|||
}
|
||||
|
||||
public final class AccountAuxiliaryMethods {
|
||||
public let fetchResource: (Account, MediaResource, Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>?
|
||||
public let fetchResource: (Account, MediaResource, Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>?
|
||||
public let fetchResourceMediaReferenceHash: (MediaResource) -> Signal<Data?, NoError>
|
||||
public let prepareSecretThumbnailData: (MediaResourceData) -> (PixelDimensions, Data)?
|
||||
|
||||
public init(fetchResource: @escaping (Account, MediaResource, Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>?, fetchResourceMediaReferenceHash: @escaping (MediaResource) -> Signal<Data?, NoError>, prepareSecretThumbnailData: @escaping (MediaResourceData) -> (PixelDimensions, Data)?) {
|
||||
public init(fetchResource: @escaping (Account, MediaResource, Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>?, fetchResourceMediaReferenceHash: @escaping (MediaResource) -> Signal<Data?, NoError>, prepareSecretThumbnailData: @escaping (MediaResourceData) -> (PixelDimensions, Data)?) {
|
||||
self.fetchResource = fetchResource
|
||||
self.fetchResourceMediaReferenceHash = fetchResourceMediaReferenceHash
|
||||
self.prepareSecretThumbnailData = prepareSecretThumbnailData
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
extension SecretChatFileReference {
|
||||
func resource(key: SecretFileEncryptionKey, decryptedSize: Int32) -> SecretFileMediaResource {
|
||||
func resource(key: SecretFileEncryptionKey, decryptedSize: Int64) -> SecretFileMediaResource {
|
||||
return SecretFileMediaResource(fileId: self.id, accessHash: self.accessHash, containerSize: self.size, decryptedSize: decryptedSize, datacenterId: Int(self.datacenterId), key: key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func telegramMediaFileFromApiDocument(_ document: Api.Document) -> TelegramMedia
|
|||
}
|
||||
}
|
||||
|
||||
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: fileReference.makeData(), fileName: fileNameFromFileAttributes(parsedAttributes)), previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: immediateThumbnail, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: size, fileReference: fileReference.makeData(), fileName: fileNameFromFileAttributes(parsedAttributes)), previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: immediateThumbnail, mimeType: mimeType, size: size, attributes: parsedAttributes)
|
||||
case .documentEmpty:
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ func telegramMediaImageRepresentationsFromApiSizes(datacenterId: Int32, photoId:
|
|||
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: nil, fileReference: fileReference)
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case let .photoSize(type, w, h, size):
|
||||
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int(size), fileReference: fileReference)
|
||||
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference)
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case let .photoSizeProgressive(type, w, h, sizes):
|
||||
if !sizes.isEmpty {
|
||||
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int(sizes[sizes.count - 1]), fileReference: fileReference)
|
||||
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int64(sizes[sizes.count - 1]), fileReference: fileReference)
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes, immediateThumbnailData: nil))
|
||||
}
|
||||
case let .photoStrippedSize(_, data):
|
||||
|
|
@ -46,7 +46,7 @@ func telegramMediaImageFromApiPhoto(_ photo: Api.Photo) -> TelegramMediaImage? {
|
|||
switch size {
|
||||
case let .videoSize(_, type, w, h, size, videoStartTs):
|
||||
let resource: TelegramMediaResource
|
||||
resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int(size), fileReference: fileReference.makeData())
|
||||
resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData())
|
||||
|
||||
videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ extension TelegramMediaWebFile {
|
|||
convenience init(_ document: Api.WebDocument) {
|
||||
switch document {
|
||||
case let .webDocument(url, accessHash, size, mimeType, attributes):
|
||||
self.init(resource: WebFileReferenceMediaResource(url: url, size: size, accessHash: accessHash), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
|
||||
self.init(resource: WebFileReferenceMediaResource(url: url, size: Int64(size), accessHash: accessHash), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
|
||||
case let .webDocumentNoProxy(url, size, mimeType, attributes):
|
||||
self.init(resource: HttpReferenceMediaResource(url: url, size: Int(size)), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
|
||||
self.init(resource: HttpReferenceMediaResource(url: url, size: Int64(size)), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
|
|||
} |> retryRequest
|
||||
}
|
||||
|
||||
func part(location: Api.InputFileLocation, offset: Int, length: Int) -> Signal<Data, NoError> {
|
||||
func part(location: Api.InputFileLocation, offset: Int64, length: Int) -> Signal<Data, NoError> {
|
||||
return Signal<Data, MTRpcError> { subscriber in
|
||||
let request = MTRequest()
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
|
|||
updatedLength += 1
|
||||
}
|
||||
|
||||
let data = Api.functions.upload.getFile(flags: 0, location: location, offset: Int32(offset), limit: Int32(updatedLength))
|
||||
let data = Api.functions.upload.getFile(flags: 0, location: location, offset: offset, limit: Int32(updatedLength))
|
||||
|
||||
request.setPayload(data.1.makeData() as Data, metadata: WrappedRequestMetadata(metadata: WrappedFunctionDescription(data.0), tag: nil), shortMetadata: WrappedRequestShortMetadata(shortMetadata: WrappedShortFunctionDescription(data.0)), responseParser: { response in
|
||||
if let result = data.2.parse(Buffer(data: response)) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public func fetchHttpResource(url: String) -> Signal<MediaResourceDataFetchResul
|
|||
subscriber.putNext(.reset)
|
||||
let disposable = signal.start(next: { next in
|
||||
if let response = next as? MTHttpResponse {
|
||||
let fetchResult: MediaResourceDataFetchResult = .dataPart(resourceOffset: 0, data: response.data, range: 0 ..< response.data.count, complete: true)
|
||||
let fetchResult: MediaResourceDataFetchResult = .dataPart(resourceOffset: 0, data: response.data, range: 0 ..< Int64(response.data.count), complete: true)
|
||||
subscriber.putNext(fetchResult)
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@ final class TelegramCloudMediaResourceFetchInfo: MediaResourceFetchInfo {
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchedMediaResource(mediaBox: MediaBox, reference: MediaResourceReference, range: (Range<Int>, MediaBoxFetchPriority)? = nil, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, FetchResourceError> {
|
||||
public func fetchedMediaResource(mediaBox: MediaBox, reference: MediaResourceReference, range: (Range<Int64>, MediaBoxFetchPriority)? = nil, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, FetchResourceError> {
|
||||
return fetchedMediaResource(mediaBox: mediaBox, reference: reference, ranges: range.flatMap({ [$0] }), statsCategory: statsCategory, reportResultStatus: reportResultStatus, preferBackgroundReferenceRevalidation: preferBackgroundReferenceRevalidation, continueInBackground: continueInBackground)
|
||||
}
|
||||
|
||||
public func fetchedMediaResource(mediaBox: MediaBox, reference: MediaResourceReference, ranges: [(Range<Int>, MediaBoxFetchPriority)]?, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, FetchResourceError> {
|
||||
public func fetchedMediaResource(mediaBox: MediaBox, reference: MediaResourceReference, ranges: [(Range<Int64>, MediaBoxFetchPriority)]?, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, FetchResourceError> {
|
||||
var isRandomAccessAllowed = true
|
||||
switch reference {
|
||||
case let .media(media, _):
|
||||
|
|
|
|||
|
|
@ -4,17 +4,28 @@ import SwiftSignalKit
|
|||
import TelegramApi
|
||||
import MtProtoKit
|
||||
|
||||
private extension Range where Bound == Int64 {
|
||||
func asIntRange() -> Range<Int> {
|
||||
return Int(self.lowerBound) ..< Int(self.upperBound)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Range where Bound == Int {
|
||||
func asInt64Range() -> Range<Int64> {
|
||||
return Int64(self.lowerBound) ..< Int64(self.upperBound)
|
||||
}
|
||||
}
|
||||
|
||||
private typealias SignalKitTimer = SwiftSignalKit.Timer
|
||||
|
||||
private final class MultipartDownloadState {
|
||||
let aesKey: Data
|
||||
var aesIv: Data
|
||||
let decryptedSize: Int32?
|
||||
let decryptedSize: Int64?
|
||||
|
||||
var currentSize: Int32 = 0
|
||||
var currentSize: Int64 = 0
|
||||
|
||||
init(encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int32?) {
|
||||
init(encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int64?) {
|
||||
if let encryptionKey = encryptionKey {
|
||||
self.aesKey = encryptionKey.aesKey
|
||||
self.aesIv = encryptionKey.aesIv
|
||||
|
|
@ -25,13 +36,13 @@ private final class MultipartDownloadState {
|
|||
self.decryptedSize = decryptedSize
|
||||
}
|
||||
|
||||
func transform(offset: Int, data: Data) -> Data {
|
||||
func transform(offset: Int64, data: Data) -> Data {
|
||||
if self.aesKey.count != 0 {
|
||||
var decryptedData = data
|
||||
assert(decryptedSize != nil)
|
||||
assert(decryptedData.count % 16 == 0)
|
||||
let decryptedDataCount = decryptedData.count
|
||||
assert(offset == Int(self.currentSize))
|
||||
assert(offset == self.currentSize)
|
||||
decryptedData.withUnsafeMutableBytes { rawBytes -> Void in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
self.aesIv.withUnsafeMutableBytes { rawIv -> Void in
|
||||
|
|
@ -39,10 +50,10 @@ private final class MultipartDownloadState {
|
|||
MTAesDecryptBytesInplaceAndModifyIv(bytes, decryptedDataCount, self.aesKey, iv)
|
||||
}
|
||||
}
|
||||
if self.currentSize + Int32(decryptedData.count) > self.decryptedSize! {
|
||||
if self.currentSize + Int64(decryptedData.count) > self.decryptedSize! {
|
||||
decryptedData.count = Int(self.decryptedSize! - self.currentSize)
|
||||
}
|
||||
self.currentSize += Int32(decryptedData.count)
|
||||
self.currentSize += Int64(decryptedData.count)
|
||||
return decryptedData
|
||||
} else {
|
||||
return data
|
||||
|
|
@ -52,7 +63,7 @@ private final class MultipartDownloadState {
|
|||
|
||||
private enum MultipartFetchDownloadError {
|
||||
case generic
|
||||
case switchToCdn(id: Int32, token: Data, key: Data, iv: Data, partHashes: [Int32: Data])
|
||||
case switchToCdn(id: Int32, token: Data, key: Data, iv: Data, partHashes: [Int64: Data])
|
||||
case reuploadToCdn(masterDatacenterId: Int32, token: Data)
|
||||
case revalidateMediaReference
|
||||
case hashesMissing
|
||||
|
|
@ -96,7 +107,7 @@ private struct DownloadWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
private func roundUp(_ value: Int, to multiple: Int) -> Int {
|
||||
private func roundUp(_ value: Int64, to multiple: Int64) -> Int64 {
|
||||
if multiple == 0 {
|
||||
return value
|
||||
}
|
||||
|
|
@ -109,15 +120,15 @@ private func roundUp(_ value: Int, to multiple: Int) -> Int {
|
|||
return value + multiple - remainder
|
||||
}
|
||||
|
||||
private let dataHashLength: Int32 = 128 * 1024
|
||||
private let dataHashLength: Int64 = 128 * 1024
|
||||
|
||||
private final class MultipartCdnHashSource {
|
||||
private final class ClusterContext {
|
||||
final class Subscriber {
|
||||
let completion: ([Int32: Data]) -> Void
|
||||
let completion: ([Int64: Data]) -> Void
|
||||
let error: (MultipartFetchDownloadError) -> Void
|
||||
|
||||
init(completion: @escaping ([Int32: Data]) -> Void, error: @escaping (MultipartFetchDownloadError) -> Void) {
|
||||
init(completion: @escaping ([Int64: Data]) -> Void, error: @escaping (MultipartFetchDownloadError) -> Void) {
|
||||
self.completion = completion
|
||||
self.error = error
|
||||
}
|
||||
|
|
@ -126,7 +137,7 @@ private final class MultipartCdnHashSource {
|
|||
let disposable: Disposable
|
||||
let subscribers = Bag<Subscriber>()
|
||||
|
||||
var result: [Int32: Data]?
|
||||
var result: [Int64: Data]?
|
||||
var error: MultipartFetchDownloadError?
|
||||
|
||||
init(disposable: Disposable) {
|
||||
|
|
@ -144,153 +155,22 @@ private final class MultipartCdnHashSource {
|
|||
private let masterDownload: DownloadWrapper
|
||||
private let continueInBackground: Bool
|
||||
|
||||
private var clusterContexts: [Int32: ClusterContext] = [:]
|
||||
private var clusterContexts: [Int64: ClusterContext] = [:]
|
||||
|
||||
/*private var knownUpperBound: Int32
|
||||
private var hashes: [Int32: Data] = [:]
|
||||
private var requestOffsetAndDisposable: (Int32, Disposable)?
|
||||
private var requestedUpperBound: Int32?
|
||||
|
||||
private var subscribers = Bag<(Int32, Int32, ([Int32: Data]) -> Void)>()*/
|
||||
|
||||
init(queue: Queue, fileToken: Data, hashes: [Int32: Data], masterDownload: DownloadWrapper, continueInBackground: Bool) {
|
||||
init(queue: Queue, fileToken: Data, hashes: [Int64: Data], masterDownload: DownloadWrapper, continueInBackground: Bool) {
|
||||
assert(queue.isCurrent())
|
||||
|
||||
self.queue = queue
|
||||
self.fileToken = fileToken
|
||||
self.masterDownload = masterDownload
|
||||
self.continueInBackground = continueInBackground
|
||||
|
||||
/*let knownUpperBound: Int32 = 0
|
||||
self.knownUpperBound = knownUpperBound*/
|
||||
}
|
||||
|
||||
deinit {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
//self.requestOffsetAndDisposable?.1.dispose()
|
||||
}
|
||||
|
||||
/*private func take(offset: Int32, limit: Int32) -> [Int32: Data]? {
|
||||
assert(offset % dataHashLength == 0)
|
||||
assert(limit % dataHashLength == 0)
|
||||
|
||||
var result: [Int32: Data] = [:]
|
||||
|
||||
var localOffset: Int32 = 0
|
||||
while localOffset < limit {
|
||||
if let hash = self.hashes[offset + localOffset] {
|
||||
result[offset + localOffset] = hash
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
localOffset += dataHashLength
|
||||
}
|
||||
|
||||
return result
|
||||
}*/
|
||||
|
||||
/*func get(offset: Int32, limit: Int32) -> Signal<[Int32: Data], MultipartFetchDownloadError> {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
if let result = strongSelf.take(offset: offset, limit: limit) {
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
let index = strongSelf.subscribers.add((offset, limit, { result in
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}))
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.subscribers.remove(index)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if let requestedUpperBound = strongSelf.requestedUpperBound {
|
||||
strongSelf.requestedUpperBound = max(requestedUpperBound, offset + limit)
|
||||
} else {
|
||||
strongSelf.requestedUpperBound = offset + limit
|
||||
}
|
||||
|
||||
if strongSelf.requestOffsetAndDisposable == nil {
|
||||
strongSelf.requestMore()
|
||||
} else {
|
||||
if let requestedUpperBound = strongSelf.requestedUpperBound {
|
||||
strongSelf.requestedUpperBound = max(requestedUpperBound, offset + limit)
|
||||
} else {
|
||||
strongSelf.requestedUpperBound = offset + limit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
private func requestMore() {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
let requestOffset = self.knownUpperBound
|
||||
let disposable = MetaDisposable()
|
||||
self.requestOffsetAndDisposable = (requestOffset, disposable)
|
||||
let queue = self.queue
|
||||
let fileToken = self.fileToken
|
||||
disposable.set((self.masterDownload.request(Api.functions.upload.getCdnFileHashes(fileToken: Buffer(data: fileToken), offset: requestOffset), tag: nil, continueInBackground: self.continueInBackground)
|
||||
|> map { partHashes -> [Int32: Data] in
|
||||
var parsedPartHashes: [Int32: Data] = [:]
|
||||
for part in partHashes {
|
||||
switch part {
|
||||
case let .fileHash(offset, limit, bytes):
|
||||
assert(limit == 128 * 1024)
|
||||
parsedPartHashes[offset] = bytes.makeData()
|
||||
}
|
||||
}
|
||||
return parsedPartHashes
|
||||
}
|
||||
|> `catch` { _ -> Signal<[Int32: Data], NoError> in
|
||||
return .single([:])
|
||||
} |> deliverOn(queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
if strongSelf.requestOffsetAndDisposable?.0 == requestOffset {
|
||||
strongSelf.requestOffsetAndDisposable = nil
|
||||
|
||||
for (hashOffset, hashData) in result {
|
||||
assert(hashOffset % dataHashLength == 0)
|
||||
strongSelf.knownUpperBound = max(strongSelf.knownUpperBound, hashOffset + dataHashLength)
|
||||
strongSelf.hashes[hashOffset] = hashData
|
||||
}
|
||||
|
||||
for (index, item) in strongSelf.subscribers.copyItemsWithIndices() {
|
||||
let (offset, limit, subscriber) = item
|
||||
if let data = strongSelf.take(offset: offset, limit: limit) {
|
||||
strongSelf.subscribers.remove(index)
|
||||
subscriber(data)
|
||||
}
|
||||
}
|
||||
|
||||
if let requestedUpperBound = strongSelf.requestedUpperBound, requestedUpperBound > strongSelf.knownUpperBound {
|
||||
strongSelf.requestMore()
|
||||
}
|
||||
} else {
|
||||
//assertionFailure()
|
||||
}
|
||||
}
|
||||
}))
|
||||
}*/
|
||||
|
||||
func getCluster(offset: Int32, completion: @escaping ([Int32: Data]) -> Void, error: @escaping (MultipartFetchDownloadError) -> Void) -> Disposable {
|
||||
func getCluster(offset: Int64, completion: @escaping ([Int64: Data]) -> Void, error: @escaping (MultipartFetchDownloadError) -> Void) -> Disposable {
|
||||
precondition(offset % (1 * 1024 * 1024) == 0)
|
||||
|
||||
let clusterContext: ClusterContext
|
||||
|
|
@ -302,8 +182,8 @@ private final class MultipartCdnHashSource {
|
|||
self.clusterContexts[offset] = clusterContext
|
||||
|
||||
disposable.set((self.masterDownload.request(Api.functions.upload.getCdnFileHashes(fileToken: Buffer(data: self.fileToken), offset: offset), tag: nil, continueInBackground: self.continueInBackground)
|
||||
|> map { partHashes -> [Int32: Data] in
|
||||
var parsedPartHashes: [Int32: Data] = [:]
|
||||
|> map { partHashes -> [Int64: Data] in
|
||||
var parsedPartHashes: [Int64: Data] = [:]
|
||||
for part in partHashes {
|
||||
switch part {
|
||||
case let .fileHash(offset, limit, bytes):
|
||||
|
|
@ -359,7 +239,7 @@ private final class MultipartCdnHashSource {
|
|||
}
|
||||
}
|
||||
|
||||
private func cluster(offset: Int32) -> Signal<[Int32: Data], MultipartFetchDownloadError> {
|
||||
private func cluster(offset: Int64) -> Signal<[Int64: Data], MultipartFetchDownloadError> {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
|
@ -382,11 +262,11 @@ private final class MultipartCdnHashSource {
|
|||
}
|
||||
}
|
||||
|
||||
func get(offset: Int32, limit: Int32) -> Signal<[Int32: Data], MultipartFetchDownloadError> {
|
||||
func get(offset: Int64, limit: Int64) -> Signal<[Int64: Data], MultipartFetchDownloadError> {
|
||||
precondition(offset % dataHashLength == 0)
|
||||
precondition((offset + limit) % dataHashLength == 0)
|
||||
|
||||
var clusterOffsets = Set<Int32>()
|
||||
var clusterOffsets = Set<Int64>()
|
||||
for partOffset in stride(from: offset, to: offset + limit, by: Int(dataHashLength)) {
|
||||
clusterOffsets.insert(partOffset - (partOffset % (1 * 1024 * 1024)))
|
||||
}
|
||||
|
|
@ -394,8 +274,8 @@ private final class MultipartCdnHashSource {
|
|||
return combineLatest(clusterOffsets.map { clusterOffset in
|
||||
return self.cluster(offset: clusterOffset)
|
||||
})
|
||||
|> mapToSignal { clusterResults -> Signal<[Int32: Data], MultipartFetchDownloadError> in
|
||||
var result: [Int32: Data] = [:]
|
||||
|> mapToSignal { clusterResults -> Signal<[Int64: Data], MultipartFetchDownloadError> in
|
||||
var result: [Int64: Data] = [:]
|
||||
|
||||
for partOffset in stride(from: offset, to: offset + limit, by: Int(dataHashLength)) {
|
||||
var found = false
|
||||
|
|
@ -420,7 +300,7 @@ private enum MultipartFetchSource {
|
|||
case master(location: MultipartFetchMasterLocation, download: DownloadWrapper)
|
||||
case cdn(masterDatacenterId: Int32, fileToken: Data, key: Data, iv: Data, download: DownloadWrapper, masterDownload: DownloadWrapper, hashSource: MultipartCdnHashSource)
|
||||
|
||||
func request(offset: Int32, limit: Int32, tag: MediaResourceFetchTag?, resource: TelegramMediaResource, resourceReference: FetchResourceReference, fileReference: Data?, continueInBackground: Bool) -> Signal<Data, MultipartFetchDownloadError> {
|
||||
func request(offset: Int64, limit: Int64, tag: MediaResourceFetchTag?, resource: TelegramMediaResource, resourceReference: FetchResourceReference, fileReference: Data?, continueInBackground: Bool) -> Signal<Data, MultipartFetchDownloadError> {
|
||||
var resourceReferenceValue: MediaResourceReference?
|
||||
switch resourceReference {
|
||||
case .forceRevalidate:
|
||||
|
|
@ -462,7 +342,7 @@ private enum MultipartFetchSource {
|
|||
}
|
||||
return .single(resultData)
|
||||
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv, partHashes):
|
||||
var parsedPartHashes: [Int32: Data] = [:]
|
||||
var parsedPartHashes: [Int64: Data] = [:]
|
||||
for part in partHashes {
|
||||
switch part {
|
||||
case let .fileHash(offset, limit, bytes):
|
||||
|
|
@ -475,7 +355,7 @@ private enum MultipartFetchSource {
|
|||
}
|
||||
}
|
||||
case let .web(_, location):
|
||||
return download.request(Api.functions.upload.getWebFile(location: location, offset: offset, limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground)
|
||||
return download.request(Api.functions.upload.getWebFile(location: location, offset: Int32(offset), limit: Int32(limit)), tag: tag, continueInBackground: continueInBackground)
|
||||
|> mapError { error -> MultipartFetchDownloadError in
|
||||
return .generic
|
||||
}
|
||||
|
|
@ -491,7 +371,7 @@ private enum MultipartFetchSource {
|
|||
}
|
||||
}
|
||||
case let .cdn(masterDatacenterId, fileToken, key, iv, download, _, hashSource):
|
||||
var updatedLength = roundUp(Int(limit), to: 4096)
|
||||
var updatedLength = roundUp(Int64(limit), to: 4096)
|
||||
while updatedLength % 4096 != 0 || 1048576 % updatedLength != 0 {
|
||||
updatedLength += 1
|
||||
}
|
||||
|
|
@ -512,7 +392,7 @@ private enum MultipartFetchSource {
|
|||
let partIvCount = partIv.count
|
||||
partIv.withUnsafeMutableBytes { rawBytes -> Void in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
var ivOffset: Int32 = (offset / 16).bigEndian
|
||||
var ivOffset: Int64 = (offset / 16).bigEndian
|
||||
memcpy(bytes.advanced(by: partIvCount - 4), &ivOffset, 4)
|
||||
}
|
||||
return .single(MTAesCtrDecrypt(bytes.makeData(), key, partIv)!)
|
||||
|
|
@ -521,23 +401,23 @@ private enum MultipartFetchSource {
|
|||
}
|
||||
|
||||
return combineLatest(part, hashSource.get(offset: offset, limit: limit))
|
||||
|> mapToSignal { partData, hashData -> Signal<Data, MultipartFetchDownloadError> in
|
||||
var localOffset = 0
|
||||
while localOffset < partData.count {
|
||||
let dataToHash = partData.subdata(in: localOffset ..< min(partData.count, localOffset + Int(dataHashLength)))
|
||||
if let hash = hashData[offset + Int32(localOffset)] {
|
||||
let localHash = MTSha256(dataToHash)
|
||||
if localHash != hash {
|
||||
return .fail(.generic)
|
||||
}
|
||||
} else {
|
||||
|> mapToSignal { partData, hashData -> Signal<Data, MultipartFetchDownloadError> in
|
||||
var localOffset: Int64 = 0
|
||||
while localOffset < partData.count {
|
||||
let dataToHash = partData.subdata(in: Int(localOffset) ..< min(partData.count, Int(localOffset + Int64(dataHashLength))))
|
||||
if let hash = hashData[offset + localOffset] {
|
||||
let localHash = MTSha256(dataToHash)
|
||||
if localHash != hash {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
localOffset += Int(dataHashLength)
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
return .single(partData)
|
||||
|
||||
localOffset += Int64(dataHashLength)
|
||||
}
|
||||
return .single(partData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -550,8 +430,8 @@ private enum FetchResourceReference {
|
|||
|
||||
private final class MultipartFetchManager {
|
||||
let parallelParts: Int
|
||||
let defaultPartSize: Int
|
||||
var partAlignment = 4 * 1024
|
||||
let defaultPartSize: Int64
|
||||
var partAlignment: Int64 = 4 * 1024
|
||||
|
||||
var resource: TelegramMediaResource
|
||||
var resourceReference: FetchResourceReference
|
||||
|
|
@ -561,26 +441,26 @@ private final class MultipartFetchManager {
|
|||
|
||||
let queue = Queue()
|
||||
|
||||
var currentIntervals: [(Range<Int>, MediaBoxFetchPriority)]?
|
||||
var currentIntervals: [(Range<Int64>, MediaBoxFetchPriority)]?
|
||||
var currentFilledRanges = IndexSet()
|
||||
|
||||
var completeSize: Int?
|
||||
var completeSize: Int64?
|
||||
var completeSizeReported = false
|
||||
|
||||
let postbox: Postbox
|
||||
let network: Network
|
||||
let revalidationContext: MediaReferenceRevalidationContext?
|
||||
let continueInBackground: Bool
|
||||
let partReady: (Int, Data) -> Void
|
||||
let reportCompleteSize: (Int) -> Void
|
||||
let partReady: (Int64, Data) -> Void
|
||||
let reportCompleteSize: (Int64) -> Void
|
||||
|
||||
private let useMainConnection: Bool
|
||||
private var source: MultipartFetchSource
|
||||
|
||||
var fetchingParts: [Int: (Int, Disposable)] = [:]
|
||||
var fetchingParts: [Int64: (Int64, Disposable)] = [:]
|
||||
var nextFetchingPartId = 0
|
||||
var fetchedParts: [Int: (Int, Data)] = [:]
|
||||
var cachedPartHashes: [Int: Data] = [:]
|
||||
var fetchedParts: [Int64: (Int64, Data)] = [:]
|
||||
var cachedPartHashes: [Int64: Data] = [:]
|
||||
|
||||
var reuploadingToCdn = false
|
||||
let reuploadToCdnDisposable = MetaDisposable()
|
||||
|
|
@ -593,7 +473,7 @@ private final class MultipartFetchManager {
|
|||
|
||||
var rangesDisposable: Disposable?
|
||||
|
||||
init(resource: TelegramMediaResource, parameters: MediaResourceFetchParameters?, size: Int?, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int32?, location: MultipartFetchMasterLocation, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext?, partReady: @escaping (Int, Data) -> Void, reportCompleteSize: @escaping (Int) -> Void, useMainConnection: Bool) {
|
||||
init(resource: TelegramMediaResource, parameters: MediaResourceFetchParameters?, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int64?, location: MultipartFetchMasterLocation, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext?, partReady: @escaping (Int64, Data) -> Void, reportCompleteSize: @escaping (Int64) -> Void, useMainConnection: Bool) {
|
||||
self.resource = resource
|
||||
self.parameters = parameters
|
||||
self.consumerId = Int64.random(in: Int64.min ... Int64.max)
|
||||
|
|
@ -698,8 +578,8 @@ private final class MultipartFetchManager {
|
|||
let isSingleContiguousRange = currentIntervals.count == 1
|
||||
for offset in self.fetchedParts.keys.sorted() {
|
||||
if let (_, data) = self.fetchedParts[offset] {
|
||||
let partRange = offset ..< (offset + data.count)
|
||||
removeFromFetchIntervals.insert(integersIn: partRange)
|
||||
let partRange = offset ..< (offset + Int64(data.count))
|
||||
removeFromFetchIntervals.insert(integersIn: Int(partRange.lowerBound) ..< Int(partRange.upperBound))
|
||||
|
||||
var hasEarlierFetchingPart = false
|
||||
if isSingleContiguousRange {
|
||||
|
|
@ -712,7 +592,7 @@ private final class MultipartFetchManager {
|
|||
}
|
||||
|
||||
if !hasEarlierFetchingPart {
|
||||
self.currentFilledRanges.insert(integersIn: partRange)
|
||||
self.currentFilledRanges.insert(integersIn: Int(partRange.lowerBound) ..< Int(partRange.upperBound))
|
||||
self.fetchedParts.removeValue(forKey: offset)
|
||||
self.partReady(offset, self.state.transform(offset: offset, data: data))
|
||||
}
|
||||
|
|
@ -720,21 +600,21 @@ private final class MultipartFetchManager {
|
|||
}
|
||||
|
||||
for (offset, (size, _)) in self.fetchingParts {
|
||||
removeFromFetchIntervals.insert(integersIn: offset ..< (offset + size))
|
||||
removeFromFetchIntervals.insert(integersIn: Int(offset) ..< Int(offset + size))
|
||||
}
|
||||
|
||||
if let completeSize = self.completeSize {
|
||||
self.currentFilledRanges.insert(integersIn: completeSize ..< Int.max)
|
||||
removeFromFetchIntervals.insert(integersIn: completeSize ..< Int.max)
|
||||
self.currentFilledRanges.insert(integersIn: Int(completeSize) ..< Int.max)
|
||||
removeFromFetchIntervals.insert(integersIn: Int(completeSize) ..< Int.max)
|
||||
}
|
||||
|
||||
var intervalsToFetch: [(Range<Int>, MediaBoxFetchPriority)] = []
|
||||
var intervalsToFetch: [(Range<Int64>, MediaBoxFetchPriority)] = []
|
||||
for (interval, priority) in currentIntervals {
|
||||
var intervalIndexSet = IndexSet(integersIn: interval)
|
||||
var intervalIndexSet = IndexSet(integersIn: Int(interval.lowerBound) ..< Int(interval.upperBound))
|
||||
intervalIndexSet.subtract(removeFromFetchIntervals)
|
||||
for cleanInterval in intervalIndexSet.rangeView {
|
||||
assert(!cleanInterval.isEmpty)
|
||||
intervalsToFetch.append((cleanInterval, priority))
|
||||
intervalsToFetch.append((Int64(cleanInterval.lowerBound) ..< Int64(cleanInterval.upperBound), priority))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -743,7 +623,7 @@ private final class MultipartFetchManager {
|
|||
self.completeSizeReported = true
|
||||
assert(self.fetchedParts.isEmpty)
|
||||
if let decryptedSize = self.state.decryptedSize {
|
||||
self.reportCompleteSize(Int(decryptedSize))
|
||||
self.reportCompleteSize(decryptedSize)
|
||||
} else {
|
||||
self.reportCompleteSize(completeSize)
|
||||
}
|
||||
|
|
@ -770,8 +650,8 @@ private final class MultipartFetchManager {
|
|||
}
|
||||
self.nextFetchingPartId += 1
|
||||
let (firstInterval, priority) = intervalsToFetch[currentIntervalIndex]
|
||||
var downloadRange: Range<Int> = firstInterval.lowerBound ..< min(firstInterval.lowerBound + self.defaultPartSize, firstInterval.upperBound)
|
||||
let rawRange: Range<Int> = downloadRange
|
||||
var downloadRange: Range<Int64> = firstInterval.lowerBound ..< min(firstInterval.lowerBound + self.defaultPartSize, firstInterval.upperBound)
|
||||
let rawRange: Range<Int64> = downloadRange
|
||||
if downloadRange.lowerBound % self.partAlignment != 0 {
|
||||
let previousBoundary = (downloadRange.lowerBound / self.partAlignment) * self.partAlignment
|
||||
downloadRange = previousBoundary ..< downloadRange.upperBound
|
||||
|
|
@ -788,26 +668,26 @@ private final class MultipartFetchManager {
|
|||
downloadRange = downloadRange.lowerBound ..< (downloadRange.upperBound - 1)
|
||||
}
|
||||
|
||||
var intervalIndexSet = IndexSet(integersIn: intervalsToFetch[currentIntervalIndex].0)
|
||||
intervalIndexSet.remove(integersIn: downloadRange)
|
||||
var intervalIndexSet = IndexSet(integersIn: intervalsToFetch[currentIntervalIndex].0.asIntRange())
|
||||
intervalIndexSet.remove(integersIn: downloadRange.asIntRange())
|
||||
intervalsToFetch.remove(at: currentIntervalIndex)
|
||||
var insertIndex = currentIntervalIndex
|
||||
for interval in intervalIndexSet.rangeView {
|
||||
intervalsToFetch.insert((interval, priority), at: insertIndex)
|
||||
intervalsToFetch.insert((interval.asInt64Range(), priority), at: insertIndex)
|
||||
insertIndex += 1
|
||||
}
|
||||
|
||||
let part = self.source.request(offset: Int32(downloadRange.lowerBound), limit: Int32(downloadRange.count), tag: self.parameters?.tag, resource: self.resource, resourceReference: self.resourceReference, fileReference: self.fileReference, continueInBackground: self.continueInBackground)
|
||||
let part = self.source.request(offset: Int64(downloadRange.lowerBound), limit: Int64(downloadRange.count), tag: self.parameters?.tag, resource: self.resource, resourceReference: self.resourceReference, fileReference: self.fileReference, continueInBackground: self.continueInBackground)
|
||||
|> deliverOn(self.queue)
|
||||
let partDisposable = MetaDisposable()
|
||||
self.fetchingParts[downloadRange.lowerBound] = (downloadRange.count, partDisposable)
|
||||
self.fetchingParts[downloadRange.lowerBound] = (Int64(downloadRange.count), partDisposable)
|
||||
|
||||
partDisposable.set(part.start(next: { [weak self] data in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if data.count < downloadRange.count {
|
||||
strongSelf.completeSize = downloadRange.lowerBound + data.count
|
||||
strongSelf.completeSize = downloadRange.lowerBound + Int64(data.count)
|
||||
}
|
||||
let _ = strongSelf.fetchingParts.removeValue(forKey: downloadRange.lowerBound)
|
||||
strongSelf.fetchedParts[downloadRange.lowerBound] = (rawRange.lowerBound, data)
|
||||
|
|
@ -849,7 +729,7 @@ private final class MultipartFetchManager {
|
|||
case let .switchToCdn(id, token, key, iv, partHashes):
|
||||
switch strongSelf.source {
|
||||
case let .master(location, download):
|
||||
strongSelf.partAlignment = Int(dataHashLength)
|
||||
strongSelf.partAlignment = dataHashLength
|
||||
strongSelf.source = .cdn(masterDatacenterId: location.datacenterId, fileToken: token, key: key, iv: iv, download: DownloadWrapper(consumerId: strongSelf.consumerId, datacenterId: id, isCdn: true, network: strongSelf.network, useMainConnection: strongSelf.useMainConnection), masterDownload: download, hashSource: MultipartCdnHashSource(queue: strongSelf.queue, fileToken: token, hashes: partHashes, masterDownload: download, continueInBackground: strongSelf.continueInBackground))
|
||||
strongSelf.checkState()
|
||||
case .cdn, .none:
|
||||
|
|
@ -882,7 +762,7 @@ private final class MultipartFetchManager {
|
|||
}
|
||||
}
|
||||
|
||||
public func standaloneMultipartFetch(postbox: Postbox, network: Network, resource: TelegramMediaResource, datacenterId: Int, size: Int?, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil, continueInBackground: Bool = false, useMainConnection: Bool = false) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
public func standaloneMultipartFetch(postbox: Postbox, network: Network, resource: TelegramMediaResource, datacenterId: Int, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil, continueInBackground: Bool = false, useMainConnection: Bool = false) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
return multipartFetch(
|
||||
postbox: postbox,
|
||||
network: network,
|
||||
|
|
@ -904,7 +784,7 @@ public func resourceFetchInfo(resource: TelegramMediaResource) -> MediaResourceF
|
|||
)
|
||||
}
|
||||
|
||||
func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext?, resource: TelegramMediaResource, datacenterId: Int, size: Int?, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil, continueInBackground: Bool = false, useMainConnection: Bool = false) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext?, resource: TelegramMediaResource, datacenterId: Int, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int64? = nil, continueInBackground: Bool = false, useMainConnection: Bool = false) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
return Signal { subscriber in
|
||||
let location: MultipartFetchMasterLocation
|
||||
if let resource = resource as? WebFileReferenceMediaResource {
|
||||
|
|
@ -958,7 +838,7 @@ func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidati
|
|||
}
|
||||
|
||||
let manager = MultipartFetchManager(resource: resource, parameters: parameters, size: size, intervals: intervals, encryptionKey: encryptionKey, decryptedSize: decryptedSize, location: location, postbox: postbox, network: network, revalidationContext: mediaReferenceRevalidationContext, partReady: { dataOffset, data in
|
||||
subscriber.putNext(.dataPart(resourceOffset: dataOffset, data: data, range: 0 ..< data.count, complete: false))
|
||||
subscriber.putNext(.dataPart(resourceOffset: dataOffset, data: data, range: 0 ..< Int64(data.count), complete: false))
|
||||
}, reportCompleteSize: { size in
|
||||
subscriber.putNext(.resourceSizeUpdated(size))
|
||||
subscriber.putCompletion()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ private func md5(_ data: Data) -> Data {
|
|||
private final class MultipartUploadState {
|
||||
let aesKey: Data
|
||||
var aesIv: Data
|
||||
var effectiveSize: Int = 0
|
||||
var effectiveSize: Int64 = 0
|
||||
|
||||
init(encryptionKey: SecretFileEncryptionKey?) {
|
||||
if let encryptionKey = encryptionKey {
|
||||
|
|
@ -41,7 +41,7 @@ private final class MultipartUploadState {
|
|||
|
||||
func transformHeader(data: Data) -> Data {
|
||||
assert(self.aesKey.isEmpty)
|
||||
self.effectiveSize += data.count
|
||||
self.effectiveSize += Int64(data.count)
|
||||
return data
|
||||
}
|
||||
|
||||
|
|
@ -66,15 +66,15 @@ private final class MultipartUploadState {
|
|||
MTAesEncryptBytesInplaceAndModifyIv(bytes, encryptedDataCount, self.aesKey, iv)
|
||||
}
|
||||
}
|
||||
self.effectiveSize += encryptedData.count
|
||||
self.effectiveSize += Int64(encryptedData.count)
|
||||
return encryptedData
|
||||
} else {
|
||||
self.effectiveSize += data.count
|
||||
self.effectiveSize += Int64(data.count)
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
func finalize() -> Int {
|
||||
func finalize() -> Int64 {
|
||||
return self.effectiveSize
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ private struct MultipartIntermediateResult {
|
|||
let id: Int64
|
||||
let partCount: Int32
|
||||
let md5Digest: String
|
||||
let size: Int32
|
||||
let size: Int64
|
||||
let bigTotalParts: Int?
|
||||
}
|
||||
|
||||
|
|
@ -91,20 +91,20 @@ private enum MultipartUploadData {
|
|||
case resourceData(MediaResourceData)
|
||||
case data(Data)
|
||||
|
||||
var size: Int {
|
||||
var size: Int64 {
|
||||
switch self {
|
||||
case let .resourceData(data):
|
||||
return data.size
|
||||
case let .data(data):
|
||||
return data.count
|
||||
case let .resourceData(data):
|
||||
return data.size
|
||||
case let .data(data):
|
||||
return Int64(data.count)
|
||||
}
|
||||
}
|
||||
var complete: Bool {
|
||||
switch self {
|
||||
case let .resourceData(data):
|
||||
return data.complete
|
||||
case .data:
|
||||
return true
|
||||
case let .resourceData(data):
|
||||
return data.complete
|
||||
case .data:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ private enum HeaderPartState {
|
|||
|
||||
private final class MultipartUploadManager {
|
||||
let parallelParts: Int
|
||||
var defaultPartSize: Int
|
||||
var defaultPartSize: Int64
|
||||
var bigTotalParts: Int?
|
||||
var bigParts: Bool
|
||||
private let forceNoBigParts: Bool
|
||||
|
|
@ -128,13 +128,13 @@ private final class MultipartUploadManager {
|
|||
|
||||
let dataSignal: Signal<MultipartUploadData, NoError>
|
||||
|
||||
var committedOffset: Int
|
||||
var committedOffset: Int64
|
||||
let uploadPart: (UploadPart) -> Signal<Void, UploadPartError>
|
||||
let progress: (Float) -> Void
|
||||
let completed: (MultipartIntermediateResult?) -> Void
|
||||
|
||||
var uploadingParts: [Int: (Int, Disposable)] = [:]
|
||||
var uploadedParts: [Int: Int] = [:]
|
||||
var uploadingParts: [Int64: (Int64, Disposable)] = [:]
|
||||
var uploadedParts: [Int64: Int64] = [:]
|
||||
|
||||
let dataDisposable = MetaDisposable()
|
||||
var resourceData: MultipartUploadData?
|
||||
|
|
@ -143,7 +143,7 @@ private final class MultipartUploadManager {
|
|||
|
||||
let state: MultipartUploadState
|
||||
|
||||
init(headerSize: Int32, data: Signal<MultipartUploadData, NoError>, encryptionKey: SecretFileEncryptionKey?, hintFileSize: Int?, hintFileIsLarge: Bool, forceNoBigParts: Bool, useLargerParts: Bool, increaseParallelParts: Bool, uploadPart: @escaping (UploadPart) -> Signal<Void, UploadPartError>, progress: @escaping (Float) -> Void, completed: @escaping (MultipartIntermediateResult?) -> Void) {
|
||||
init(headerSize: Int32, data: Signal<MultipartUploadData, NoError>, encryptionKey: SecretFileEncryptionKey?, hintFileSize: Int64?, hintFileIsLarge: Bool, forceNoBigParts: Bool, useLargerParts: Bool, increaseParallelParts: Bool, uploadPart: @escaping (UploadPart) -> Signal<Void, UploadPartError>, progress: @escaping (Float) -> Void, completed: @escaping (MultipartIntermediateResult?) -> Void) {
|
||||
self.dataSignal = data
|
||||
|
||||
var fileId: Int64 = 0
|
||||
|
|
@ -174,7 +174,7 @@ private final class MultipartUploadManager {
|
|||
|
||||
if let hintFileSize = hintFileSize, hintFileSize > 10 * 1024 * 1024, !forceNoBigParts {
|
||||
self.defaultPartSize = 512 * 1024
|
||||
self.bigTotalParts = (hintFileSize / self.defaultPartSize) + (hintFileSize % self.defaultPartSize == 0 ? 0 : 1)
|
||||
self.bigTotalParts = Int((hintFileSize / self.defaultPartSize) + (hintFileSize % self.defaultPartSize == 0 ? 0 : 1))
|
||||
self.bigParts = true
|
||||
} else if hintFileIsLarge, !forceNoBigParts {
|
||||
self.defaultPartSize = 512 * 1024
|
||||
|
|
@ -216,7 +216,7 @@ private final class MultipartUploadManager {
|
|||
if self.committedOffset == 0 && self.uploadedParts.isEmpty && self.uploadingParts.isEmpty {
|
||||
if resourceData.size > 10 * 1024 * 1024, !self.forceNoBigParts {
|
||||
self.defaultPartSize = 512 * 1024
|
||||
self.bigTotalParts = (resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
self.bigTotalParts = Int(resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
self.bigParts = true
|
||||
} else {
|
||||
self.bigParts = false
|
||||
|
|
@ -252,13 +252,13 @@ private final class MultipartUploadManager {
|
|||
let effectivePartCount = Int32(effectiveSize / self.defaultPartSize + (effectiveSize % self.defaultPartSize == 0 ? 0 : 1))
|
||||
var currentBigTotalParts = self.bigTotalParts
|
||||
if self.bigParts {
|
||||
currentBigTotalParts = (resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
currentBigTotalParts = Int(resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
}
|
||||
self.completed(MultipartIntermediateResult(id: self.fileId, partCount: effectivePartCount, md5Digest: "", size: Int32(resourceData.size), bigTotalParts: currentBigTotalParts))
|
||||
self.completed(MultipartIntermediateResult(id: self.fileId, partCount: effectivePartCount, md5Digest: "", size: resourceData.size, bigTotalParts: currentBigTotalParts))
|
||||
case .notStarted:
|
||||
let partOffset = 0
|
||||
let partOffset: Int64 = 0
|
||||
let partSize = min(resourceData.size - partOffset, self.defaultPartSize)
|
||||
let partIndex = partOffset / self.defaultPartSize
|
||||
let partIndex = Int(partOffset / self.defaultPartSize)
|
||||
let fileData: Data?
|
||||
switch resourceData {
|
||||
case let .resourceData(data):
|
||||
|
|
@ -267,11 +267,11 @@ private final class MultipartUploadManager {
|
|||
fileData = data
|
||||
}
|
||||
if let fileData = fileData {
|
||||
let partData = self.state.transformHeader(data: fileData.subdata(in: partOffset ..< (partOffset + partSize)))
|
||||
let partData = self.state.transformHeader(data: fileData.subdata(in: Int(partOffset) ..< Int(partOffset + partSize)))
|
||||
var currentBigTotalParts: Int? = nil
|
||||
if self.bigParts {
|
||||
let totalParts = (resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
currentBigTotalParts = totalParts
|
||||
currentBigTotalParts = Int(totalParts)
|
||||
}
|
||||
self.headerPartState = .uploading
|
||||
let part = self.uploadPart(UploadPart(fileId: self.fileId, index: partIndex, data: partData, bigTotalParts: currentBigTotalParts, bigPart: self.bigParts))
|
||||
|
|
@ -312,13 +312,13 @@ private final class MultipartUploadManager {
|
|||
let partSize = min(resourceData.size - partOffset, self.defaultPartSize)
|
||||
|
||||
if nextOffset < resourceData.size && partSize > 0 && (resourceData.complete || partSize == self.defaultPartSize) {
|
||||
let partIndex = partOffset / self.defaultPartSize
|
||||
let partIndex = Int(partOffset / self.defaultPartSize)
|
||||
let partData: Data?
|
||||
switch resourceData {
|
||||
case let .resourceData(data):
|
||||
if let file = ManagedFile(queue: nil, path: data.path, mode: .read) {
|
||||
file.seek(position: Int64(partOffset))
|
||||
let data = file.readData(count: partSize)
|
||||
let data = file.readData(count: Int(partSize))
|
||||
if data.count == partSize {
|
||||
partData = data
|
||||
} else {
|
||||
|
|
@ -329,7 +329,7 @@ private final class MultipartUploadManager {
|
|||
}
|
||||
case let .data(data):
|
||||
if data.count >= partOffset + partSize {
|
||||
partData = data.subdata(in: partOffset ..< (partOffset + partSize))
|
||||
partData = data.subdata(in: Int(partOffset) ..< Int(partOffset + partSize))
|
||||
} else {
|
||||
partData = nil
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ private final class MultipartUploadManager {
|
|||
let partData = self.state.transform(data: partData)
|
||||
var currentBigTotalParts = self.bigTotalParts
|
||||
if self.bigParts && resourceData.complete && partOffset + partSize == resourceData.size {
|
||||
currentBigTotalParts = (resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
currentBigTotalParts = Int(resourceData.size / self.defaultPartSize) + (resourceData.size % self.defaultPartSize == 0 ? 0 : 1)
|
||||
}
|
||||
let part = self.uploadPart(UploadPart(fileId: self.fileId, index: partIndex, data: partData, bigTotalParts: currentBigTotalParts, bigPart: self.bigParts))
|
||||
|> deliverOn(self.queue)
|
||||
|
|
@ -376,7 +376,7 @@ private final class MultipartUploadManager {
|
|||
enum MultipartUploadResult {
|
||||
case progress(Float)
|
||||
case inputFile(Api.InputFile)
|
||||
case inputSecretFile(Api.InputEncryptedFile, Int32, SecretFileEncryptionKey)
|
||||
case inputSecretFile(Api.InputEncryptedFile, Int64, SecretFileEncryptionKey)
|
||||
}
|
||||
|
||||
public enum MultipartUploadSource {
|
||||
|
|
@ -390,7 +390,7 @@ enum MultipartUploadError {
|
|||
case generic
|
||||
}
|
||||
|
||||
func multipartUpload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int?, hintFileIsLarge: Bool, forceNoBigParts: Bool, useLargerParts: Bool = false, increaseParallelParts: Bool = false, useMultiplexedRequests: Bool = true, useCompression: Bool = false) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
func multipartUpload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int64?, hintFileIsLarge: Bool, forceNoBigParts: Bool, useLargerParts: Bool = false, increaseParallelParts: Bool = false, useMultiplexedRequests: Bool = true, useCompression: Bool = false) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
enum UploadInterface {
|
||||
case download(Download)
|
||||
case multiplexed(manager: MultiplexedRequestManager, datacenterId: Int, consumerId: Int64)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ enum PendingMessageUploadedContent {
|
|||
case media(Api.InputMedia, String)
|
||||
case forward(ForwardSourceInfoAttribute)
|
||||
case chatContextResult(OutgoingChatContextResultMessageAttribute)
|
||||
case secretMedia(Api.InputEncryptedFile, Int32, SecretFileEncryptionKey)
|
||||
case secretMedia(Api.InputEncryptedFile, Int64, SecretFileEncryptionKey)
|
||||
case messageScreenshot
|
||||
}
|
||||
|
||||
|
|
@ -610,11 +610,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
|||
}
|
||||
|
||||
var hintFileIsLarge = false
|
||||
var hintSize: Int?
|
||||
var hintSize: Int64?
|
||||
if let size = file.size {
|
||||
hintSize = size
|
||||
} else if let resource = file.resource as? LocalFileReferenceMediaResource, let size = resource.size {
|
||||
hintSize = Int(size)
|
||||
hintSize = size
|
||||
}
|
||||
|
||||
loop: for attribute in file.attributes {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ private func uploadedImage(account: Account, data: Data) -> Signal<UploadMediaEv
|
|||
}
|
||||
|
||||
private func uploadedFile(account: Account, data: Data, mimeType: String, attributes: [TelegramMediaFileAttribute]) -> Signal<UploadMediaEvent, PendingMessageUploadError> {
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(attributes)), hintFileSize: data.count, hintFileIsLarge: false, forceNoBigParts: false)
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(attributes)), hintFileSize: Int64(data.count), hintFileIsLarge: false, forceNoBigParts: false)
|
||||
|> mapError { _ -> PendingMessageUploadError in return .generic }
|
||||
|> map { next -> UploadMediaEvent in
|
||||
switch next {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public func standaloneUploadedImage(account: Account, peerId: PeerId, text: Stri
|
|||
|> mapToSignal { result -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||
switch result {
|
||||
case let .encryptedFile(id, accessHash, size, dcId, _):
|
||||
return .single(.result(.media(.standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: Int32(data.count), datacenterId: Int(dcId), key: key), progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])))))
|
||||
return .single(.result(.media(.standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: Int64(data.count), datacenterId: Int(dcId), key: key), progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])))))
|
||||
case .encryptedFileEmpty:
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ public func standaloneUploadedFile(account: Account, peerId: PeerId, text: Strin
|
|||
|> mapToSignal { result -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||
switch result {
|
||||
case let .encryptedFile(id, accessHash, size, dcId, _):
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: size, datacenterId: Int(dcId), key: key), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: attributes)
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: size, datacenterId: Int(dcId), key: key), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: size, attributes: attributes)
|
||||
|
||||
return .single(.result(.media(.standalone(media: media))))
|
||||
case .encryptedFileEmpty:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ extension AutodownloadPresetSettings {
|
|||
init(apiAutodownloadSettings: Api.AutoDownloadSettings) {
|
||||
switch apiAutodownloadSettings {
|
||||
case let .autoDownloadSettings(flags, photoSizeMax, videoSizeMax, fileSizeMax, videoUploadMaxbitrate):
|
||||
self.init(disabled: (flags & (1 << 0)) != 0, photoSizeMax: photoSizeMax, videoSizeMax: videoSizeMax, fileSizeMax: fileSizeMax, preloadLargeVideo: (flags & (1 << 1)) != 0, lessDataForPhoneCalls: (flags & (1 << 3)) != 0, videoUploadMaxbitrate: videoUploadMaxbitrate)
|
||||
self.init(disabled: (flags & (1 << 0)) != 0, photoSizeMax: Int64(photoSizeMax), videoSizeMax: videoSizeMax, fileSizeMax: fileSizeMax, preloadLargeVideo: (flags & (1 << 1)) != 0, lessDataForPhoneCalls: (flags & (1 << 3)) != 0, videoUploadMaxbitrate: videoUploadMaxbitrate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,6 @@ func apiAutodownloadPresetSettings(_ autodownloadPresetSettings: AutodownloadPre
|
|||
if autodownloadPresetSettings.lessDataForPhoneCalls {
|
||||
flags |= (1 << 3)
|
||||
}
|
||||
return .autoDownloadSettings(flags: flags, photoSizeMax: autodownloadPresetSettings.photoSizeMax, videoSizeMax: autodownloadPresetSettings.videoSizeMax, fileSizeMax: autodownloadPresetSettings.fileSizeMax, videoUploadMaxbitrate: autodownloadPresetSettings.videoUploadMaxbitrate)
|
||||
return .autoDownloadSettings(flags: flags, photoSizeMax: Int32(autodownloadPresetSettings.photoSizeMax), videoSizeMax: autodownloadPresetSettings.videoSizeMax, fileSizeMax: autodownloadPresetSettings.fileSizeMax, videoUploadMaxbitrate: autodownloadPresetSettings.videoUploadMaxbitrate)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ public enum CallSessionConnection: Equatable {
|
|||
public let id: Int64
|
||||
public let ip: String
|
||||
public let ipv6: String
|
||||
public let isTcp: Bool
|
||||
public let port: Int32
|
||||
public let peerTag: Data
|
||||
|
||||
|
|
@ -224,12 +225,14 @@ public enum CallSessionConnection: Equatable {
|
|||
id: Int64,
|
||||
ip: String,
|
||||
ipv6: String,
|
||||
isTcp: Bool,
|
||||
port: Int32,
|
||||
peerTag: Data
|
||||
) {
|
||||
self.id = id
|
||||
self.ip = ip
|
||||
self.ipv6 = ipv6
|
||||
self.isTcp = isTcp
|
||||
self.port = port
|
||||
self.peerTag = peerTag
|
||||
}
|
||||
|
|
@ -272,8 +275,9 @@ public enum CallSessionConnection: Equatable {
|
|||
|
||||
private func parseConnection(_ apiConnection: Api.PhoneConnection) -> CallSessionConnection {
|
||||
switch apiConnection {
|
||||
case let .phoneConnection(id, ip, ipv6, port, peerTag):
|
||||
return .reflector(CallSessionConnection.Reflector(id: id, ip: ip, ipv6: ipv6, port: port, peerTag: peerTag.makeData()))
|
||||
case let .phoneConnection(flags, id, ip, ipv6, port, peerTag):
|
||||
let isTcp = (flags & (1 << 0)) != 0
|
||||
return .reflector(CallSessionConnection.Reflector(id: id, ip: ip, ipv6: ipv6, isTcp: isTcp, port: port, peerTag: peerTag.makeData()))
|
||||
case let .phoneConnectionWebrtc(flags, id, ip, ipv6, port, username, password):
|
||||
return .webRtcReflector(CallSessionConnection.WebRtcReflector(
|
||||
id: id,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ private final class MediaResourceDataCopyFile : MediaResourceDataFetchCopyLocalI
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchCloudMediaLocation(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int?, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
public func fetchCloudMediaLocation(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int64?, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
return multipartFetch(postbox: account.postbox, network: account.network, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, resource: resource, datacenterId: datacenterId, size: size, intervals: intervals, parameters: parameters)
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ private func fetchLocalFileResource(path: String, move: Bool) -> Signal<MediaRes
|
|||
}
|
||||
}
|
||||
|
||||
func fetchResource(account: Account, resource: MediaResource, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>? {
|
||||
func fetchResource(account: Account, resource: MediaResource, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>? {
|
||||
if let _ = resource as? EmptyMediaResource {
|
||||
return .single(.reset)
|
||||
|> then(.never())
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ import SwiftSignalKit
|
|||
import MtProtoKit
|
||||
|
||||
|
||||
func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||
return multipartFetch(postbox: account.postbox, network: account.network, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, resource: resource, datacenterId: resource.datacenterId, size: resource.size, intervals: intervals, parameters: parameters, encryptionKey: resource.key, decryptedSize: resource.decryptedSize)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -825,7 +825,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
arc4random_buf(randomBytesData, 15)
|
||||
let randomBytes = Buffer(memory: randomBytesData, size: 15, capacity: 15, freeWhenDone: true)
|
||||
|
||||
let decryptedMedia = SecretApi8.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
let decryptedMedia = SecretApi8.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
|
||||
return .layer8(.decryptedMessage(randomId: globallyUniqueId, randomBytes: randomBytes, message: message.text, media: decryptedMedia))
|
||||
case .layer46:
|
||||
|
|
@ -835,7 +835,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
let decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
flags |= (1 << 9)
|
||||
return .layer46(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: nil, viaBotName: viaBotName, replyToRandomId: replyGlobalId))
|
||||
case .layer73:
|
||||
|
|
@ -849,7 +849,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
let decryptedMedia = SecretApi73.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
let decryptedMedia = SecretApi73.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
flags |= (1 << 9)
|
||||
if message.groupingKey != nil {
|
||||
flags |= (1 << 17)
|
||||
|
|
@ -866,7 +866,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
let decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
let decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
flags |= (1 << 9)
|
||||
if message.groupingKey != nil {
|
||||
flags |= (1 << 17)
|
||||
|
|
@ -894,7 +894,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
arc4random_buf(randomBytesData, 15)
|
||||
let randomBytes = Buffer(memory: randomBytesData, size: 15, capacity: 15, freeWhenDone: true)
|
||||
|
||||
let decryptedMedia = SecretApi8.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, fileName: file.fileName ?? "file", mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
let decryptedMedia = SecretApi8.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, fileName: file.fileName ?? "file", mimeType: file.mimeType, size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
|
||||
return .layer8(.decryptedMessage(randomId: globallyUniqueId, randomBytes: randomBytes, message: message.text, media: decryptedMedia))
|
||||
}
|
||||
|
|
@ -913,9 +913,9 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
}
|
||||
|
||||
if let voiceDuration = voiceDuration {
|
||||
decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaAudio(duration: voiceDuration, mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaAudio(duration: voiceDuration, mimeType: file.mimeType, size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv))
|
||||
} else {
|
||||
decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes46(file.attributes, transaction: transaction), caption: "")
|
||||
decryptedMedia = SecretApi46.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes46(file.attributes, transaction: transaction), caption: "")
|
||||
}
|
||||
} else {
|
||||
if let resource = file.resource as? CloudDocumentMediaResource, let size = file.size {
|
||||
|
|
@ -943,7 +943,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
var decryptedMedia: SecretApi73.DecryptedMessageMedia?
|
||||
|
||||
if let uploadedFile = uploadedFile {
|
||||
decryptedMedia = SecretApi73.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes73(file.attributes, transaction: transaction), caption: "")
|
||||
decryptedMedia = SecretApi73.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes73(file.attributes, transaction: transaction), caption: "")
|
||||
} else {
|
||||
if let resource = file.resource as? CloudDocumentMediaResource, let size = file.size {
|
||||
let thumb: SecretApi73.PhotoSize
|
||||
|
|
@ -977,7 +977,7 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
|||
var decryptedMedia: SecretApi101.DecryptedMessageMedia?
|
||||
|
||||
if let uploadedFile = uploadedFile {
|
||||
decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes101(file.attributes, transaction: transaction), caption: "")
|
||||
decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: Int32(uploadedFile.size), key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes101(file.attributes, transaction: transaction), caption: "")
|
||||
} else {
|
||||
if let resource = file.resource as? CloudDocumentMediaResource, let size = file.size {
|
||||
let thumb: SecretApi101.PhotoSize
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ private final class MessageMediaPreuploadManagerContext {
|
|||
}))
|
||||
}
|
||||
|
||||
func upload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int?, hintFileIsLarge: Bool) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
func upload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int64?, hintFileIsLarge: Bool) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
|
|
@ -118,7 +118,7 @@ final class MessageMediaPreuploadManager {
|
|||
}
|
||||
}
|
||||
|
||||
func upload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int?, hintFileIsLarge: Bool) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
func upload(network: Network, postbox: Postbox, source: MultipartUploadSource, encrypt: Bool, tag: MediaResourceFetchTag?, hintFileSize: Int64?, hintFileIsLarge: Bool) -> Signal<MultipartUploadResult, MultipartUploadError> {
|
||||
return Signal<Signal<MultipartUploadResult, MultipartUploadError>, MultipartUploadError> { subscriber in
|
||||
self.impl.with { context in
|
||||
subscriber.putNext(context.upload(network: network, postbox: postbox, source: source, encrypt: encrypt, tag: tag, hintFileSize: hintFileSize, hintFileIsLarge: hintFileIsLarge))
|
||||
|
|
|
|||
|
|
@ -699,13 +699,13 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
let image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudSecretImage, id: file.id), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
parsedMedia.append(image)
|
||||
}
|
||||
case let .decryptedMessageMediaAudio(duration, mimeType, size, key, iv):
|
||||
if let file = file {
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaDocument(thumb, thumbW, thumbH, mimeType, size, key, iv, attributes, caption):
|
||||
|
|
@ -725,7 +725,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaVideo(thumb, thumbW, thumbH, duration, mimeType, w, h, size, key, iv, caption):
|
||||
|
|
@ -740,7 +740,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaExternalDocument(id, accessHash, _, mimeType, size, thumb, dcId, attributes):
|
||||
|
|
@ -755,7 +755,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
case let .photoSize(_, location, w, h, size):
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int64(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
break
|
||||
}
|
||||
|
|
@ -763,7 +763,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
if bytes.size > 0 {
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: bytes.size, fileReference: nil)
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: Int64(bytes.size), fileReference: nil)
|
||||
resources.append((resource, bytes.makeData()))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
|
|
@ -773,7 +773,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
default:
|
||||
break
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int64(size), fileReference: nil, fileName: nil), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
|
|
@ -901,13 +901,13 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
let image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudSecretImage, id: file.id), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
parsedMedia.append(image)
|
||||
}
|
||||
case let .decryptedMessageMediaAudio(duration, mimeType, size, key, iv):
|
||||
if let file = file {
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
parsedMedia.append(fileMedia)
|
||||
attributes.append(ConsumableContentMessageAttribute(consumed: false))
|
||||
}
|
||||
|
|
@ -928,7 +928,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
|
||||
loop: for attr in parsedAttributes {
|
||||
|
|
@ -959,7 +959,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaExternalDocument(id, accessHash, _, mimeType, size, thumb, dcId, attributes):
|
||||
|
|
@ -974,7 +974,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
case let .photoSize(_, location, w, h, size):
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int64(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
break
|
||||
}
|
||||
|
|
@ -982,7 +982,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
if bytes.size > 0 {
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: bytes.size, fileReference: nil)
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: Int64(bytes.size), fileReference: nil)
|
||||
resources.append((resource, bytes.makeData()))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
|
|
@ -992,7 +992,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
default:
|
||||
break
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int64(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
|
|
@ -1139,13 +1139,13 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
let image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudSecretImage, id: file.id), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
parsedMedia.append(image)
|
||||
}
|
||||
case let .decryptedMessageMediaAudio(duration, mimeType, size, key, iv):
|
||||
if let file = file {
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
parsedMedia.append(fileMedia)
|
||||
attributes.append(ConsumableContentMessageAttribute(consumed: false))
|
||||
}
|
||||
|
|
@ -1166,7 +1166,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
|
||||
loop: for attr in parsedAttributes {
|
||||
|
|
@ -1197,7 +1197,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: Int64(size)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaExternalDocument(id, accessHash, _, mimeType, size, thumb, dcId, attributes):
|
||||
|
|
@ -1212,7 +1212,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
case let .photoSize(_, location, w, h, size):
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int64(size), fileReference: nil), progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
break
|
||||
}
|
||||
|
|
@ -1220,7 +1220,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
if bytes.size > 0 {
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: bytes.size, fileReference: nil)
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: Int64(bytes.size), fileReference: nil)
|
||||
resources.append((resource, bytes.makeData()))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
case .fileLocationUnavailable:
|
||||
|
|
@ -1230,7 +1230,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||
default:
|
||||
break
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int64(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 142
|
||||
return 143
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ public enum AutodownloadPreset {
|
|||
|
||||
public struct AutodownloadPresetSettings: Codable {
|
||||
public let disabled: Bool
|
||||
public let photoSizeMax: Int32
|
||||
public let videoSizeMax: Int32
|
||||
public let fileSizeMax: Int32
|
||||
public let photoSizeMax: Int64
|
||||
public let videoSizeMax: Int64
|
||||
public let fileSizeMax: Int64
|
||||
public let preloadLargeVideo: Bool
|
||||
public let lessDataForPhoneCalls: Bool
|
||||
public let videoUploadMaxbitrate: Int32
|
||||
|
||||
public init(disabled: Bool, photoSizeMax: Int32, videoSizeMax: Int32, fileSizeMax: Int32, preloadLargeVideo: Bool, lessDataForPhoneCalls: Bool, videoUploadMaxbitrate: Int32) {
|
||||
public init(disabled: Bool, photoSizeMax: Int64, videoSizeMax: Int64, fileSizeMax: Int64, preloadLargeVideo: Bool, lessDataForPhoneCalls: Bool, videoUploadMaxbitrate: Int32) {
|
||||
self.disabled = disabled
|
||||
self.photoSizeMax = photoSizeMax
|
||||
self.videoSizeMax = videoSizeMax
|
||||
|
|
@ -29,9 +29,22 @@ public struct AutodownloadPresetSettings: Codable {
|
|||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
self.disabled = ((try? container.decode(Int32.self, forKey: "disabled")) ?? 0) != 0
|
||||
self.photoSizeMax = (try? container.decode(Int32.self, forKey: "photoSizeMax")) ?? 0
|
||||
self.videoSizeMax = (try? container.decode(Int32.self, forKey: "videoSizeMax")) ?? 0
|
||||
self.fileSizeMax = (try? container.decode(Int32.self, forKey: "fileSizeMax")) ?? 0
|
||||
|
||||
if let photoSizeMax = try? container.decode(Int64.self, forKey: "photoSizeMax64") {
|
||||
self.photoSizeMax = photoSizeMax
|
||||
} else {
|
||||
self.photoSizeMax = Int64((try? container.decode(Int32.self, forKey: "photoSizeMax")) ?? 0)
|
||||
}
|
||||
if let videoSizeMax = try? container.decode(Int64.self, forKey: "videoSizeMax64") {
|
||||
self.videoSizeMax = videoSizeMax
|
||||
} else {
|
||||
self.videoSizeMax = Int64((try? container.decode(Int32.self, forKey: "videoSizeMax")) ?? 0)
|
||||
}
|
||||
if let fileSizeMax = try? container.decode(Int64.self, forKey: "fileSizeMax64") {
|
||||
self.fileSizeMax = fileSizeMax
|
||||
} else {
|
||||
self.fileSizeMax = Int64((try? container.decode(Int32.self, forKey: "fileSizeMax")) ?? 0)
|
||||
}
|
||||
self.preloadLargeVideo = ((try? container.decode(Int32.self, forKey: "preloadLargeVideo")) ?? 0) != 0
|
||||
self.lessDataForPhoneCalls = ((try? container.decode(Int32.self, forKey: "lessDataForPhoneCalls")) ?? 0) != 0
|
||||
self.videoUploadMaxbitrate = (try? container.decode(Int32.self, forKey: "videoUploadMaxbitrate")) ?? 0
|
||||
|
|
@ -41,9 +54,9 @@ public struct AutodownloadPresetSettings: Codable {
|
|||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
try container.encode((self.disabled ? 1 : 0) as Int32, forKey: "disabled")
|
||||
try container.encode(self.photoSizeMax, forKey: "photoSizeMax")
|
||||
try container.encode(self.videoSizeMax, forKey: "videoSizeMax")
|
||||
try container.encode(self.fileSizeMax, forKey: "fileSizeMax")
|
||||
try container.encode(self.photoSizeMax, forKey: "photoSizeMax64")
|
||||
try container.encode(self.videoSizeMax, forKey: "videoSizeMax64")
|
||||
try container.encode(self.fileSizeMax, forKey: "fileSizeMax64")
|
||||
try container.encode((self.preloadLargeVideo ? 1 : 0) as Int32, forKey: "preloadLargeVideo")
|
||||
try container.encode((self.lessDataForPhoneCalls ? 1 : 0) as Int32, forKey: "lessDataForPhoneCalls")
|
||||
try container.encode(self.videoUploadMaxbitrate, forKey: "videoUploadMaxbitrate")
|
||||
|
|
@ -58,7 +71,7 @@ public struct AutodownloadSettings: Codable {
|
|||
public static var defaultSettings: AutodownloadSettings {
|
||||
return AutodownloadSettings(
|
||||
lowPreset: AutodownloadPresetSettings(disabled: false, photoSizeMax: 1 * 1024 * 1024, videoSizeMax: 0, fileSizeMax: 0, preloadLargeVideo: false, lessDataForPhoneCalls: true, videoUploadMaxbitrate: 0),
|
||||
mediumPreset: AutodownloadPresetSettings(disabled: false, photoSizeMax: 1 * 1024 * 1024, videoSizeMax: Int32(2.5 * 1024 * 1024), fileSizeMax: 1 * 1024 * 1024, preloadLargeVideo: false, lessDataForPhoneCalls: false, videoUploadMaxbitrate: 0),
|
||||
mediumPreset: AutodownloadPresetSettings(disabled: false, photoSizeMax: 1 * 1024 * 1024, videoSizeMax: Int64(2.5 * 1024 * 1024), fileSizeMax: 1 * 1024 * 1024, preloadLargeVideo: false, lessDataForPhoneCalls: false, videoUploadMaxbitrate: 0),
|
||||
highPreset: AutodownloadPresetSettings(disabled: false, photoSizeMax: 1 * 1024 * 1024, videoSizeMax: 10 * 1024 * 1024, fileSizeMax: 3 * 1024 * 1024, preloadLargeVideo: false, lessDataForPhoneCalls: false, videoUploadMaxbitrate: 0))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ public final class CloudFileMediaResource: TelegramMediaResource {
|
|||
public let volumeId: Int64
|
||||
public let localId: Int32
|
||||
public let secret: Int64
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
public let fileReference: Data?
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(CloudFileMediaResourceId(datacenterId: self.datacenterId, volumeId: self.volumeId, localId: self.localId, secret: self.secret).uniqueId)
|
||||
}
|
||||
|
||||
public init(datacenterId: Int, volumeId: Int64, localId: Int32, secret: Int64, size: Int?, fileReference: Data?) {
|
||||
public init(datacenterId: Int, volumeId: Int64, localId: Int32, secret: Int64, size: Int64?, fileReference: Data?) {
|
||||
self.datacenterId = datacenterId
|
||||
self.volumeId = volumeId
|
||||
self.localId = localId
|
||||
|
|
@ -45,8 +45,10 @@ public final class CloudFileMediaResource: TelegramMediaResource {
|
|||
self.volumeId = decoder.decodeInt64ForKey("v", orElse: 0)
|
||||
self.localId = decoder.decodeInt32ForKey("l", orElse: 0)
|
||||
self.secret = decoder.decodeInt64ForKey("s", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("n64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -59,9 +61,9 @@ public final class CloudFileMediaResource: TelegramMediaResource {
|
|||
encoder.encodeInt32(self.localId, forKey: "l")
|
||||
encoder.encodeInt64(self.secret, forKey: "s")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "n")
|
||||
encoder.encodeInt64(size, forKey: "n64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "n")
|
||||
encoder.encodeNil(forKey: "n64")
|
||||
}
|
||||
if let fileReference = self.fileReference {
|
||||
encoder.encodeBytes(MemoryBuffer(data: fileReference), forKey: "fr")
|
||||
|
|
@ -100,14 +102,14 @@ public final class CloudPhotoSizeMediaResource: TelegramMediaResource {
|
|||
public let photoId: Int64
|
||||
public let accessHash: Int64
|
||||
public let sizeSpec: String
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
public let fileReference: Data?
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(CloudPhotoSizeMediaResourceId(datacenterId: Int32(self.datacenterId), photoId: self.photoId, sizeSpec: self.sizeSpec).uniqueId)
|
||||
}
|
||||
|
||||
public init(datacenterId: Int32, photoId: Int64, accessHash: Int64, sizeSpec: String, size: Int?, fileReference: Data?) {
|
||||
public init(datacenterId: Int32, photoId: Int64, accessHash: Int64, sizeSpec: String, size: Int64?, fileReference: Data?) {
|
||||
self.datacenterId = Int(datacenterId)
|
||||
self.photoId = photoId
|
||||
self.accessHash = accessHash
|
||||
|
|
@ -121,8 +123,10 @@ public final class CloudPhotoSizeMediaResource: TelegramMediaResource {
|
|||
self.photoId = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("h", orElse: 0)
|
||||
self.sizeSpec = decoder.decodeStringForKey("s", orElse: "")
|
||||
if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("n64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -135,9 +139,9 @@ public final class CloudPhotoSizeMediaResource: TelegramMediaResource {
|
|||
encoder.encodeInt64(self.accessHash, forKey: "h")
|
||||
encoder.encodeString(self.sizeSpec, forKey: "s")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "n")
|
||||
encoder.encodeInt64(size, forKey: "n64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "n")
|
||||
encoder.encodeNil(forKey: "n64")
|
||||
}
|
||||
if let fileReference = self.fileReference {
|
||||
encoder.encodeBytes(MemoryBuffer(data: fileReference), forKey: "fr")
|
||||
|
|
@ -177,6 +181,9 @@ public final class CloudDocumentSizeMediaResource: TelegramMediaResource {
|
|||
public let accessHash: Int64
|
||||
public let sizeSpec: String
|
||||
public let fileReference: Data?
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(CloudDocumentSizeMediaResourceId(datacenterId: Int32(self.datacenterId), documentId: self.documentId, sizeSpec: self.sizeSpec).uniqueId)
|
||||
|
|
@ -254,6 +261,9 @@ public final class CloudPeerPhotoSizeMediaResource: TelegramMediaResource {
|
|||
public let sizeSpec: CloudPeerPhotoSizeSpec
|
||||
public let volumeId: Int64?
|
||||
public let localId: Int32?
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(CloudPeerPhotoSizeMediaResourceId(datacenterId: Int32(self.datacenterId), photoId: self.photoId, sizeSpec: self.sizeSpec, volumeId: self.volumeId, localId: self.localId).uniqueId)
|
||||
|
|
@ -331,6 +341,9 @@ public final class CloudStickerPackThumbnailMediaResource: TelegramMediaResource
|
|||
public let thumbVersion: Int32?
|
||||
public let volumeId: Int64?
|
||||
public let localId: Int32?
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(CloudStickerPackThumbnailMediaResourceId(datacenterId: Int32(self.datacenterId), thumbVersion: self.thumbVersion, volumeId: self.volumeId, localId: self.localId).uniqueId)
|
||||
|
|
@ -396,7 +409,7 @@ public final class CloudDocumentMediaResource: TelegramMediaResource {
|
|||
public let datacenterId: Int
|
||||
public let fileId: Int64
|
||||
public let accessHash: Int64
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
public let fileReference: Data?
|
||||
public let fileName: String?
|
||||
|
||||
|
|
@ -404,7 +417,7 @@ public final class CloudDocumentMediaResource: TelegramMediaResource {
|
|||
return MediaResourceId(CloudDocumentMediaResourceId(datacenterId: self.datacenterId, fileId: self.fileId).uniqueId)
|
||||
}
|
||||
|
||||
public init(datacenterId: Int, fileId: Int64, accessHash: Int64, size: Int?, fileReference: Data?, fileName: String?) {
|
||||
public init(datacenterId: Int, fileId: Int64, accessHash: Int64, size: Int64?, fileReference: Data?, fileName: String?) {
|
||||
self.datacenterId = datacenterId
|
||||
self.fileId = fileId
|
||||
self.accessHash = accessHash
|
||||
|
|
@ -417,8 +430,10 @@ public final class CloudDocumentMediaResource: TelegramMediaResource {
|
|||
self.datacenterId = Int(decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
self.fileId = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("n64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -431,9 +446,9 @@ public final class CloudDocumentMediaResource: TelegramMediaResource {
|
|||
encoder.encodeInt64(self.fileId, forKey: "f")
|
||||
encoder.encodeInt64(self.accessHash, forKey: "a")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "n")
|
||||
encoder.encodeInt64(size, forKey: "n64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "n")
|
||||
encoder.encodeNil(forKey: "n64")
|
||||
}
|
||||
if let fileReference = self.fileReference {
|
||||
encoder.encodeBytes(MemoryBuffer(data: fileReference), forKey: "fr")
|
||||
|
|
@ -466,11 +481,11 @@ public struct LocalFileMediaResourceId: Hashable, Equatable {
|
|||
|
||||
public class LocalFileMediaResource: TelegramMediaResource, Codable {
|
||||
public let fileId: Int64
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
|
||||
public let isSecretRelated: Bool
|
||||
|
||||
public init(fileId: Int64, size: Int? = nil, isSecretRelated: Bool = false) {
|
||||
public init(fileId: Int64, size: Int64? = nil, isSecretRelated: Bool = false) {
|
||||
self.fileId = fileId
|
||||
self.size = size
|
||||
self.isSecretRelated = isSecretRelated
|
||||
|
|
@ -479,8 +494,10 @@ public class LocalFileMediaResource: TelegramMediaResource, Codable {
|
|||
public required init(decoder: PostboxDecoder) {
|
||||
self.fileId = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
self.isSecretRelated = decoder.decodeBoolForKey("sr", orElse: false)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -491,16 +508,20 @@ public class LocalFileMediaResource: TelegramMediaResource, Codable {
|
|||
|
||||
self.fileId = try container.decode(Int64.self, forKey: "f")
|
||||
self.isSecretRelated = try container.decodeIfPresent(Bool.self, forKey: "sr") ?? false
|
||||
self.size = (try container.decodeIfPresent(Int32.self, forKey: "s")).flatMap(Int.init)
|
||||
if let size = try container.decodeIfPresent(Int64.self, forKey: "s64") {
|
||||
self.size = size
|
||||
} else {
|
||||
self.size = (try container.decodeIfPresent(Int32.self, forKey: "s")).flatMap(Int64.init)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.fileId, forKey: "f")
|
||||
encoder.encodeBool(self.isSecretRelated, forKey: "sr")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "s")
|
||||
encoder.encodeInt64(size, forKey: "s64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "s")
|
||||
encoder.encodeNil(forKey: "s64")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +530,7 @@ public class LocalFileMediaResource: TelegramMediaResource, Codable {
|
|||
|
||||
try container.encode(self.fileId, forKey: "f")
|
||||
try container.encode(self.isSecretRelated, forKey: "sr")
|
||||
try container.encodeIfPresent(self.size.flatMap(Int32.init), forKey: "s")
|
||||
try container.encodeIfPresent(self.size, forKey: "s64")
|
||||
}
|
||||
|
||||
public var id: MediaResourceId {
|
||||
|
|
@ -537,9 +558,9 @@ public class LocalFileReferenceMediaResource: TelegramMediaResource {
|
|||
public let localFilePath: String
|
||||
public let randomId: Int64
|
||||
public let isUniquelyReferencedTemporaryFile: Bool
|
||||
public let size: Int32?
|
||||
public let size: Int64?
|
||||
|
||||
public init(localFilePath: String, randomId: Int64, isUniquelyReferencedTemporaryFile: Bool = false, size: Int32? = nil) {
|
||||
public init(localFilePath: String, randomId: Int64, isUniquelyReferencedTemporaryFile: Bool = false, size: Int64? = nil) {
|
||||
self.localFilePath = localFilePath
|
||||
self.randomId = randomId
|
||||
self.isUniquelyReferencedTemporaryFile = isUniquelyReferencedTemporaryFile
|
||||
|
|
@ -550,7 +571,13 @@ public class LocalFileReferenceMediaResource: TelegramMediaResource {
|
|||
self.localFilePath = decoder.decodeStringForKey("p", orElse: "")
|
||||
self.randomId = decoder.decodeInt64ForKey("r", orElse: 0)
|
||||
self.isUniquelyReferencedTemporaryFile = decoder.decodeInt32ForKey("t", orElse: 0) != 0
|
||||
self.size = decoder.decodeOptionalInt32ForKey("s")
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
|
|
@ -558,7 +585,7 @@ public class LocalFileReferenceMediaResource: TelegramMediaResource {
|
|||
encoder.encodeInt64(self.randomId, forKey: "r")
|
||||
encoder.encodeInt32(self.isUniquelyReferencedTemporaryFile ? 1 : 0, forKey: "t")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(size, forKey: "s")
|
||||
encoder.encodeInt64(size, forKey: "s64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "s")
|
||||
}
|
||||
|
|
@ -587,17 +614,19 @@ public struct HttpReferenceMediaResourceId: Hashable, Equatable {
|
|||
|
||||
public final class HttpReferenceMediaResource: TelegramMediaResource {
|
||||
public let url: String
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
|
||||
public init(url: String, size: Int?) {
|
||||
public init(url: String, size: Int64?) {
|
||||
self.url = url
|
||||
self.size = size
|
||||
}
|
||||
|
||||
public required init(decoder: PostboxDecoder) {
|
||||
self.url = decoder.decodeStringForKey("u", orElse: "")
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -606,9 +635,9 @@ public final class HttpReferenceMediaResource: TelegramMediaResource {
|
|||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeString(self.url, forKey: "u")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "s")
|
||||
encoder.encodeInt64(size, forKey: "s64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "s")
|
||||
encoder.encodeNil(forKey: "s64")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -628,7 +657,7 @@ public final class HttpReferenceMediaResource: TelegramMediaResource {
|
|||
public struct WebFileReferenceMediaResourceId: Hashable, Equatable {
|
||||
public let url: String
|
||||
public let accessHash: Int64
|
||||
public let size: Int32
|
||||
public let size: Int64
|
||||
|
||||
public var uniqueId: String {
|
||||
return "proxy-\(persistentHash32(self.url))-\(size)-\(accessHash)"
|
||||
|
|
@ -637,29 +666,36 @@ public struct WebFileReferenceMediaResourceId: Hashable, Equatable {
|
|||
|
||||
public final class WebFileReferenceMediaResource: TelegramMediaResource {
|
||||
public let url: String
|
||||
public let size: Int32
|
||||
public let actualSize: Int64
|
||||
public var size: Int64? {
|
||||
return self.actualSize
|
||||
}
|
||||
public let accessHash: Int64
|
||||
|
||||
public init(url: String, size: Int32, accessHash: Int64) {
|
||||
public init(url: String, size: Int64, accessHash: Int64) {
|
||||
self.url = url
|
||||
self.size = size
|
||||
self.actualSize = size
|
||||
self.accessHash = accessHash
|
||||
}
|
||||
|
||||
public required init(decoder: PostboxDecoder) {
|
||||
self.url = decoder.decodeStringForKey("u", orElse: "")
|
||||
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.actualSize = size
|
||||
} else {
|
||||
self.actualSize = Int64(decoder.decodeInt32ForKey("s", orElse: 0))
|
||||
}
|
||||
self.accessHash = decoder.decodeInt64ForKey("h", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeString(self.url, forKey: "u")
|
||||
encoder.encodeInt32(self.size, forKey: "s")
|
||||
encoder.encodeInt64(self.actualSize, forKey: "s64")
|
||||
encoder.encodeInt64(self.accessHash, forKey: "h")
|
||||
}
|
||||
|
||||
public var id: MediaResourceId {
|
||||
return MediaResourceId(WebFileReferenceMediaResourceId(url: self.url, accessHash: accessHash, size: self.size).uniqueId)
|
||||
return MediaResourceId(WebFileReferenceMediaResourceId(url: self.url, accessHash: accessHash, size: self.actualSize).uniqueId)
|
||||
}
|
||||
|
||||
public func isEqual(to: MediaResource) -> Bool {
|
||||
|
|
@ -689,15 +725,15 @@ public struct SecretFileMediaResourceId: Hashable, Equatable {
|
|||
public final class SecretFileMediaResource: TelegramMediaResource {
|
||||
public let fileId: Int64
|
||||
public let accessHash: Int64
|
||||
public var size: Int? {
|
||||
return Int(self.decryptedSize)
|
||||
public var size: Int64? {
|
||||
return self.decryptedSize
|
||||
}
|
||||
public let containerSize: Int32
|
||||
public let decryptedSize: Int32
|
||||
public let containerSize: Int64
|
||||
public let decryptedSize: Int64
|
||||
public let datacenterId: Int
|
||||
public let key: SecretFileEncryptionKey
|
||||
|
||||
public init(fileId: Int64, accessHash: Int64, containerSize: Int32, decryptedSize: Int32, datacenterId: Int, key: SecretFileEncryptionKey) {
|
||||
public init(fileId: Int64, accessHash: Int64, containerSize: Int64, decryptedSize: Int64, datacenterId: Int, key: SecretFileEncryptionKey) {
|
||||
self.fileId = fileId
|
||||
self.accessHash = accessHash
|
||||
self.containerSize = containerSize
|
||||
|
|
@ -709,8 +745,17 @@ public final class SecretFileMediaResource: TelegramMediaResource {
|
|||
public init(decoder: PostboxDecoder) {
|
||||
self.fileId = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
self.containerSize = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
self.decryptedSize = decoder.decodeInt32ForKey("ds", orElse: 0)
|
||||
|
||||
if let containerSize = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.containerSize = containerSize
|
||||
} else {
|
||||
self.containerSize = Int64(decoder.decodeInt32ForKey("s", orElse: 0))
|
||||
}
|
||||
if let decryptedSize = decoder.decodeOptionalInt64ForKey("ds64") {
|
||||
self.decryptedSize = decryptedSize
|
||||
} else {
|
||||
self.decryptedSize = Int64(decoder.decodeInt32ForKey("ds", orElse: 0))
|
||||
}
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
self.key = decoder.decodeObjectForKey("k", decoder: { SecretFileEncryptionKey(decoder: $0) }) as! SecretFileEncryptionKey
|
||||
}
|
||||
|
|
@ -718,8 +763,8 @@ public final class SecretFileMediaResource: TelegramMediaResource {
|
|||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.fileId, forKey: "i")
|
||||
encoder.encodeInt64(self.accessHash, forKey: "a")
|
||||
encoder.encodeInt32(self.containerSize, forKey: "s")
|
||||
encoder.encodeInt32(self.decryptedSize, forKey: "ds")
|
||||
encoder.encodeInt64(self.containerSize, forKey: "s64")
|
||||
encoder.encodeInt64(self.decryptedSize, forKey: "ds64")
|
||||
encoder.encodeInt32(Int32(self.datacenterId), forKey: "d")
|
||||
encoder.encodeObject(self.key, forKey: "k")
|
||||
}
|
||||
|
|
@ -766,6 +811,10 @@ public struct EmptyMediaResourceId {
|
|||
}
|
||||
|
||||
public final class EmptyMediaResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
|
|
@ -801,6 +850,10 @@ public struct WallpaperDataResourceId {
|
|||
}
|
||||
|
||||
public final class WallpaperDataResource: TelegramMediaResource {
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public let slug: String
|
||||
|
||||
public init(slug: String) {
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ public final class RenderedRecentDownloadItem: Equatable {
|
|||
public let timestamp: Int32
|
||||
public let isSeen: Bool
|
||||
public let resourceId: String
|
||||
public let size: Int
|
||||
public let size: Int64
|
||||
|
||||
public init(message: Message, timestamp: Int32, isSeen: Bool, resourceId: String, size: Int) {
|
||||
public init(message: Message, timestamp: Int32, isSeen: Bool, resourceId: String, size: Int64) {
|
||||
self.message = message
|
||||
self.timestamp = timestamp
|
||||
self.isSeen = isSeen
|
||||
|
|
@ -135,7 +135,7 @@ public func recentDownloadItems(postbox: Postbox) -> Signal<[RenderedRecentDownl
|
|||
continue
|
||||
}
|
||||
|
||||
var size: Int?
|
||||
var size: Int64?
|
||||
for media in message.media {
|
||||
if let result = findMediaResourceById(media: media, resourceId: MediaResourceId(item.resourceId)) {
|
||||
size = result.size
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import Postbox
|
|||
public final class SecretChatFileReference: PostboxCoding {
|
||||
public let id: Int64
|
||||
public let accessHash: Int64
|
||||
public let size: Int32
|
||||
public let size: Int64
|
||||
public let datacenterId: Int32
|
||||
public let keyFingerprint: Int32
|
||||
|
||||
public init(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, keyFingerprint: Int32) {
|
||||
public init(id: Int64, accessHash: Int64, size: Int64, datacenterId: Int32, keyFingerprint: Int32) {
|
||||
self.id = id
|
||||
self.accessHash = accessHash
|
||||
self.size = size
|
||||
|
|
@ -18,7 +18,11 @@ public final class SecretChatFileReference: PostboxCoding {
|
|||
public init(decoder: PostboxDecoder) {
|
||||
self.id = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else {
|
||||
self.size = Int64(decoder.decodeInt32ForKey("s", orElse: 0))
|
||||
}
|
||||
self.datacenterId = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
self.keyFingerprint = decoder.decodeInt32ForKey("f", orElse: 0)
|
||||
}
|
||||
|
|
@ -26,7 +30,7 @@ public final class SecretChatFileReference: PostboxCoding {
|
|||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.id, forKey: "i")
|
||||
encoder.encodeInt64(self.accessHash, forKey: "a")
|
||||
encoder.encodeInt32(self.size, forKey: "s")
|
||||
encoder.encodeInt64(self.size, forKey: "s64")
|
||||
encoder.encodeInt32(self.datacenterId, forKey: "d")
|
||||
encoder.encodeInt32(self.keyFingerprint, forKey: "f")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ public enum SecretChatOutgoingFileReference: PostboxCoding {
|
|||
|
||||
public struct SecretChatOutgoingFile: PostboxCoding {
|
||||
public let reference: SecretChatOutgoingFileReference
|
||||
public let size: Int32
|
||||
public let size: Int64
|
||||
public let key: SecretFileEncryptionKey
|
||||
|
||||
public init(reference: SecretChatOutgoingFileReference, size: Int32, key: SecretFileEncryptionKey) {
|
||||
public init(reference: SecretChatOutgoingFileReference, size: Int64, key: SecretFileEncryptionKey) {
|
||||
self.reference = reference
|
||||
self.size = size
|
||||
self.key = key
|
||||
|
|
@ -60,13 +60,17 @@ public struct SecretChatOutgoingFile: PostboxCoding {
|
|||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.reference = decoder.decodeObjectForKey("r", decoder: { SecretChatOutgoingFileReference(decoder: $0) }) as! SecretChatOutgoingFileReference
|
||||
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else {
|
||||
self.size = Int64(decoder.decodeInt32ForKey("s", orElse: 0))
|
||||
}
|
||||
self.key = SecretFileEncryptionKey(aesKey: decoder.decodeBytesForKey("k")!.makeData(), aesIv: decoder.decodeBytesForKey("i")!.makeData())
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeObject(self.reference, forKey: "r")
|
||||
encoder.encodeInt32(self.size, forKey: "s")
|
||||
encoder.encodeInt64(self.size, forKey: "s64")
|
||||
encoder.encodeBytes(MemoryBuffer(data: self.key.aesKey), forKey: "k")
|
||||
encoder.encodeBytes(MemoryBuffer(data: self.key.aesIv), forKey: "i")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ public final class SecureFileMediaResource: TelegramMediaResource {
|
|||
return Int(self.file.datacenterId)
|
||||
}
|
||||
|
||||
public var size: Int? {
|
||||
return Int(self.file.size)
|
||||
public var size: Int64? {
|
||||
return self.file.size
|
||||
}
|
||||
|
||||
public init(file: SecureIdFileReference) {
|
||||
|
|
@ -37,13 +37,19 @@ public final class SecureFileMediaResource: TelegramMediaResource {
|
|||
}
|
||||
|
||||
public required init(decoder: PostboxDecoder) {
|
||||
self.file = SecureIdFileReference(id: decoder.decodeInt64ForKey("f", orElse: 0), accessHash: decoder.decodeInt64ForKey("a", orElse: 0), size: decoder.decodeInt32ForKey("n", orElse: 0), datacenterId: decoder.decodeInt32ForKey("d", orElse: 0), timestamp: decoder.decodeInt32ForKey("t", orElse: 0), fileHash: decoder.decodeBytesForKey("h")?.makeData() ?? Data(), encryptedSecret: decoder.decodeBytesForKey("s")?.makeData() ?? Data())
|
||||
let size: Int64
|
||||
if let value = decoder.decodeOptionalInt64ForKey("n64") {
|
||||
size = value
|
||||
} else {
|
||||
size = Int64(decoder.decodeInt32ForKey("n", orElse: 0))
|
||||
}
|
||||
self.file = SecureIdFileReference(id: decoder.decodeInt64ForKey("f", orElse: 0), accessHash: decoder.decodeInt64ForKey("a", orElse: 0), size: size, datacenterId: decoder.decodeInt32ForKey("d", orElse: 0), timestamp: decoder.decodeInt32ForKey("t", orElse: 0), fileHash: decoder.decodeBytesForKey("h")?.makeData() ?? Data(), encryptedSecret: decoder.decodeBytesForKey("s")?.makeData() ?? Data())
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.file.id, forKey: "f")
|
||||
encoder.encodeInt64(self.file.accessHash, forKey: "a")
|
||||
encoder.encodeInt32(self.file.size, forKey: "n")
|
||||
encoder.encodeInt64(self.file.size, forKey: "n64")
|
||||
encoder.encodeInt32(self.file.datacenterId, forKey: "d")
|
||||
encoder.encodeInt32(self.file.timestamp, forKey: "t")
|
||||
encoder.encodeBytes(MemoryBuffer(data: self.file.fileHash), forKey: "h")
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import Postbox
|
|||
public struct SecureIdFileReference: Equatable {
|
||||
public let id: Int64
|
||||
public let accessHash: Int64
|
||||
public let size: Int32
|
||||
public let size: Int64
|
||||
public let datacenterId: Int32
|
||||
public let timestamp: Int32
|
||||
public let fileHash: Data
|
||||
public let encryptedSecret: Data
|
||||
|
||||
public init(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, timestamp: Int32, fileHash: Data, encryptedSecret: Data) {
|
||||
public init(id: Int64, accessHash: Int64, size: Int64, datacenterId: Int32, timestamp: Int32, fileHash: Data, encryptedSecret: Data) {
|
||||
self.id = id
|
||||
self.accessHash = accessHash
|
||||
self.size = size
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
|||
public let videoThumbnails: [TelegramMediaFile.VideoThumbnail]
|
||||
public let immediateThumbnailData: Data?
|
||||
public let mimeType: String
|
||||
public let size: Int?
|
||||
public let size: Int64?
|
||||
public let attributes: [TelegramMediaFileAttribute]
|
||||
public let peerIds: [PeerId] = []
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
|||
return result.isEmpty ? nil : result
|
||||
}
|
||||
|
||||
public init(fileId: MediaId, partialReference: PartialMediaReference?, resource: TelegramMediaResource, previewRepresentations: [TelegramMediaImageRepresentation], videoThumbnails: [TelegramMediaFile.VideoThumbnail], immediateThumbnailData: Data?, mimeType: String, size: Int?, attributes: [TelegramMediaFileAttribute]) {
|
||||
public init(fileId: MediaId, partialReference: PartialMediaReference?, resource: TelegramMediaResource, previewRepresentations: [TelegramMediaImageRepresentation], videoThumbnails: [TelegramMediaFile.VideoThumbnail], immediateThumbnailData: Data?, mimeType: String, size: Int64?, attributes: [TelegramMediaFileAttribute]) {
|
||||
self.fileId = fileId
|
||||
self.partialReference = partialReference
|
||||
self.resource = resource
|
||||
|
|
@ -348,8 +348,10 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
|||
self.videoThumbnails = decoder.decodeObjectArrayForKey("vr")
|
||||
self.immediateThumbnailData = decoder.decodeDataForKey("itd")
|
||||
self.mimeType = decoder.decodeStringForKey("mt", orElse: "")
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
if let size = decoder.decodeOptionalInt64ForKey("s64") {
|
||||
self.size = size
|
||||
} else if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int64(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
|
|
@ -375,9 +377,9 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
|||
}
|
||||
encoder.encodeString(self.mimeType, forKey: "mt")
|
||||
if let size = self.size {
|
||||
encoder.encodeInt32(Int32(size), forKey: "s")
|
||||
encoder.encodeInt64(size, forKey: "s64")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "s")
|
||||
encoder.encodeNil(forKey: "s64")
|
||||
}
|
||||
encoder.encodeObjectArray(self.attributes, forKey: "at")
|
||||
}
|
||||
|
|
@ -622,7 +624,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
|||
return TelegramMediaFile(fileId: self.fileId, partialReference: self.partialReference, resource: resource, previewRepresentations: self.previewRepresentations, videoThumbnails: self.videoThumbnails, immediateThumbnailData: self.immediateThumbnailData, mimeType: self.mimeType, size: self.size, attributes: self.attributes)
|
||||
}
|
||||
|
||||
public func withUpdatedSize(_ size: Int?) -> TelegramMediaFile {
|
||||
public func withUpdatedSize(_ size: Int64?) -> TelegramMediaFile {
|
||||
return TelegramMediaFile(fileId: self.fileId, partialReference: self.partialReference, resource: self.resource, previewRepresentations: self.previewRepresentations, videoThumbnails: self.videoThumbnails, immediateThumbnailData: self.immediateThumbnailData, mimeType: self.mimeType, size: size, attributes: self.attributes)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ public enum UploadNotificationSoundError {
|
|||
}
|
||||
|
||||
func _internal_uploadNotificationSound(account: Account, title: String, data: Data) -> Signal<NotificationSoundList.NotificationSound, UploadNotificationSoundError> {
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: nil, hintFileSize: data.count, hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: false, increaseParallelParts: false, useMultiplexedRequests: false, useCompression: false)
|
||||
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: nil, hintFileSize: Int64(data.count), hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: false, increaseParallelParts: false, useMultiplexedRequests: false, useCompression: false)
|
||||
|> mapError { _ -> UploadNotificationSoundError in
|
||||
return .generic
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||
switch size {
|
||||
case let .videoSize(_, type, w, h, size, videoStartTs):
|
||||
let resource: TelegramMediaResource
|
||||
resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int(size), fileReference: fileReference.makeData())
|
||||
resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData())
|
||||
|
||||
videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ public final class EngineMediaResource: Equatable {
|
|||
|
||||
public final class ResourceData {
|
||||
public let path: String
|
||||
public let availableSize: Int
|
||||
public let availableSize: Int64
|
||||
public let isComplete: Bool
|
||||
|
||||
public init(
|
||||
path: String,
|
||||
availableSize: Int,
|
||||
availableSize: Int64,
|
||||
isComplete: Bool
|
||||
) {
|
||||
self.path = path
|
||||
|
|
|
|||
|
|
@ -1220,7 +1220,7 @@ public func defaultBuiltinWallpaper(data: BuiltinWallpaperData, colors: [UInt32]
|
|||
datacenterId: data.datacenterId,
|
||||
fileId: data.fileId,
|
||||
accessHash: data.fileAccessHash,
|
||||
size: data.fileSize,
|
||||
size: Int64(data.fileSize),
|
||||
fileReference: Data(),
|
||||
fileName: "pattern.tgv"
|
||||
),
|
||||
|
|
@ -1241,7 +1241,7 @@ public func defaultBuiltinWallpaper(data: BuiltinWallpaperData, colors: [UInt32]
|
|||
videoThumbnails: [],
|
||||
immediateThumbnailData: nil,
|
||||
mimeType: "application/x-tgwallpattern",
|
||||
size: data.fileSize,
|
||||
size: Int64(data.fileSize),
|
||||
attributes: [
|
||||
.ImageSize(size: PixelDimensions(width: 1440, height: 2960)),
|
||||
.FileName(fileName: "pattern.tgv")
|
||||
|
|
|
|||
|
|
@ -11509,7 +11509,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
attributes.append(.Audio(isVoice: false, duration: audioMetadata.duration, title: audioMetadata.title, performer: audioMetadata.performer, waveform: nil))
|
||||
}
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: item.fileSize, attributes: attributes)
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes)
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil)
|
||||
messages.append(message)
|
||||
}
|
||||
|
|
@ -12655,7 +12655,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil))
|
||||
fileAttributes.append(.ImageSize(size: PixelDimensions(size)))
|
||||
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: data.count, attributes: fileAttributes)
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes)
|
||||
let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
|
||||
|
|
@ -12865,7 +12865,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
})
|
||||
} else if let waveform = data.waveform {
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max), size: data.compressedData.count)
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max), size: Int64(data.compressedData.count))
|
||||
|
||||
strongSelf.context.account.postbox.mediaBox.storeResourceData(resource.id, data: data.compressedData)
|
||||
|
||||
|
|
@ -12919,7 +12919,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
}, usedCorrelationId ? correlationId : nil)
|
||||
|
||||
strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: data.compressedData.count, attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)])
|
||||
strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)])
|
||||
|
||||
strongSelf.recorderFeedback?.tap()
|
||||
strongSelf.recorderFeedback = nil
|
||||
|
|
@ -13014,7 +13014,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
}, nil)
|
||||
|
||||
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)]
|
||||
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)]
|
||||
|
||||
let transformedMessages: [EnqueueMessage]
|
||||
if let silentPosting = silentPosting {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ public struct EmojiThumbnailResourceId {
|
|||
public class EmojiThumbnailResource: TelegramMediaResource {
|
||||
public let emoji: String
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init(emoji: String) {
|
||||
self.emoji = emoji
|
||||
}
|
||||
|
|
@ -67,6 +71,10 @@ public class EmojiSpriteResource: TelegramMediaResource {
|
|||
public let packId: UInt8
|
||||
public let stickerId: UInt8
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init(packId: UInt8, stickerId: UInt8) {
|
||||
self.packId = packId
|
||||
self.stickerId = stickerId
|
||||
|
|
@ -277,7 +285,7 @@ func fetchEmojiSpriteResource(account: Account, resource: EmojiSpriteResource) -
|
|||
|
||||
subscriber.putNext(.reset)
|
||||
|
||||
let fetch = fetchResource(sticker.file.resource, .single([(0 ..< Int.max, .default)]), nil)
|
||||
let fetch = fetchResource(sticker.file.resource, .single([(0 ..< Int64.max, .default)]), nil)
|
||||
let buffer = Atomic<Buffer>(value: Buffer())
|
||||
let disposable = fetch.start(next: { result in
|
||||
switch result {
|
||||
|
|
@ -314,18 +322,18 @@ func fetchEmojiSpriteResource(account: Account, resource: EmojiSpriteResource) -
|
|||
buffer.data.withUnsafeMutableBytes { rawBytes -> Void in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
|
||||
data.copyBytes(to: bytes, from: range)
|
||||
data.copyBytes(to: bytes, from: Int(range.lowerBound) ..< Int(range.upperBound))
|
||||
}
|
||||
}
|
||||
case let .dataPart(resourceOffset, data, range, _):
|
||||
let _ = buffer.with { buffer in
|
||||
if buffer.data.count < resourceOffset + range.count {
|
||||
buffer.data.count = resourceOffset + range.count
|
||||
if buffer.data.count < Int(resourceOffset) + range.count {
|
||||
buffer.data.count = Int(resourceOffset) + range.count
|
||||
}
|
||||
buffer.data.withUnsafeMutableBytes { rawBytes -> Void in
|
||||
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
|
||||
data.copyBytes(to: bytes.advanced(by: resourceOffset), from: range)
|
||||
data.copyBytes(to: bytes.advanced(by: Int(resourceOffset)), from: Int(range.lowerBound) ..< Int(range.upperBound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,7 +342,7 @@ func fetchEmojiSpriteResource(account: Account, resource: EmojiSpriteResource) -
|
|||
return WebP.convert(fromWebP: buffer.data)
|
||||
}
|
||||
if let image = image, let data = image.pngData() {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR
|
|||
|> `catch` { error -> Signal<CachedMediaResourceRepresentationResult, NoError> in
|
||||
switch error {
|
||||
case let .moreDataNeeded(targetSize):
|
||||
return account.postbox.mediaBox.resourceData(resource, size: size, in: 0 ..< min(size, targetSize))
|
||||
return account.postbox.mediaBox.resourceData(resource, size: size, in: 0 ..< min(size, Int64(targetSize)))
|
||||
|> mapToSignal { result ->
|
||||
Signal<CachedMediaResourceRepresentationResult, NoError> in
|
||||
let (data, _) = result
|
||||
|
|
@ -149,7 +149,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR
|
|||
return .never()
|
||||
}
|
||||
|
||||
private func videoFirstFrameData(account: Account, resource: MediaResource, chunkSize: Int) -> Signal<CachedMediaResourceRepresentationResult, NoError> {
|
||||
private func videoFirstFrameData(account: Account, resource: MediaResource, chunkSize: Int64) -> Signal<CachedMediaResourceRepresentationResult, NoError> {
|
||||
if let size = resource.size {
|
||||
return account.postbox.mediaBox.resourceData(resource, size: size, in: 0 ..< min(size, chunkSize))
|
||||
|> mapToSignal { _ -> Signal<CachedMediaResourceRepresentationResult, NoError> in
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ public func fetchVideoLibraryMediaResource(account: Account, resource: VideoLibr
|
|||
}
|
||||
}
|
||||
}
|
||||
let updatedSize = Atomic<Int>(value: 0)
|
||||
let updatedSize = Atomic<Int64>(value: 0)
|
||||
let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
|
||||
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
|
||||
return LegacyPaintEntityRenderer(account: account, adjustments: adjustments)
|
||||
|
|
@ -269,10 +269,10 @@ public func fetchVideoLibraryMediaResource(account: Account, resource: VideoLibr
|
|||
var value = stat()
|
||||
if stat(path, &value) == 0 {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedRead]) {
|
||||
var range: Range<Int>?
|
||||
var range: Range<Int64>?
|
||||
let _ = updatedSize.modify { updatedSize in
|
||||
range = updatedSize ..< Int(value.st_size)
|
||||
return Int(value.st_size)
|
||||
range = updatedSize ..< value.st_size
|
||||
return value.st_size
|
||||
}
|
||||
//print("size = \(Int(value.st_size)), range: \(range!)")
|
||||
subscriber.putNext(.dataPart(resourceOffset: range!.lowerBound, data: data, range: range!, complete: false))
|
||||
|
|
@ -284,15 +284,15 @@ public func fetchVideoLibraryMediaResource(account: Account, resource: VideoLibr
|
|||
var value = stat()
|
||||
if stat(result.fileURL.path, &value) == 0 {
|
||||
if let data = try? Data(contentsOf: result.fileURL, options: [.mappedRead]) {
|
||||
var range: Range<Int>?
|
||||
var range: Range<Int64>?
|
||||
let _ = updatedSize.modify { updatedSize in
|
||||
range = updatedSize ..< Int(value.st_size)
|
||||
return Int(value.st_size)
|
||||
range = updatedSize ..< value.st_size
|
||||
return value.st_size
|
||||
}
|
||||
//print("finish size = \(Int(value.st_size)), range: \(range!)")
|
||||
subscriber.putNext(.dataPart(resourceOffset: range!.lowerBound, data: data, range: range!, complete: false))
|
||||
subscriber.putNext(.replaceHeader(data: data, range: 0 ..< 1024))
|
||||
subscriber.putNext(.dataPart(resourceOffset: data.count, data: Data(), range: 0 ..< 0, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: Int64(data.count), data: Data(), range: 0 ..< 0, complete: true))
|
||||
}
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
|
|
@ -342,7 +342,7 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
|
|||
adjustments = TGVideoEditAdjustments(dictionary: dict)
|
||||
}
|
||||
}
|
||||
let updatedSize = Atomic<Int>(value: 0)
|
||||
let updatedSize = Atomic<Int64>(value: 0)
|
||||
let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
|
||||
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
|
||||
return LegacyPaintEntityRenderer(account: account, adjustments: adjustments)
|
||||
|
|
@ -370,10 +370,10 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
|
|||
var value = stat()
|
||||
if stat(path, &value) == 0 {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedRead]) {
|
||||
var range: Range<Int>?
|
||||
var range: Range<Int64>?
|
||||
let _ = updatedSize.modify { updatedSize in
|
||||
range = updatedSize ..< Int(value.st_size)
|
||||
return Int(value.st_size)
|
||||
range = updatedSize ..< value.st_size
|
||||
return value.st_size
|
||||
}
|
||||
//print("size = \(Int(value.st_size)), range: \(range!)")
|
||||
subscriber.putNext(.dataPart(resourceOffset: range!.lowerBound, data: data, range: range!, complete: false))
|
||||
|
|
@ -392,10 +392,10 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
|
|||
var value = stat()
|
||||
if stat(path, &value) == 0 {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedRead]) {
|
||||
var range: Range<Int>?
|
||||
var range: Range<Int64>?
|
||||
let _ = updatedSize.modify { updatedSize in
|
||||
range = updatedSize ..< Int(value.st_size)
|
||||
return Int(value.st_size)
|
||||
range = updatedSize ..< Int64(value.st_size)
|
||||
return value.st_size
|
||||
}
|
||||
//print("size = \(Int(value.st_size)), range: \(range!)")
|
||||
subscriber.putNext(.dataPart(resourceOffset: range!.lowerBound, data: data, range: range!, complete: false))
|
||||
|
|
@ -421,10 +421,10 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
|
|||
// subscriber.putNext(.moveLocalFile(path: result.fileURL.path))
|
||||
// }
|
||||
if let data = try? Data(contentsOf: result.fileURL, options: [.mappedRead]) {
|
||||
var range: Range<Int>?
|
||||
var range: Range<Int64>?
|
||||
let _ = updatedSize.modify { updatedSize in
|
||||
range = updatedSize ..< Int(value.st_size)
|
||||
return Int(value.st_size)
|
||||
range = updatedSize ..< value.st_size
|
||||
return value.st_size
|
||||
}
|
||||
//print("finish size = \(Int(value.st_size)), range: \(range!)")
|
||||
subscriber.putNext(.dataPart(resourceOffset: range!.lowerBound, data: data, range: range!, complete: false))
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ public class ICloudFileResource: TelegramMediaResource {
|
|||
public let urlData: String
|
||||
public let thumbnail: Bool
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init(urlData: String, thumbnail: Bool) {
|
||||
self.urlData = urlData
|
||||
self.thumbnail = thumbnail
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||
strongSelf.currentFileReference = fileReference
|
||||
if let size = fileReference.media.size {
|
||||
strongSelf.scrubberNode.bufferingStatus = strongSelf.postbox.mediaBox.resourceRangesStatus(fileReference.media.resource)
|
||||
|> map { ranges -> (IndexSet, Int) in
|
||||
|> map { ranges -> (IndexSet, Int64) in
|
||||
return (ranges, size)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ private func extractTextFileHeader(path: String) -> String? {
|
|||
return nil
|
||||
}
|
||||
|
||||
let limit = 3000
|
||||
let limit: Int64 = 3000
|
||||
|
||||
var data = file.readData(count: min(size, limit))
|
||||
let additionalCapacity = min(10, max(0, size - data.count))
|
||||
var data = file.readData(count: Int(min(size, limit)))
|
||||
let additionalCapacity = min(10, max(0, Int(size) - data.count))
|
||||
|
||||
for alignment in 0 ... additionalCapacity {
|
||||
if alignment != 0 {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour
|
|||
return Signal { subscriber in
|
||||
subscriber.putNext(.reset)
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: resource.path), options: .mappedRead) {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour
|
|||
return Signal { subscriber in
|
||||
subscriber.putNext(.reset)
|
||||
if let data = try? Data(contentsOf: url, options: .mappedRead) {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
}
|
||||
|
||||
return EmptyDisposable
|
||||
|
|
@ -60,7 +60,7 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour
|
|||
return Signal { subscriber in
|
||||
subscriber.putNext(.reset)
|
||||
if let data = try? Data(contentsOf: url, options: .mappedRead) {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
}
|
||||
|
||||
return EmptyDisposable
|
||||
|
|
@ -75,7 +75,7 @@ public let telegramAccountAuxiliaryMethods = AccountAuxiliaryMethods(fetchResour
|
|||
return Signal { subscriber in
|
||||
subscriber.putNext(.reset)
|
||||
if let data = try? Data(contentsOf: url, options: .mappedRead) {
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true))
|
||||
subscriber.putNext(.dataPart(resourceOffset: 0, data: data, range: 0 ..< Int64(data.count), complete: true))
|
||||
}
|
||||
|
||||
return EmptyDisposable
|
||||
|
|
|
|||
|
|
@ -126,10 +126,10 @@ public struct MediaAutoDownloadCategory: Codable, Equatable {
|
|||
public var otherPrivate: Bool
|
||||
public var groups: Bool
|
||||
public var channels: Bool
|
||||
public var sizeLimit: Int32
|
||||
public var sizeLimit: Int64
|
||||
public var predownload: Bool
|
||||
|
||||
public init(contacts: Bool, otherPrivate: Bool, groups: Bool, channels: Bool, sizeLimit: Int32, predownload: Bool) {
|
||||
public init(contacts: Bool, otherPrivate: Bool, groups: Bool, channels: Bool, sizeLimit: Int64, predownload: Bool) {
|
||||
self.contacts = contacts
|
||||
self.otherPrivate = otherPrivate
|
||||
self.groups = groups
|
||||
|
|
@ -145,7 +145,11 @@ public struct MediaAutoDownloadCategory: Codable, Equatable {
|
|||
self.otherPrivate = try container.decode(Int32.self, forKey: "otherPrivate") != 0
|
||||
self.groups = try container.decode(Int32.self, forKey: "groups") != 0
|
||||
self.channels = try container.decode(Int32.self, forKey: "channels") != 0
|
||||
self.sizeLimit = try container.decode(Int32.self, forKey: "size")
|
||||
if let sizeLimit = try container.decodeIfPresent(Int64.self, forKey: "size64") {
|
||||
self.sizeLimit = sizeLimit
|
||||
} else {
|
||||
self.sizeLimit = Int64(try container.decode(Int32.self, forKey: "size"))
|
||||
}
|
||||
self.predownload = try container.decode(Int32.self, forKey: "predownload") != 0
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +160,7 @@ public struct MediaAutoDownloadCategory: Codable, Equatable {
|
|||
try container.encode((self.otherPrivate ? 1 : 0) as Int32, forKey: "otherPrivate")
|
||||
try container.encode((self.groups ? 1 : 0) as Int32, forKey: "groups")
|
||||
try container.encode((self.channels ? 1 : 0) as Int32, forKey: "channels")
|
||||
try container.encode(self.sizeLimit, forKey: "size")
|
||||
try container.encode(self.sizeLimit, forKey: "size64")
|
||||
try container.encode((self.predownload ? 1 : 0) as Int32, forKey: "predownload")
|
||||
}
|
||||
}
|
||||
|
|
@ -172,12 +176,12 @@ public struct MediaAutoDownloadSettings: Codable, Equatable {
|
|||
public var downloadInBackground: Bool
|
||||
|
||||
public static var defaultSettings: MediaAutoDownloadSettings {
|
||||
let mb: Int32 = 1024 * 1024
|
||||
let mb: Int64 = 1024 * 1024
|
||||
let presets = MediaAutoDownloadPresets(low: MediaAutoDownloadCategories(basePreset: .low, photo: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: 1 * mb, predownload: false),
|
||||
video: MediaAutoDownloadCategory(contacts: false, otherPrivate: false, groups: false, channels: false, sizeLimit: 1 * mb, predownload: false),
|
||||
file: MediaAutoDownloadCategory(contacts: false, otherPrivate: false, groups: false, channels: false, sizeLimit: 1 * mb, predownload: false)),
|
||||
medium: MediaAutoDownloadCategories(basePreset: .medium, photo: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: 1 * mb, predownload: false),
|
||||
video: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: Int32(2.5 * CGFloat(mb)), predownload: false),
|
||||
video: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: Int64(2.5 * CGFloat(mb)), predownload: false),
|
||||
file: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: 1 * mb, predownload: false)),
|
||||
high: MediaAutoDownloadCategories(basePreset: .high, photo: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: 1 * mb, predownload: false),
|
||||
video: MediaAutoDownloadCategory(contacts: true, otherPrivate: true, groups: true, channels: true, sizeLimit: 10 * mb, predownload: true),
|
||||
|
|
|
|||
|
|
@ -130,8 +130,8 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
|
|||
}
|
||||
}
|
||||
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int)?, NoError> {
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int64)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> {
|
||||
return self._bufferingStatus.get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
|
|||
return self._status.get()
|
||||
}
|
||||
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int)?, NoError> {
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int64)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> {
|
||||
return self._bufferingStatus.get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
|||
return self._status.get()
|
||||
}
|
||||
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int)?, NoError> {
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int64)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> {
|
||||
return self._bufferingStatus.get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ private final class UniversalVideoContentHolder {
|
|||
var statusValue: MediaPlayerStatus?
|
||||
|
||||
var bufferingStatusDisposable: Disposable?
|
||||
var bufferingStatusValue: (IndexSet, Int)?
|
||||
var bufferingStatusValue: (IndexSet, Int64)?
|
||||
|
||||
var playbackCompletedIndex: Int?
|
||||
|
||||
init(content: UniversalVideoContent, contentNode: UniversalVideoContentNode & ASDisplayNode, statusUpdated: @escaping (MediaPlayerStatus?) -> Void, bufferingStatusUpdated: @escaping ((IndexSet, Int)?) -> Void, playbackCompleted: @escaping () -> Void) {
|
||||
init(content: UniversalVideoContent, contentNode: UniversalVideoContentNode & ASDisplayNode, statusUpdated: @escaping (MediaPlayerStatus?) -> Void, bufferingStatusUpdated: @escaping ((IndexSet, Int64)?) -> Void, playbackCompleted: @escaping () -> Void) {
|
||||
self.content = content
|
||||
self.contentNode = contentNode
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ private final class UniversalVideoContentHolder {
|
|||
private final class UniversalVideoContentHolderCallbacks {
|
||||
let playbackCompleted = Bag<() -> Void>()
|
||||
let status = Bag<(MediaPlayerStatus?) -> Void>()
|
||||
let bufferingStatus = Bag<((IndexSet, Int)?) -> Void>()
|
||||
let bufferingStatus = Bag<((IndexSet, Int64)?) -> Void>()
|
||||
|
||||
var isEmpty: Bool {
|
||||
return self.playbackCompleted.isEmpty && self.status.isEmpty && self.bufferingStatus.isEmpty
|
||||
|
|
@ -278,7 +278,7 @@ public final class UniversalVideoManagerImpl: UniversalVideoManager {
|
|||
} |> runOn(Queue.mainQueue())
|
||||
}
|
||||
|
||||
public func bufferingStatusSignal(content: UniversalVideoContent) -> Signal<(IndexSet, Int)?, NoError> {
|
||||
public func bufferingStatusSignal(content: UniversalVideoContent) -> Signal<(IndexSet, Int64)?, NoError> {
|
||||
return Signal { subscriber in
|
||||
var callbacks: UniversalVideoContentHolderCallbacks
|
||||
if let current = self.holderCallbacks[content.id] {
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ final class WebEmbedVideoContentNode: ASDisplayNode, UniversalVideoContentNode {
|
|||
return self._status.get()
|
||||
}
|
||||
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int)?, NoError> {
|
||||
private let _bufferingStatus = Promise<(IndexSet, Int64)?>()
|
||||
var bufferingStatus: Signal<(IndexSet, Int64)?, NoError> {
|
||||
return self._bufferingStatus.get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,10 @@ public class YoutubeEmbedStoryboardMediaResource: TelegramMediaResource {
|
|||
public let storyboardId: Int32
|
||||
public let url: String
|
||||
|
||||
public var size: Int64? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public init(videoId: String, storyboardId: Int32, url: String) {
|
||||
self.videoId = videoId
|
||||
self.storyboardId = storyboardId
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import TgVoip
|
|||
import TgVoipWebrtc
|
||||
|
||||
private let debugUseLegacyVersionForReflectors: Bool = {
|
||||
#if DEBUG
|
||||
#if DEBUG && false
|
||||
return true
|
||||
#else
|
||||
return false
|
||||
|
|
@ -81,10 +81,10 @@ private func callConnectionDescriptionsWebrtc(_ connection: CallSessionConnectio
|
|||
}
|
||||
var result: [OngoingCallConnectionDescriptionWebrtc] = []
|
||||
if !reflector.ip.isEmpty {
|
||||
result.append(OngoingCallConnectionDescriptionWebrtc(reflectorId: id, hasStun: false, hasTurn: true, hasTcp: false, ip: reflector.ip, port: reflector.port, username: "reflector", password: hexString(reflector.peerTag)))
|
||||
result.append(OngoingCallConnectionDescriptionWebrtc(reflectorId: id, hasStun: false, hasTurn: true, hasTcp: reflector.isTcp, ip: reflector.ip, port: reflector.port, username: "reflector", password: hexString(reflector.peerTag)))
|
||||
}
|
||||
if !reflector.ipv6.isEmpty {
|
||||
result.append(OngoingCallConnectionDescriptionWebrtc(reflectorId: id, hasStun: false, hasTurn: true, hasTcp: false, ip: reflector.ipv6, port: reflector.port, username: "reflector", password: hexString(reflector.peerTag)))
|
||||
result.append(OngoingCallConnectionDescriptionWebrtc(reflectorId: id, hasStun: false, hasTurn: true, hasTcp: reflector.isTcp, ip: reflector.ipv6, port: reflector.port, username: "reflector", password: hexString(reflector.peerTag)))
|
||||
}
|
||||
return result
|
||||
case let .webRtcReflector(reflector):
|
||||
|
|
@ -743,6 +743,12 @@ public final class OngoingCallContext {
|
|||
private var signalingConnectionManager: QueueLocalObject<CallSignalingConnectionManager>?
|
||||
|
||||
public static func versions(includeExperimental: Bool, includeReference: Bool) -> [(version: String, supportsVideo: Bool)] {
|
||||
#if DEBUG
|
||||
if "".isEmpty {
|
||||
return [("5.0.0", true)]
|
||||
}
|
||||
#endif
|
||||
|
||||
if debugUseLegacyVersionForReflectors {
|
||||
return [(OngoingCallThreadLocalContext.version(), true)]
|
||||
} else {
|
||||
|
|
@ -784,7 +790,7 @@ public final class OngoingCallContext {
|
|||
var allowP2P = allowP2P
|
||||
if debugUseLegacyVersionForReflectors {
|
||||
useModernImplementation = true
|
||||
version = "4.1.2"
|
||||
version = "5.0.0"
|
||||
allowP2P = false
|
||||
} else {
|
||||
useModernImplementation = version != OngoingCallThreadLocalContext.version()
|
||||
|
|
@ -820,35 +826,53 @@ public final class OngoingCallContext {
|
|||
reflectorIdMapping[reflectorIdList[i]] = UInt8(i + 1)
|
||||
}
|
||||
|
||||
var signalingReflector: OngoingCallConnectionDescriptionWebrtc?
|
||||
|
||||
var processedConnections: [CallSessionConnection] = []
|
||||
var filteredConnections: [OngoingCallConnectionDescriptionWebrtc] = []
|
||||
for connection in unfilteredConnections {
|
||||
connectionsLoop: for connection in unfilteredConnections {
|
||||
if processedConnections.contains(connection) {
|
||||
continue
|
||||
}
|
||||
processedConnections.append(connection)
|
||||
filteredConnections.append(contentsOf: callConnectionDescriptionsWebrtc(connection, idMapping: reflectorIdMapping))
|
||||
|
||||
switch connection {
|
||||
case let .reflector(reflector):
|
||||
if reflector.isTcp {
|
||||
if signalingReflector == nil {
|
||||
signalingReflector = OngoingCallConnectionDescriptionWebrtc(reflectorId: 0, hasStun: false, hasTurn: true, hasTcp: true, ip: reflector.ip, port: reflector.port, username: "reflector", password: hexString(reflector.peerTag))
|
||||
}
|
||||
|
||||
continue connectionsLoop
|
||||
}
|
||||
case .webRtcReflector:
|
||||
break
|
||||
}
|
||||
|
||||
var webrtcConnections: [OngoingCallConnectionDescriptionWebrtc] = []
|
||||
for connection in callConnectionDescriptionsWebrtc(connection, idMapping: reflectorIdMapping) {
|
||||
webrtcConnections.append(connection)
|
||||
}
|
||||
|
||||
filteredConnections.append(contentsOf: webrtcConnections)
|
||||
}
|
||||
|
||||
for connection in filteredConnections {
|
||||
if connection.username == "reflector" {
|
||||
let peerTag = dataWithHexString(connection.password)
|
||||
if #available(iOS 12.0, *) {
|
||||
strongSelf.signalingConnectionManager = QueueLocalObject(queue: queue, generate: {
|
||||
return CallSignalingConnectionManager(queue: queue, peerTag: peerTag, servers: [OngoingCallConnectionDescriptionWebrtc(reflectorId: 0, hasStun: false, hasTurn: true, hasTcp: true, ip: "91.108.12.1", port: 533, username: "reflector", password: connection.password)], dataReceived: { data in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.withContext { context in
|
||||
if let context = context as? OngoingCallThreadLocalContextWebrtc {
|
||||
context.addSignaling(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if let signalingReflector = signalingReflector {
|
||||
if #available(iOS 12.0, *) {
|
||||
let peerTag = dataWithHexString(signalingReflector.password)
|
||||
|
||||
break
|
||||
strongSelf.signalingConnectionManager = QueueLocalObject(queue: queue, generate: {
|
||||
return CallSignalingConnectionManager(queue: queue, peerTag: peerTag, servers: [signalingReflector], dataReceived: { data in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.withContext { context in
|
||||
if let context = context as? OngoingCallThreadLocalContextWebrtc {
|
||||
context.addSignaling(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit f3c148739bf0ad37a0882a7fcafcbc56969c4f8a
|
||||
Subproject commit c741da4568b0971ed06d9ccdc7a94db566bb84a0
|
||||
|
|
@ -727,7 +727,7 @@ final class WatchAudioHandler: WatchRequestHandler {
|
|||
replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToMid)
|
||||
}
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: data.count, attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]).start()
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]).start()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue