From 8eecacec4fe64e8d2e3eb9f7fc7d04749a334015 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Mon, 14 Nov 2022 18:53:38 -0800 Subject: [PATCH] AVIF support --- CALCKEY.md | 3 ++- package.json | 2 +- packages/backend/src/misc/get-file-info.ts | 4 ++-- packages/backend/src/misc/is-mime-image.ts | 2 +- packages/backend/src/models/repositories/drive-file.ts | 2 +- packages/backend/src/server/file/send-drive-file.ts | 2 +- packages/backend/src/services/drive/add-file.ts | 5 +++-- packages/client/src/const.ts | 1 + packages/client/src/pages/user/index.photos.vue | 1 + packages/client/src/scripts/upload.ts | 1 + 10 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CALCKEY.md b/CALCKEY.md index c2925d4c8f..7f07910750 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -84,7 +84,8 @@ - Phosphor icons instead of FontAwesome - Fully deprecate MkEmojiPickerWindow in favor of MkEmojiPickerDialog - Link hover effect -- Replace all `$ts` with i18n +- Replace all `$ts` with i18n\ +- AVIF support - Obliteration of Ai-chan - [Make showing ads optional](https://github.com/misskey-dev/misskey/pull/8996) - [Tapping avatar in mobile opens account modal](https://github.com/misskey-dev/misskey/pull/9056) diff --git a/package.json b/package.json index 69d84d4b99..54dca8520d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "12.119.0-calc.13-rc.10", + "version": "12.119.0-calc.13-rc.11", "codename": "aqua", "repository": { "type": "git", diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 1c988b2487..b4922779aa 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -63,7 +63,7 @@ export async function getFileInfo(path: string, opts: { let height: number | undefined; let orientation: number | undefined; - if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/bmp', 'image/tiff', 'image/svg+xml', 'image/vnd.adobe.photoshop'].includes(type.mime)) { + if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/bmp', 'image/tiff', 'image/svg+xml', 'image/vnd.adobe.photoshop', 'image/avif'].includes(type.mime)) { const imageSize = await detectImageSize(path).catch(e => { warnings.push(`detectImageSize failed: ${e}`); return undefined; @@ -90,7 +90,7 @@ export async function getFileInfo(path: string, opts: { let blurhash: string | undefined; - if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/svg+xml'].includes(type.mime)) { + if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/svg+xml', 'image/avif'].includes(type.mime)) { blurhash = await getBlurhash(path).catch(e => { warnings.push(`getBlurhash failed: ${e}`); return undefined; diff --git a/packages/backend/src/misc/is-mime-image.ts b/packages/backend/src/misc/is-mime-image.ts index 8993ede33a..9d6e28f15a 100644 --- a/packages/backend/src/misc/is-mime-image.ts +++ b/packages/backend/src/misc/is-mime-image.ts @@ -2,7 +2,7 @@ import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; const dictionary = { 'safe-file': FILE_TYPE_BROWSERSAFE, - 'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/svg+xml'], + 'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/svg+xml', 'image/avif'], }; export const isMimeImage = (mime: string, type: keyof typeof dictionary): boolean => dictionary[type].includes(mime); diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index 0d589d4f11..4366b02cc0 100644 --- a/packages/backend/src/models/repositories/drive-file.ts +++ b/packages/backend/src/models/repositories/drive-file.ts @@ -60,7 +60,7 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({ } } - const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/svg+xml'].includes(file.type); + const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/svg+xml', 'image/avif'].includes(file.type); return thumbnail ? (file.thumbnailUrl || (isImage ? (file.webpublicUrl || file.url) : null)) : (file.webpublicUrl || file.url); }, diff --git a/packages/backend/src/server/file/send-drive-file.ts b/packages/backend/src/server/file/send-drive-file.ts index c34e043145..acfde9cfc9 100644 --- a/packages/backend/src/server/file/send-drive-file.ts +++ b/packages/backend/src/server/file/send-drive-file.ts @@ -59,7 +59,7 @@ export default async function(ctx: Koa.Context) { const convertFile = async () => { if (isThumbnail) { - if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(mime)) { + if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml', 'image/avif'].includes(mime)) { return await convertToWebp(path, 498, 280); } else if (mime.startsWith('video/')) { return await GenerateVideoThumbnail(path); diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 709db88f2f..a790fd5104 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -49,6 +49,7 @@ async function save(file: DriveFile, path: string, name: string, type: string, h if (type === 'image/png') ext = '.png'; if (type === 'image/webp') ext = '.webp'; if (type === 'image/apng') ext = '.apng'; + if (type === 'image/avif') ext = '.avif'; if (type === 'image/vnd.mozilla.apng') ext = '.apng'; } @@ -171,7 +172,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool } } - if (!['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml'].includes(type)) { + if (!['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml', 'image/avif'].includes(type)) { logger.debug('web image and thumbnail not created (not an required file)'); return { webpublic: null, @@ -238,7 +239,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool let thumbnail: IImage | null = null; try { - if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(type)) { + if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml', 'image/avif'].includes(type)) { thumbnail = await convertSharpToWebp(img, 498, 280); } else { logger.debug('thumbnail not created (not an required file)'); diff --git a/packages/client/src/const.ts b/packages/client/src/const.ts index 505cf2748e..88534f2a90 100644 --- a/packages/client/src/const.ts +++ b/packages/client/src/const.ts @@ -11,6 +11,7 @@ export const FILE_TYPE_BROWSERSAFE = [ 'image/bmp', 'image/tiff', 'image/x-icon', + 'image/avif', // OggS 'audio/opus', diff --git a/packages/client/src/pages/user/index.photos.vue b/packages/client/src/pages/user/index.photos.vue index 703b3adce3..21907a134b 100644 --- a/packages/client/src/pages/user/index.photos.vue +++ b/packages/client/src/pages/user/index.photos.vue @@ -52,6 +52,7 @@ onMounted(() => { 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', + 'image/avif', ]; os.api('users/notes', { userId: props.user.id, diff --git a/packages/client/src/scripts/upload.ts b/packages/client/src/scripts/upload.ts index 6f50e9bd9c..9f34685f64 100644 --- a/packages/client/src/scripts/upload.ts +++ b/packages/client/src/scripts/upload.ts @@ -26,6 +26,7 @@ const mimeTypeMap = { 'image/webp': 'webp', 'image/jpeg': 'jpg', 'image/png': 'png', + 'image/avif': 'avif', } as const; export function uploadFile(