summaryrefslogtreecommitdiff
path: root/packages/client/src/scripts/upload.ts
diff options
context:
space:
mode:
authorKagami Sascha Rosylight <saschanaz@outlook.com>2022-12-18 15:40:38 +0900
committerGitHub <noreply@github.com>2022-12-18 15:40:38 +0900
commita47d172d60b1ae712738e0ba5dfbb6b81be3f809 (patch)
tree8aeba3a1880507fc6b48458dd3c3632d97185a78 /packages/client/src/scripts/upload.ts
parentchore: deploy vue-tsc for client typecheck (#9341) (diff)
downloadsharkey-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.ts47
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) {