diff options
| author | Kagami Sascha Rosylight <saschanaz@outlook.com> | 2022-12-18 15:40:38 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-18 15:40:38 +0900 |
| commit | a47d172d60b1ae712738e0ba5dfbb6b81be3f809 (patch) | |
| tree | 8aeba3a1880507fc6b48458dd3c3632d97185a78 /packages/client/src/scripts/upload.ts | |
| parent | chore: deploy vue-tsc for client typecheck (#9341) (diff) | |
| download | sharkey-a47d172d60b1ae712738e0ba5dfbb6b81be3f809.tar.gz sharkey-a47d172d60b1ae712738e0ba5dfbb6b81be3f809.tar.bz2 sharkey-a47d172d60b1ae712738e0ba5dfbb6b81be3f809.zip | |
enhance(client): Compress non-animated PNG files (#9334)
* style: fix TS lint errors about `ev.target`
* enhance: compress non-animated PNG
* PNG to PNG?
* defer jest things (add it later)
* Delete jest.config.cjs
* check the compressed file size
* log compression stats
* use ??
* handle if ($i == null)
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Diffstat (limited to 'packages/client/src/scripts/upload.ts')
| -rw-r--r-- | packages/client/src/scripts/upload.ts | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/packages/client/src/scripts/upload.ts b/packages/client/src/scripts/upload.ts index 51f1c1b86f..9a39652ef5 100644 --- a/packages/client/src/scripts/upload.ts +++ b/packages/client/src/scripts/upload.ts @@ -1,6 +1,7 @@ import { reactive, ref } from 'vue'; import * as Misskey from 'misskey-js'; import { readAndCompressImage } from 'browser-image-resizer'; +import { getCompressionConfig } from './upload/compress-config'; import { defaultStore } from '@/store'; import { apiUrl } from '@/config'; import { $i } from '@/account'; @@ -16,12 +17,6 @@ type Uploading = { }; export const uploads = ref<Uploading[]>([]); -const compressTypeMap = { - 'image/jpeg': { quality: 0.85, mimeType: 'image/jpeg' }, - 'image/webp': { quality: 0.85, mimeType: 'image/jpeg' }, - 'image/svg+xml': { quality: 1, mimeType: 'image/png' }, -} as const; - const mimeTypeMap = { 'image/webp': 'webp', 'image/jpeg': 'jpg', @@ -34,16 +29,18 @@ export function uploadFile( name?: string, keepOriginal: boolean = defaultStore.state.keepOriginalUploading, ): Promise<Misskey.entities.DriveFile> { + if ($i == null) throw new Error('Not logged in'); + if (folder && typeof folder === 'object') folder = folder.id; return new Promise((resolve, reject) => { const id = Math.random().toString(); const reader = new FileReader(); - reader.onload = async (ev) => { + reader.onload = async (): Promise<void> => { const ctx = reactive<Uploading>({ id: id, - name: name || file.name || 'untitled', + name: name ?? file.name ?? 'untitled', progressMax: undefined, progressValue: undefined, img: window.URL.createObjectURL(file), @@ -51,20 +48,22 @@ export function uploadFile( uploads.value.push(ctx); - let resizedImage: any; - if (!keepOriginal && file.type in compressTypeMap) { - const imgConfig = compressTypeMap[file.type]; - - const config = { - maxWidth: 2048, - maxHeight: 2048, - debug: true, - ...imgConfig, - }; - + const config = !keepOriginal ? await getCompressionConfig(file) : undefined; + let resizedImage: Blob | undefined; + if (config) { try { - resizedImage = await readAndCompressImage(file, config); - ctx.name = file.type !== imgConfig.mimeType ? `${ctx.name}.${mimeTypeMap[compressTypeMap[file.type].mimeType]}` : ctx.name; + const resized = await readAndCompressImage(file, config); + if (resized.size < file.size || file.type === 'image/webp') { + // The compression may not always reduce the file size + // (and WebP is not browser safe yet) + resizedImage = resized; + } + if (_DEV_) { + const saved = ((1 - resized.size / file.size) * 100).toFixed(2); + console.log(`Image compression: before ${file.size} bytes, after ${resized.size} bytes, saved ${saved}%`); + } + + ctx.name = file.type !== config.mimeType ? `${ctx.name}.${mimeTypeMap[config.mimeType]}` : ctx.name; } catch (err) { console.error('Failed to resize image', err); } @@ -73,13 +72,13 @@ export function uploadFile( const formData = new FormData(); formData.append('i', $i.token); formData.append('force', 'true'); - formData.append('file', resizedImage || file); + formData.append('file', resizedImage ?? file); formData.append('name', ctx.name); if (folder) formData.append('folderId', folder); const xhr = new XMLHttpRequest(); xhr.open('POST', apiUrl + '/drive/files/create', true); - xhr.onload = (ev) => { + xhr.onload = ((ev: ProgressEvent<XMLHttpRequest>) => { if (xhr.status !== 200 || ev.target == null || ev.target.response == null) { // TODO: 消すのではなくて(ネットワーク的なエラーなら)再送できるようにしたい uploads.value = uploads.value.filter(x => x.id !== id); @@ -122,7 +121,7 @@ export function uploadFile( resolve(driveFile); uploads.value = uploads.value.filter(x => x.id !== id); - }; + }) as (ev: ProgressEvent<EventTarget>) => any; xhr.upload.onprogress = ev => { if (ev.lengthComputable) { |