diff --git a/static/css/upload.css b/static/css/upload.css index 78226ca..f74ff49 100644 --- a/static/css/upload.css +++ b/static/css/upload.css @@ -34,6 +34,59 @@ border: 1px dotted #000000; } +.upload-dropzone.is-dragging { + background: #c7d8f2; + outline: 2px solid #000078; + outline-offset: -4px; +} + +.upload-dropzone:focus-visible { + outline: 1px dotted #000000; + outline-offset: -5px; +} + +.upload-icon { + width: 34px; + height: 30px; + position: relative; + box-sizing: border-box; + background: #ffffff; + border: 2px solid #000000; + box-shadow: inset -3px -3px 0 #dfdfdf; +} + +.upload-icon::before { + content: ""; + position: absolute; + right: -2px; + top: -2px; + width: 10px; + height: 10px; + box-sizing: border-box; + background: #dfdfdf; + border-left: 2px solid #000000; + border-bottom: 2px solid #000000; +} + +.upload-primary { + font-size: 18px; + line-height: 18px; + font-weight: bold; +} + +.upload-secondary { + font-size: 13px; + line-height: 15px; +} + +.upload-input { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); +} + .upload-options { flex: 0 0 auto; display: grid; @@ -104,59 +157,6 @@ background: #c0c0c0; } -.upload-dropzone.is-dragging { - background: #c7d8f2; - outline: 2px solid #000078; - outline-offset: -4px; -} - -.upload-dropzone:focus-visible { - outline: 1px dotted #000000; - outline-offset: -5px; -} - -.upload-icon { - width: 34px; - height: 30px; - position: relative; - box-sizing: border-box; - background: #ffffff; - border: 2px solid #000000; - box-shadow: inset -3px -3px 0 #dfdfdf; -} - -.upload-icon::before { - content: ""; - position: absolute; - right: -2px; - top: -2px; - width: 10px; - height: 10px; - box-sizing: border-box; - background: #dfdfdf; - border-left: 2px solid #000000; - border-bottom: 2px solid #000000; -} - -.upload-primary { - font-size: 18px; - line-height: 18px; - font-weight: bold; -} - -.upload-secondary { - font-size: 13px; - line-height: 15px; -} - -.upload-input { - position: absolute; - width: 1px; - height: 1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); -} - .upload-details { flex: 0 0 auto; display: flex; @@ -280,25 +280,10 @@ .upload-file-icon { grid-row: 1 / 3; - width: 16px; + width: 18px; height: 18px; - position: relative; - box-sizing: border-box; - background: #ffffff; - border: 1px solid #000000; - box-shadow: inset -2px -2px 0 #dfdfdf; -} - -.upload-file-icon::before { - content: ""; - position: absolute; - top: -1px; - right: -1px; - width: 5px; - height: 5px; - background: #dfdfdf; - border-left: 1px solid #000000; - border-bottom: 1px solid #000000; + object-fit: contain; + image-rendering: pixelated; } .upload-file-name, diff --git a/static/css/window.css b/static/css/window.css index 82507e0..340fd7d 100644 --- a/static/css/window.css +++ b/static/css/window.css @@ -26,14 +26,34 @@ } .win98-titlebar h1 { + min-width: 0; margin: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; font-size: 14px; line-height: 14px; font-weight: bold; } +.win98-titlebar-label { + display: flex; + align-items: center; + min-width: 0; + gap: 5px; +} + +.win98-titlebar-icon { + flex: 0 0 auto; + width: 16px; + height: 16px; + object-fit: contain; + image-rendering: pixelated; +} + .win98-window-controls { display: flex; + flex: 0 0 auto; gap: 2px; } diff --git a/static/js/app.js b/static/js/app.js index 2abc5cc..a7c8d58 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -36,6 +36,50 @@ function formatBytes(bytes) { return `${size.toFixed(1)} ${units[unitIndex]}`; } +function iconForFile(file) { + const filename = file.name || ""; + const mimeType = file.type || ""; + const extension = filename.includes(".") ? filename.slice(filename.lastIndexOf(".")).toLowerCase() : ""; + + if (extension === ".exe") { + return "/static/img/icons/Program Files Icons - PNG/MSONSEXT.DLL_14_6-0.png"; + } + + if (mimeType.startsWith("image/")) { + return "/static/img/sprites/bitmap.png"; + } + + if (mimeType.startsWith("video/") || mimeType.startsWith("audio/")) { + return "/static/img/icons/netshow_notransm-1.png"; + } + + if (mimeType.startsWith("text/") || extension === ".md") { + return "/static/img/sprites/notepad_file-1.png"; + } + + if ( + mimeType.includes("zip") || + mimeType.includes("compressed") || + [".rar", ".7z", ".tar", ".gz"].includes(extension) + ) { + return "/static/img/icons/Windows Icons - PNG/zipfldr.dll_14_101-0.png"; + } + + if ([".ttf", ".otf", ".woff", ".woff2"].includes(extension)) { + return "/static/img/sprites/font.png"; + } + + if (extension === ".pdf") { + return "/static/img/sprites/journal.png"; + } + + if ([".html", ".css", ".js"].includes(extension)) { + return "/static/img/sprites/frame_web-0.png"; + } + + return "/static/img/icons/Windows Icons - PNG/ole2.dll_14_DEFICON.png"; +} + function updateStatus(message) { if (uploadStatus) { uploadStatus.textContent = message; @@ -124,8 +168,10 @@ function createFileRow(selectedFile) { const row = document.createElement("div"); row.className = "upload-file-row"; - const icon = document.createElement("span"); + const icon = document.createElement("img"); icon.className = "upload-file-icon"; + icon.src = iconForFile(selectedFile.file); + icon.alt = ""; icon.setAttribute("aria-hidden", "true"); const name = document.createElement("span"); @@ -391,6 +437,10 @@ if (uploadForm) { selectedFiles.forEach((selectedFile, index) => { selectedFile.boxID = box.box_id; selectedFile.boxFile = box.files[index]; + const icon = selectedFile.row.querySelector(".upload-file-icon"); + if (icon && selectedFile.boxFile.icon_path) { + icon.src = selectedFile.boxFile.icon_path; + } }); await Promise.allSettled(selectedFiles.map((selectedFile) => { diff --git a/templates/box.html b/templates/box.html index 3607327..7e9dfbf 100644 --- a/templates/box.html +++ b/templates/box.html @@ -4,6 +4,7 @@ WarpBox - {{ .BoxID }} + @@ -14,7 +15,10 @@
-

WarpBox Explorer - {{ .BoxID }}

+
+ +

WarpBox Explorer - {{ .BoxID }}

+