fix: PhotoSwipeによるクライアントのメモリリークの解消 (#11395)

* Destroy PhotoSwipe on unmounted

* Update CHANGELOG.md
This commit is contained in:
kabo2468
2023-07-27 06:44:16 +09:00
committed by GitHub
parent 090253c2d2
commit 71b016b293
2 changed files with 18 additions and 9 deletions

View File

@@ -58,7 +58,7 @@ async function getClientWidthWithCache(targetEl: HTMLElement, containerEl: HTMLE
</script>
<script lang="ts" setup>
import { onMounted, shallowRef } from 'vue';
import { onMounted, onUnmounted, shallowRef } from 'vue';
import * as misskey from 'misskey-js';
import PhotoSwipeLightbox from 'photoswipe/lightbox';
import PhotoSwipe from 'photoswipe';
@@ -82,12 +82,19 @@ const gallery = shallowRef<HTMLDivElement>();
const pswpZIndex = os.claimZIndex('middle');
document.documentElement.style.setProperty('--mk-pswp-root-z-index', pswpZIndex.toString());
const count = $computed(() => props.mediaList.filter(media => previewable(media)).length);
let lightbox: PhotoSwipeLightbox | null;
const popstateHandler = (): void => {
if (lightbox.pswp && lightbox.pswp.isOpen === true) {
lightbox.pswp.close();
}
};
/**
* アスペクト比をmediaListWithOneImageAppearanceに基づいていい感じに調整する
* aspect-ratioではなくheightを使う
*/
async function calcAspectRatio() {
async function calcAspectRatio() {
if (!gallery.value || !root.value) return;
let img = props.mediaList[0];
@@ -137,7 +144,7 @@ const count = $computed(() => props.mediaList.filter(media => previewable(media)
onMounted(() => {
calcAspectRatio();
const lightbox = new PhotoSwipeLightbox({
lightbox = new PhotoSwipeLightbox({
dataSource: props.mediaList
.filter(media => {
if (media.type === 'image/svg+xml') return true; // svgのwebpublicはpngなのでtrue
@@ -221,12 +228,7 @@ onMounted(() => {
lightbox.init();
window.addEventListener('popstate', () => {
if (lightbox.pswp && lightbox.pswp.isOpen === true) {
lightbox.pswp.close();
return;
}
});
window.addEventListener('popstate', popstateHandler);
lightbox.on('beforeOpen', () => {
history.pushState(null, '', '#pswp');
@@ -239,6 +241,12 @@ onMounted(() => {
});
});
onUnmounted(() => {
window.removeEventListener('popstate', popstateHandler);
lightbox?.destroy();
lightbox = null;
});
const previewable = (file: misskey.entities.DriveFile): boolean => {
if (file.type === 'image/svg+xml') return true; // svgのwebpublic/thumbnailはpngなのでtrue
// FILE_TYPE_BROWSERSAFEに適合しないものはブラウザで表示するのに不適切