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

View file

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

View file

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

View file

@ -1,11 +1,11 @@
<template> <template>
<div class="mk-media-list"> <div class="hoawjimk">
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/> <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 v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
<div :data-count="mediaList.filter(media => previewable(media)).length" :style="gridInnerStyle"> <div :data-count="mediaList.filter(media => previewable(media)).length" ref="gallery">
<template v-for="media in mediaList"> <template v-for="media in mediaList">
<XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/> <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> </template>
</div> </div>
</div> </div>
@ -13,11 +13,16 @@
</template> </template>
<script lang="ts"> <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 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 '@client/os'; import * as os from '@client/os';
import { defaultStore } from '@client/store';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -27,63 +32,65 @@ export default defineComponent({
}, },
props: { props: {
mediaList: { mediaList: {
required: true type: Array as PropType<misskey.entities.DriveFile[]>,
required: true,
}, },
raw: { raw: {
default: false default: false
}, },
}, },
data() { setup(props) {
return { const gallery = ref(null);
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;
this.sizeWaiting = true; onMounted(() => {
const lightbox = new PhotoSwipeLightbox({
window.requestAnimationFrame(() => { dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => ({
this.sizeWaiting = false; src: media.url,
w: media.properties.width,
if (this.$refs.gridOuter) { h: media.properties.height,
let height = 287; alt: media.name,
const parent = this.$parent.$el; })),
gallery: gallery.value,
if (this.$refs.gridOuter.clientHeight) { children: '.image',
height = this.$refs.gridOuter.clientHeight; thumbSelector: '.image',
} else if (parent) { pswpModule: PhotoSwipe
height = parent.getBoundingClientRect().width * 9 / 16;
}
this.gridInnerStyle = { height: `${height}px` };
} else {
this.gridInnerStyle = {};
}
}); });
}
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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.mk-media-list { .hoawjimk {
> .gird-container { > .gird-container {
position: relative; position: relative;
width: 100%; width: 100%;

View file

@ -8271,6 +8271,10 @@ pgpass@1.x:
dependencies: dependencies:
split "^1.0.0" 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: picocolors@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"