Fix gallery view/preview
This commit is contained in:
parent
ae61bf36aa
commit
480ca0b8c0
8 changed files with 259 additions and 29 deletions
143
src/components/file_mode/GalleryItemsView.vue
Normal file
143
src/components/file_mode/GalleryItemsView.vue
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<div class="fill-screen file-drop-root">
|
||||
|
||||
<div class="chat-header">
|
||||
<v-container fluid class="d-flex justify-space-between align-center">
|
||||
<v-icon @click.stop="$emit('close')" color="white" class="clickable">arrow_back</v-icon>
|
||||
<div class="room-name no-upper">{{ displayDate }}</div>
|
||||
<v-icon @click.stop="showMoreMenu = true" color="white" class="clickable">more_vert</v-icon>
|
||||
</v-container>
|
||||
</div>
|
||||
|
||||
<div class="file-drop-current-item">
|
||||
<ThumbnailView :item="items[currentItemIndex]" />
|
||||
<div class="download-button clickable" @click.stop="downloadOne">
|
||||
<v-icon color="black">arrow_downward</v-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-drop-thumbnail-container">
|
||||
<div :class="{ 'file-drop-thumbnail': true, 'clickable': true, 'current': id == currentItemIndex }"
|
||||
@click="currentItemIndex = id" v-for="(currentImageInput, id) in items" :key="id">
|
||||
<v-img v-if="currentImageInput && currentImageInput.src" :src="currentImageInput.src" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MORE MENU POPUP -->
|
||||
<MoreMenuPopup :show="showMoreMenu" :menuItems="moreMenuItems" :showProfile="false" @close="showMoreMenu = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MoreMenuPopup from "../MoreMenuPopup";
|
||||
import messageMixin from "../messages/messageMixin";
|
||||
import util from "../../plugins/utils";
|
||||
import ThumbnailView from './ThumbnailView.vue';
|
||||
|
||||
export default {
|
||||
mixins: [messageMixin],
|
||||
components: { MoreMenuPopup, ThumbnailView },
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
initialItem: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentItemIndex: 0,
|
||||
showMoreMenu: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
document.body.classList.add("dark");
|
||||
if (this.initialItem) {
|
||||
this.currentItemIndex = this.items.findIndex((v) => v === this.initialItem);
|
||||
if (this.currentItemIndex < 0) {
|
||||
this.currentItemIndex = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.body.classList.remove("dark");
|
||||
},
|
||||
computed: {
|
||||
displayDate() {
|
||||
return util.formatRecordStartTime(this.originalEvent.getTs())
|
||||
},
|
||||
moreMenuItems() {
|
||||
let items = [];
|
||||
items.push({
|
||||
icon: '$vuetify.icons.ic_download', text: this.$t("message.download_all"), handler: () => {
|
||||
this.downloadAll();
|
||||
}
|
||||
});
|
||||
return items;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
items(newValue, oldValue) {
|
||||
// Added or removed?
|
||||
if (newValue && oldValue && newValue.length > oldValue.length) {
|
||||
this.currentItemIndex = oldValue.length;
|
||||
} else if (newValue) {
|
||||
this.currentItemIndex = newValue.length - 1;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
downloadOne() {
|
||||
if (this.currentItemIndex >= 0 && this.currentItemIndex < this.items.length) {
|
||||
util.download(this.$matrix.matrixClient, this.items[this.currentItemIndex].event);
|
||||
}
|
||||
},
|
||||
downloadAll() {
|
||||
this.items.forEach(item => util.download(this.$matrix.matrixClient, item.event));
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
|
||||
.chat-header {
|
||||
position: relative !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-drop-current-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.download-button {
|
||||
position: absolute;
|
||||
right: 21px;
|
||||
bottom: 21px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius: 17px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.fill-screen {
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: black;
|
||||
z-index: 20;
|
||||
justify-content: space-between !important;
|
||||
}
|
||||
</style>
|
||||
61
src/components/file_mode/ThumbnailView.vue
Normal file
61
src/components/file_mode/ThumbnailView.vue
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<v-responsive v-if="item.event.getContent().msgtype == 'm.video'" :class="{'thumbnail-item': true, 'preview': previewOnly}"
|
||||
@click.stop="$emit('itemclick', {item: item})">
|
||||
<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'" :aspect-ratio="previewOnly ? (16 / 9) : undefined" :class="{'thumbnail-item': true, 'preview': previewOnly}" :src="item.src" :contain="!previewOnly" :cover="previewOnly"
|
||||
@click.stop="$emit('itemclick', {item: item})" />
|
||||
<div v-else :class="{'thumbnail-item': true, 'preview': previewOnly, 'file-item': true}" @click.stop="$emit('itemclick', {item: item})">
|
||||
<v-icon>description</v-icon>
|
||||
{{ $sanitize(item.event.getContent().body) }}
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* Item is an object of { event: MXEvent, src: URL }
|
||||
*/
|
||||
item: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
previewOnly: {
|
||||
type: Boolean,
|
||||
default: function() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
|
||||
.thumbnail-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.6rem;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
.v-icon {
|
||||
margin-bottom: 10px;
|
||||
color: currentColor;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue