Allow enlarge user profile image as lightbox, initial work by Lhcfl

This commit is contained in:
Crimekillz 2024-04-18 02:38:27 +02:00
parent 1d168e811a
commit e318c48a5e
2 changed files with 107 additions and 1 deletions

View File

@ -15,6 +15,26 @@
:user="user"
/>
</span>
<span
v-else-if="showLightBox"
v-user-preview="disablePreview ? undefined : user.id"
class="eiwwqkts _noSelect showLightBox"
:class="{
cat: user.isCat,
square: defaultStore.state.squareAvatars,
}"
:style="{ color }"
:title="acct(user)"
ref="gallery"
@click.stop
>
<img class="inner avatar" :src="url" decoding="async" />
<MkUserOnlineIndicator
v-if="showIndicator && user.instance == null"
class="indicator"
:user="user"
/>
</span>
<MkA
v-else
v-user-preview="disablePreview ? undefined : user.id"
@ -36,25 +56,30 @@
</template>
<script lang="ts" setup>
import { onMounted, watch } from "vue";
import { onMounted, ref, watch } from "vue";
import type * as misskey from "trashposs-js";
import { getStaticImageUrl } from "@/scripts/get-static-image-url";
import { extractAvgColorFromBlurhash } from "@/scripts/extract-avg-color-from-blurhash";
import { acct, userPage } from "@/filters/user";
import MkUserOnlineIndicator from "@/components/MkUserOnlineIndicator.vue";
import { defaultStore } from "@/store";
import PhotoSwipeLightbox from "photoswipe/lightbox";
import PhotoSwipe from "photoswipe";
import "photoswipe/style.css";
const props = withDefaults(
defineProps<{
user: misskey.entities.User;
target?: string | null;
disableLink?: boolean;
showLightBox?: boolean;
disablePreview?: boolean;
showIndicator?: boolean;
}>(),
{
target: null,
disableLink: false,
showLightBox: false,
disablePreview: false,
showIndicator: false,
},
@ -85,6 +110,82 @@ watch(
immediate: true,
},
);
async function prepareImageForPhotoswipe() {
const promise = new Promise(function (resolve) {
let image = new Image();
image.src = url;
image.onload = () => {
resolve([image.naturalWidth,image.naturalHeight]); // Resolve the promise only if the image has been loaded
}
image.onerror = () => { resolve([0,0]); };
});
await promise;
}
// Call the function using await
const dimensions = prepareImageForPhotoswipe();
const gallery = ref(null);
onMounted(() => {
const lightbox = new PhotoSwipeLightbox({
dataSource: [{
src: url,
w: dimensions[0],
h: dimensions[1],
}],
gallery: gallery.value,
children: ".avatar",
thumbSelector: ".avatar",
loop: false,
padding:
window.innerWidth > 500
? {
top: 32,
bottom: 32,
left: 32,
right: 32,
}
: {
top: 0,
bottom: 0,
left: 0,
right: 0,
},
imageClickAction: "close",
tapAction: "toggle-controls",
preloadFirstSlide: false,
pswpModule: PhotoSwipe,
});
lightbox.on("itemData", (ev) => {
const { itemData } = ev;
itemData.src = url;
itemData.msrc = url;
itemData.h = dimensions[1];
itemData.w = dimensions[0];
});
lightbox.on("afterInit", () => {
history.pushState(null, "", location.href);
addEventListener("popstate", close);
// This is a workaround. Not sure why, but when clicking to open, it doesn't move focus to the photoswipe. Preventing using esc to close. However when using keyboard to open it already focuses the lightbox fine.
lightbox.pswp.element.focus();
});
lightbox.on("close", () => {
removeEventListener("popstate", close);
history.back();
});
lightbox.init();
function close() {
removeEventListener("popstate", close);
history.forward();
lightbox.pswp.close();
}
});
</script>
<style lang="scss" scoped>
@ -132,6 +233,10 @@ watch(
border-radius: 100%;
line-height: 16px;
&.showLightBox {
cursor: zoom-in;
}
> .inner {
position: absolute;
bottom: 0;

View File

@ -114,6 +114,7 @@
</div>
<MkAvatar
class="avatar"
:showLightBox="true"
:user="user"
:disable-preview="true"
:show-indicator="true"