filebrowser/frontend/src/views/files/Listing.vue

791 lines
22 KiB
Vue
Raw Normal View History

2018-02-01 12:17:04 +00:00
<template>
<div>
2023-08-19 18:32:29 +00:00
<div v-if="selectedCount > 0" id="file-selection">
<span >{{ selectedCount }} selected</span>
2023-07-30 22:20:22 +00:00
<template>
<action
v-if="headerButtons.select"
icon="info"
:label="$t('buttons.info')"
show="info"
/>
<action
v-if="headerButtons.select"
icon="check_circle"
:label="$t('buttons.selectMultiple')"
@action="toggleMultipleSelection"
/>
2023-08-05 14:58:06 +00:00
<action
v-if="headerButtons.download"
icon="file_download"
:label="$t('buttons.download')"
@action="download"
:counter="selectedCount"
/>
2023-07-30 22:20:22 +00:00
<action
v-if="headerButtons.share"
icon="share"
:label="$t('buttons.share')"
show="share"
/>
<action
v-if="headerButtons.rename"
icon="mode_edit"
:label="$t('buttons.rename')"
show="rename"
/>
<action
v-if="headerButtons.copy"
icon="content_copy"
:label="$t('buttons.copyFile')"
show="copy"
/>
<action
v-if="headerButtons.move"
icon="forward"
:label="$t('buttons.moveFile')"
show="move"
/>
<action
v-if="headerButtons.delete"
icon="delete"
:label="$t('buttons.delete')"
show="delete"
/>
2023-07-30 18:19:03 +00:00
</template>
2018-02-01 12:17:04 +00:00
</div>
<div v-if="loading">
<h2 class="message delayed">
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
2021-03-21 11:51:58 +00:00
<span>{{ $t("files.loading") }}</span>
</h2>
2018-02-01 12:17:04 +00:00
</div>
2021-03-01 16:12:17 +00:00
<template v-else>
2021-03-21 11:51:58 +00:00
<div v-if="req.numDirs + req.numFiles == 0">
2021-03-01 16:12:17 +00:00
<h2 class="message">
<i class="material-icons">sentiment_dissatisfied</i>
2021-03-21 11:51:58 +00:00
<span>{{ $t("files.lonely") }}</span>
2021-03-01 16:12:17 +00:00
</h2>
2021-03-21 11:51:58 +00:00
<input
style="display: none"
type="file"
id="upload-input"
@change="uploadInput($event)"
multiple
/>
<input
style="display: none"
type="file"
id="upload-folder-input"
@change="uploadInput($event)"
webkitdirectory
multiple
/>
2021-03-01 16:12:17 +00:00
</div>
<div v-else id="listing" ref="listing" :class="listingViewMode + ' file-icons'">
2021-03-01 16:12:17 +00:00
<div>
<div class="item header">
<div></div>
<div>
2021-03-21 11:51:58 +00:00
<p
:class="{ active: nameSorted }"
class="name"
2021-03-01 16:12:17 +00:00
role="button"
tabindex="0"
@click="sort('name')"
:title="$t('files.sortByName')"
2021-03-21 11:51:58 +00:00
:aria-label="$t('files.sortByName')"
>
<span>{{ $t("files.name") }}</span>
2021-03-01 16:12:17 +00:00
<i class="material-icons">{{ nameIcon }}</i>
</p>
2021-03-21 11:51:58 +00:00
<p
:class="{ active: sizeSorted }"
class="size"
2021-03-01 16:12:17 +00:00
role="button"
tabindex="0"
@click="sort('size')"
:title="$t('files.sortBySize')"
2021-03-21 11:51:58 +00:00
:aria-label="$t('files.sortBySize')"
>
<span>{{ $t("files.size") }}</span>
2021-03-01 16:12:17 +00:00
<i class="material-icons">{{ sizeIcon }}</i>
</p>
2021-03-21 11:51:58 +00:00
<p
:class="{ active: modifiedSorted }"
class="modified"
2021-03-01 16:12:17 +00:00
role="button"
tabindex="0"
@click="sort('modified')"
:title="$t('files.sortByLastModified')"
2021-03-21 11:51:58 +00:00
:aria-label="$t('files.sortByLastModified')"
>
<span>{{ $t("files.lastModified") }}</span>
2021-03-01 16:12:17 +00:00
<i class="material-icons">{{ modifiedIcon }}</i>
</p>
</div>
</div>
</div>
<div v-if="req.numDirs > 0">
<div class="header-items">
<h2>{{ $t("files.folders") }}</h2>
</div>
</div>
2021-03-01 16:12:17 +00:00
<div v-if="req.numDirs > 0">
2021-03-21 11:51:58 +00:00
<item
v-for="item in dirs"
2021-03-01 16:12:17 +00:00
:key="base64(item.name)"
v-bind:index="item.index"
v-bind:name="item.name"
v-bind:isDir="item.isDir"
v-bind:url="item.url"
v-bind:modified="item.modified"
v-bind:type="item.type"
2021-03-21 11:51:58 +00:00
v-bind:size="item.size"
2022-05-02 13:47:22 +00:00
v-bind:path="item.path"
2021-03-21 11:51:58 +00:00
>
2021-03-01 16:12:17 +00:00
</item>
</div>
2018-02-01 12:17:04 +00:00
<div v-if="req.numFiles > 0">
<div class="header-items">
<h2>{{ $t("files.files") }}</h2>
</div>
</div>
2021-03-01 16:12:17 +00:00
<div v-if="req.numFiles > 0">
2021-03-21 11:51:58 +00:00
<item
v-for="item in files"
2021-03-01 16:12:17 +00:00
:key="base64(item.name)"
v-bind:index="item.index"
v-bind:name="item.name"
v-bind:isDir="item.isDir"
v-bind:url="item.url"
v-bind:modified="item.modified"
v-bind:type="item.type"
2021-03-21 11:51:58 +00:00
v-bind:size="item.size"
2022-05-02 13:47:22 +00:00
v-bind:path="item.path"
2021-03-21 11:51:58 +00:00
>
2021-03-01 16:12:17 +00:00
</item>
</div>
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
<input
style="display: none"
type="file"
id="upload-input"
@change="uploadInput($event)"
multiple
/>
<input
style="display: none"
type="file"
id="upload-folder-input"
@change="uploadInput($event)"
webkitdirectory
multiple
/>
2021-03-01 16:12:17 +00:00
<div :class="{ active: $store.state.multiple }" id="multiple-selection">
2021-03-21 11:51:58 +00:00
<p>{{ $t("files.multipleSelectionEnabled") }}</p>
<div
@click="$store.commit('multiple', false)"
tabindex="0"
role="button"
:title="$t('files.clear')"
:aria-label="$t('files.clear')"
class="action"
>
2021-03-01 16:12:17 +00:00
<i class="material-icons">clear</i>
</div>
</div>
2018-02-01 12:17:04 +00:00
</div>
2021-03-01 16:12:17 +00:00
</template>
2018-02-01 12:17:04 +00:00
</div>
</template>
<style>
.header-items {
width: 100% !important;
max-width: 100% !important;
justify-content: center;
}
</style>
2018-02-01 12:17:04 +00:00
<script>
import Vue from "vue";
2021-03-21 11:51:58 +00:00
import { mapState, mapGetters, mapMutations } from "vuex";
import { users, files as api } from "@/api";
import * as upload from "@/utils/upload";
import css from "@/utils/css";
import throttle from "lodash.throttle";
2021-03-21 11:51:58 +00:00
import Action from "@/components/header/Action";
import Item from "@/components/files/ListingItem";
2018-02-01 12:17:04 +00:00
export default {
name: "listing",
components: {
Action,
2021-03-21 11:51:58 +00:00
Item,
},
data: function () {
return {
2020-07-20 18:14:27 +00:00
showLimit: 50,
columnWidth: 280,
dragCounter: 0,
2021-03-21 11:51:58 +00:00
width: window.innerWidth,
itemWeight: 0,
2021-03-21 11:51:58 +00:00
};
},
2018-02-01 12:17:04 +00:00
computed: {
2023-07-30 22:20:22 +00:00
...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]),
2021-03-21 11:51:58 +00:00
...mapGetters(["selectedCount"]),
nameSorted() {
return this.req.sorting.by === "name";
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
sizeSorted() {
return this.req.sorting.by === "size";
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
modifiedSorted() {
return this.req.sorting.by === "modified";
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
ascOrdered() {
return this.req.sorting.asc;
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
items() {
const dirs = [];
const files = [];
this.req.items.forEach((item) => {
if (item.isDir) {
2021-03-21 11:51:58 +00:00
dirs.push(item);
} else {
2021-03-21 11:51:58 +00:00
files.push(item);
}
2021-03-21 11:51:58 +00:00
});
2021-03-21 11:51:58 +00:00
return { dirs, files };
},
2021-03-21 11:51:58 +00:00
dirs() {
return this.items.dirs.slice(0, this.showLimit);
},
2021-03-21 11:51:58 +00:00
files() {
let showLimit = this.showLimit - this.items.dirs.length;
2021-03-21 11:51:58 +00:00
if (showLimit < 0) showLimit = 0;
2021-03-21 11:51:58 +00:00
return this.items.files.slice(0, showLimit);
},
2021-03-21 11:51:58 +00:00
nameIcon() {
2018-02-01 12:17:04 +00:00
if (this.nameSorted && !this.ascOrdered) {
2021-03-21 11:51:58 +00:00
return "arrow_upward";
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
return "arrow_downward";
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
sizeIcon() {
2018-02-01 12:17:04 +00:00
if (this.sizeSorted && this.ascOrdered) {
2021-03-21 11:51:58 +00:00
return "arrow_downward";
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
return "arrow_upward";
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
modifiedIcon() {
2018-02-01 12:17:04 +00:00
if (this.modifiedSorted && this.ascOrdered) {
2021-03-21 11:51:58 +00:00
return "arrow_downward";
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
return "arrow_upward";
},
2022-01-15 18:20:13 +00:00
viewIcon() {
const icons = {
list: "view_module",
compact: "view_module",
normal: "grid_view",
gallery: "view_list",
2022-01-15 18:20:13 +00:00
};
return icons[this.user.viewMode];
},
listingViewMode() {
return this.user.viewMode
},
headerButtons() {
return {
2023-07-23 04:12:26 +00:00
select: this.selectedCount > 0,
2023-08-05 14:58:06 +00:00
upload: this.user.perm.create && this.selectedCount > 0,
download: this.user.perm.download && this.selectedCount > 0,
delete: this.selectedCount > 0 && this.user.perm.delete,
rename: this.selectedCount === 1 && this.user.perm.rename,
share: this.selectedCount === 1 && this.user.perm.share,
move: this.selectedCount > 0 && this.user.perm.rename,
copy: this.selectedCount > 0 && this.user.perm.create,
2021-03-21 11:51:58 +00:00
};
},
2018-02-01 12:17:04 +00:00
},
watch: {
req: function () {
// Reset the show value
this.showLimit = 50;
// Ensures that the listing is displayed
Vue.nextTick(() => {
// How much every listing item affects the window height
this.setItemWeight();
// Fill and fit the window with listing items
this.fillWindow(true);
});
},
},
2018-02-01 12:17:04 +00:00
mounted: function () {
// Check the columns size for the first time.
this.colunmsResize();
// How much every listing item affects the window height
this.setItemWeight();
// Fill and fit the window with listing items
this.fillWindow(true);
2018-02-01 12:17:04 +00:00
// Add the needed event listeners to the window and document.
2021-03-21 11:51:58 +00:00
window.addEventListener("keydown", this.keyEvent);
window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.windowsResize);
if (!this.user.perm.create) return;
2021-03-21 11:51:58 +00:00
document.addEventListener("dragover", this.preventDefault);
document.addEventListener("dragenter", this.dragEnter);
document.addEventListener("dragleave", this.dragLeave);
document.addEventListener("drop", this.drop);
2018-02-01 12:17:04 +00:00
},
2023-09-25 01:03:09 +00:00
beforeUnmount() {
2018-02-01 12:17:04 +00:00
// Remove event listeners before destroying this page.
2021-03-21 11:51:58 +00:00
window.removeEventListener("keydown", this.keyEvent);
window.removeEventListener("scroll", this.scrollEvent);
window.removeEventListener("resize", this.windowsResize);
2021-04-19 12:49:40 +00:00
if (this.user && !this.user.perm.create) return;
2021-03-21 11:51:58 +00:00
document.removeEventListener("dragover", this.preventDefault);
document.removeEventListener("dragenter", this.dragEnter);
document.removeEventListener("dragleave", this.dragLeave);
document.removeEventListener("drop", this.drop);
2018-02-01 12:17:04 +00:00
},
methods: {
2021-03-21 11:51:58 +00:00
...mapMutations(["updateUser", "addSelected"]),
2018-02-01 12:17:04 +00:00
base64: function (name) {
2021-03-21 11:51:58 +00:00
return window.btoa(unescape(encodeURIComponent(name)));
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
keyEvent(event) {
// No prompts are shown
2020-07-04 14:19:03 +00:00
if (this.show !== null) {
2021-03-21 11:51:58 +00:00
return;
2020-07-04 14:19:03 +00:00
}
// Esc!
if (event.keyCode === 27) {
// Reset files selection.
2021-03-21 11:51:58 +00:00
this.$store.commit("resetSelected");
}
// Del!
if (event.keyCode === 46) {
2021-03-21 11:51:58 +00:00
if (!this.user.perm.delete || this.selectedCount == 0) return;
// Show delete prompt.
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", "delete");
}
// F2!
if (event.keyCode === 113) {
2021-03-21 11:51:58 +00:00
if (!this.user.perm.rename || this.selectedCount !== 1) return;
// Show rename prompt.
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", "rename");
}
// Ctrl is pressed
2018-02-01 12:17:04 +00:00
if (!event.ctrlKey && !event.metaKey) {
2021-03-21 11:51:58 +00:00
return;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
let key = String.fromCharCode(event.which).toLowerCase();
2018-02-01 12:17:04 +00:00
switch (key) {
2021-03-21 11:51:58 +00:00
case "f":
event.preventDefault();
this.$store.commit("showHover", "search");
break;
case "c":
case "x":
this.copyCut(event, key);
break;
case "v":
this.paste(event);
break;
case "a":
event.preventDefault();
for (let file of this.items.files) {
if (this.$store.state.selected.indexOf(file.index) === -1) {
2021-03-21 11:51:58 +00:00
this.addSelected(file.index);
}
}
for (let dir of this.items.dirs) {
if (this.$store.state.selected.indexOf(dir.index) === -1) {
2021-03-21 11:51:58 +00:00
this.addSelected(dir.index);
}
}
2021-03-21 11:51:58 +00:00
break;
case "s":
event.preventDefault();
document.getElementById("download-button").click();
break;
2018-02-01 12:17:04 +00:00
}
},
2021-03-21 11:51:58 +00:00
preventDefault(event) {
2018-02-01 12:17:04 +00:00
// Wrapper around prevent default.
2021-03-21 11:51:58 +00:00
event.preventDefault();
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
copyCut(event, key) {
if (event.target.tagName.toLowerCase() === "input") {
return;
}
2021-03-21 11:51:58 +00:00
let items = [];
2018-02-01 12:17:04 +00:00
for (let i of this.selected) {
items.push({
from: this.req.items[i].url,
name: this.req.items[i].name,
2021-03-21 11:51:58 +00:00
});
2018-02-01 12:17:04 +00:00
}
if (items.length == 0) {
2021-03-21 11:51:58 +00:00
return;
}
2021-03-21 11:51:58 +00:00
this.$store.commit("updateClipboard", {
2018-02-01 12:17:04 +00:00
key: key,
items: items,
2021-03-21 11:51:58 +00:00
path: this.$route.path,
});
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
paste(event) {
if (event.target.tagName.toLowerCase() === "input") {
return;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
let items = [];
2018-02-01 12:17:04 +00:00
for (let item of this.$store.state.clipboard.items) {
2023-07-30 22:20:22 +00:00
const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from;
const to = this.$route.path + encodeURIComponent(item.name);
2021-03-21 11:51:58 +00:00
items.push({ from, to, name: item.name });
}
if (items.length === 0) {
2021-03-21 11:51:58 +00:00
return;
2018-02-01 12:17:04 +00:00
}
2020-07-16 19:30:17 +00:00
let action = (overwrite, rename) => {
2021-03-21 11:51:58 +00:00
api
.copy(items, overwrite, rename)
.then(() => {
this.$store.commit("setReload", true);
})
.catch(this.$showError);
};
if (this.$store.state.clipboard.key === "x") {
2020-07-16 19:30:17 +00:00
action = (overwrite, rename) => {
2021-03-21 11:51:58 +00:00
api
.move(items, overwrite, rename)
.then(() => {
this.$store.commit("resetClipboard");
this.$store.commit("setReload", true);
})
.catch(this.$showError);
};
}
if (this.$store.state.clipboard.path == this.$route.path) {
2021-03-21 11:51:58 +00:00
action(false, true);
2021-03-21 11:51:58 +00:00
return;
}
2021-03-21 11:51:58 +00:00
let conflict = upload.checkConflict(items, this.req.items);
2021-03-21 11:51:58 +00:00
let overwrite = false;
let rename = false;
2020-07-16 19:30:17 +00:00
if (conflict) {
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", {
prompt: "replace-rename",
2020-07-16 19:30:17 +00:00
confirm: (event, option) => {
2021-03-21 11:51:58 +00:00
overwrite = option == "overwrite";
rename = option == "rename";
2020-07-16 19:30:17 +00:00
2021-03-21 11:51:58 +00:00
event.preventDefault();
this.$store.commit("closeHovers");
action(overwrite, rename);
},
});
2021-03-21 11:51:58 +00:00
return;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
action(overwrite, rename);
2018-02-01 12:17:04 +00:00
},
colunmsResize() {
2018-02-01 12:17:04 +00:00
// Update the columns size based on the window width.
2021-03-21 11:51:58 +00:00
let columns = Math.floor(
document.querySelector("main").offsetWidth / this.columnWidth
2021-03-21 11:51:58 +00:00
);
let items = css(["#listing .item", "#listing .item"]);
2021-03-21 11:51:58 +00:00
if (columns === 0) columns = 1;
items.style.width = `calc(${100 / columns}% - 1em)`;
2018-02-01 12:17:04 +00:00
},
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
2023-07-30 22:20:22 +00:00
const showQuantity = Math.ceil((window.innerHeight * 2) / this.itemWeight);
// Increase the number of displayed items
this.showLimit += showQuantity;
}
}, 100),
2021-03-21 11:51:58 +00:00
dragEnter() {
this.dragCounter++;
2020-07-20 18:14:27 +00:00
2018-02-01 12:17:04 +00:00
// When the user starts dragging an item, put every
// file on the listing with 50% opacity.
2021-03-21 11:51:58 +00:00
let items = document.getElementsByClassName("item");
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
Array.from(items).forEach((file) => {
file.style.opacity = 0.5;
});
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
dragLeave() {
this.dragCounter--;
2020-07-20 18:14:27 +00:00
if (this.dragCounter == 0) {
2021-03-21 11:51:58 +00:00
this.resetOpacity();
2020-07-20 18:14:27 +00:00
}
2018-02-01 12:17:04 +00:00
},
drop: async function (event) {
2021-03-21 11:51:58 +00:00
event.preventDefault();
this.dragCounter = 0;
this.resetOpacity();
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
let dt = event.dataTransfer;
let el = event.target;
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
if (dt.files.length <= 0) return;
2018-02-01 12:17:04 +00:00
for (let i = 0; i < 5; i++) {
2021-03-21 11:51:58 +00:00
if (el !== null && !el.classList.contains("item")) {
el = el.parentElement;
2018-02-01 12:17:04 +00:00
}
}
let files = await upload.scanFiles(dt);
let items = this.req.items;
let path = this.$route.path.endsWith("/")
? this.$route.path
: this.$route.path + "/";
2023-07-30 22:20:22 +00:00
if (el !== null && el.classList.contains("item") && el.dataset.dir === "true") {
// Get url from ListingItem instance
path = el.__vue__.url;
try {
2021-03-21 11:51:58 +00:00
items = (await api.fetch(path)).items;
} catch (error) {
2021-03-21 11:51:58 +00:00
this.$showError(error);
}
}
2021-03-21 11:51:58 +00:00
let conflict = upload.checkConflict(files, items);
if (conflict) {
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", {
prompt: "replace",
confirm: (event) => {
2021-03-21 11:51:58 +00:00
event.preventDefault();
this.$store.commit("closeHovers");
upload.handleFiles(files, path, true);
},
});
2021-03-21 11:51:58 +00:00
return;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
upload.handleFiles(files, path);
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
uploadInput(event) {
this.$store.commit("closeHovers");
2021-03-21 11:51:58 +00:00
let files = event.currentTarget.files;
let folder_upload =
2023-07-30 22:20:22 +00:00
files[0].webkitRelativePath !== undefined && files[0].webkitRelativePath !== "";
if (folder_upload) {
for (let i = 0; i < files.length; i++) {
2021-03-21 11:51:58 +00:00
let file = files[i];
files[i].fullPath = file.webkitRelativePath;
}
}
2021-03-21 11:51:58 +00:00
let path = this.$route.path.endsWith("/")
? this.$route.path
: this.$route.path + "/";
let conflict = upload.checkConflict(files, this.req.items);
if (conflict) {
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", {
prompt: "replace",
confirm: (event) => {
2021-03-21 11:51:58 +00:00
event.preventDefault();
this.$store.commit("closeHovers");
upload.handleFiles(files, path, true);
},
});
2021-03-21 11:51:58 +00:00
return;
}
2021-03-21 11:51:58 +00:00
upload.handleFiles(files, path);
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
resetOpacity() {
let items = document.getElementsByClassName("item");
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
Array.from(items).forEach((file) => {
file.style.opacity = 1;
});
2018-02-01 12:17:04 +00:00
},
2021-03-21 11:51:58 +00:00
async sort(by) {
let asc = false;
2018-02-01 12:17:04 +00:00
2021-03-21 11:51:58 +00:00
if (by === "name") {
if (this.nameIcon === "arrow_upward") {
asc = true;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
} else if (by === "size") {
if (this.sizeIcon === "arrow_upward") {
asc = true;
2018-02-01 12:17:04 +00:00
}
2021-03-21 11:51:58 +00:00
} else if (by === "modified") {
if (this.modifiedIcon === "arrow_upward") {
asc = true;
2018-02-01 12:17:04 +00:00
}
}
try {
2023-07-30 22:20:22 +00:00
await users.update({ id: this.user.id, sorting: { by, asc } }, ["sorting"]);
} catch (e) {
2021-03-21 11:51:58 +00:00
this.$showError(e);
}
2021-03-21 11:51:58 +00:00
this.$store.commit("setReload", true);
},
2021-03-21 11:51:58 +00:00
openSearch() {
this.$store.commit("showHover", "search");
},
2021-03-21 11:51:58 +00:00
toggleMultipleSelection() {
this.$store.commit("multiple", !this.multiple);
this.$store.commit("closeHovers");
},
windowsResize: throttle(function () {
this.colunmsResize();
2021-03-21 11:51:58 +00:00
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) {
2021-03-21 11:51:58 +00:00
api.download(null, this.req.items[this.selected[0]].url);
return;
}
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", {
prompt: "download",
2021-03-03 17:46:37 +00:00
confirm: (format) => {
2021-03-21 11:51:58 +00:00
this.$store.commit("closeHovers");
let files = [];
if (this.selectedCount > 0) {
for (let i of this.selected) {
2021-03-21 11:51:58 +00:00
files.push(this.req.items[i].url);
}
} else {
2021-03-21 11:51:58 +00:00
files.push(this.$route.path);
2021-03-03 17:46:37 +00:00
}
2021-03-21 11:51:58 +00:00
api.download(format, ...files);
},
});
},
upload: function () {
2021-04-15 12:28:19 +00:00
if (
typeof window.DataTransferItem !== "undefined" &&
typeof DataTransferItem.prototype.webkitGetAsEntry !== "undefined"
) {
2021-03-21 11:51:58 +00:00
this.$store.commit("showHover", "upload");
} else {
2021-03-21 11:51:58 +00:00
document.getElementById("upload-input").click();
}
2021-03-21 11:51:58 +00:00
},
setItemWeight() {
// Listing element is not displayed
if (this.$refs.listing == null) return;
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
2023-07-30 22:20:22 +00:00
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;
},
2021-03-21 11:51:58 +00:00
},
};
2018-02-01 12:17:04 +00:00
</script>