more file manager progress

This commit is contained in:
2020-01-30 22:55:32 +01:00
parent 5d59b52f1e
commit 047169e080
2 changed files with 190 additions and 49 deletions

View File

@@ -9,9 +9,32 @@ function FileManager(windowElement) {
this.breadcrumbs = this.navBar.querySelector("#breadcrumbs"); this.breadcrumbs = this.navBar.querySelector("#breadcrumbs");
this.btnReload = this.navBar.querySelector("#btn_reload"); this.btnReload = this.navBar.querySelector("#btn_reload");
this.inputSearch = this.navBar.querySelector("#input_search"); this.inputSearch = this.navBar.querySelector("#input_search");
this.directorySorters = this.window.querySelector("#directory_sorters");
this.directoryArea = this.window.querySelector("#directory_area"); this.directoryArea = this.window.querySelector("#directory_area");
this.directoryFooter = this.window.querySelector("#directory_footer"); this.directoryFooter = this.window.querySelector("#directory_footer");
// Sorters
this.currentSortField = "";
this.currentSortAscending = true;
this.btnSortName = document.createElement("div");
this.btnSortName.innerText = "Name";
this.btnSortName.addEventListener("click", () => { this.sortBy("name"); });
this.directorySorters.appendChild(this.btnSortName);
this.btnSortType = document.createElement("div");
this.btnSortType.innerText = "Type";
this.btnSortType.addEventListener("click", () => { this.sortBy("type"); });
this.directorySorters.appendChild(this.btnSortType);
this.btnSortSize = document.createElement("div");
this.btnSortSize.innerText = "Size";
this.btnSortSize.addEventListener("click", () => { this.sortBy("size"); });
this.directorySorters.appendChild(this.btnSortSize);
// Buttons
this.btnReload.addEventListener("click", () => { this.getUserFiles(); })
this.dirContainer = document.createElement("div"); this.dirContainer = document.createElement("div");
this.directoryArea.appendChild(this.dirContainer); this.directoryArea.appendChild(this.dirContainer);
@@ -22,12 +45,27 @@ function FileManager(windowElement) {
this.renderVisibleFiles(this.visibleFiles, false); this.renderVisibleFiles(this.visibleFiles, false);
}) })
// type: {icon, name, href, type, size}
this.allFiles = []; this.allFiles = [];
this.visibleFiles = []; this.visibleFiles = [];
this.lastScrollTop = 0; this.lastScrollTop = 0;
} }
FileManager.prototype.setSpinner = function() {
this.window.appendChild(document.getElementById("tpl_spinner").content.cloneNode(true));
}
FileManager.prototype.delSpinner = function() {
for (let i in this.window.children) {
if (
typeof(this.window.children[i].classList) === "object" &&
this.window.children[i].classList.contains("spinner")
) {
this.window.children[i].remove();
}
}
}
FileManager.prototype.search = function(term) { FileManager.prototype.search = function(term) {
if (term === "") { if (term === "") {
this.visibleFiles = this.allFiles; this.visibleFiles = this.allFiles;
@@ -51,28 +89,36 @@ FileManager.prototype.getDirectory = function(path) {
} }
FileManager.prototype.getUserFiles = function() { FileManager.prototype.getUserFiles = function() {
this.setSpinner();
let getAll = (page) => { let getAll = (page) => {
fetch(apiEndpoint+"/user/files?page="+page+"&limit=10000").then(resp => { fetch(apiEndpoint+"/user/files?page="+page+"&limit=10000").then(resp => {
if (!resp.ok) {Promise.reject("yo");} if (!resp.ok) {Promise.reject("yo");}
return resp.json(); return resp.json();
}).then(resp => { }).then(resp => {
if (page === 0) { for (let i in resp.files) {
this.allFiles = resp.files; this.allFiles.push({
} else { icon: apiEndpoint+"/file/"+resp.files[i].id+"/thumbnail?width=32&height=32",
this.allFiles = this.allFiles.concat(resp.files); name: resp.files[i].name,
href: "/u/"+resp.files[i].id,
type: resp.files[i].mime_type,
size: resp.files[i].size
})
} }
this.allFiles.sort((a, b) => {
return a.name.localeCompare(b.name);
});
this.visibleFiles = this.allFiles; this.visibleFiles = this.allFiles;
this.currentSortField = "";
this.renderVisibleFiles(this.visibleFiles, true); this.sortBy("name");
if (resp.files.length === 10000) { if (resp.files.length === 10000) {
getAll(page+1); getAll(page+1);
} else {
// Less than 10000 results means we're done loading, we can
// remove the loading spinner
this.delSpinner();
} }
}).catch((err) => { }).catch((err) => {
this.delSpinner();
console.log("Req failed:" + err); console.log("Req failed:" + err);
}) })
} }
@@ -80,9 +126,77 @@ FileManager.prototype.getUserFiles = function() {
getAll(0); getAll(0);
} }
FileManager.prototype.getUserLists = function() {
this.setSpinner();
let getAll = (page) => {
fetch(apiEndpoint+"/user/lists?page="+page+"&limit=10000").then(resp => {
if (!resp.ok) {Promise.reject("yo");}
return resp.json();
}).then(resp => {
for (let i in resp.lists) {
this.allFiles.push({
icon: apiEndpoint+"/list/"+resp.lists[i].id+"/thumbnail?width=32&height=32",
name: resp.lists[i].title,
href: "/l/"+resp.lists[i].id,
type: "list",
size: 0
})
}
this.visibleFiles = this.allFiles;
this.currentSortField = "";
this.sortBy("name");
if (resp.lists.length === 10000) {
getAll(page+1);
} else {
// Less than 10000 results means we're done loading, we can
// remove the loading spinner
this.delSpinner();
}
}).catch((err) => {
this.delSpinner();
console.log("Req failed:" + err);
})
}
getAll(0);
}
FileManager.prototype.sortBy = function(field) {
if (this.currentSortField !== field) {
this.currentSortAscending = true;
this.currentSortField = field;
} else if (this.currentSortField === field) {
this.currentSortAscending = !this.currentSortAscending;
}
this.visibleFiles.sort((a, b) => {
if (this.currentSortAscending) {
return a[field].localeCompare(b[field]);
} else {
return b[field].localeCompare(a[field]);
}
});
this.renderVisibleFiles(this.visibleFiles, true);
}
FileManager.prototype.renderVisibleFiles = function(files, freshStart) { FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
let scrollDown = this.lastScrollTop <= this.directoryArea.scrollTop;
this.lastScrollTop = this.directoryArea.scrollTop;
let fileMargin = 4;
let fileHeight = 32 + fileMargin;
let totalHeight = (files.length * fileHeight);
let viewportHeight = this.directoryArea.clientHeight;
if (freshStart) { if (freshStart) {
this.dirContainer.innerHTML = ""; this.dirContainer.innerHTML = "";
this.dirContainer.style.height = totalHeight+"px";
this.dirContainer.scrollTop = 0;
this.lastScrollTop = 0;
scrollDown = true;
let totalSize = 0; let totalSize = 0;
for (let i in files) { for (let i in files) {
@@ -95,25 +209,15 @@ FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
+formatDataVolume(totalSize, 4); +formatDataVolume(totalSize, 4);
} }
let scrollDown = this.lastScrollTop <= this.directoryArea.scrollTop;
this.lastScrollTop = this.directoryArea.scrollTop;
let fileHeight = 32;
let totalHeight = (files.length * fileHeight)+38;
let viewportHeight = this.directoryArea.clientHeight;
let paddingTop = this.lastScrollTop - this.lastScrollTop%fileHeight; let paddingTop = this.lastScrollTop - this.lastScrollTop%fileHeight;
if (paddingTop < 0) { paddingTop = 0;} let start = Math.floor(paddingTop/fileHeight) - 5;
let paddingBottom = totalHeight - paddingTop - viewportHeight - this.lastScrollTop%fileHeight; if (start < 0) { start = 0; }
if (paddingBottom < 0) {paddingBottom = 0;}
// Pad the items out which we're not going to show let end = Math.ceil((paddingTop+viewportHeight)/fileHeight) + 5;
this.dirContainer.style.marginTop = paddingTop+"px";
this.dirContainer.style.marginBottom = paddingBottom+"px";
let start = Math.floor(paddingTop/fileHeight);
let end = Math.ceil((paddingTop+viewportHeight)/fileHeight);
if (end > files.length) { end = files.length-1; } if (end > files.length) { end = files.length-1; }
this.dirContainer.style.paddingTop = (start*fileHeight)+"px";
// First remove the elements which are out of bounds // First remove the elements which are out of bounds
let firstEl; let firstEl;
let firstIdx = -1; let firstIdx = -1;
@@ -142,13 +246,13 @@ FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
let makeButton = (i, file) => { let makeButton = (i, file) => {
let el = document.createElement("a"); let el = document.createElement("a");
el.classList = "node"; el.classList = "node";
el.href = "/u/"+file.id; el.href = file.href;
el.target = "_blank"; el.target = "_blank";
el.title = file.name; el.title = file.name;
el.setAttribute("fileindex", i); el.setAttribute("fileindex", i);
let thumb = document.createElement("img"); let thumb = document.createElement("img");
thumb.src = apiEndpoint+"/file/"+file.id+"/thumbnail?width=32&height=32"; thumb.src = file.icon;
let label = document.createElement("span"); let label = document.createElement("span");
label.innerText = file.name; label.innerText = file.name;

View File

@@ -9,18 +9,31 @@
padding: 0; padding: 0;
} }
#button_toggle_navigation {
display: none;
}
.file_manager { .file_manager {
position: absolute; position: absolute;
padding: 0; padding: 0;
background-color: var(--layer_1_color); background-color: var(--layer_1_color);
box-shadow: #000000 8px 8px 50px 5px; box-shadow: #000000 8px 8px 50px 5px;
left:2%; left:3%;
top:2%; top:3%;
right:2%; right:3%;
bottom:2%; bottom:3%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@media (max-width: 800px) {
.file_manager {
left: 0;
top: 0;
right: 0;
bottom: 0;
}
}
.file_manager > .nav_bar { .file_manager > .nav_bar {
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
@@ -30,11 +43,28 @@
.file_manager > .nav_bar > .breadcrumbs { .file_manager > .nav_bar > .breadcrumbs {
flex-grow: .8; flex-grow: .8;
flex-shrink: 1; flex-shrink: 1;
min-width: 0;
} }
.file_manager > .nav_bar > .input_search { .file_manager > .nav_bar > .input_search {
flex-grow: .2; flex-grow: .2;
flex-shrink: 1; flex-shrink: 1;
min-width: 0;
} }
.file_manager > .directory_sorters {
flex-shrink: 0;
display: flex;
flex-direction: row;
position: relative;
}
.file_manager > .directory_sorters > div {
flex-shrink: 0;
flex-grow: 1;
display: inline-block;
margin: 4px 12px;
border-bottom: 1px solid var(--input_color);
}
.file_manager > .directory_area { .file_manager > .directory_area {
flex-shrink: 1; flex-shrink: 1;
flex-grow: 1; flex-grow: 1;
@@ -45,6 +75,9 @@
text-align: left; text-align: left;
box-sizing: border-box; box-sizing: border-box;
} }
.file_manager > .directory_area > div {
box-sizing: border-box;
}
.file_manager > .status_bar { .file_manager > .status_bar {
flex-shrink: 0; flex-shrink: 0;
text-align: left; text-align: left;
@@ -52,9 +85,10 @@
.node { .node {
position: relative; position: relative;
height: 24px; height: 32px;
overflow: hidden; overflow: hidden;
margin: 8px; border-radius: 4px;
margin: 6px;
box-sizing: border-box; box-sizing: border-box;
display: block; display: block;
color: var(--text_color); color: var(--text_color);
@@ -69,13 +103,14 @@
} }
.spinner { .spinner {
position: relative; position: absolute;
display: block; display: block;
margin: auto; margin: auto;
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
top: 50%; top: 50%;
transform: translateY(-50%); left: 50%;
transform: translate(-50%, -50%);
width: 100px; width: 100px;
height: 100px; height: 100px;
} }
@@ -90,7 +125,7 @@
<div id="page_body" class="page_body"> <div id="page_body" class="page_body">
<div id="file_manager" class="file_manager"> <div id="file_manager" class="file_manager">
<div id="nav_bar" class="nav_bar highlight_light"> <div id="nav_bar" class="nav_bar highlight_light">
<button id="btn_menu"></button> <button id="btn_menu" onclick="toggleMenu();"></button>
<div class="spacer"></div> <div class="spacer"></div>
<button id="btn_back" ></button id="btn_forward"> <button id="btn_back" ></button id="btn_forward">
<button id="btn_up" ></button id="btn_forward"> <button id="btn_up" ></button id="btn_forward">
@@ -104,6 +139,7 @@
<div class="spacer"></div> <div class="spacer"></div>
<button id="btn_reload"></button> <button id="btn_reload"></button>
</div> </div>
<div id="directory_sorters" class="directory_sorters"></div>
<div id="directory_area" class="directory_area"></div> <div id="directory_area" class="directory_area"></div>
<div id="directory_footer" class="status_bar highlight_light"></div> <div id="directory_footer" class="status_bar highlight_light"></div>
</div> </div>
@@ -115,8 +151,9 @@
{{template `util.js`}} {{template `util.js`}}
{{template `FileManager.js`}} {{template `FileManager.js`}}
let fm = null;
window.addEventListener("load", () => { window.addEventListener("load", () => {
let fm = new FileManager(document.getElementById("file_manager")); fm = new FileManager(document.getElementById("file_manager"));
fm.getUserFiles(); fm.getUserFiles();
}); });
</script> </script>