commit
84e3a98303
|
@ -170,7 +170,7 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
|
||||||
case strings.HasPrefix(mimetype, "image"):
|
case strings.HasPrefix(mimetype, "image"):
|
||||||
i.Type = "image"
|
i.Type = "image"
|
||||||
return nil
|
return nil
|
||||||
case (strings.HasPrefix(mimetype, "text") || (len(buffer) > 0 && !isBinary(buffer))) && i.Size <= 10*1024*1024: // 10 MB
|
case (strings.HasPrefix(mimetype, "text") || !isBinary(buffer)) && i.Size <= 10*1024*1024: // 10 MB
|
||||||
i.Type = "text"
|
i.Type = "text"
|
||||||
|
|
||||||
if !modify {
|
if !modify {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -29,14 +29,6 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 200,
|
default: () => 200,
|
||||||
},
|
},
|
||||||
maxScale: {
|
|
||||||
type: Number,
|
|
||||||
default: () => 4,
|
|
||||||
},
|
|
||||||
minScale: {
|
|
||||||
type: Number,
|
|
||||||
default: () => 0.25,
|
|
||||||
},
|
|
||||||
classList: {
|
classList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
|
@ -45,10 +37,6 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 0.25,
|
default: () => 0.25,
|
||||||
},
|
},
|
||||||
autofill: {
|
|
||||||
type: Boolean,
|
|
||||||
default: () => false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -64,6 +52,8 @@ export default {
|
||||||
center: { x: 0, y: 0 },
|
center: { x: 0, y: 0 },
|
||||||
relative: { x: 0, y: 0 },
|
relative: { x: 0, y: 0 },
|
||||||
},
|
},
|
||||||
|
maxScale: 4,
|
||||||
|
minScale: 0.25,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -88,6 +78,10 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
src: function () {
|
src: function () {
|
||||||
|
if (!this.decodeUTIF()) {
|
||||||
|
this.$refs.imgex.src = this.src;
|
||||||
|
}
|
||||||
|
|
||||||
this.scale = 1;
|
this.scale = 1;
|
||||||
this.setZoom();
|
this.setZoom();
|
||||||
this.setCenter();
|
this.setCenter();
|
||||||
|
@ -122,6 +116,21 @@ export default {
|
||||||
img.classList.add("image-ex-img-ready");
|
img.classList.add("image-ex-img-ready");
|
||||||
|
|
||||||
document.addEventListener("mouseup", this.onMouseUp);
|
document.addEventListener("mouseup", this.onMouseUp);
|
||||||
|
|
||||||
|
let realSize = img.naturalWidth;
|
||||||
|
let displaySize = img.offsetWidth;
|
||||||
|
|
||||||
|
// Image is in portrait orientation
|
||||||
|
if (img.naturalHeight > img.naturalWidth) {
|
||||||
|
realSize = img.naturalHeight;
|
||||||
|
displaySize = img.offsetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale needed to display the image on full size
|
||||||
|
const fullScale = realSize / displaySize;
|
||||||
|
|
||||||
|
// Full size plus additional zoom
|
||||||
|
this.maxScale = fullScale + 4;
|
||||||
},
|
},
|
||||||
onMouseUp() {
|
onMouseUp() {
|
||||||
this.inDrag = false;
|
this.inDrag = false;
|
||||||
|
@ -251,7 +260,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
wheelMove(event) {
|
wheelMove(event) {
|
||||||
this.scale += (event.wheelDeltaY / 100) * this.zoomStep;
|
this.scale += -Math.sign(event.deltaY) * this.zoomStep;
|
||||||
this.setZoom();
|
this.setZoom();
|
||||||
},
|
},
|
||||||
setZoom() {
|
setZoom() {
|
||||||
|
|
|
@ -56,6 +56,12 @@ export default {
|
||||||
|
|
||||||
let prompt = this.$refs.currentComponent;
|
let prompt = this.$refs.currentComponent;
|
||||||
|
|
||||||
|
// Esc!
|
||||||
|
if (event.keyCode === 27) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
this.$store.commit("closeHovers");
|
||||||
|
}
|
||||||
|
|
||||||
// Enter
|
// Enter
|
||||||
if (event.keyCode == 13) {
|
if (event.keyCode == 13) {
|
||||||
switch (this.show) {
|
switch (this.show) {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.share__box__info {
|
.share__box__info {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 18em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share__box__element {
|
.share__box__element {
|
||||||
|
|
|
@ -110,4 +110,60 @@
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-cyrillic-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-cyrillic.woff2) format('woff2');
|
||||||
|
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-greek-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+1F00-1FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-greek.woff2) format('woff2');
|
||||||
|
unicode-range: U+0370-03FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-vietnamese.woff2) format('woff2');
|
||||||
|
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
|
}
|
||||||
|
|
||||||
@import "~material-design-icons/iconfont/material-icons.css";
|
@import "~material-design-icons/iconfont/material-icons.css";
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
transition: .1s ease background, .1s ease opacity;
|
transition: .1s ease background, .1s ease opacity;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#listing .item div:last-of-type {
|
#listing .item div:last-of-type {
|
||||||
|
|
|
@ -109,6 +109,7 @@
|
||||||
|
|
||||||
#previewer {
|
#previewer {
|
||||||
background-color: rgba(0, 0, 0, 0.9);
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
padding-top: 4em;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -142,7 +143,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#previewer .preview {
|
#previewer .preview {
|
||||||
margin-top: 4em;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: calc(100vh - 4em);
|
height: calc(100vh - 4em);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@
|
||||||
#editor-container {
|
#editor-container {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin-top: 4em;
|
padding-top: 4em;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<header-bar v-if="error || !req.type" showMenu showLogo />
|
<header-bar v-if="error || req.type == null" showMenu showLogo />
|
||||||
|
|
||||||
<breadcrumbs base="/files" />
|
<breadcrumbs base="/files" />
|
||||||
|
|
||||||
|
@ -124,15 +124,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
keyEvent(event) {
|
keyEvent(event) {
|
||||||
if (this.show !== null) {
|
|
||||||
// Esc!
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
this.$store.commit("closeHovers");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// F1!
|
// F1!
|
||||||
if (event.keyCode === 112) {
|
if (event.keyCode === 112) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -10,26 +10,22 @@
|
||||||
{{ $t("settings.profileSettings") }}
|
{{ $t("settings.profileSettings") }}
|
||||||
</li></router-link
|
</li></router-link
|
||||||
>
|
>
|
||||||
<router-link to="/settings/shares"
|
<router-link to="/settings/shares" v-if="user.perm.share"
|
||||||
><li :class="{ active: $route.path === '/settings/shares' }">
|
><li :class="{ active: $route.path === '/settings/shares' }">
|
||||||
{{ $t("settings.shareManagement") }}
|
{{ $t("settings.shareManagement") }}
|
||||||
</li></router-link
|
</li></router-link
|
||||||
>
|
>
|
||||||
<router-link to="/settings/global"
|
<router-link to="/settings/global" v-if="user.perm.admin"
|
||||||
><li
|
><li :class="{ active: $route.path === '/settings/global' }">
|
||||||
:class="{ active: $route.path === '/settings/global' }"
|
|
||||||
v-if="user.perm.admin"
|
|
||||||
>
|
|
||||||
{{ $t("settings.globalSettings") }}
|
{{ $t("settings.globalSettings") }}
|
||||||
</li></router-link
|
</li></router-link
|
||||||
>
|
>
|
||||||
<router-link to="/settings/users"
|
<router-link to="/settings/users" v-if="user.perm.admin"
|
||||||
><li
|
><li
|
||||||
:class="{
|
:class="{
|
||||||
active:
|
active:
|
||||||
$route.path === '/settings/users' || $route.name === 'User',
|
$route.path === '/settings/users' || $route.name === 'User',
|
||||||
}"
|
}"
|
||||||
v-if="user.perm.admin"
|
|
||||||
>
|
>
|
||||||
{{ $t("settings.userManagement") }}
|
{{ $t("settings.userManagement") }}
|
||||||
</li></router-link
|
</li></router-link
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<action
|
<action
|
||||||
|
v-if="user.perm.modify"
|
||||||
id="save-button"
|
id="save-button"
|
||||||
icon="save"
|
icon="save"
|
||||||
:label="$t('buttons.save')"
|
:label="$t('buttons.save')"
|
||||||
|
|
|
@ -25,18 +25,21 @@
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
v-if="headerButtons.copy"
|
v-if="headerButtons.copy"
|
||||||
|
id="copy-button"
|
||||||
icon="content_copy"
|
icon="content_copy"
|
||||||
:label="$t('buttons.copyFile')"
|
:label="$t('buttons.copyFile')"
|
||||||
show="copy"
|
show="copy"
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
v-if="headerButtons.move"
|
v-if="headerButtons.move"
|
||||||
|
id="move-button"
|
||||||
icon="forward"
|
icon="forward"
|
||||||
:label="$t('buttons.moveFile')"
|
:label="$t('buttons.moveFile')"
|
||||||
show="move"
|
show="move"
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
v-if="headerButtons.delete"
|
v-if="headerButtons.delete"
|
||||||
|
id="delete-button"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
:label="$t('buttons.delete')"
|
:label="$t('buttons.delete')"
|
||||||
show="delete"
|
show="delete"
|
||||||
|
@ -55,13 +58,16 @@
|
||||||
@action="switchView"
|
@action="switchView"
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
|
v-if="headerButtons.download"
|
||||||
icon="file_download"
|
icon="file_download"
|
||||||
:label="$t('buttons.download')"
|
:label="$t('buttons.download')"
|
||||||
@action="download"
|
@action="download"
|
||||||
:counter="selectedCount"
|
:counter="selectedCount"
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
|
v-if="headerButtons.upload"
|
||||||
icon="file_upload"
|
icon="file_upload"
|
||||||
|
id="upload-button"
|
||||||
:label="$t('buttons.upload')"
|
:label="$t('buttons.upload')"
|
||||||
@action="upload"
|
@action="upload"
|
||||||
/>
|
/>
|
||||||
|
@ -135,7 +141,7 @@
|
||||||
multiple
|
multiple
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else id="listing" :class="user.viewMode">
|
<div v-else id="listing" ref="listing" :class="user.viewMode">
|
||||||
<div>
|
<div>
|
||||||
<div class="item header">
|
<div class="item header">
|
||||||
<div></div>
|
<div></div>
|
||||||
|
@ -253,6 +259,7 @@ import { users, files as api } from "@/api";
|
||||||
import { enableExec } from "@/utils/constants";
|
import { enableExec } from "@/utils/constants";
|
||||||
import * as upload from "@/utils/upload";
|
import * as upload from "@/utils/upload";
|
||||||
import css from "@/utils/css";
|
import css from "@/utils/css";
|
||||||
|
import throttle from "lodash.throttle";
|
||||||
|
|
||||||
import HeaderBar from "@/components/header/HeaderBar";
|
import HeaderBar from "@/components/header/HeaderBar";
|
||||||
import Action from "@/components/header/Action";
|
import Action from "@/components/header/Action";
|
||||||
|
@ -350,15 +357,31 @@ export default {
|
||||||
return this.width <= 736;
|
return this.width <= 736;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
req: function () {
|
||||||
|
// Reset the show value
|
||||||
|
this.showLimit = 50;
|
||||||
|
|
||||||
|
// Fill and fit the window with listing items
|
||||||
|
this.fillWindow(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
// Check the columns size for the first time.
|
// Check the columns size for the first time.
|
||||||
this.resizeEvent();
|
this.colunmsResize();
|
||||||
|
|
||||||
|
// How much every listing item affects the window height
|
||||||
|
this.setItemWeight();
|
||||||
|
|
||||||
|
// Fill and fit the window with listing items
|
||||||
|
this.fillWindow(true);
|
||||||
|
|
||||||
// Add the needed event listeners to the window and document.
|
// Add the needed event listeners to the window and document.
|
||||||
window.addEventListener("keydown", this.keyEvent);
|
window.addEventListener("keydown", this.keyEvent);
|
||||||
window.addEventListener("resize", this.resizeEvent);
|
|
||||||
window.addEventListener("scroll", this.scrollEvent);
|
window.addEventListener("scroll", this.scrollEvent);
|
||||||
window.addEventListener("resize", this.windowsResize);
|
window.addEventListener("resize", this.windowsResize);
|
||||||
|
|
||||||
|
if (!this.user.perm.create) return;
|
||||||
document.addEventListener("dragover", this.preventDefault);
|
document.addEventListener("dragover", this.preventDefault);
|
||||||
document.addEventListener("dragenter", this.dragEnter);
|
document.addEventListener("dragenter", this.dragEnter);
|
||||||
document.addEventListener("dragleave", this.dragLeave);
|
document.addEventListener("dragleave", this.dragLeave);
|
||||||
|
@ -367,9 +390,10 @@ export default {
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
// Remove event listeners before destroying this page.
|
// Remove event listeners before destroying this page.
|
||||||
window.removeEventListener("keydown", this.keyEvent);
|
window.removeEventListener("keydown", this.keyEvent);
|
||||||
window.removeEventListener("resize", this.resizeEvent);
|
|
||||||
window.removeEventListener("scroll", this.scrollEvent);
|
window.removeEventListener("scroll", this.scrollEvent);
|
||||||
window.removeEventListener("resize", this.windowsResize);
|
window.removeEventListener("resize", this.windowsResize);
|
||||||
|
|
||||||
|
if (!this.user.perm.create) return;
|
||||||
document.removeEventListener("dragover", this.preventDefault);
|
document.removeEventListener("dragover", this.preventDefault);
|
||||||
document.removeEventListener("dragenter", this.dragEnter);
|
document.removeEventListener("dragenter", this.dragEnter);
|
||||||
document.removeEventListener("dragleave", this.dragLeave);
|
document.removeEventListener("dragleave", this.dragLeave);
|
||||||
|
@ -543,7 +567,7 @@ export default {
|
||||||
|
|
||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
},
|
||||||
resizeEvent() {
|
colunmsResize() {
|
||||||
// Update the columns size based on the window width.
|
// Update the columns size based on the window width.
|
||||||
let columns = Math.floor(
|
let columns = Math.floor(
|
||||||
document.querySelector("main").offsetWidth / 300
|
document.querySelector("main").offsetWidth / 300
|
||||||
|
@ -552,11 +576,27 @@ export default {
|
||||||
if (columns === 0) columns = 1;
|
if (columns === 0) columns = 1;
|
||||||
items.style.width = `calc(${100 / columns}% - 1em)`;
|
items.style.width = `calc(${100 / columns}% - 1em)`;
|
||||||
},
|
},
|
||||||
scrollEvent() {
|
scrollEvent: throttle(function () {
|
||||||
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
|
const totalItems = this.req.numDirs + this.req.numFiles;
|
||||||
this.showLimit += 50;
|
|
||||||
|
// All items are displayed
|
||||||
|
if (this.showLimit >= totalItems) return;
|
||||||
|
|
||||||
|
const currentPos = window.innerHeight + window.scrollY;
|
||||||
|
|
||||||
|
// Trigger at the 75% of the window height
|
||||||
|
const triggerPos = document.body.offsetHeight - window.innerHeight * 0.25;
|
||||||
|
|
||||||
|
if (currentPos > triggerPos) {
|
||||||
|
// Quantity of items needed to fill 2x of the window height
|
||||||
|
const showQuantity = Math.ceil(
|
||||||
|
(window.innerHeight * 2) / this.itemWeight
|
||||||
|
);
|
||||||
|
|
||||||
|
// Increase the number of displayed items
|
||||||
|
this.showLimit += showQuantity;
|
||||||
}
|
}
|
||||||
},
|
}, 100),
|
||||||
dragEnter() {
|
dragEnter() {
|
||||||
this.dragCounter++;
|
this.dragCounter++;
|
||||||
|
|
||||||
|
@ -707,9 +747,19 @@ export default {
|
||||||
this.$store.commit("multiple", !this.multiple);
|
this.$store.commit("multiple", !this.multiple);
|
||||||
this.$store.commit("closeHovers");
|
this.$store.commit("closeHovers");
|
||||||
},
|
},
|
||||||
windowsResize() {
|
windowsResize: throttle(function () {
|
||||||
|
this.colunmsResize();
|
||||||
this.width = window.innerWidth;
|
this.width = window.innerWidth;
|
||||||
},
|
|
||||||
|
// Listing element is not displayed
|
||||||
|
if (this.$refs.listing == null) return;
|
||||||
|
|
||||||
|
// How much every listing item affects the window height
|
||||||
|
this.setItemWeight();
|
||||||
|
|
||||||
|
// Fill but not fit the window
|
||||||
|
this.fillWindow();
|
||||||
|
}, 100),
|
||||||
download() {
|
download() {
|
||||||
if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) {
|
if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) {
|
||||||
api.download(null, this.req.items[this.selected[0]].url);
|
api.download(null, this.req.items[this.selected[0]].url);
|
||||||
|
@ -745,7 +795,12 @@ export default {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await users.update(data, ["viewMode"]);
|
await users.update(data, ["viewMode"]);
|
||||||
this.$store.commit("updateUser", data);
|
|
||||||
|
// Await ensures correct value for setItemWeight()
|
||||||
|
await this.$store.commit("updateUser", data);
|
||||||
|
|
||||||
|
this.setItemWeight();
|
||||||
|
this.fillWindow();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showError(e);
|
this.$showError(e);
|
||||||
}
|
}
|
||||||
|
@ -757,6 +812,32 @@ export default {
|
||||||
document.getElementById("upload-input").click();
|
document.getElementById("upload-input").click();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setItemWeight() {
|
||||||
|
let itemQuantity = this.req.numDirs + this.req.numFiles;
|
||||||
|
if (itemQuantity > this.showLimit) itemQuantity = this.showLimit;
|
||||||
|
|
||||||
|
// How much every listing item affects the window height
|
||||||
|
this.itemWeight = this.$refs.listing.offsetHeight / itemQuantity;
|
||||||
|
},
|
||||||
|
fillWindow(fit = false) {
|
||||||
|
const totalItems = this.req.numDirs + this.req.numFiles;
|
||||||
|
|
||||||
|
// More items are displayed than the total
|
||||||
|
if (this.showLimit >= totalItems && !fit) return;
|
||||||
|
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// Quantity of items needed to fill 2x of the window height
|
||||||
|
const showQuantity = Math.ceil(
|
||||||
|
(windowHeight + windowHeight * 2) / this.itemWeight
|
||||||
|
);
|
||||||
|
|
||||||
|
// Less items to display than current
|
||||||
|
if (this.showLimit > showQuantity && !fit) return;
|
||||||
|
|
||||||
|
// Set the number of displayed items
|
||||||
|
this.showLimit = showQuantity > totalItems ? totalItems : showQuantity;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,12 +17,14 @@
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<action
|
<action
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
|
v-if="user.perm.rename"
|
||||||
icon="mode_edit"
|
icon="mode_edit"
|
||||||
:label="$t('buttons.rename')"
|
:label="$t('buttons.rename')"
|
||||||
show="rename"
|
show="rename"
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
|
v-if="user.perm.delete"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
:label="$t('buttons.delete')"
|
:label="$t('buttons.delete')"
|
||||||
@action="deleteFile"
|
@action="deleteFile"
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
/>
|
/>
|
||||||
<action
|
<action
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
|
v-if="user.perm.download"
|
||||||
icon="file_download"
|
icon="file_download"
|
||||||
:label="$t('buttons.download')"
|
:label="$t('buttons.download')"
|
||||||
@action="download"
|
@action="download"
|
||||||
|
@ -54,8 +57,22 @@
|
||||||
<template v-if="!loading">
|
<template v-if="!loading">
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
<ExtendedImage v-if="req.type == 'image'" :src="raw"></ExtendedImage>
|
<ExtendedImage v-if="req.type == 'image'" :src="raw"></ExtendedImage>
|
||||||
<audio v-else-if="req.type == 'audio'" :src="raw" controls></audio>
|
<audio
|
||||||
<video v-else-if="req.type == 'video'" :src="raw" controls>
|
v-else-if="req.type == 'audio'"
|
||||||
|
ref="player"
|
||||||
|
:src="raw"
|
||||||
|
controls
|
||||||
|
:autoplay="autoPlay"
|
||||||
|
@play="autoPlay = true"
|
||||||
|
></audio>
|
||||||
|
<video
|
||||||
|
v-else-if="req.type == 'video'"
|
||||||
|
ref="player"
|
||||||
|
:src="raw"
|
||||||
|
controls
|
||||||
|
:autoplay="autoPlay"
|
||||||
|
@play="autoPlay = true"
|
||||||
|
>
|
||||||
<track
|
<track
|
||||||
kind="captions"
|
kind="captions"
|
||||||
v-for="(sub, index) in subtitles"
|
v-for="(sub, index) in subtitles"
|
||||||
|
@ -136,6 +153,7 @@ export default {
|
||||||
showNav: true,
|
showNav: true,
|
||||||
navTimeout: null,
|
navTimeout: null,
|
||||||
hoverNav: false,
|
hoverNav: false,
|
||||||
|
autoPlay: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -230,6 +248,14 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async updatePreview() {
|
async updatePreview() {
|
||||||
|
if (
|
||||||
|
this.$refs.player &&
|
||||||
|
this.$refs.player.paused &&
|
||||||
|
!this.$refs.player.ended
|
||||||
|
) {
|
||||||
|
this.autoPlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.req.subtitles) {
|
if (this.req.subtitles) {
|
||||||
this.subtitles = this.req.subtitles.map(
|
this.subtitles = this.req.subtitles.map(
|
||||||
(sub) => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`
|
(sub) => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`
|
||||||
|
|
12
http/raw.go
12
http/raw.go
|
@ -181,14 +181,14 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files.
|
||||||
|
|
||||||
commonDir := fileutils.CommonPrefix(filepath.Separator, filenames...)
|
commonDir := fileutils.CommonPrefix(filepath.Separator, filenames...)
|
||||||
|
|
||||||
var name string
|
name := filepath.Base(commonDir)
|
||||||
if len(filenames) > 1 {
|
if name == "." || name == "" || name == string(filepath.Separator) {
|
||||||
name = "_" + filepath.Base(commonDir)
|
|
||||||
} else {
|
|
||||||
name = file.Name
|
name = file.Name
|
||||||
}
|
}
|
||||||
if name == "." || name == "" {
|
// Prefix used to distinguish a filelist generated
|
||||||
name = "archive"
|
// archive from the full directory archive
|
||||||
|
if len(filenames) > 1 {
|
||||||
|
name = "_" + name
|
||||||
}
|
}
|
||||||
name += extension
|
name += extension
|
||||||
w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
|
w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
|
||||||
|
|
|
@ -118,6 +118,11 @@ func resourcePostHandler(fileCache FileCache) handleFunc {
|
||||||
return http.StatusConflict, nil
|
return http.StatusConflict, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permission for overwriting the file
|
||||||
|
if !d.user.Perm.Modify {
|
||||||
|
return http.StatusForbidden, nil
|
||||||
|
}
|
||||||
|
|
||||||
err = delThumbs(r.Context(), fileCache, file)
|
err = delThumbs(r.Context(), fileCache, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
|
@ -125,7 +130,10 @@ func resourcePostHandler(fileCache FileCache) handleFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.RunHook(func() error {
|
err = d.RunHook(func() error {
|
||||||
info, _ := writeFile(d.user.Fs, r.URL.Path, r.Body)
|
info, writeErr := writeFile(d.user.Fs, r.URL.Path, r.Body)
|
||||||
|
if writeErr != nil {
|
||||||
|
return writeErr
|
||||||
|
}
|
||||||
|
|
||||||
etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size())
|
etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size())
|
||||||
w.Header().Set("ETag", etag)
|
w.Header().Set("ETag", etag)
|
||||||
|
@ -155,7 +163,10 @@ var resourcePutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
|
||||||
}
|
}
|
||||||
|
|
||||||
err := d.RunHook(func() error {
|
err := d.RunHook(func() error {
|
||||||
info, _ := writeFile(d.user.Fs, r.URL.Path, r.Body)
|
info, writeErr := writeFile(d.user.Fs, r.URL.Path, r.Body)
|
||||||
|
if writeErr != nil {
|
||||||
|
return writeErr
|
||||||
|
}
|
||||||
|
|
||||||
etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size())
|
etag := fmt.Sprintf(`"%x%x"`, info.ModTime().UnixNano(), info.Size())
|
||||||
w.Header().Set("ETag", etag)
|
w.Header().Set("ETag", etag)
|
||||||
|
@ -198,6 +209,11 @@ var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request,
|
||||||
dst = addVersionSuffix(dst, d.user.Fs)
|
dst = addVersionSuffix(dst, d.user.Fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permission for overwriting the file
|
||||||
|
if override && !d.user.Perm.Modify {
|
||||||
|
return http.StatusForbidden, nil
|
||||||
|
}
|
||||||
|
|
||||||
err = d.RunHook(func() error {
|
err = d.RunHook(func() error {
|
||||||
switch action {
|
switch action {
|
||||||
// TODO: use enum
|
// TODO: use enum
|
||||||
|
|
Loading…
Reference in New Issue