mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
198 lines
6.5 KiB
Vue
198 lines
6.5 KiB
Vue
<template>
|
|
<div v-if="currentFile" class="absolute top-[56px] left-0 right-0 bottom-0 select-none lg:top-[66px]">
|
|
<!--Arrow navigation-->
|
|
<div v-if="!$isMobile() && files.length > 1" class="">
|
|
<div @click.prevent="prev" class="fixed top-1/2 left-0 z-20 cursor-pointer p-3">
|
|
<chevron-left-icon size="20" />
|
|
</div>
|
|
|
|
<div @click.prevent="next" class="fixed top-1/2 right-0 z-20 cursor-pointer p-3">
|
|
<chevron-right-icon size="20" />
|
|
</div>
|
|
</div>
|
|
|
|
<!--Desktop preview-->
|
|
<div
|
|
v-if="!$isMobile() && (isAudio || isImage || isVideo || isPDF)"
|
|
class="flex h-full w-full items-center justify-center"
|
|
>
|
|
<!--Show PDF-->
|
|
<PdfFile v-if="isPDF" :file="currentFile" />
|
|
|
|
<!--Show Audio, Video and Image-->
|
|
<div class="flex h-full w-full items-center justify-center">
|
|
<Audio v-if="isAudio" :file="currentFile" />
|
|
<Video v-if="isVideo" :file="currentFile" class="mx-auto max-h-full max-w-[1080px] self-center" />
|
|
<ImageFile v-if="isImage" :file="currentFile" class="mx-auto max-h-[100%] max-w-[100%] self-center" />
|
|
</div>
|
|
</div>
|
|
|
|
<!--Mobile Preview-->
|
|
<div
|
|
v-if="$isMobile() && (isAudio || isImage || isVideo || isPDF)"
|
|
@scroll="checkGroupInView"
|
|
id="group-box"
|
|
ref="scrollBox"
|
|
class="flex h-full snap-x snap-mandatory gap-6 overflow-x-auto"
|
|
>
|
|
<div
|
|
v-for="(file, i) in files"
|
|
:key="i"
|
|
:id="`group-${file.data.id}`"
|
|
class="relative flex h-full w-screen shrink-0 snap-center items-center justify-center"
|
|
>
|
|
<ImageFile v-if="isImage" :file="file" class="mx-auto max-h-[100%] max-w-[100%] self-center" />
|
|
<Audio v-if="isAudio" :file="file" />
|
|
<Video v-if="isVideo" :file="file" />
|
|
<PdfFile v-if="isPDF" :file="file" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ChevronLeftIcon, ChevronRightIcon } from 'vue-feather-icons'
|
|
import ToolbarButton from '../FilesView/ToolbarButton'
|
|
import ImageFile from './Media/ImageFile'
|
|
import PdfFile from './Media/PdfFile'
|
|
import Audio from './Media/Audio'
|
|
import Video from './Media/Video'
|
|
import Spinner from '../FilesView/Spinner'
|
|
import { mapGetters } from 'vuex'
|
|
import { events } from '../../bus'
|
|
|
|
export default {
|
|
name: 'FilePreviewMedia',
|
|
components: {
|
|
ChevronRightIcon,
|
|
ChevronLeftIcon,
|
|
ToolbarButton,
|
|
ImageFile,
|
|
PdfFile,
|
|
Spinner,
|
|
Audio,
|
|
Video,
|
|
},
|
|
computed: {
|
|
...mapGetters(['fastPreview', 'clipboard', 'entries']),
|
|
currentFile() {
|
|
return this.fastPreview ? this.fastPreview : this.files[Math.abs(this.currentIndex) % this.files.length]
|
|
},
|
|
isPDF() {
|
|
return this.currentFile.data.attributes.mimetype === 'pdf'
|
|
},
|
|
isVideo() {
|
|
return this.currentFile.data.type === 'video'
|
|
},
|
|
isAudio() {
|
|
return this.currentFile.data.type === 'audio'
|
|
},
|
|
isImage() {
|
|
return this.currentFile.data.type === 'image'
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
currentIndex: 0,
|
|
files: [],
|
|
}
|
|
},
|
|
watch: {
|
|
files() {
|
|
if (this.files.length === 0) events.$emit('file-preview-wrapper:hide')
|
|
},
|
|
currentFile() {
|
|
if (this.clipboard[0]) {
|
|
this.$store.commit('CLIPBOARD_CLEAR')
|
|
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
|
|
}
|
|
},
|
|
clipboard() {
|
|
if (!this.clipboard[0]) {
|
|
this.currentIndex -= 1
|
|
|
|
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
|
|
|
|
this.files = []
|
|
}
|
|
},
|
|
data(newValue, oldValue) {
|
|
if (newValue !== oldValue) {
|
|
this.files = []
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
checkGroupInView: _.debounce(function () {
|
|
this.files.forEach((file, index) => {
|
|
let element = document.getElementById(`group-${file.data.id}`).getBoundingClientRect()
|
|
let scrollBox = document.getElementById('group-box').getBoundingClientRect()
|
|
|
|
// Get video
|
|
const video = document.querySelector(`#group-${file.data.id} video`)
|
|
|
|
// Pause video when playing
|
|
if (video && !video.paused) {
|
|
video.pause()
|
|
}
|
|
|
|
// Check if the group is in the viewport of group-box
|
|
if (element.left === scrollBox.left) {
|
|
this.currentIndex = index
|
|
}
|
|
})
|
|
}, 50),
|
|
getFilesForView() {
|
|
let requestedFile = this.clipboard[0]
|
|
|
|
this.entries.map((element) => {
|
|
if (requestedFile.data.attributes.mimetype === 'pdf') {
|
|
if (element.data.attributes.mimetype === 'pdf') this.files.push(element)
|
|
} else {
|
|
if (element.data.type === requestedFile.data.type) this.files.push(element)
|
|
}
|
|
})
|
|
|
|
this.files.forEach((element, index) => {
|
|
if (element.data.id === this.clipboard[0].data.id) {
|
|
this.currentIndex = index
|
|
}
|
|
})
|
|
|
|
// Scroll to the selected item
|
|
if (this.$isMobile()) {
|
|
this.$nextTick(() => {
|
|
let element = document.getElementById(`group-${this.files[this.currentIndex].data.id}`)
|
|
|
|
this.$refs.scrollBox.scrollLeft = element.getBoundingClientRect().left
|
|
})
|
|
}
|
|
},
|
|
next() {
|
|
if (!this.files.length > 1) return
|
|
|
|
this.currentIndex += 1
|
|
|
|
if (this.currentIndex > this.files.length - 1) {
|
|
this.currentIndex = 0
|
|
}
|
|
},
|
|
prev() {
|
|
if (!this.files.length > 1) return
|
|
|
|
this.currentIndex -= 1
|
|
|
|
if (this.currentIndex < 0) {
|
|
this.currentIndex = this.files.length - 1
|
|
}
|
|
},
|
|
},
|
|
created() {
|
|
events.$on('file-preview:next', () => this.next())
|
|
events.$on('file-preview:prev', () => this.prev())
|
|
|
|
this.getFilesForView()
|
|
},
|
|
}
|
|
</script>
|