feat: dynamic item count on file listing

pull/1353/head
Ramires Viana 2021-03-24 17:50:16 +00:00
parent b521dec8f9
commit 6c8ee96e6a
1 changed files with 83 additions and 12 deletions

View File

@ -135,7 +135,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 +253,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,13 +351,27 @@ 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);
document.addEventListener("dragover", this.preventDefault); document.addEventListener("dragover", this.preventDefault);
@ -367,7 +382,6 @@ 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);
document.removeEventListener("dragover", this.preventDefault); document.removeEventListener("dragover", this.preventDefault);
@ -543,7 +557,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 +566,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 +737,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 +785,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 +802,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>