feat(client): Improve image viewer

Resolve #7545
Resolve #6811
Close #7808
This commit is contained in:
syuilo 2021-10-25 02:28:18 +09:00
parent 67bf6ff3ce
commit e52a9e0a65
5 changed files with 67 additions and 62 deletions

View file

@ -10,11 +10,16 @@
## 12.x.x (unreleased)
### Improvements
- クライアント: 画像ビューアを強化
- クライアント: メンションにユーザーのアバターを表示するように
- クライアント: デザインの調整
- クライアント: twemojiをセルフホスティングするように
### Bugfixes
- クライアント: CWで画像が隠されたとき、画像の高さがおかしいことになる問題を修正
### NOTE
- このバージョンから、iOS 15未満のサポートがされなくなります。対象のバージョンをお使いの方は、iOSのバージョンアップを行ってください。
## 12.93.2 (2021/10/23)

View file

@ -183,6 +183,7 @@
"os-utils": "0.0.14",
"parse5": "6.0.1",
"pg": "8.7.1",
"photoswipe": "git://github.com/dimsemenov/photoswipe#v5-beta",
"portscanner": "2.2.0",
"postcss": "8.3.11",
"postcss-loader": "6.2.0",

View file

@ -12,7 +12,6 @@
<a
:href="image.url"
:title="image.name"
@click.prevent="onClick"
>
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
@ -73,17 +72,6 @@ export default defineComponent({
immediate: true,
});
},
methods: {
onClick() {
if (this.$store.state.imageNewTab) {
window.open(this.image.url, '_blank');
} else {
os.popup(ImageViewer, {
image: this.image
}, {}, 'closed');
}
}
}
});
</script>

View file

@ -1,11 +1,11 @@
<template>
<div class="mk-media-list">
<div class="hoawjimk">
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/>
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container" ref="gridOuter">
<div :data-count="mediaList.filter(media => previewable(media)).length" :style="gridInnerStyle">
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
<div :data-count="mediaList.filter(media => previewable(media)).length" ref="gallery">
<template v-for="media in mediaList">
<XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/>
<XImage :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/>
<XImage class="image" :data-id="media.id" :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/>
</template>
</div>
</div>
@ -13,11 +13,16 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, PropType, ref } from 'vue';
import * as misskey from 'misskey-js';
import PhotoSwipeLightbox from 'photoswipe/dist/photoswipe-lightbox.esm.js';
import PhotoSwipe from 'photoswipe/dist/photoswipe.esm.js';
import 'photoswipe/dist/photoswipe.css';
import XBanner from './media-banner.vue';
import XImage from './media-image.vue';
import XVideo from './media-video.vue';
import * as os from '@client/os';
import { defaultStore } from '@client/store';
export default defineComponent({
components: {
@ -27,63 +32,65 @@ export default defineComponent({
},
props: {
mediaList: {
required: true
type: Array as PropType<misskey.entities.DriveFile[]>,
required: true,
},
raw: {
default: false
},
},
data() {
return {
gridInnerStyle: {},
sizeWaiting: false
}
},
mounted() {
this.size();
window.addEventListener('resize', this.size);
},
beforeUnmount() {
window.removeEventListener('resize', this.size);
},
activated() {
this.size();
},
methods: {
previewable(file) {
return file.type.startsWith('video') || file.type.startsWith('image');
},
size() {
// for Safari bug
if (this.sizeWaiting) return;
setup(props) {
const gallery = ref(null);
this.sizeWaiting = true;
window.requestAnimationFrame(() => {
this.sizeWaiting = false;
if (this.$refs.gridOuter) {
let height = 287;
const parent = this.$parent.$el;
if (this.$refs.gridOuter.clientHeight) {
height = this.$refs.gridOuter.clientHeight;
} else if (parent) {
height = parent.getBoundingClientRect().width * 9 / 16;
}
this.gridInnerStyle = { height: `${height}px` };
} else {
this.gridInnerStyle = {};
}
onMounted(() => {
const lightbox = new PhotoSwipeLightbox({
dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => ({
src: media.url,
w: media.properties.width,
h: media.properties.height,
alt: media.name,
})),
gallery: gallery.value,
children: '.image',
thumbSelector: '.image',
pswpModule: PhotoSwipe
});
}
lightbox.on('itemData', (e) => {
const { itemData } = e;
// element is children
const { element } = itemData;
console.log(element);
const id = element.dataset.id;
const file = props.mediaList.find(media => media.id === id);
itemData.src = file.url;
itemData.w = Number(file.properties.width);
itemData.h = Number(file.properties.height);
itemData.msrc = file.thumbnailUrl;
itemData.thumbCropped = true;
});
lightbox.init();
});
const previewable = (file: misskey.entities.DriveFile): boolean => {
return file.type.startsWith('video') || file.type.startsWith('image');
};
return {
previewable,
gallery,
};
},
});
</script>
<style lang="scss" scoped>
.mk-media-list {
.hoawjimk {
> .gird-container {
position: relative;
width: 100%;

View file

@ -8271,6 +8271,10 @@ pgpass@1.x:
dependencies:
split "^1.0.0"
"photoswipe@git://github.com/dimsemenov/photoswipe#v5-beta":
version "5.1.7"
resolved "git://github.com/dimsemenov/photoswipe#60040164333bd257409669e715e4327afdb3aec7"
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"