diff --git a/res/include/script/file_manager/FileManager.js b/res/include/script/file_manager/FileManager.js new file mode 100644 index 0000000..344dc8f --- /dev/null +++ b/res/include/script/file_manager/FileManager.js @@ -0,0 +1,186 @@ +function FileManager(windowElement) { + this.window = windowElement; + this.navBar = this.window.querySelector("#nav_bar"); + this.btnMenu = this.navBar.querySelector("#btn_menu"); + this.btnBack = this.navBar.querySelector("#btn_back"); + this.btnUp = this.navBar.querySelector("#btn_up"); + this.btnForward = this.navBar.querySelector("#btn_forward"); + this.btnHome = this.navBar.querySelector("#btn_home"); + this.breadcrumbs = this.navBar.querySelector("#breadcrumbs"); + this.btnReload = this.navBar.querySelector("#btn_reload"); + this.inputSearch = this.navBar.querySelector("#input_search"); + this.directoryArea = this.window.querySelector("#directory_area"); + this.directoryFooter = this.window.querySelector("#directory_footer"); + + this.dirContainer = document.createElement("div"); + this.directoryArea.appendChild(this.dirContainer); + + this.inputSearch.addEventListener("keyup", (e) => { + this.search(this.inputSearch.value); + }) + this.directoryArea.addEventListener("scroll", (e) => { + this.renderVisibleFiles(this.visibleFiles, false); + }) + + this.allFiles = []; + this.visibleFiles = []; + + this.lastScrollTop = 0; +} + +FileManager.prototype.search = function(term) { + if (term === "") { + this.visibleFiles = this.allFiles; + this.renderVisibleFiles(this.visibleFiles, true); + return + } + + this.visibleFiles = []; + + term = term.toLowerCase(); + for (let i in this.allFiles) { + if (this.allFiles[i].name.toLowerCase().includes(term)) { + this.visibleFiles.push(this.allFiles[i]); + } + } + this.renderVisibleFiles(this.visibleFiles, true); +} + +FileManager.prototype.getDirectory = function(path) { + console.log("ayy!"); +} + +FileManager.prototype.getUserFiles = function() { + let getAll = (page) => { + fetch(apiEndpoint+"/user/files?page="+page+"&limit=10000").then(resp => { + if (!resp.ok) {Promise.reject("yo");} + return resp.json(); + }).then(resp => { + if (page === 0) { + this.allFiles = resp.files; + } else { + this.allFiles = this.allFiles.concat(resp.files); + } + + this.allFiles.sort((a, b) => { + return a.name.localeCompare(b.name); + }); + this.visibleFiles = this.allFiles; + + this.renderVisibleFiles(this.visibleFiles, true); + + if (resp.files.length === 10000) { + getAll(page+1); + } + }).catch((err) => { + console.log("Req failed:" + err); + }) + } + + getAll(0); +} + +FileManager.prototype.renderVisibleFiles = function(files, freshStart) { + if (freshStart) { + this.dirContainer.innerHTML = ""; + + let totalSize = 0; + for (let i in files) { + totalSize += files[i].size; + } + this.directoryFooter.innerText = files.length+ + " items (0 directories and "+ + files.length+ + " files). Total size: " + +formatDataVolume(totalSize); + } + + let scrollDown = this.lastScrollTop <= this.directoryArea.scrollTop; + this.lastScrollTop = this.directoryArea.scrollTop; + + let fileHeight = 28; + let totalHeight = (files.length * fileHeight)+16; + let viewportHeight = this.directoryArea.clientHeight+100; + let paddingTop = this.directoryArea.scrollTop-100; + if (paddingTop < 0) { paddingTop = 0;} + let paddingBottom = totalHeight - paddingTop - viewportHeight; + if (paddingBottom < 0) {paddingBottom = 0;} + + // Pad the items out which we're not going to show + 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; } + + // First remove the elements which are out of bounds + let firstEl; + let firstIdx = -1; + let lastEl; + let lastIdx = -1; + while (true && !freshStart) { + firstEl = this.dirContainer.firstElementChild; + if (firstEl === null) {break;} + firstIdx = Number.parseInt(firstEl.getAttribute("fileindex")); + lastEl = this.dirContainer.lastElementChild; + lastIdx = Number.parseInt(lastEl.getAttribute("fileindex")); + + this.dirContainer.insert + + if (firstIdx < start) { + this.dirContainer.removeChild(firstEl); + console.debug("Remove start "+firstIdx); + } else if (lastIdx > end) { + this.dirContainer.removeChild(lastEl); + console.debug("Remove end "+lastIdx); + } else { + break; + } + } + + console.debug("Start "+start+" end "+end+" first el "+firstIdx+" last el "+lastIdx); + + + let makeButton = (i, file) => { + let el = document.createElement("a"); + el.classList = "node"; + el.href = "/u/"+file.id; + el.target = "_blank"; + el.title = file.name; + el.setAttribute("fileindex", i); + + let thumb = document.createElement("img"); + thumb.src = apiEndpoint+"/file/"+file.id+"/thumbnail?width=32&height=32"; + + let label = document.createElement("span"); + label.innerText = file.name; + + el.appendChild(thumb); + el.appendChild(label); + return el; + } + + // Then add the elements which have become visible. When the user scrolls + // down we can append the items in chronologic order, but when the user + // scrolls up we have to prepend the items in reverse order to avoid them + // appearing from high to low. + if (scrollDown) { + for (let i = start; i <= end && i < files.length; i++) { + if (firstIdx !== -1 && lastIdx !== -1 && i >= firstIdx && i <= lastIdx) { + continue; + } + + this.dirContainer.append(makeButton(i, files[i])); + console.debug("Append "+i+" "+files[i].name); + } + } else { + for (let i = end; i >= start && i < files.length; i--) { + if (firstIdx !== -1 && lastIdx !== -1 && i >= firstIdx && i <= lastIdx) { + continue; + } + this.dirContainer.prepend(makeButton(i, files[i])); + console.debug("Prepend "+i+" "+files[i].name); + } + } +} diff --git a/res/include/script/file_viewer/viewer_scripts/TextViewer.js b/res/include/script/file_viewer/viewer_scripts/TextViewer.js index 52018d0..867ed0f 100644 --- a/res/include/script/file_viewer/viewer_scripts/TextViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/TextViewer.js @@ -20,7 +20,7 @@ TextViewer.prototype.getText = function() { this.pre.innerText = "Loading..."; this.container.appendChild(this.pre); - if (this.file.size > 1<<22) { // File larger than 4 MiB + if (this.file.size > 1<<20) { // File larger than 1 MiB this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."; return; } diff --git a/res/include/script/homepage.js b/res/include/script/homepage.js index 714bbbd..5d84cf3 100644 --- a/res/include/script/homepage.js +++ b/res/include/script/homepage.js @@ -53,14 +53,14 @@ UploadProgressBar.prototype.onFinished = function(id){ this.uploadDiv.appendChild(document.createElement("br")) this.uploadDiv.appendChild(linkSpan) } -UploadProgressBar.prototype.onFailure = function(error) { +UploadProgressBar.prototype.onFailure = function(val, msg) { this.uploadDiv.innerHTML = "" // Remove uploading progress this.uploadDiv.style.background = 'var(--danger_color)' this.uploadDiv.appendChild(document.createTextNode(this.file.name)) this.uploadDiv.appendChild(document.createElement("br")) this.uploadDiv.appendChild(document.createTextNode("Upload failed after three tries:")) this.uploadDiv.appendChild(document.createElement("br")) - this.uploadDiv.appendChild(document.createTextNode(error)) + this.uploadDiv.appendChild(document.createTextNode(val)) } diff --git a/res/template/account/file_manager.html b/res/template/account/file_manager.html index a336a6a..ecdbd27 100644 --- a/res/template/account/file_manager.html +++ b/res/template/account/file_manager.html @@ -3,7 +3,6 @@ {{template "meta_tags" "File Manager"}} {{template "user_style" .}} - + + {{template "page_menu" .}}
-
- + {{template "analytics"}}