keanu-weblite/src/components/file_mode/ThumbnailView.vue

125 lines
3.3 KiB
Vue
Raw Normal View History

2023-10-25 10:44:25 +00:00
<template>
2025-06-09 09:44:49 +02:00
<div ref="thumbnailRef">
<v-responsive
v-if="item.event.getContent().msgtype == 'm.video' && item.src"
:class="{ 'thumbnail-item': true, preview: previewOnly }"
>
<video :src="item.src" :controls="!previewOnly" class="w-100 h-100">
{{ $t("fallbacks.video_file") }}
</video>
</v-responsive>
<v-img
v-else-if="item.event.getContent().msgtype == 'm.image' && item.src"
:aspect-ratio="previewOnly ? 16 / 9 : undefined"
:class="{ 'thumbnail-item': true, preview: previewOnly }"
:src="item.src"
:contain="!previewOnly"
:cover="previewOnly"
/>
<div v-else :class="{ 'thumbnail-item': true, preview: previewOnly, 'file-item': true }">
<v-icon :class="fileTypeIconClass">{{ fileTypeIcon }}</v-icon>
<div class="file-name">{{ $sanitize(fileName) }}</div>
<div class="file-size">{{ fileSize }}</div>
2023-10-25 10:44:25 +00:00
</div>
2025-06-09 09:44:49 +02:00
</div>
2023-10-25 10:44:25 +00:00
</template>
2025-06-09 09:44:49 +02:00
<script lang="ts">
2023-12-04 11:29:23 +01:00
import util from "../../plugins/utils";
2025-06-09 09:44:49 +02:00
import { defineComponent } from "vue";
import type { PropType } from 'vue'
import { EventAttachment } from "../../models/eventAttachment";
2023-12-04 11:29:23 +01:00
2025-06-09 09:44:49 +02:00
export default defineComponent({
props: {
/**
* Item is an object of { event: MXEvent, src: URL }
*/
item: {
type: Object as PropType<EventAttachment>,
default: function () {
return {};
},
2023-10-25 10:44:25 +00:00
},
2025-06-09 09:44:49 +02:00
previewOnly: {
type: Boolean,
default: function () {
return false;
},
},
2025-06-09 09:44:49 +02:00
},
computed: {
fileTypeIcon() {
if (util.isFileTypeAPK(this.item.event)) {
if (this.item.event.isChannelMessage) {
return "$vuetify.icons.ic_channel_apk";
}
2025-06-09 09:44:49 +02:00
return "$vuetify.icons.ic_apk";
} else if (util.isFileTypeIPA(this.item.event)) {
return "$vuetify.icons.ic_ipa";
} else if (util.isFileTypePDF(this.item.event)) {
if (this.item.event.isChannelMessage) {
return "$vuetify.icons.ic_channel_pdf";
}
return "$vuetify.icons.ic_pdf";
} else if (util.isFileTypeZip(this.item.event)) {
return "$vuetify.icons.ic_zip";
}
return "description";
},
fileTypeIconClass() {
if (util.isFileTypeZip(this.item.event)) {
return "zip";
}
return undefined;
},
fileName() {
return util.getFileName(this.item.event);
},
2025-06-09 09:44:49 +02:00
fileSize() {
return util.getFileSizeFormatted(this.item.event);
},
},
methods: {
// listen for custom hammerJs singletab click to differentiate it from double click(heart animation).
initThumbnailHammerJs(element: any) {
const hammerInstance = util.singleOrDoubleTabRecognizer(element);
hammerInstance.on("singletap doubletap", (ev: any) => {
if (ev.type === "singletap") {
this.$emit("itemclick", { item: this.item });
}
2025-06-09 09:44:49 +02:00
});
},
2025-06-09 09:44:49 +02:00
},
mounted() {
if (this.$refs.thumbnailRef) {
this.initThumbnailHammerJs(this.$refs.thumbnailRef);
}
},
});
2023-10-25 10:44:25 +00:00
</script>
<style lang="scss">
@use "@/assets/css/chat.scss" as *;
2023-10-25 10:44:25 +00:00
.thumbnail-item {
2025-06-09 09:44:49 +02:00
width: 100%;
height: 100%;
margin: 0;
padding: 0;
2023-10-25 10:44:25 +00:00
}
.file-item {
2025-06-09 09:44:49 +02:00
display: flex;
align-items: center;
justify-content: center;
font-size: 0.6rem;
flex-direction: column;
padding: 20px;
.v-icon {
margin-bottom: 10px;
color: currentColor;
}
2023-10-25 10:44:25 +00:00
}
2025-06-09 09:44:49 +02:00
</style>