Added support for thumbnails in standalone media file upload

This commit is contained in:
Ilya Laktyushin 2019-07-15 18:12:44 +02:00
parent a94cce354b
commit 0144957e82
3 changed files with 133 additions and 73 deletions

View File

@ -42,7 +42,7 @@ func augmentMediaWithReference(_ mediaReference: AnyMediaReference) -> Media {
if file.partialReference != nil { if file.partialReference != nil {
return file return file
} else { } else {
return file.withUpdatedPartialReference(mediaReference.partial) return file.withUpdatedPartialReference(mediaReference.partial)
} }
} else if let image = mediaReference.media as? TelegramMediaImage { } else if let image = mediaReference.media as? TelegramMediaImage {
if image.partialReference != nil { if image.partialReference != nil {
@ -367,7 +367,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
} }
let authorId: PeerId? let authorId: PeerId?
if let peer = peer as? TelegramChannel, case let .broadcast(info) = peer.info { if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
authorId = peer.id authorId = peer.id
} else { } else {
authorId = account.peerId authorId = account.peerId
@ -388,12 +388,9 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] { if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] {
if let peer = peer as? TelegramSecretChat { if let peer = peer as? TelegramSecretChat {
var isAction = false var isAction = false
var mediaDuration: Int32?
for media in sourceMessage.media { for media in sourceMessage.media {
if let _ = media as? TelegramMediaAction { if let _ = media as? TelegramMediaAction {
isAction = true isAction = true
} else if let file = media as? TelegramMediaFile, let duration = file.duration {
mediaDuration = duration
} }
} }
if !disableAutoremove, let messageAutoremoveTimeout = peer.messageAutoremoveTimeout, !isAction { if !disableAutoremove, let messageAutoremoveTimeout = peer.messageAutoremoveTimeout, !isAction {

View File

@ -476,17 +476,17 @@ private enum UploadedMediaFileAndThumbnail {
private func uploadedThumbnail(network: Network, postbox: Postbox, resourceReference: MediaResourceReference) -> Signal<Api.InputFile?, PendingMessageUploadError> { private func uploadedThumbnail(network: Network, postbox: Postbox, resourceReference: MediaResourceReference) -> Signal<Api.InputFile?, PendingMessageUploadError> {
return multipartUpload(network: network, postbox: postbox, source: .resource(resourceReference), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false) return multipartUpload(network: network, postbox: postbox, source: .resource(resourceReference), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false)
|> mapError { _ -> PendingMessageUploadError in return .generic } |> mapError { _ -> PendingMessageUploadError in return .generic }
|> mapToSignal { result -> Signal<Api.InputFile?, PendingMessageUploadError> in |> mapToSignal { result -> Signal<Api.InputFile?, PendingMessageUploadError> in
switch result { switch result {
case .progress: case .progress:
return .complete() return .complete()
case let .inputFile(inputFile): case let .inputFile(inputFile):
return .single(inputFile) return .single(inputFile)
case .inputSecretFile: case .inputSecretFile:
return .single(nil) return .single(nil)
}
} }
}
} }
public func statsCategoryForFileWithAttributes(_ attributes: [TelegramMediaFileAttribute]) -> MediaResourceStatsCategory { public func statsCategoryForFileWithAttributes(_ attributes: [TelegramMediaFileAttribute]) -> MediaResourceStatsCategory {

View File

@ -21,6 +21,20 @@ public struct StandaloneUploadSecretFile {
let key: SecretFileEncryptionKey let key: SecretFileEncryptionKey
} }
public enum StandaloneUploadMediaThumbnailResult {
case pending
case file(Api.InputFile)
case none
var file: Api.InputFile? {
if case let .file(file) = self {
return file
} else {
return nil
}
}
}
public enum StandaloneUploadMediaResult { public enum StandaloneUploadMediaResult {
case media(AnyMediaReference) case media(AnyMediaReference)
} }
@ -30,7 +44,22 @@ public enum StandaloneUploadMediaEvent {
case result(StandaloneUploadMediaResult) case result(StandaloneUploadMediaResult)
} }
public func standaloneUploadedImage(account: Account, peerId: PeerId, text: String, data: Data, dimensions: CGSize) -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> { private func uploadedThumbnail(network: Network, postbox: Postbox, data: Data) -> Signal<Api.InputFile?, StandaloneUploadMediaError> {
return multipartUpload(network: network, postbox: postbox, source: .data(data), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false)
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { result -> Signal<Api.InputFile?, StandaloneUploadMediaError> in
switch result {
case .progress:
return .complete()
case let .inputFile(inputFile):
return .single(inputFile)
case .inputSecretFile:
return .single(nil)
}
}
}
public func standaloneUploadedImage(account: Account, peerId: PeerId, text: String, data: Data, thumbnailData: Data? = nil, dimensions: CGSize) -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> {
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false) return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false)
|> mapError { _ -> StandaloneUploadMediaError in return .generic } |> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { next -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in |> mapToSignal { next -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
@ -91,65 +120,99 @@ public func standaloneUploadedImage(account: Account, peerId: PeerId, text: Stri
} }
} }
public func standaloneUploadedFile(account: Account, peerId: PeerId, text: String, source: MultipartUploadSource, mimeType: String, attributes: [TelegramMediaFileAttribute], hintFileIsLarge: Bool) -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> { public func standaloneUploadedFile(account: Account, peerId: PeerId, text: String, source: MultipartUploadSource, thumbnailData: Data? = nil, mimeType: String, attributes: [TelegramMediaFileAttribute], hintFileIsLarge: Bool) -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> {
return multipartUpload(network: account.network, postbox: account.postbox, source: source, encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(attributes)), hintFileSize: nil, hintFileIsLarge: hintFileIsLarge) let upload = multipartUpload(network: account.network, postbox: account.postbox, source: source, encrypt: peerId.namespace == Namespaces.Peer.SecretChat, tag: TelegramMediaResourceFetchTag(statsCategory: statsCategoryForFileWithAttributes(attributes)), hintFileSize: nil, hintFileIsLarge: hintFileIsLarge)
|> mapError { _ -> StandaloneUploadMediaError in return .generic } |> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { next -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch next { let uploadThumbnail: Signal<StandaloneUploadMediaThumbnailResult, StandaloneUploadMediaError>
case let .inputFile(inputFile): if let thumbnailData = thumbnailData {
return account.postbox.transaction { transaction -> Api.InputPeer? in uploadThumbnail = .single(.pending)
return transaction.getPeer(peerId).flatMap(apiInputPeer) |> then(
} uploadedThumbnail(network: account.network, postbox: account.postbox, data: thumbnailData)
|> mapError { _ -> StandaloneUploadMediaError in return .generic } |> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { inputPeer -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in |> map { result in
if let inputPeer = inputPeer { if let result = result {
return account.network.request(Api.functions.messages.uploadMedia(peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, ttlSeconds: nil))) return .file(result)
|> mapError { _ -> StandaloneUploadMediaError in return .generic } } else {
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in return .none
switch media {
case let .messageMediaDocument(_, document, _):
if let document = document {
if let mediaFile = telegramMediaFileFromApiDocument(document) {
return .single(.result(.media(.standalone(media: mediaFile))))
}
}
default:
break
}
return .fail(.generic)
}
} else {
return .fail(.generic)
}
}
case let .inputSecretFile(file, size, key):
return account.postbox.transaction { transaction -> Api.InputEncryptedChat? in
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
return Api.InputEncryptedChat.inputEncryptedChat(chatId: peer.id.id, accessHash: peer.accessHash)
}
return nil
}
|> introduceError(StandaloneUploadMediaError.self)
|> mapToSignal { inputChat -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
guard let inputChat = inputChat else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.uploadEncryptedFile(peer: inputChat, file: file))
|> mapError { _ -> StandaloneUploadMediaError in return .generic
}
|> 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: arc4random64()), partialReference: nil, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: size, datacenterId: Int(dcId), key: key), previewRepresentations: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: attributes)
return .single(.result(.media(.standalone(media: media))))
case .encryptedFileEmpty:
return .fail(.generic)
}
}
} }
}
)
} else {
uploadThumbnail = .single(.none)
}
return combineLatest(upload, uploadThumbnail)
|> mapToSignal { result, thumbnail in
switch result {
case let .progress(progress): case let .progress(progress):
return .single(.progress(progress)) return .single(.progress(progress))
} default:
switch thumbnail {
case .pending:
return .complete()
default:
switch result {
case let .inputFile(inputFile):
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { inputPeer -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
if let inputPeer = inputPeer {
var flags: Int32 = 0
let thumbnailFile = thumbnail.file
if let _ = thumbnailFile {
flags |= 1 << 2
}
return account.network.request(Api.functions.messages.uploadMedia(peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, ttlSeconds: nil)))
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch media {
case let .messageMediaDocument(_, document, _):
if let document = document {
if let mediaFile = telegramMediaFileFromApiDocument(document) {
return .single(.result(.media(.standalone(media: mediaFile))))
}
}
default:
break
}
return .fail(.generic)
}
} else {
return .fail(.generic)
}
}
case let .inputSecretFile(file, _, key):
return account.postbox.transaction { transaction -> Api.InputEncryptedChat? in
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
return Api.InputEncryptedChat.inputEncryptedChat(chatId: peer.id.id, accessHash: peer.accessHash)
}
return nil
}
|> introduceError(StandaloneUploadMediaError.self)
|> mapToSignal { inputChat -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
guard let inputChat = inputChat else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.uploadEncryptedFile(peer: inputChat, file: file))
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> 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: arc4random64()), partialReference: nil, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: size, datacenterId: Int(dcId), key: key), previewRepresentations: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: attributes)
return .single(.result(.media(.standalone(media: media))))
case .encryptedFileEmpty:
return .fail(.generic)
}
}
}
case .progress:
return .never()
}
}
}
} }
} }