diff --git a/app/src/Download.vue b/app/src/Download.vue
index 9043de8..6cace9f 100644
--- a/app/src/Download.vue
+++ b/app/src/Download.vue
@@ -41,24 +41,15 @@
clipboard.btn.btn-sm.btn-default(:value='host + file.url', @change='copied(file, $event)', title='Copy to clipboard', style='margin: 0 5px')
a
i.fa.fa-fw.fa-copy
- a.btn.btn-sm.btn-default(title="Preview", @click.prevent.stop="preview=file", v-if="getPreviewType(file)")
+ a.btn.btn-sm.btn-default(title="Preview", @click.prevent.stop="preview=file", v-if="file.previewType")
i.fa.fa-fw.fa-eye
p
strong {{ file.metadata.name }}
small(v-if="Number.isFinite(file.size)", style="margin-left:15px") ({{ humanFileSize(file.size) }})
p {{ file.metadata.comment }}
- modal(v-if="preview", @close="preview=false", :has-header="true")
- h4(slot="header") {{preview.metadata.name}}
- div(slot="body")
- div(v-if="getPreviewType(preview) === 'image'", style="text-align:center")
- img(:src="preview.url", style="max-width: 100%; height:auto")
- div(v-if="getPreviewType(preview) === 'text'")
- a.btn.btn-sm(style="position:absolute; right:5px; top:-30px;", title="toggle line wrap", @click="lineWrap = !lineWrap", :class="{active:lineWrap}")
- i.fa.fa-fw.fa-rotate-left.fa-flip-vertical
- pre(:style="{'white-space':lineWrap?'pre-wrap':'pre'}") {{ previewText }}
- p(v-if="getPreviewType(preview) === false", style="text-align:center")
- strong.text-danger No preview available
+ preview-modal(:preview="preview", :files="previewFiles", :max-size="config.maxPreviewSize", @close="preview=false")
+
@@ -70,11 +61,25 @@
import FileIcon from './common/FileIcon.vue';
import Clipboard from './common/Clipboard.vue';
- import Modal from './common/Modal.vue';
+ import PreviewModal from './Download/PreviewModal.vue';
+
+ function getPreviewType(file, maxSize) {
+ if(!file || !file.metadata) return false;
+ if(file.metadata.retention === 'one-time') return false;
+ // no preview for files size > 2MB
+ if(file.size > maxSize) return false;
+ if(file.metadata.type && file.metadata.type.startsWith('image/')) return 'image';
+ else if(file.metadata.type && file.metadata.type.match(/(text\/|xml|json|javascript|x-sh)/)
+ || file.metadata.name && file.metadata.name
+ .match(/\.(jsx|vue|sh|pug|less|scss|sass|c|h|conf|log|bat|cmd|lua|class|java|py|php|yml|sql|md)$/)) {
+ return 'text';
+ }
+ return false;
+ }
export default {
name: 'app',
- components: { FileIcon, Clipboard, Modal },
+ components: { FileIcon, Clipboard, PreviewModal },
data () {
return {
files: [],
@@ -86,53 +91,21 @@
error: '',
host: document.location.protocol + '//' + document.location.host,
config: {},
- preview: false,
- previewText: '',
- lineWrap: false
- }
- },
-
- watch: {
- preview: function(preview, old) {
- if(this.getPreviewType(preview) !== 'text' || preview === old) return;
- this.getPreviewText();
+ preview: false
}
},
computed: {
downloadsAvailable: function() {
return this.files.filter(f => !f.downloaded || f.metadata.retention !== 'one-time').length > 0
+ },
+ previewFiles: function() {
+ return this.files.filter(f => !!f.previewType);
}
+
},
methods: {
- getPreviewType(file) {
- if(!file || !file.metadata) return false;
- if(file.metadata.retention === 'one-time') return false;
- // no preview for files size > 2MB
- if(file.size > this.config.maxPreviewSize) return false;
- if(file.metadata.type && file.metadata.type.startsWith('image/')) return 'image';
- else if(file.metadata.type && file.metadata.type.match(/(text\/|xml|json|javascript|x-sh)/)
- || file.metadata.name && file.metadata.name
- .match(/\.(jsx|vue|sh|pug|less|scss|sass|c|h|conf|log|bat|cmd|lua|class|java|py|php|yml|sql)$/)) {
- return 'text';
- }
- return false;
- },
- getPreviewText() {
- this.previewText = '';
- const xhr = new XMLHttpRequest();
- xhr.open('GET', '//' + document.location.host + this.preview.url);
- xhr.onload = () => {
- if(xhr.status === 200) {
- this.previewText = xhr.responseText
- } else {
- this.previewText = `${xhr.status} ${xhr.statusText}: ${xhr.responseText}`;
- }
- };
- xhr.send();
- },
-
download(file) {
if(file.downloaded && file.metadata.retention === 'one-time') {
alert('One-Time Download: File is not available anymore.');
@@ -210,7 +183,10 @@
this.needsPassword = true;
return f;
}
- return Object.assign(f, {downloaded: false});
+ return Object.assign(f, {
+ downloaded: false,
+ previewType: getPreviewType(f, this.config.maxPreviewSize)
+ });
});
} catch(e) {
this.error = e.toString();
diff --git a/app/src/Download/PreviewModal.vue b/app/src/Download/PreviewModal.vue
new file mode 100644
index 0000000..4c60893
--- /dev/null
+++ b/app/src/Download/PreviewModal.vue
@@ -0,0 +1,81 @@
+
+ modal(v-if="current", @close="current=false", :has-header="true", @next="next", @prev="prev")
+ div(slot="header")
+ p
+ strong {{current.metadata.name}}
+ div
+ small {{currentIndex+1}} / {{files.length}}
+ span.btn-group(style="margin-left: 15px")
+ a.btn.btn-sm.btn-default(title="previous", @click="prev", v-show="currentIndex > 0")
+ i.fa.fa-fw.fa-arrow-left
+ a.btn.btn-sm.btn-default(title="next", @click="next", v-show="currentIndex < files.length-1")
+ i.fa.fa-fw.fa-arrow-right
+ a.btn.btn-sm.btn-default(title="toggle line wrap", @click="lineWrap = !lineWrap", :class="{active:lineWrap}", v-show="current.previewType === 'text'")
+ i.fa.fa-fw.fa-rotate-left.fa-flip-vertical
+ div(slot="body")
+ div(v-if="current.previewType === 'image'", style="text-align:center")
+ img(:src="current.url", style="max-width: 100%; height:auto")
+ div(v-if="current.previewType === 'text'")
+ pre(:style="{'white-space':lineWrap?'pre-wrap':'pre'}") {{ previewText }}
+ p(v-if="current.previewType === false", style="text-align:center")
+ strong.text-danger No preview available
+
+
+
+
diff --git a/app/src/common/Modal.vue b/app/src/common/Modal.vue
index f933e99..bed819c 100644
--- a/app/src/common/Modal.vue
+++ b/app/src/common/Modal.vue
@@ -1,5 +1,5 @@
- .modal.fade.in.background-darken(ref='modal', style="display:block", tabindex='-1', role='dialog', @click.self='close()', @keyup.esc='close()')
+ .modal.fade.in.background-darken(ref='modal', style="display:block", tabindex='-1', role='dialog', @click.self='close()', @keyup.esc='close()', @keyup.left="$emit('prev')", @keyup.right="$emit('next')")
.modal-dialog.modal-fluid(role='document')
.modal-content
.modal-header(v-if='hasHeader')
@@ -26,11 +26,6 @@
}
},
- data() {
- return {
- }
- },
-
mounted() {
this.$nextTick(function() {
this.$refs.modal.focus();