Fix gallery view and lazy load thumbnails

This commit is contained in:
N-Pex 2025-06-19 10:58:11 +02:00
parent f0382afd83
commit acdef62880
6 changed files with 69 additions and 27 deletions

View file

@ -73,7 +73,7 @@ $hiliteColor: #4642f1;
color: rgba($text, 80%) !important; color: rgba($text, 80%) !important;
} }
.send-attachments__selecting__current-item { .send-attachments__selecting__current-item, .gallery-current-item {
width: 100%; width: 100%;
flex: 1 1 100%; flex: 1 1 100%;
background-color: $backgroundSection; background-color: $backgroundSection;
@ -102,7 +102,7 @@ $hiliteColor: #4642f1;
} }
} }
.file-drop-thumbnail-container { .file-drop-thumbnail-container, .gallery-thumbnail-container {
width: 100%; width: 100%;
padding: 13px 20px 15px 20px; padding: 13px 20px 15px 20px;
flex: 0 0 74px; flex: 0 0 74px;

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="fill-screen file-drop-root"> <div class="fill-screen send-attachments">
<div class="chat-header"> <div class="chat-header">
<v-container fluid class="d-flex justify-space-between align-center"> <v-container fluid class="d-flex justify-space-between align-center">
@ -9,13 +9,13 @@
</v-container> </v-container>
</div> </div>
<div class="file-drop-current-item"> <div class="gallery-current-item">
<ThumbnailView :item="items[currentItemIndex]" /> <ThumbnailView :item="items[currentItemIndex]" />
<div class="download-button clickable" @click.stop="downloadOne"> <div class="download-button clickable" @click.stop="downloadOne">
<v-icon color="black">arrow_downward</v-icon> <v-icon color="black">arrow_downward</v-icon>
</div> </div>
</div> </div>
<div class="file-drop-thumbnail-container"> <div class="gallery-thumbnail-container">
<div :class="{ 'file-drop-thumbnail': true, 'clickable': true, 'current': id == currentItemIndex }" <div :class="{ 'file-drop-thumbnail': true, 'clickable': true, 'current': id == currentItemIndex }"
@click="currentItemIndex = id" v-for="(currentImageInput, id) in items" :key="id"> @click="currentItemIndex = id" v-for="(currentImageInput, id) in items" :key="id">
<v-img v-if="currentImageInput" :src="currentImageInput.thumbnail ? currentImageInput.thumbnail : currentImageInput.src" /> <v-img v-if="currentImageInput" :src="currentImageInput.thumbnail ? currentImageInput.thumbnail : currentImageInput.src" />
@ -107,15 +107,17 @@ export default {
<style lang="scss"> <style lang="scss">
@use "@/assets/css/chat.scss" as *; @use "@/assets/css/chat.scss" as *;
@use "@/assets/css/sendattachments.scss" as *;
.chat-header { .chat-header {
position: relative !important; position: relative !important;
width: 100%; width: 100%;
flex: 0 0 auto;
} }
.file-drop-current-item { // .file-drop-current-item {
position: relative; // position: relative;
} // }
.download-button { .download-button {
position: absolute; position: absolute;
@ -137,7 +139,7 @@ export default {
right: 0; right: 0;
bottom: 0; bottom: 0;
background: black; background: black;
z-index: 20; z-index: 20 !important;
justify-content: space-between !important; justify-content: space-between !important;
} }
</style> </style>

View file

@ -1,5 +1,5 @@
<template> <template>
<message-incoming v-bind="{ ...$props, ...$attrs }"> <message-incoming v-bind="{ ...$props, ...$attrs }" v-intersect="onIntersect">
<div class="bubble image-bubble" ref="imageRef"> <div class="bubble image-bubble" ref="imageRef">
<ImageWithProgress <ImageWithProgress
:aspect-ratio="16 / 9" :aspect-ratio="16 / 9"
@ -30,6 +30,7 @@ export default {
cover: true, cover: true,
contain: false, contain: false,
dialog: false, dialog: false,
isVisible: false,
}; };
}, },
methods: { methods: {
@ -44,6 +45,15 @@ export default {
} }
}); });
}, },
loadThumbnail() {
if (this.isVisible) {
this.eventAttachment?.loadThumbnail();
}
},
onIntersect(isIntersecting, entries, observer) {
this.isVisible = isIntersecting;
this.loadThumbnail();
}
}, },
mounted() { mounted() {
//console.log("Mounted with event:", JSON.stringify(this.event.getContent())); //console.log("Mounted with event:", JSON.stringify(this.event.getContent()));
@ -62,7 +72,7 @@ export default {
} }
this.eventAttachment = this.$matrix.attachmentManager.getEventAttachment(this.event); this.eventAttachment = this.$matrix.attachmentManager.getEventAttachment(this.event);
this.eventAttachment?.loadThumbnail(); this.loadThumbnail();
}, },
beforeUnmount() { beforeUnmount() {
this.eventAttachment?.release(); this.eventAttachment?.release();

View file

@ -1,5 +1,5 @@
<template> <template>
<message-outgoing v-bind="{ ...$props, ...$attrs }"> <message-outgoing v-bind="{ ...$props, ...$attrs }" v-intersect="onIntersect">
<div class="bubble image-bubble" ref="imageRef"> <div class="bubble image-bubble" ref="imageRef">
<ImageWithProgress <ImageWithProgress
:aspect-ratio="16 / 9" :aspect-ratio="16 / 9"
@ -30,6 +30,7 @@ export default {
cover: true, cover: true,
contain: false, contain: false,
dialog: false, dialog: false,
isVisible: false,
}; };
}, },
methods: { methods: {
@ -44,6 +45,15 @@ export default {
} }
}); });
}, },
loadThumbnail() {
if (this.isVisible) {
this.eventAttachment?.loadThumbnail();
}
},
onIntersect(isIntersecting, entries, observer) {
this.isVisible = isIntersecting;
this.loadThumbnail();
}
}, },
mounted() { mounted() {
console.error("Mounted outgoing image, load thumbnail!"); console.error("Mounted outgoing image, load thumbnail!");
@ -62,7 +72,7 @@ export default {
this.initMessageOutImageHammerJs(this.$refs.imageRef); this.initMessageOutImageHammerJs(this.$refs.imageRef);
} }
this.eventAttachment = this.$matrix.attachmentManager.getEventAttachment(this.event); this.eventAttachment = this.$matrix.attachmentManager.getEventAttachment(this.event);
this.eventAttachment?.loadThumbnail(); this.loadThumbnail();
}, },
beforeUnmount() { beforeUnmount() {
this.eventAttachment?.release(); this.eventAttachment?.release();

View file

@ -3,6 +3,7 @@
ref="root" ref="root"
v-bind="{ ...$props, ...$attrs }" v-bind="{ ...$props, ...$attrs }"
v-if="showMultiview" v-if="showMultiview"
v-intersect="onIntersect"
> >
<div class="bubble"> <div class="bubble">
<div class="original-message" v-if="inReplyToText"> <div class="original-message" v-if="inReplyToText">
@ -74,6 +75,7 @@ const emits = defineEmits<MessageEmits & {(event: "layout-change", value: {eleme
const items: Ref<EventAttachment[]> = ref([]); const items: Ref<EventAttachment[]> = ref([]);
const showItem: Ref<EventAttachment | undefined> = ref(undefined); const showItem: Ref<EventAttachment | undefined> = ref(undefined);
const isVisible: Ref<boolean> = ref(false);
const props = defineProps<MessageProps>(); const props = defineProps<MessageProps>();
@ -96,6 +98,17 @@ const {
linkify, linkify,
} = useMessage($matrix, t, props, emits, processThread); } = useMessage($matrix, t, props, emits, processThread);
const onRelationsCreated = () => {
if (event.value) {
thread.value = props.timelineSet.relations.getChildEventsForEvent(
event.value.getId() ?? "",
util.threadMessageType(),
"m.room.message"
);
event.value.off(MatrixEventEvent.RelationsCreated, onRelationsCreated);
}
};
watch(event, () => { watch(event, () => {
if (event.value) { if (event.value) {
if (thread.value === undefined) { if (thread.value === undefined) {
@ -123,17 +136,6 @@ const showMultiview = computed((): boolean => {
messageText.value?.length > 0 messageText.value?.length > 0
}); });
const onRelationsCreated = () => {
if (event.value) {
thread.value = props.timelineSet.relations.getChildEventsForEvent(
event.value.getId() ?? "",
util.threadMessageType(),
"m.room.message"
);
event.value.off(MatrixEventEvent.RelationsCreated, onRelationsCreated);
}
};
const onItemClick = (event: any) => { const onItemClick = (event: any) => {
showItem.value = event.item; showItem.value = event.item;
}; };
@ -145,7 +147,7 @@ const _processThread = () => {
items.value = eventItems.map((e: MatrixEvent) => { items.value = eventItems.map((e: MatrixEvent) => {
let ea = $matrix.attachmentManager.getEventAttachment(e); let ea = $matrix.attachmentManager.getEventAttachment(e);
if (showMultiview.value) { if (showMultiview.value && isVisible.value) {
ea.loadThumbnail(); ea.loadThumbnail();
} }
return ea; return ea;
@ -184,6 +186,14 @@ const layoutedItems = computed(() => {
} }
return rows; return rows;
}); });
const onIntersect = (isIntersecting: boolean, entries: any, observer: any) => {
isVisible.value = isIntersecting;
if (showMultiview.value && isIntersecting) {
items.value.forEach((a) => a.loadThumbnail());
}
};
</script> </script>
<style lang="scss"> <style lang="scss">
@use "@/assets/css/chat.scss" as *; @use "@/assets/css/chat.scss" as *;

View file

@ -3,6 +3,7 @@
ref="root" ref="root"
v-bind="{ ...$props, ...$attrs }" v-bind="{ ...$props, ...$attrs }"
v-if="showMultiview" v-if="showMultiview"
v-intersect="onIntersect"
> >
<div class="bubble"> <div class="bubble">
<div class="original-message" v-if="inReplyToText"> <div class="original-message" v-if="inReplyToText">
@ -74,6 +75,7 @@ const emits = defineEmits<MessageEmits & {(event: "layout-change", value: {eleme
const items: Ref<EventAttachment[]> = ref([]); const items: Ref<EventAttachment[]> = ref([]);
const showItem: Ref<EventAttachment | undefined> = ref(undefined); const showItem: Ref<EventAttachment | undefined> = ref(undefined);
const isVisible: Ref<boolean> = ref(false);
const props = defineProps<MessageProps>(); const props = defineProps<MessageProps>();
@ -143,7 +145,7 @@ const _processThread = () => {
items.value = eventItems.map((e: MatrixEvent) => { items.value = eventItems.map((e: MatrixEvent) => {
let ea = $matrix.attachmentManager.getEventAttachment(e); let ea = $matrix.attachmentManager.getEventAttachment(e);
if (showMultiview.value) { if (showMultiview.value && isVisible.value) {
ea.loadThumbnail(); ea.loadThumbnail();
} }
return ea; return ea;
@ -182,6 +184,14 @@ const layoutedItems = computed(() => {
} }
return rows; return rows;
}); });
const onIntersect = (isIntersecting: boolean, entries: any, observer: any) => {
isVisible.value = isIntersecting;
if (showMultiview.value && isIntersecting) {
items.value.forEach((a) => a.loadThumbnail());
}
};
</script> </script>
<style lang="scss"> <style lang="scss">
@use "@/assets/css/chat.scss" as *; @use "@/assets/css/chat.scss" as *;