From 2f67ec2f843bc05f37b960399f7f6e37ac37d54b Mon Sep 17 00:00:00 2001 From: tamaina <tamaina@hotmail.co.jp> Date: Thu, 27 Jan 2022 00:08:48 +0900 Subject: [PATCH] =?UTF-8?q?enhance:=20MediaList=E3=81=A7=E3=81=AF=E3=80=81?= =?UTF-8?q?=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=A7=E8=A8=B1=E5=8F=AF?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=9F=E5=BD=A2=E5=BC=8F=E3=81=97=E3=81=8B?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=20(#8113)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * fix --- packages/client/src/components/media-list.vue | 36 +++++++++------ packages/client/src/const.ts | 44 +++++++++++++++++++ 2 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 packages/client/src/const.ts diff --git a/packages/client/src/components/media-list.vue b/packages/client/src/components/media-list.vue index 2970d06c9..efcbb1292 100644 --- a/packages/client/src/components/media-list.vue +++ b/packages/client/src/components/media-list.vue @@ -3,7 +3,7 @@ <XBanner v-for="media in mediaList.filter(media => !previewable(media))" :key="media.id" :media="media"/> <div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container"> <div ref="gallery" :data-count="mediaList.filter(media => previewable(media)).length"> - <template v-for="media in mediaList"> + <template v-for="media in mediaList.filter(media => previewable(media))"> <XVideo v-if="media.type.startsWith('video')" :key="media.id" :video="media"/> <XImage v-else-if="media.type.startsWith('image')" :key="media.id" class="image" :data-id="media.id" :image="media" :raw="raw"/> </template> @@ -22,6 +22,7 @@ import XBanner from './media-banner.vue'; import XImage from './media-image.vue'; import XVideo from './media-video.vue'; import * as os from '@/os'; +import { FILE_TYPE_BROWSERSAFE } from '@/const'; import { defaultStore } from '@/store'; export default defineComponent({ @@ -44,18 +45,23 @@ export default defineComponent({ onMounted(() => { const lightbox = new PhotoSwipeLightbox({ - dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => { - const item = { - src: media.url, - w: media.properties.width, - h: media.properties.height, - alt: media.name, - }; - if (media.properties.orientation != null && media.properties.orientation >= 5) { - [item.w, item.h] = [item.h, item.w]; - } - return item; - }), + dataSource: props.mediaList + .filter(media => { + if (media.type === 'image/svg+xml') return true; // svgのwebpublicはpngなのでtrue + return media.type.startsWith('image') && FILE_TYPE_BROWSERSAFE.includes(media.type); + }) + .map(media => { + const item = { + src: media.url, + w: media.properties.width, + h: media.properties.height, + alt: media.name, + }; + if (media.properties.orientation != null && media.properties.orientation >= 5) { + [item.w, item.h] = [item.h, item.w]; + } + return item; + }), gallery: gallery.value, children: '.image', thumbSelector: '.image', @@ -99,7 +105,9 @@ export default defineComponent({ }); const previewable = (file: misskey.entities.DriveFile): boolean => { - return file.type.startsWith('video') || file.type.startsWith('image'); + if (file.type === 'image/svg+xml') return true; // svgのwebpublic/thumbnailはpngなのでtrue + // FILE_TYPE_BROWSERSAFEに適合しないものはブラウザで表示するのに不適切 + return (file.type.startsWith('video') || file.type.startsWith('image')) && FILE_TYPE_BROWSERSAFE.includes(file.type); }; return { diff --git a/packages/client/src/const.ts b/packages/client/src/const.ts new file mode 100644 index 000000000..505cf2748 --- /dev/null +++ b/packages/client/src/const.ts @@ -0,0 +1,44 @@ +// ブラウザで直接表示することを許可するファイルの種類のリスト +// ここに含まれないものは application/octet-stream としてレスポンスされる +// SVGはXSSを生むので許可しない +export const FILE_TYPE_BROWSERSAFE = [ + // Images + 'image/png', + 'image/gif', + 'image/jpeg', + 'image/webp', + 'image/apng', + 'image/bmp', + 'image/tiff', + 'image/x-icon', + + // OggS + 'audio/opus', + 'video/ogg', + 'audio/ogg', + 'application/ogg', + + // ISO/IEC base media file format + 'video/quicktime', + 'video/mp4', + 'audio/mp4', + 'video/x-m4v', + 'audio/x-m4a', + 'video/3gpp', + 'video/3gpp2', + + 'video/mpeg', + 'audio/mpeg', + + 'video/webm', + 'audio/webm', + + 'audio/aac', + 'audio/x-flac', + 'audio/vnd.wave', +]; +/* +https://github.com/sindresorhus/file-type/blob/main/supported.js +https://github.com/sindresorhus/file-type/blob/main/core.js +https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers +*/