diff --git a/pixelapi/file.go b/pixelapi/file.go index fe4cefb..21f0d4f 100644 --- a/pixelapi/file.go +++ b/pixelapi/file.go @@ -24,7 +24,12 @@ type FileInfo struct { MimeType string `json:"mime_type"` MimeImage string `json:"mime_image"` ThumbnailHREF string `json:"thumbnail_href"` - Availability string `json:"availability"` + + Availability string `json:"availability"` + AvailabilityMessage string `json:"availability_message"` + AvailabilityName string `json:"availability_name"` + + CanEdit bool `json:"can_edit"` } // GetFileInfo gets the FileInfo from the pixeldrain API diff --git a/res/include/img/icons/edit.svg b/res/include/img/icons/edit.svg new file mode 100644 index 0000000..4b8a056 --- /dev/null +++ b/res/include/img/icons/edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/include/script/dependencies/Modal.js b/res/include/script/dependencies/Modal.js new file mode 100644 index 0000000..95f15fb --- /dev/null +++ b/res/include/script/dependencies/Modal.js @@ -0,0 +1,95 @@ + +let modal_global_index = 100 + +// Modal creates a new modal window and shows it. The width and height are will +// be adjusted to the screen size. Content should be added to the `body` +// property +function Modal(parent, closeCallback, title, width, height) { + this.parent = parent + this.closeCallback = closeCallback + this.title = title + this.width = width + this.height = height + this.visible = false + + this.background = document.createElement("div") + this.background.classList = "modal_background" + this.background.addEventListener("click", e => { this.close() }) + + this.window = document.createElement("div") + this.window.classList = "modal_window" + this.window.style.width = this.width + this.window.style.height = this.height + this.window.addEventListener("click", e => { e.stopPropagation() }) + + this.header = document.createElement("div") + this.header.classList = "modal_header highlight_1" + + this.titleDiv = document.createElement("div") + this.titleDiv.classList = "modal_title" + this.titleDiv.innerText = this.title + + this.btnClose = document.createElement("button") + this.btnClose.classList = "modal_btn_close button_red" + this.btnClose.innerHTML = 'close' + this.btnClose.addEventListener("click", e => { this.close() }) + + this.body = document.createElement("div") + this.body.classList = "modal_body" + + // And add all the elements to eachother. + this.header.append(this.titleDiv) + this.header.append(this.btnClose) + this.window.append(this.header) + this.window.append(this.body) + this.background.append(this.window) +} + +Modal.prototype.setTitle = function(title) { + this.title = title + this.titleDiv.innerText = title +} + +Modal.prototype.setBody = function(element) { + this.body.innerHTML = "" + this.body.append(element) +} + +Modal.prototype.open = function() { + if (this.visible) { return } + this.visible = true + + console.debug("Showing modal "+this.title) + + // Each time a modal is shown it gets a z-index which is one higher of the + // previous one. This makes sure they are always shown and closed in order + this.background.style.zIndex = modal_global_index + modal_global_index++ + + this.parent.prepend(this.background) + + // If an element is created and shown in the same frame it won't render the + // transition. So here we wait for a few frames to make it visible + this.background.style.display = "" + setTimeout(() => { this.background.style.opacity = 1 }, 40) + + // This is a workaround for a chrome bug which makes it so hidden + // windows can't be scrolled after they are shown + this.body.focus() +} + +Modal.prototype.close = function() { + if (!this.visible) { return } + this.visible = false + + if (this.closeCallback) { + this.closeCallback() + } + + // First we make it invisible with a transition. When we remove it so the + // user can click through it + this.background.style.opacity = 0 + + // Wait for the animation to finish and remove the window + setTimeout(() => {this.parent.removeChild(this.background)}, 400) +} diff --git a/res/include/script/file_manager/DirectoryElement.js b/res/include/script/file_manager/DirectoryElement.js index 7c8c994..3b035cd 100644 --- a/res/include/script/file_manager/DirectoryElement.js +++ b/res/include/script/file_manager/DirectoryElement.js @@ -53,7 +53,7 @@ function DirectoryElement(directoryArea, footer) { // files in the directory and the last scroll position. These are used for // rendering the file list correctly - // type: {icon, name, href, type, size, sizeLabel, dateCreated} + // type: {icon, name, href, type, size, sizeLabel, dateCreated, selected} this.allFiles = [] // This array contains indexes referring to places in the allFiles array @@ -77,6 +77,7 @@ DirectoryElement.prototype.addFile = function(icon, name, href, type, size, size size: size, sizeLabel: sizeLabel, dateCreated: dateCreated, + selected: false, }) } diff --git a/res/include/script/file_manager/DirectoryNode.js b/res/include/script/file_manager/DirectoryNode.js new file mode 100644 index 0000000..0933a91 --- /dev/null +++ b/res/include/script/file_manager/DirectoryNode.js @@ -0,0 +1,99 @@ + +function DirectoryNode(file, index) { + this.el = document.createElement("div") + this.el.classList = "node" + if (file.selected) { + this.el.classList += " node_selected" + } + this.el.href = file.href + this.el.target = "_blank" + this.el.title = file.name + this.el.setAttribute("fileindex", index) + + this.el.addEventListener("click", e => { + if (e.detail > 1) { + return // Prevent dblclick from triggering click + } + if (e.which == 2) { + // Middle mouse button opens the file in a new window + this.open(true) + return + } + this.select() + }) + this.el.addEventListener("tap") + this.el.addEventListener("dblclick", e => { + this.open(false) + }) + + { + let cell = document.createElement("div") + let thumb = document.createElement("img") + thumb.src = file.icon + cell.appendChild(thumb) + let label = document.createElement("span") + label.innerText = file.name + cell.appendChild(label) + cell.appendChild(label) + this.el.appendChild(cell) + } + { + let cell = document.createElement("div") + cell.style.width = this.fieldDateWidth + let label = document.createElement("span") + label.innerText = printDate(new Date(file.dateCreated), true, true, false) + cell.appendChild(label) + this.el.appendChild(cell) + } + { + let cell = document.createElement("div") + cell.style.width = this.fieldSizeWidth + let label = document.createElement("span") + label.innerText = file.sizeLabel + cell.appendChild(label) + this.el.appendChild(cell) + } + { + let cell = document.createElement("div") + cell.style.width = this.fieldTypeWidth + let label = document.createElement("span") + label.innerText = file.type + cell.appendChild(label) + this.el.appendChild(cell) + } + + return this.el +} + +DirectoryNode.prototype.select = function() { + if (this.el.classList.contains("node_selected")) { + this.el.classList = "node" + file.selected = false + } else { + this.el.classList = "node node_selected" + file.selected = true + } +} +DirectoryNode.prototype.open = function(newTab) { + if (newTab) { + window.open(file.href, "_blank") + } else { + window.open(file.href) + } +} +DirectoryNode.prototype.click = function(e) { + if (e.detail > 1) { + return // Prevent dblclick from triggering click + } + if (e.which == 2) { + // Middle mouse button opens the file in a new window + e.preventDefault() + window.open(file.href, "_blank") + return + } + + +} +DirectoryNode.prototype.doubleClick = function() { + window.open(file.href) +} diff --git a/res/include/script/file_viewer/DetailsWindow.js b/res/include/script/file_viewer/DetailsWindow.js index a7401fb..8afe5ca 100644 --- a/res/include/script/file_viewer/DetailsWindow.js +++ b/res/include/script/file_viewer/DetailsWindow.js @@ -3,32 +3,30 @@ function DetailsWindow(viewer) { this.visible = false this.file = null this.graph = 0 + this.modal = new Modal( + document.getElementById("file_viewer"), + () => { this.toggle() }, + "File Details", "1200px", "1000px", + ) - this.divPopup = document.getElementById("details_popup") - this.btnDetails = document.getElementById("btn_details") - this.btnCloseDetails = document.getElementById("btn_close_details") - this.divFileDetails = document.getElementById("info_file_details") + let clone = document.getElementById("tpl_details_popup").content.cloneNode(true) + this.divFileDetails = clone.querySelector(".info_file_details") + this.modal.setBody(clone) - this.btnDetails.addEventListener("click", () => { this.toggle() }) - this.btnCloseDetails.addEventListener("click", () => { this.toggle() }) + this.btnDetails = document.getElementById("btn_details") + this.btnDetails.addEventListener("click", () => { this.toggle() }) } DetailsWindow.prototype.toggle = function() { if (this.visible) { - this.divPopup.style.opacity = "0" - this.divPopup.style.visibility = "hidden" + this.modal.close() this.btnDetails.classList.remove("button_highlight") this.visible = false } else { - this.divPopup.style.opacity = "1" - this.divPopup.style.visibility = "visible" + this.modal.open() this.btnDetails.classList.add("button_highlight") this.visible = true - // This is a workaround for a chrome bug which makes it so hidden - // windows can't be scrolled after they are shown - this.divPopup.focus() - if (this.graph === 0) { this.renderGraph() } @@ -42,8 +40,7 @@ DetailsWindow.prototype.setFile = function(file) { if (this.viewer.isList) { desc = file.description } - this.divFileDetails.innerHTML = "" - + "" + this.divFileDetails.innerHTML = "" + "" + "" + "" @@ -51,7 +48,6 @@ DetailsWindow.prototype.setFile = function(file) { + "" + "" + "" - + "
Name" + escapeHTML(file.name) + "
Name" + escapeHTML(file.name) + "
URL"+file.link+"
Mime Type" + escapeHTML(file.mime_type) + "
ID" + file.id + "
Bandwidth" + formatDataVolume(file.bandwidth_used, 4) + "
Upload Date" + printDate(file.date_created, true, true, true) + "
Description" + escapeHTML(desc) + "
" if(this.visible && file.timeseries_href !== "") { this.updateGraph(file) diff --git a/res/include/script/file_viewer/EditWindow.js b/res/include/script/file_viewer/EditWindow.js new file mode 100644 index 0000000..26c84a9 --- /dev/null +++ b/res/include/script/file_viewer/EditWindow.js @@ -0,0 +1,52 @@ +function EditWindow() { + this.visible = false + this.modal = new Modal( + document.getElementById("file_viewer"), + () => { this.toggle() }, + "Edit File", "1000px", "auto", + ) + + let clone = document.getElementById("tpl_edit_file").content.cloneNode(true) + clone.querySelector(".btn_delete_file").addEventListener("click", () => { this.deleteFile() }) + this.modal.setBody(clone) + + this.btnEdit = document.getElementById("btn_edit") + this.btnEdit.addEventListener("click", () => { this.toggle() }) +} + +EditWindow.prototype.toggle = function() { + if (this.visible) { + this.modal.close() + this.btnEdit.classList.remove("button_highlight") + this.visible = false + } else if (!this.visible && this.file.can_edit) { + this.modal.open() + this.btnEdit.classList.add("button_highlight") + this.visible = true + } +} + +EditWindow.prototype.setFile = function(file) { + this.file = file + this.modal.setTitle("Editing "+file.name) + + if (this.file.can_edit) { + this.btnEdit.style.display = "" + } else { + this.btnEdit.style.display = "none" + } +} + +EditWindow.prototype.deleteFile = function() { + if (!confirm("Are you sure you want to delete '"+this.file.name+"'?")) { + return + } + + fetch( + this.file.get_href, {method: "DELETE"} + ).then(resp => { + this.modal.setBody(document.createTextNode("This file has been deleted")) + }).catch(err => { + alert("Error! Could not delete file") + }) +} diff --git a/res/include/script/file_viewer/Toolbar.js b/res/include/script/file_viewer/Toolbar.js index c9d00a1..d7be9b4 100644 --- a/res/include/script/file_viewer/Toolbar.js +++ b/res/include/script/file_viewer/Toolbar.js @@ -1,8 +1,9 @@ function Toolbar(viewer) { - this.viewer = viewer - this.visible = false - this.sharebarVisible = false - this.currentFile = null + this.viewer = viewer + this.visible = false + this.sharebarVisible = false + this.currentFile = null + this.editWindow = null this.divToolbar = document.getElementById("toolbar") this.divFilePreview = document.getElementById("filepreview") @@ -69,71 +70,67 @@ Toolbar.prototype.toggleSharebar = function() { } Toolbar.prototype.download = function() { - let triggerDL = (captchaResp = "") => { - if (captchaResp === "") { - this.downloadFrame.src = this.currentFile.download_href - } else { - this.downloadFrame.src = this.currentFile.download_href+"&recaptcha_response="+captchaResp - } - } - if (captchaKey === "none" || captchaKey === ""){ - // If the server doesn't support captcha there's no use in checking - // availability - triggerDL() - return - } - if (recaptchaResponse !== "") { - // Captcha already filled in. Use the saved captcha responsse to - // download the file - triggerDL(recaptchaResponse) - - // Reset the key - recaptchaResponse = "" + console.debug("Server doesn't support captcha, starting download") + this.downloadFrame.src = this.currentFile.download_href return } - fetch(this.currentFile.availability_href).then(resp => { - return resp.json() - }).then(resp => { - let popupDiv = document.getElementById("captcha_popup") - let popupTitle = document.getElementById("captcha_popup_title") - let popupContent = document.getElementById("captcha_popup_content") + if (this.currentFile.availability === "") { + console.debug("File is available, starting download") + this.downloadFrame.src = this.currentFile.download_href + } else { + console.debug("File is not readily available, showing captcha dialog") + + let showCaptcha = (title, text) => { + // Create the modal + this.captchaModal = new Modal( + document.getElementById("file_viewer"), + null, title, "500px", "auto", + ) + + // Clone the popup contents and insert them into the popup + let clone = document.getElementById("tpl_captcha_popup").content.cloneNode(true) + clone.querySelector(".captcha_text").innerText = text + recaptchaElement = clone.querySelector(".captcha_popup_captcha") + this.captchaModal.setBody(clone) + + // Set the callback function + recaptchaCallback = token => { + // Download the file using the recaptcha token + this.downloadFrame.src = this.currentFile.download_href+"&recaptcha_response="+token + this.captchaModal.close() + } - let showCaptcha = () => { // Load the recaptcha script with a load function let script = document.createElement("script") script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit" document.body.appendChild(script) // Show the popup - popupDiv.style.opacity = "1" - popupDiv.style.visibility = "visible" + this.captchaModal.open() } - if (resp.value === "file_rate_limited_captcha_required") { - popupTitle.innerText = "Rate limiting enabled!" - popupContent.innerText = "This file is using a suspicious "+ - "amount of bandwidth relative to its popularity. To "+ - "continue downloading this file you will have to "+ - "prove that you're a human first." - showCaptcha() - } else if (resp.value === "virus_detected_captcha_required") { - popupTitle.innerText = "Malware warning!" - popupContent.innerText = "According to our scanning "+ - "systems this file may contain a virus of type '"+ - resp.extra+"'. You can continue downloading this file at "+ - "your own risk, but you will have to prove that you're a "+ - "human first." - showCaptcha() - } else { - console.warn("resp.value not valid: "+resp.value) - triggerDL() + console.log(this.currentFile.availability) + if (this.currentFile.availability === "file_rate_limited_captcha_required") { + console.debug("Showing rate limiting captcha") + showCaptcha( + "Rate limiting enabled!", + "This file is using a suspicious amount of bandwidth relative "+ + "to its popularity. To continue downloading this file you "+ + "will have to prove that you're a human first.", + ) + } else if (this.currentFile.availability === "virus_detected_captcha_required") { + console.debug("Showing virus captcha") + showCaptcha( + "Malware warning!", + "According to our scanning systems this file may contain a "+ + "virus of type '"+this.currentFile.availability_name+"'. You "+ + "can continue downloading this file at your own risk, but you "+ + "will have to prove that you're a human first.", + ) } - }).catch(e => { - console.warn("fetch availability failed: "+e) - triggerDL() - }) + } } Toolbar.prototype.copyUrl = function() { @@ -154,23 +151,13 @@ Toolbar.prototype.copyUrl = function() { }, 60000) } - // Called by the google recaptcha script -let recaptchaResponse = "" +let recaptchaElement = null +let recaptchaCallback = null function loadCaptcha(){ - grecaptcha.render("captcha_popup_captcha", { + grecaptcha.render(recaptchaElement, { sitekey: captchaKey, theme: "dark", - callback: token => { - recaptchaResponse = token - document.getElementById("btn_download").click() - - // Hide the popup - setTimeout(() => { - let popupDiv = document.getElementById("captcha_popup") - popupDiv.style.opacity = "0" - popupDiv.style.visibility = "hidden" - }, 1000) - } + callback: recaptchaCallback, }) } diff --git a/res/include/script/file_viewer/Viewer.js b/res/include/script/file_viewer/Viewer.js index e208e65..89bb2e4 100644 --- a/res/include/script/file_viewer/Viewer.js +++ b/res/include/script/file_viewer/Viewer.js @@ -4,6 +4,7 @@ function Viewer(type, viewToken, data) { this.listNavigator = null this.detailsWindow = null this.divFilepreview = null + this.file = null this.title = "" // Contains either the file name or list title this.listId = "" this.viewToken = "" @@ -14,6 +15,7 @@ function Viewer(type, viewToken, data) { this.viewToken = viewToken this.toolbar = new Toolbar(this) this.detailsWindow = new DetailsWindow(this) + this.editWindow = new EditWindow() this.divFilepreview = document.getElementById("filepreview") @@ -63,7 +65,13 @@ function Viewer(type, viewToken, data) { this.initialized = true } +Viewer.prototype.getFile = function() { + return this.file +} + Viewer.prototype.setFile = function(file) { + this.file = file + if (this.isList) { document.getElementById("file_viewer_headerbar_title").style.lineHeight = "1em" document.getElementById("file_viewer_list_title").innerText = this.title @@ -76,6 +84,7 @@ Viewer.prototype.setFile = function(file) { // Relay the file change event to all components this.detailsWindow.setFile(file) + this.editWindow.setFile(file) this.toolbar.setFile(file) // Register a new view. We don't care what this returns becasue we can't @@ -169,6 +178,7 @@ Viewer.prototype.keyboardEvent = function(evt) { return // prevent custom shortcuts from interfering with system shortcuts } + console.debug("Key pressed: "+evt.keyCode) switch (evt.keyCode) { case 65: // A or left arrow key go to previous file case 37: @@ -200,6 +210,9 @@ Viewer.prototype.keyboardEvent = function(evt) { case 73: // I to open the details window this.detailsWindow.toggle() break + case 69: // E to open the edit window + this.editWindow.toggle() + break case 81: // Q to close the window window.close() break @@ -217,35 +230,28 @@ function escapeHTML(str) { } function fileFromAPIResp(resp) { - let file = { - id: resp.id, - name: resp.name, - mime_type: resp.mime_type, - size: resp.size, - date_created: new Date(resp.date_upload), - date_last_view: new Date(resp.date_last_view), - views: resp.views, - bandwidth_used: resp.bandwidth_used, - description: "", - icon_href: apiEndpoint+"/file/"+resp.id+"/thumbnail", - get_href: apiEndpoint+"/file/"+resp.id, - download_href: apiEndpoint+"/file/"+resp.id+"?download", - availability_href: apiEndpoint+"/file/"+resp.id+"/availability", - view_href: apiEndpoint+"/file/"+resp.id+"/view", - timeseries_href: apiEndpoint+"/file/"+resp.id+"/timeseries", - link: domainURL()+"/u/"+resp.id, + resp.date_created = new Date(resp.date_upload) + resp.date_last_view = new Date(resp.date_last_view) + resp.icon_href = apiEndpoint+"/file/"+resp.id+"/thumbnail" + resp.get_href = apiEndpoint+"/file/"+resp.id + resp.download_href = apiEndpoint+"/file/"+resp.id+"?download" + resp.view_href = apiEndpoint+"/file/"+resp.id+"/view" + resp.timeseries_href = apiEndpoint+"/file/"+resp.id+"/timeseries" + resp.link = domainURL()+"/u/"+resp.id + if (resp.description === undefined) { + resp.description = "" } - if (resp.description !== undefined) { - file.description = resp.description - } - return file + + console.debug("New file:") + console.debug(resp) + + return resp } function fileFromSkyNet(resp) { let file = fileFromAPIResp(resp) file.icon_href = "/res/img/mime/empty.png" - file.get_href = "https://sky.pixeldrain.com/file/"+resp.id - file.download_href = "https://sky.pixeldrain.com/file/"+resp.id+"?attachment=1" - file.availability_href = "" + file.get_href = "https://skydrain.net/file/"+resp.id + file.download_href = "https://skydrain.net/file/"+resp.id+"?attachment=1" file.view_href = "" file.timeseries_href = "" file.link = domainURL()+"/s/"+resp.id diff --git a/res/include/style/file_manager.css b/res/include/style/file_manager.css index fea4098..6386613 100644 --- a/res/include/style/file_manager.css +++ b/res/include/style/file_manager.css @@ -123,11 +123,15 @@ /* padding-top: 6px; */ } -.node:hover, .node_selected { +.node:hover:not(.node_selected) { background-color: var(--input_color_dark); color: var(--input_text_color); text-decoration: none; } +.node_selected { + background-color: var(--highlight_color); + color: var(--highlight_text_color); +} .node > div { height: 100%; overflow: hidden; diff --git a/res/include/style/layout.css b/res/include/style/layout.css index 1388005..ee054c6 100644 --- a/res/include/style/layout.css +++ b/res/include/style/layout.css @@ -17,7 +17,35 @@ local('Cantarell Light'), local('Cantarell, Light'), local('Cantarell-Light'), - url("/res/misc/Cantarell-Light.otf") format("opentype"); + url(/res/misc/Cantarell-Light.otf) format("opentype"); +} + +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: local('Material Icons'), + local('MaterialIcons-Regular'), + url(/res/misc/MaterialIcons-Regular.woff2) format('woff2'), + url(/res/misc/MaterialIcons-Regular.woff) format('woff'), + url(/res/misc/MaterialIcons-Regular.ttf) format('truetype'); +} +.icon { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; /* Preferred icon size */ + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + text-rendering: optimizeLegibility; +} +.icon.small { + font-size: 16px; } /* Page rendering configuration */ diff --git a/res/include/style/modal.css b/res/include/style/modal.css new file mode 100644 index 0000000..4873931 --- /dev/null +++ b/res/include/style/modal.css @@ -0,0 +1,58 @@ +.modal_background { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.6); + opacity: 0; + transition: opacity .4s; +} + +.modal_window { + position: absolute; + z-index: inherit; + display: flex; + flex-direction: column; + background-color: var(--layer_2_color); + max-height: 100%; + max-width: 100%; + top: 20%; + left: 50%; + transform: translate(-50%, -20%); + padding: 0; + box-sizing: border-box; + text-align: left; + box-shadow: var(--shadow_color) 0px 0px 50px; +} + +.modal_header { + flex-grow: 0; + flex-shrink: 0; + display: flex; + flex-direction: row; + padding: 4px; +} + +.modal_title { + flex-grow: 1; + flex-shrink: 0; + + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + font-size: 1.2em; +} + +.modal_btn_close { + flex-grow: 0; + flex-shrink: 0; +} + +.modal_body { + flex-grow: 1; + flex-shrink: 1; + overflow: auto; + padding: 10px; +} diff --git a/res/include/style/viewer.css b/res/include/style/viewer.css index 3d6816d..2aa3959 100644 --- a/res/include/style/viewer.css +++ b/res/include/style/viewer.css @@ -253,45 +253,7 @@ || MISC COMPONENTS || ===================== */ -.popup { - position: absolute; - visibility: hidden; - display: flex; - flex-direction: column; - opacity: 0; - transition: visibility .5s, opacity .5s; - background-color: var(--layer_2_color); - border-color: var(--layer_2_color_border); - max-height: 100%; - max-width: 100%; - top: 20%; - left: 50%; - transform: translate(-50%, -20%); - padding: 0; - box-sizing: border-box; - text-align: left; - box-shadow: var(--shadow_color) 0px 0px 50px; -} -.popup > .highlight_1 { - font-size: 1.2em; -} -.popup > .content_area { - flex: 1; - overflow: auto; - padding: 10px; -} - -.details_popup{ - width: 1500px; - height: 800px; - z-index: 200; -} -.captcha_popup{ - height: auto; - width: 450px; - z-index: 201; -} -#captcha_popup_captcha > div { +.captcha_popup_captcha > div { display: inline-block; } diff --git a/res/static/misc/MaterialIcons-Regular.ttf b/res/static/misc/MaterialIcons-Regular.ttf new file mode 100644 index 0000000..7015564 Binary files /dev/null and b/res/static/misc/MaterialIcons-Regular.ttf differ diff --git a/res/static/misc/MaterialIcons-Regular.woff b/res/static/misc/MaterialIcons-Regular.woff new file mode 100644 index 0000000..b648a3e Binary files /dev/null and b/res/static/misc/MaterialIcons-Regular.woff differ diff --git a/res/static/misc/MaterialIcons-Regular.woff2 b/res/static/misc/MaterialIcons-Regular.woff2 new file mode 100644 index 0000000..9fa2112 Binary files /dev/null and b/res/static/misc/MaterialIcons-Regular.woff2 differ diff --git a/res/template/account/file_manager.html b/res/template/account/file_manager.html index 09b865b..1cdfa38 100644 --- a/res/template/account/file_manager.html +++ b/res/template/account/file_manager.html @@ -50,10 +50,10 @@ let breadcrumbs = document.querySelector("#nav_bar > .breadcrumbs") if (window.location.href.endsWith("?files")) { - breadcrumbs.value += "/Files" + breadcrumbs.value = "/{{.Username}}/Files" fm.getUserFiles() } else if (window.location.href.endsWith("?lists")) { - breadcrumbs.value += "/Lists" + breadcrumbs.value = "/{{.Username}}/Lists" fm.getUserLists() } else { alert("invalid file manager type") diff --git a/res/template/file_viewer.html b/res/template/file_viewer.html index 57c0fb5..bcec57b 100644 --- a/res/template/file_viewer.html +++ b/res/template/file_viewer.html @@ -13,7 +13,7 @@ {{.OGData}} @@ -22,7 +22,7 @@
- + {{template `pixeldrain.svg` .}} @@ -30,7 +30,9 @@
{{.Title}}
- +
@@ -43,29 +45,33 @@
N/A
- - + {{template "advertisement" .}} @@ -99,52 +105,61 @@
{{template "spinner.svg" .}}
- - - - + + + + + +