Merge pull request #1353 from ramiresviana/fixes-8

Some fixes
This commit is contained in:
Oleg Lobanov 2021-03-30 09:43:27 +02:00 committed by GitHub
commit 84e3a98303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 240 additions and 57 deletions

View File

@ -170,7 +170,7 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
case strings.HasPrefix(mimetype, "image"):
i.Type = "image"
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"
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.

View File

@ -29,14 +29,6 @@ export default {
type: Number,
default: () => 200,
},
maxScale: {
type: Number,
default: () => 4,
},
minScale: {
type: Number,
default: () => 0.25,
},
classList: {
type: Array,
default: () => [],
@ -45,10 +37,6 @@ export default {
type: Number,
default: () => 0.25,
},
autofill: {
type: Boolean,
default: () => false,
},
},
data() {
return {
@ -64,6 +52,8 @@ export default {
center: { x: 0, y: 0 },
relative: { x: 0, y: 0 },
},
maxScale: 4,
minScale: 0.25,
};
},
mounted() {
@ -88,6 +78,10 @@ export default {
},
watch: {
src: function () {
if (!this.decodeUTIF()) {
this.$refs.imgex.src = this.src;
}
this.scale = 1;
this.setZoom();
this.setCenter();
@ -122,6 +116,21 @@ export default {
img.classList.add("image-ex-img-ready");
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() {
this.inDrag = false;
@ -251,7 +260,7 @@ export default {
}
},
wheelMove(event) {
this.scale += (event.wheelDeltaY / 100) * this.zoomStep;
this.scale += -Math.sign(event.deltaY) * this.zoomStep;
this.setZoom();
},
setZoom() {

View File

@ -56,6 +56,12 @@ export default {
let prompt = this.$refs.currentComponent;
// Esc!
if (event.keyCode === 27) {
event.stopImmediatePropagation();
this.$store.commit("closeHovers");
}
// Enter
if (event.keyCode == 13) {
switch (this.show) {

View File

@ -34,7 +34,7 @@
}
.share__box__info {
flex: 1 1 auto;
flex: 1 1 18em;
}
.share__box__element {

View File

@ -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;
}
@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";

View File

@ -25,6 +25,7 @@
transition: .1s ease background, .1s ease opacity;
align-items: center;
cursor: pointer;
user-select: none;
}
#listing .item div:last-of-type {

View File

@ -109,6 +109,7 @@
#previewer {
background-color: rgba(0, 0, 0, 0.9);
padding-top: 4em;
position: fixed;
top: 0;
left: 0;
@ -142,7 +143,6 @@
}
#previewer .preview {
margin-top: 4em;
text-align: center;
height: calc(100vh - 4em);
}
@ -209,7 +209,7 @@
#editor-container {
background-color: #fafafa;
position: fixed;
margin-top: 4em;
padding-top: 4em;
top: 0;
left: 0;
width: 100%;

View File

@ -1,6 +1,6 @@
<template>
<div>
<header-bar v-if="error || !req.type" showMenu showLogo />
<header-bar v-if="error || req.type == null" showMenu showLogo />
<breadcrumbs base="/files" />
@ -124,15 +124,6 @@ export default {
}
},
keyEvent(event) {
if (this.show !== null) {
// Esc!
if (event.keyCode === 27) {
this.$store.commit("closeHovers");
}
return;
}
// F1!
if (event.keyCode === 112) {
event.preventDefault();

View File

@ -10,26 +10,22 @@
{{ $t("settings.profileSettings") }}
</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' }">
{{ $t("settings.shareManagement") }}
</li></router-link
>
<router-link to="/settings/global"
><li
:class="{ active: $route.path === '/settings/global' }"
v-if="user.perm.admin"
>
<router-link to="/settings/global" v-if="user.perm.admin"
><li :class="{ active: $route.path === '/settings/global' }">
{{ $t("settings.globalSettings") }}
</li></router-link
>
<router-link to="/settings/users"
<router-link to="/settings/users" v-if="user.perm.admin"
><li
:class="{
active:
$route.path === '/settings/users' || $route.name === 'User',
}"
v-if="user.perm.admin"
>
{{ $t("settings.userManagement") }}
</li></router-link

View File

@ -6,6 +6,7 @@
<template #actions>
<action
v-if="user.perm.modify"
id="save-button"
icon="save"
:label="$t('buttons.save')"

View File

@ -25,18 +25,21 @@
/>
<action
v-if="headerButtons.copy"
id="copy-button"
icon="content_copy"
:label="$t('buttons.copyFile')"
show="copy"
/>
<action
v-if="headerButtons.move"
id="move-button"
icon="forward"
:label="$t('buttons.moveFile')"
show="move"
/>
<action
v-if="headerButtons.delete"
id="delete-button"
icon="delete"
:label="$t('buttons.delete')"
show="delete"
@ -55,13 +58,16 @@
@action="switchView"
/>
<action
v-if="headerButtons.download"
icon="file_download"
:label="$t('buttons.download')"
@action="download"
:counter="selectedCount"
/>
<action
v-if="headerButtons.upload"
icon="file_upload"
id="upload-button"
:label="$t('buttons.upload')"
@action="upload"
/>
@ -135,7 +141,7 @@
multiple
/>
</div>
<div v-else id="listing" :class="user.viewMode">
<div v-else id="listing" ref="listing" :class="user.viewMode">
<div>
<div class="item header">
<div></div>
@ -253,6 +259,7 @@ import { users, files as api } from "@/api";
import { enableExec } from "@/utils/constants";
import * as upload from "@/utils/upload";
import css from "@/utils/css";
import throttle from "lodash.throttle";
import HeaderBar from "@/components/header/HeaderBar";
import Action from "@/components/header/Action";
@ -350,15 +357,31 @@ export default {
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 () {
// 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.
window.addEventListener("keydown", this.keyEvent);
window.addEventListener("resize", this.resizeEvent);
window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.windowsResize);
if (!this.user.perm.create) return;
document.addEventListener("dragover", this.preventDefault);
document.addEventListener("dragenter", this.dragEnter);
document.addEventListener("dragleave", this.dragLeave);
@ -367,9 +390,10 @@ export default {
beforeDestroy() {
// Remove event listeners before destroying this page.
window.removeEventListener("keydown", this.keyEvent);
window.removeEventListener("resize", this.resizeEvent);
window.removeEventListener("scroll", this.scrollEvent);
window.removeEventListener("resize", this.windowsResize);
if (!this.user.perm.create) return;
document.removeEventListener("dragover", this.preventDefault);
document.removeEventListener("dragenter", this.dragEnter);
document.removeEventListener("dragleave", this.dragLeave);
@ -543,7 +567,7 @@ export default {
action(overwrite, rename);
},
resizeEvent() {
colunmsResize() {
// Update the columns size based on the window width.
let columns = Math.floor(
document.querySelector("main").offsetWidth / 300
@ -552,11 +576,27 @@ export default {
if (columns === 0) columns = 1;
items.style.width = `calc(${100 / columns}% - 1em)`;
},
scrollEvent() {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
this.showLimit += 50;
scrollEvent: throttle(function () {
const totalItems = this.req.numDirs + this.req.numFiles;
// 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() {
this.dragCounter++;
@ -707,9 +747,19 @@ export default {
this.$store.commit("multiple", !this.multiple);
this.$store.commit("closeHovers");
},
windowsResize() {
windowsResize: throttle(function () {
this.colunmsResize();
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() {
if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) {
api.download(null, this.req.items[this.selected[0]].url);
@ -745,7 +795,12 @@ export default {
try {
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) {
this.$showError(e);
}
@ -757,6 +812,32 @@ export default {
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>

View File

@ -17,12 +17,14 @@
<template #actions>
<action
:disabled="loading"
v-if="user.perm.rename"
icon="mode_edit"
:label="$t('buttons.rename')"
show="rename"
/>
<action
:disabled="loading"
v-if="user.perm.delete"
icon="delete"
:label="$t('buttons.delete')"
@action="deleteFile"
@ -30,6 +32,7 @@
/>
<action
:disabled="loading"
v-if="user.perm.download"
icon="file_download"
:label="$t('buttons.download')"
@action="download"
@ -54,8 +57,22 @@
<template v-if="!loading">
<div class="preview">
<ExtendedImage v-if="req.type == 'image'" :src="raw"></ExtendedImage>
<audio v-else-if="req.type == 'audio'" :src="raw" controls></audio>
<video v-else-if="req.type == 'video'" :src="raw" controls>
<audio
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
kind="captions"
v-for="(sub, index) in subtitles"
@ -136,6 +153,7 @@ export default {
showNav: true,
navTimeout: null,
hoverNav: false,
autoPlay: false,
};
},
computed: {
@ -230,6 +248,14 @@ export default {
}
},
async updatePreview() {
if (
this.$refs.player &&
this.$refs.player.paused &&
!this.$refs.player.ended
) {
this.autoPlay = false;
}
if (this.req.subtitles) {
this.subtitles = this.req.subtitles.map(
(sub) => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`

View File

@ -181,14 +181,14 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files.
commonDir := fileutils.CommonPrefix(filepath.Separator, filenames...)
var name string
if len(filenames) > 1 {
name = "_" + filepath.Base(commonDir)
} else {
name := filepath.Base(commonDir)
if name == "." || name == "" || name == string(filepath.Separator) {
name = file.Name
}
if name == "." || name == "" {
name = "archive"
// Prefix used to distinguish a filelist generated
// archive from the full directory archive
if len(filenames) > 1 {
name = "_" + name
}
name += extension
w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))

View File

@ -118,6 +118,11 @@ func resourcePostHandler(fileCache FileCache) handleFunc {
return http.StatusConflict, nil
}
// Permission for overwriting the file
if !d.user.Perm.Modify {
return http.StatusForbidden, nil
}
err = delThumbs(r.Context(), fileCache, file)
if err != nil {
return errToStatus(err), err
@ -125,7 +130,10 @@ func resourcePostHandler(fileCache FileCache) handleFunc {
}
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())
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 {
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())
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)
}
// Permission for overwriting the file
if override && !d.user.Perm.Modify {
return http.StatusForbidden, nil
}
err = d.RunHook(func() error {
switch action {
// TODO: use enum