diff --git a/src/environment/mimeTypeMap.ts b/src/environment/mimeTypeMap.ts new file mode 100644 index 00000000..9a2275f4 --- /dev/null +++ b/src/environment/mimeTypeMap.ts @@ -0,0 +1,24 @@ +export const EXTENSION_MIME_TYPE_MAP: {[ext in MTFileExtension]: MTMimeType} = { + pdf: 'application/pdf', + tgv: 'application/x-tgwallpattern', + tgs: 'application/x-tgsticker', + json: 'application/json', + wav: 'audio/wav', + mp3: 'audio/mpeg', + ogg: 'audio/ogg', + jpeg: 'image/jpeg', + jpg: 'image/jpeg', + png: 'image/png', + gif: 'image/gif', + webp: 'image/webp', + mp4: 'video/mp4', + webm: 'video/webm', + mov: 'video/quicktime', + svg: 'image/svg+xml' +}; + +export const MIME_TYPE_EXTENSION_MAP: {[mimeType in MTMimeType]?: MTFileExtension} = {}; + +for(const ext in EXTENSION_MIME_TYPE_MAP) { + MIME_TYPE_EXTENSION_MAP[EXTENSION_MIME_TYPE_MAP[ext as MTFileExtension]] = ext as MTFileExtension; +} diff --git a/src/global.d.ts b/src/global.d.ts index 72324ed2..817ce4f1 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -23,6 +23,14 @@ declare global { type Long = string | number; type MTLong = string; + type MTMimeType = 'video/quicktime' | 'image/gif' | 'image/jpeg' | 'application/pdf' | + 'video/mp4' | 'image/webp' | 'audio/mpeg' | 'audio/ogg' | 'application/octet-stream' | + 'application/x-tgsticker' | 'video/webm' | 'image/svg+xml' | 'image/png' | 'application/json' | + 'application/x-tgwallpattern' | 'audio/wav'; + + type MTFileExtension = 'mov' | 'gif' | 'pdf' | 'jpg' | 'jpeg' | 'wav' | + 'tgv' | 'tgs' | 'svg' | 'mp4' | 'webm' | 'webp' | 'mp3' | 'ogg' | 'json' | 'png'; + type ApiFileManagerError = 'DOWNLOAD_CANCELED' | 'UPLOAD_CANCELED' | 'FILE_TOO_BIG' | 'REFERENCE_IS_NOT_REFRESHED'; type StorageError = 'STORAGE_OFFLINE' | 'NO_ENTRY_FOUND' | 'IDB_CREATE_TIMEOUT'; type ReferenceError = 'NO_NEW_CONTEXT'; diff --git a/src/layer.d.ts b/src/layer.d.ts index a807a762..bedd0853 100644 --- a/src/layer.d.ts +++ b/src/layer.d.ts @@ -3307,7 +3307,6 @@ export namespace Document { access_hash: string | number, file_reference: Uint8Array | number[], date: number, - mime_type: string, video_thumbs?: Array, dc_id: number, attributes: Array, @@ -3326,7 +3325,8 @@ export namespace Document { }>, animated?: boolean, supportsStreaming?: boolean, - size?: number + size?: number, + mime_type?: MTMimeType }; } @@ -5924,20 +5924,20 @@ export namespace WebDocument { url: string, access_hash: string | number, size: number, - mime_type: string, attributes: Array, h?: number, - w?: number + w?: number, + mime_type?: MTMimeType }; export type webDocumentNoProxy = { _: 'webDocumentNoProxy', url: string, size: number, - mime_type: string, attributes: Array, h?: number, - w?: number + w?: number, + mime_type?: MTMimeType }; } diff --git a/src/lib/appManagers/appDocsManager.ts b/src/lib/appManagers/appDocsManager.ts index 0f4f03d8..bbde58dc 100644 --- a/src/lib/appManagers/appDocsManager.ts +++ b/src/lib/appManagers/appDocsManager.ts @@ -24,17 +24,12 @@ import getDocumentInputFileLocation from './utils/docs/getDocumentInputFileLocat import getDocumentURL from './utils/docs/getDocumentURL'; import type {ThumbCache} from '../storages/thumbs'; import makeError from '../../helpers/makeError'; +import {EXTENSION_MIME_TYPE_MAP} from '../../environment/mimeTypeMap'; export type MyDocument = Document.document; // TODO: если залить картинку файлом, а потом перезайти в диалог - превьюшка заново скачается -const EXTENSION_MIME_TYPE_MAP = { - mov: 'video/quicktime', - gif: 'image/gif', - pdf: 'application/pdf' -}; - type WallPaperId = WallPaper.wallPaper['id']; let uploadWallPaperTempId = 0; @@ -340,7 +335,7 @@ export class AppDocsManager extends AppManager { dc_id: 0, file_reference: [], id, - mime_type: file.type, + mime_type: file.type as MTMimeType, size: file.size, date: Date.now() / 1000, pFlags: {}, diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index a89891dd..de7b8e8e 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -5,6 +5,7 @@ */ import type {MyDocument} from './appDocsManager'; +import type {DownloadOptions} from '../mtproto/apiFileManager'; import {Document, InputFileLocation, InputStickerSet, MessagesAllStickers, MessagesFavedStickers, MessagesFeaturedStickers, MessagesFoundStickerSets, MessagesRecentStickers, MessagesStickers, MessagesStickerSet, PhotoSize, StickerPack, StickerSet, StickerSetCovered, Update} from '../../layer'; import {Modify} from '../../types'; import AppStorage from '../storage'; @@ -384,7 +385,7 @@ export class AppStickersManager extends AppManager { this.storage.set({[id]: stickerSet}, !needSave); } - public getStickerSetThumbDownloadOptions(stickerSet: StickerSet.stickerSet) { + public getStickerSetThumbDownloadOptions(stickerSet: StickerSet.stickerSet): DownloadOptions { const thumb = stickerSet.thumbs.find((thumb) => thumb._ === 'photoSize') as PhotoSize.photoSize; const dcId = stickerSet.thumb_dc_id; diff --git a/src/lib/appManagers/utils/docs/getDocumentDownloadOptions.ts b/src/lib/appManagers/utils/docs/getDocumentDownloadOptions.ts index 070c6be9..c05c00ce 100644 --- a/src/lib/appManagers/utils/docs/getDocumentDownloadOptions.ts +++ b/src/lib/appManagers/utils/docs/getDocumentDownloadOptions.ts @@ -11,7 +11,7 @@ import getDocumentInputFileLocation from './getDocumentInputFileLocation'; export default function getDocumentDownloadOptions(doc: Document.document, thumb?: PhotoSize.photoSize | VideoSize, queueId?: number, onlyCache?: boolean): DownloadOptions { const inputFileLocation = getDocumentInputFileLocation(doc, thumb?.type); - let mimeType: string; + let mimeType: MTMimeType; if(thumb?._ === 'photoSize') { mimeType = doc.sticker ? 'image/webp' : 'image/jpeg'/* doc.mime_type */; } else { diff --git a/src/lib/appManagers/utils/photos/getPhotoDownloadOptions.ts b/src/lib/appManagers/utils/photos/getPhotoDownloadOptions.ts index 7155080e..b20615e6 100644 --- a/src/lib/appManagers/utils/photos/getPhotoDownloadOptions.ts +++ b/src/lib/appManagers/utils/photos/getPhotoDownloadOptions.ts @@ -18,7 +18,7 @@ export default function getPhotoDownloadOptions(photo: MyPhoto | MyDocument, pho } // maybe it's a thumb - const isPhoto = (photoSize._ === 'photoSize' || photoSize._ === 'photoSizeProgressive') && photo.access_hash && photo.file_reference; + const isPhoto = !!((photoSize._ === 'photoSize' || photoSize._ === 'photoSizeProgressive') && photo.access_hash && photo.file_reference); const location: InputFileLocation.inputPhotoFileLocation | InputFileLocation.inputDocumentFileLocation = { _: isDocument ? 'inputDocumentFileLocation' : 'inputPhotoFileLocation', id: photo.id, @@ -31,6 +31,7 @@ export default function getPhotoDownloadOptions(photo: MyPhoto | MyDocument, pho dcId: photo.dc_id, location, size: isPhoto ? (photoSize as PhotoSize.photoSize).size : undefined, + mimeType: 'image/jpeg', queueId, onlyCache }; diff --git a/src/lib/mtproto/apiFileManager.ts b/src/lib/mtproto/apiFileManager.ts index 6687db32..fa2f920b 100644 --- a/src/lib/mtproto/apiFileManager.ts +++ b/src/lib/mtproto/apiFileManager.ts @@ -40,6 +40,7 @@ import readBlobAsUint8Array from '../../helpers/blob/readBlobAsUint8Array'; import DownloadStorage from '../files/downloadStorage'; import copy from '../../helpers/object/copy'; import indexOfAndSplice from '../../helpers/array/indexOfAndSplice'; +import {MIME_TYPE_EXTENSION_MAP} from '../../environment/mimeTypeMap'; type Delayed = { offset: number, @@ -52,7 +53,7 @@ export type DownloadOptions = { location: InputFileLocation | InputWebFileLocation, size?: number, fileName?: string, - mimeType?: string, + mimeType?: MTMimeType, limitPart?: number, queueId?: number, onlyCache?: boolean, @@ -428,7 +429,7 @@ export class ApiFileManager extends AppManager { return this.uploadPromises[fileName]; } - private getConvertMethod(mimeType: string) { + private getConvertMethod(mimeType: MTMimeType) { let process: ApiFileManager['uncompressTGS'] | ApiFileManager['convertWebp']; if(mimeType === 'application/x-tgwallpattern') { process = this.uncompressTGV; @@ -558,8 +559,17 @@ export class ApiFileManager extends AppManager { } if(downloadStorage) { + let downloadFileName = options.fileName; // it's doc file_name + if(!downloadFileName) { + downloadFileName = cacheFileName; + const ext = MIME_TYPE_EXTENSION_MAP[options.mimeType]; + if(ext) { + downloadFileName += '.' + ext; + } + } + downloadPrepared = downloadStorage.prepareWriting({ - fileName: options.fileName, // it's doc file_name + fileName: downloadFileName, downloadId, size: possibleSize }); diff --git a/src/scripts/in/schema_additional_params.json b/src/scripts/in/schema_additional_params.json index 772495f6..e0157e2b 100644 --- a/src/scripts/in/schema_additional_params.json +++ b/src/scripts/in/schema_additional_params.json @@ -14,7 +14,8 @@ {"name": "stickerThumbConverted", "type": "true"}, {"name": "animated", "type": "boolean"}, {"name": "supportsStreaming", "type": "boolean"}, - {"name": "size", "type": "number"} + {"name": "size", "type": "number"}, + {"name": "mime_type", "type": "MTMimeType"} ] }, { "predicate": "photoSizeProgressive", @@ -349,12 +350,14 @@ "predicate": "webDocument", "params": [ {"name": "h", "type": "number"}, - {"name": "w", "type": "number"} + {"name": "w", "type": "number"}, + {"name": "mime_type", "type": "MTMimeType"} ] }, { "predicate": "webDocumentNoProxy", "params": [ {"name": "h", "type": "number"}, - {"name": "w", "type": "number"} + {"name": "w", "type": "number"}, + {"name": "mime_type", "type": "MTMimeType"} ] }] \ No newline at end of file