parent
f6a6766f7d
commit
2f67ec2f84
2 changed files with 66 additions and 14 deletions
|
@ -3,7 +3,7 @@
|
||||||
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :key="media.id" :media="media"/>
|
<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 v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
|
||||||
<div ref="gallery" :data-count="mediaList.filter(media => previewable(media)).length">
|
<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"/>
|
<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"/>
|
<XImage v-else-if="media.type.startsWith('image')" :key="media.id" class="image" :data-id="media.id" :image="media" :raw="raw"/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -22,6 +22,7 @@ import XBanner from './media-banner.vue';
|
||||||
import XImage from './media-image.vue';
|
import XImage from './media-image.vue';
|
||||||
import XVideo from './media-video.vue';
|
import XVideo from './media-video.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import { FILE_TYPE_BROWSERSAFE } from '@/const';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -44,18 +45,23 @@ export default defineComponent({
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const lightbox = new PhotoSwipeLightbox({
|
const lightbox = new PhotoSwipeLightbox({
|
||||||
dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => {
|
dataSource: props.mediaList
|
||||||
const item = {
|
.filter(media => {
|
||||||
src: media.url,
|
if (media.type === 'image/svg+xml') return true; // svgのwebpublicはpngなのでtrue
|
||||||
w: media.properties.width,
|
return media.type.startsWith('image') && FILE_TYPE_BROWSERSAFE.includes(media.type);
|
||||||
h: media.properties.height,
|
})
|
||||||
alt: media.name,
|
.map(media => {
|
||||||
};
|
const item = {
|
||||||
if (media.properties.orientation != null && media.properties.orientation >= 5) {
|
src: media.url,
|
||||||
[item.w, item.h] = [item.h, item.w];
|
w: media.properties.width,
|
||||||
}
|
h: media.properties.height,
|
||||||
return item;
|
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,
|
gallery: gallery.value,
|
||||||
children: '.image',
|
children: '.image',
|
||||||
thumbSelector: '.image',
|
thumbSelector: '.image',
|
||||||
|
@ -99,7 +105,9 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
const previewable = (file: misskey.entities.DriveFile): boolean => {
|
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 {
|
return {
|
||||||
|
|
44
packages/client/src/const.ts
Normal file
44
packages/client/src/const.ts
Normal file
|
@ -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
|
||||||
|
*/
|
Loading…
Reference in a new issue