reuse preview component, optimize logic
This commit is contained in:
parent
61a5d9a069
commit
04f847042a
@ -52,7 +52,7 @@ export default {
|
||||
lastY: null,
|
||||
inDrag: false,
|
||||
touches: 0,
|
||||
navOffset: 50,
|
||||
navThreshold: 50,
|
||||
lastTouchDistance: 0,
|
||||
moveDisabled: false,
|
||||
disabledTimer: null,
|
||||
@ -92,7 +92,7 @@ export default {
|
||||
const wScale = window.innerWidth / img.clientWidth
|
||||
const hScale = window.innerHeight / img.clientHeight
|
||||
|
||||
this.scale = wScale < hScale? wScale: hScale
|
||||
this.scale = Math.min(wScale, hScale)
|
||||
this.minScale = this.scale
|
||||
this.setZoom()
|
||||
},
|
||||
@ -117,32 +117,31 @@ export default {
|
||||
let x = 0,y = 0
|
||||
|
||||
// left out of viewport
|
||||
if (rect.left < 0 && rect.right < width) x = width - rect.right
|
||||
|
||||
if (rect.left < 0 && rect.right < width) x = Math.min(-rect.left, width - rect.right)
|
||||
// right out of viewport
|
||||
else if (rect.left > 0 && rect.right > width) x = -rect.left
|
||||
else if (rect.left > 0 && rect.right > width) x = Math.min(-rect.left, width - rect.right)
|
||||
|
||||
// top out of viewport
|
||||
if (rect.top < 0 && rect.bottom < height) y = height - rect.bottom
|
||||
if (rect.top < 0 && rect.bottom < height) y = Math.min(-rect.top, height - rect.bottom)
|
||||
|
||||
// bottom out of viewport
|
||||
else if (rect.top > 0 && rect.bottom > height) y = -rect.top
|
||||
else if (rect.top > 0 && rect.bottom > height) y = Math.min(-rect.top, height - rect.bottom)
|
||||
|
||||
return [x,y]
|
||||
}
|
||||
},
|
||||
checkNav(x) {
|
||||
if (this.scale <= this.minScale) {
|
||||
if (x > this.navOffset) this.$root.$emit('gallery-nav', 0)
|
||||
else if (x < -this.navOffset) this.$root.$emit('gallery-nav', 1)
|
||||
if (x > this.navThreshold) this.$root.$emit('gallery-nav', 0)
|
||||
else if (x < -this.navThreshold) this.$root.$emit('gallery-nav', 1)
|
||||
} else {
|
||||
let img = this.$refs.imgex
|
||||
|
||||
const rect = img.getBoundingClientRect()
|
||||
const width = window.innerWidth
|
||||
|
||||
if (rect.left > this.navOffset && rect.right > width + this.navOffset) this.$root.$emit('gallery-nav', 0)
|
||||
else if (rect.left < - this.navOffset && rect.right < width - this.navOffset) this.$root.$emit('gallery-nav', 1)
|
||||
if (x > this.navThreshold && rect.left > this.navThreshold && rect.right > width + this.navThreshold) this.$root.$emit('gallery-nav', 0)
|
||||
else if (x < -this.navThreshold && rect.left < - this.navThreshold && rect.right < width - this.navThreshold) this.$root.$emit('gallery-nav', 1)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
@ -214,18 +213,8 @@ export default {
|
||||
event.preventDefault()
|
||||
},
|
||||
zoomAuto(event) {
|
||||
switch (this.scale) {
|
||||
case 1:
|
||||
this.scale = 2
|
||||
break
|
||||
case 2:
|
||||
this.scale = 4
|
||||
break
|
||||
default:
|
||||
case 4:
|
||||
this.scale = 1
|
||||
break
|
||||
}
|
||||
if (this.minScale <= this.scale && this.scale < 2 * this.minScale) this.scale *= 2
|
||||
else this.scale /= 2
|
||||
this.setZoom()
|
||||
event.preventDefault()
|
||||
},
|
||||
@ -300,6 +289,7 @@ export default {
|
||||
this.scale = this.scale < this.minScale ? this.minScale : this.scale
|
||||
this.scale = this.scale > this.maxScale ? this.maxScale : this.scale
|
||||
this.$refs.imgex.style.transform = `scale(${this.scale})`
|
||||
this.refit()
|
||||
},
|
||||
pxStringToNumber(style) {
|
||||
return +style.replace("px", "")
|
||||
|
||||
@ -1,218 +0,0 @@
|
||||
<template>
|
||||
<div id="previewer">
|
||||
<div class="image-bar">
|
||||
<button @click="back" class="action" :title="$t('files.closePreview')" :aria-label="$t('files.closePreview')" id="close">
|
||||
<i class="material-icons">close</i>
|
||||
</button>
|
||||
|
||||
<div class="title">{{ this.name }}</div>
|
||||
|
||||
<preview-size-button v-if="isResizeEnabled" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
|
||||
<button @click="openMore" id="more" :aria-label="$t('buttons.more')" :title="$t('buttons.more')" class="action">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
|
||||
<div id="dropdown" :class="{ active : showMore }">
|
||||
<rename-button :disabled="loading" v-if="user.perm.rename"></rename-button>
|
||||
<delete-button :disabled="loading" v-if="user.perm.delete"></delete-button>
|
||||
<download-button :disabled="loading" v-if="user.perm.download"></download-button>
|
||||
<info-button :disabled="loading"></info-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="loading" v-if="loading">
|
||||
<div class="spinner">
|
||||
<div class="bounce1"></div>
|
||||
<div class="bounce2"></div>
|
||||
<div class="bounce3"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="action" @click="prev" v-show="hasPrevious" :aria-label="$t('buttons.previous')" :title="$t('buttons.previous')">
|
||||
<i class="material-icons">chevron_left</i>
|
||||
</button>
|
||||
<button class="action" @click="next" v-show="hasNext" :aria-label="$t('buttons.next')" :title="$t('buttons.next')">
|
||||
<i class="material-icons">chevron_right</i>
|
||||
</button>
|
||||
|
||||
<template v-if="!loading">
|
||||
<div class="preview">
|
||||
<ExtendedImage :src="raw"></ExtendedImage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-show="showMore" @click="resetPrompts" class="overlay"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import url from '@/utils/url'
|
||||
import { baseURL, resizePreview } from '@/utils/constants'
|
||||
import { files as api } from '@/api'
|
||||
import PreviewSizeButton from '@/components/buttons/PreviewSize'
|
||||
import InfoButton from '@/components/buttons/Info'
|
||||
import DeleteButton from '@/components/buttons/Delete'
|
||||
import RenameButton from '@/components/buttons/Rename'
|
||||
import DownloadButton from '@/components/buttons/Download'
|
||||
import ExtendedImage from './ExtendedImage'
|
||||
|
||||
export default {
|
||||
name: 'image-preview',
|
||||
components: {
|
||||
PreviewSizeButton,
|
||||
InfoButton,
|
||||
DeleteButton,
|
||||
RenameButton,
|
||||
DownloadButton,
|
||||
ExtendedImage
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
previousLink: '',
|
||||
nextLink: '',
|
||||
listing: null,
|
||||
name: '',
|
||||
fullSize: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['req', 'user', 'oldReq', 'jwt', 'loading', 'show']),
|
||||
hasPrevious () {
|
||||
return (this.previousLink !== '')
|
||||
},
|
||||
hasNext () {
|
||||
return (this.nextLink !== '')
|
||||
},
|
||||
download () {
|
||||
return `${baseURL}/api/raw${url.encodePath(this.req.path)}?auth=${this.jwt}`
|
||||
},
|
||||
previewUrl () {
|
||||
if (!this.fullSize) {
|
||||
return `${baseURL}/api/preview/big${url.encodePath(this.req.path)}?auth=${this.jwt}`
|
||||
}
|
||||
return `${baseURL}/api/raw${url.encodePath(this.req.path)}?auth=${this.jwt}`
|
||||
},
|
||||
raw () {
|
||||
return `${this.previewUrl}&inline=true`
|
||||
},
|
||||
showMore () {
|
||||
return this.$store.state.show === 'more'
|
||||
},
|
||||
isResizeEnabled () {
|
||||
return resizePreview
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route: function () {
|
||||
this.updatePreview()
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
window.addEventListener('keydown', this.key)
|
||||
this.$store.commit('setPreviewMode', true)
|
||||
this.listing = this.oldReq.items
|
||||
this.$root.$on('preview-deleted', this.deleted)
|
||||
this.$root.$on('gallery-nav', this.nav)
|
||||
this.updatePreview()
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.key)
|
||||
this.$store.commit('setPreviewMode', false)
|
||||
this.$root.$off('preview-deleted', this.deleted)
|
||||
this.$root.$off('gallery-nav', this.nav)
|
||||
},
|
||||
methods: {
|
||||
nav(e) {
|
||||
if (e===0 && this.hasPrevious) this.prev()
|
||||
else if (e===1 && this.hasNext) this.next()
|
||||
},
|
||||
deleted () {
|
||||
this.listing = this.listing.filter(item => item.name !== this.name)
|
||||
|
||||
if (this.hasNext) {
|
||||
this.next()
|
||||
} else if (!this.hasPrevious && !this.hasNext) {
|
||||
this.back()
|
||||
} else {
|
||||
this.prev()
|
||||
}
|
||||
},
|
||||
back () {
|
||||
this.$store.commit('setPreviewMode', false)
|
||||
let uri = url.removeLastDir(this.$route.path) + '/'
|
||||
this.$router.push({ path: uri })
|
||||
},
|
||||
prev () {
|
||||
this.$router.push({ path: this.previousLink })
|
||||
},
|
||||
next () {
|
||||
this.$router.push({ path: this.nextLink })
|
||||
},
|
||||
key (event) {
|
||||
|
||||
if (this.show !== null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.which === 13 || event.which === 39) { // right arrow
|
||||
if (this.hasNext) this.next()
|
||||
} else if (event.which === 37) { // left arrow
|
||||
if (this.hasPrevious) this.prev()
|
||||
}
|
||||
},
|
||||
async updatePreview () {
|
||||
if (this.req.subtitles) {
|
||||
this.subtitles = this.req.subtitles.map(sub => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`)
|
||||
}
|
||||
|
||||
let dirs = this.$route.fullPath.split("/")
|
||||
this.name = decodeURIComponent(dirs[dirs.length - 1])
|
||||
|
||||
if (!this.listing) {
|
||||
try {
|
||||
const path = url.removeLastDir(this.$route.path)
|
||||
const res = await api.fetch(path)
|
||||
this.listing = res.items
|
||||
} catch (e) {
|
||||
this.$showError(e)
|
||||
}
|
||||
}
|
||||
|
||||
this.previousLink = ''
|
||||
this.nextLink = ''
|
||||
|
||||
for (let i = 0; i < this.listing.length; i++) {
|
||||
if (this.listing[i].name !== this.name) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
if (this.listing[j].type === 'image') {
|
||||
this.previousLink = this.listing[j].url
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = i + 1; j < this.listing.length; j++) {
|
||||
if (this.listing[j].type === 'image') {
|
||||
this.nextLink = this.listing[j].url
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
},
|
||||
openMore () {
|
||||
this.$store.commit('showHover', 'more')
|
||||
},
|
||||
resetPrompts () {
|
||||
this.$store.commit('closeHovers')
|
||||
},
|
||||
toggleSize () {
|
||||
this.fullSize = !this.fullSize
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div id="previewer">
|
||||
<div class="bar">
|
||||
<div :class="isGallery ? 'gallery-bar' : 'bar'">
|
||||
<button @click="back" class="action" :title="$t('files.closePreview')" :aria-label="$t('files.closePreview')" id="close">
|
||||
<i class="material-icons">close</i>
|
||||
</button>
|
||||
|
||||
<div class="title">{{ this.name }}</div>
|
||||
|
||||
<preview-size-button v-if="isResizeEnabled && this.req.type === 'image'" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
|
||||
<preview-size-button v-if="isResizeEnabled && req.type === 'image'" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
|
||||
<button @click="openMore" id="more" :aria-label="$t('buttons.more')" :title="$t('buttons.more')" class="action">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
@ -37,7 +37,8 @@
|
||||
|
||||
<template v-if="!loading">
|
||||
<div class="preview">
|
||||
<audio v-if="req.type == 'audio'" :src="raw" autoplay controls></audio>
|
||||
<ExtendedImage v-if="isGallery" :src="raw"></ExtendedImage>
|
||||
<audio v-else-if="req.type == 'audio'" :src="raw" autoplay controls></audio>
|
||||
<video v-else-if="req.type == 'video'" :src="raw" autoplay controls>
|
||||
<track
|
||||
kind="captions"
|
||||
@ -70,6 +71,7 @@ import InfoButton from '@/components/buttons/Info'
|
||||
import DeleteButton from '@/components/buttons/Delete'
|
||||
import RenameButton from '@/components/buttons/Rename'
|
||||
import DownloadButton from '@/components/buttons/Download'
|
||||
import ExtendedImage from './ExtendedImage'
|
||||
|
||||
const mediaTypes = [
|
||||
"video",
|
||||
@ -84,7 +86,8 @@ export default {
|
||||
InfoButton,
|
||||
DeleteButton,
|
||||
RenameButton,
|
||||
DownloadButton
|
||||
DownloadButton,
|
||||
ExtendedImage
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
@ -93,7 +96,8 @@ export default {
|
||||
listing: null,
|
||||
name: '',
|
||||
subtitles: [],
|
||||
fullSize: false
|
||||
fullSize: false,
|
||||
isGallery: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -128,19 +132,28 @@ export default {
|
||||
this.updatePreview()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.req.type === 'image') this.isGallery = true
|
||||
},
|
||||
async mounted () {
|
||||
window.addEventListener('keydown', this.key)
|
||||
this.$store.commit('setPreviewMode', true)
|
||||
this.listing = this.oldReq.items
|
||||
this.$root.$on('preview-deleted', this.deleted)
|
||||
if (this.isGallery) this.$root.$on('gallery-nav', this.nav)
|
||||
this.updatePreview()
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.key)
|
||||
this.$store.commit('setPreviewMode', false)
|
||||
this.$root.$off('preview-deleted', this.deleted)
|
||||
if (this.isGallery) this.$root.$off('gallery-nav', this.nav)
|
||||
},
|
||||
methods: {
|
||||
nav(e) {
|
||||
if (e===0 && this.hasPrevious) this.prev()
|
||||
else if (e===1 && this.hasNext) this.next()
|
||||
},
|
||||
deleted () {
|
||||
this.listing = this.listing.filter(item => item.name !== this.name)
|
||||
|
||||
@ -202,14 +215,20 @@ export default {
|
||||
}
|
||||
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
if (mediaTypes.includes(this.listing[j].type)) {
|
||||
if (this.isGallery && this.listing[j].type === 'image') {
|
||||
this.previousLink = this.listing[j].url
|
||||
break
|
||||
} else if (mediaTypes.includes(this.listing[j].type)) {
|
||||
this.previousLink = this.listing[j].url
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = i + 1; j < this.listing.length; j++) {
|
||||
if (mediaTypes.includes(this.listing[j].type)) {
|
||||
if (this.isGallery && this.listing[j].type === 'image') {
|
||||
this.nextLink = this.listing[j].url
|
||||
break
|
||||
} else if (mediaTypes.includes(this.listing[j].type)) {
|
||||
this.nextLink = this.listing[j].url
|
||||
break
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#previewer .image-bar {
|
||||
#previewer .gallery-bar {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
@ -151,15 +151,15 @@
|
||||
transition: opacity 0.1s ease;
|
||||
}
|
||||
|
||||
#previewer .image-bar:hover {
|
||||
#previewer .gallery-bar:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#previewer .image-bar > * {
|
||||
#previewer .gallery-bar > * {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
#previewer .image-bar .title {
|
||||
#previewer .gallery-bar .title {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
padding: 0 1em;
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
<forbidden v-else-if="error.message === '403'"></forbidden>
|
||||
<internal-error v-else></internal-error>
|
||||
</div>
|
||||
<image-preview v-else-if="isImagePreview"></image-preview>
|
||||
<preview v-else-if="isPreview"></preview>
|
||||
<editor v-else-if="isEditor"></editor>
|
||||
<listing :class="{ multiple }" v-else-if="isListing"></listing>
|
||||
@ -33,8 +32,8 @@ import Forbidden from './errors/403'
|
||||
import NotFound from './errors/404'
|
||||
import InternalError from './errors/500'
|
||||
import Preview from '@/components/files/Preview'
|
||||
import ImagePreview from "@/components/files/ImagePreview"
|
||||
import Listing from '@/components/files/Listing'
|
||||
import Editor from '@/components/files/Editor'
|
||||
import { files as api } from '@/api'
|
||||
import { mapGetters, mapState, mapMutations } from 'vuex'
|
||||
|
||||
@ -45,13 +44,12 @@ function clean (path) {
|
||||
export default {
|
||||
name: 'files',
|
||||
components: {
|
||||
ImagePreview,
|
||||
Forbidden,
|
||||
NotFound,
|
||||
InternalError,
|
||||
Preview,
|
||||
Listing,
|
||||
Editor: () => import('@/components/files/Editor')
|
||||
Editor
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
@ -68,11 +66,8 @@ export default {
|
||||
'loading',
|
||||
'show'
|
||||
]),
|
||||
isImagePreview () {
|
||||
return (!this.loading && !this.isListing && !this.isEditor || this.loading && this.$store.state.previewMode) && this.req.type === 'image'
|
||||
},
|
||||
isPreview () {
|
||||
return (!this.loading && !this.isListing && !this.isEditor || this.loading && this.$store.state.previewMode) && this.req.type !== 'image'
|
||||
return !this.loading && !this.isListing && !this.isEditor || this.loading && this.$store.state.previewMode
|
||||
},
|
||||
breadcrumbs () {
|
||||
let parts = this.$route.path.split('/')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user