style(update): Updated the styling amd layout to be much better!

This commit is contained in:
2026-04-29 01:16:17 +03:00
parent cb026d4fd1
commit 82acaffdd8
9 changed files with 2475 additions and 863 deletions

View File

@@ -516,10 +516,39 @@ func (app *App) handleLegacyUpload(ctx *gin.Context) {
return return
} }
savedFiles := make([]models.BoxFile, 0, len(files)) retentionKey := strings.TrimSpace(ctx.PostForm("retention_key"))
if retentionKey == "" {
retentionKey = strings.TrimSpace(ctx.PostForm("retention"))
}
allowZip := true
if strings.EqualFold(strings.TrimSpace(ctx.PostForm("allow_zip")), "false") {
allowZip = false
}
request := models.CreateBoxRequest{
RetentionKey: retentionKey,
Password: ctx.PostForm("password"),
AllowZip: &allowZip,
Files: make([]models.CreateBoxFileRequest, 0, len(files)),
}
for _, file := range files { for _, file := range files {
savedFile, err := boxstore.SaveUpload(boxID, file) request.Files = append(request.Files, models.CreateBoxFileRequest{Name: file.Filename, Size: file.Size})
}
if err := app.validateCreateBoxRequest(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
manifestFiles, err := boxstore.CreateManifest(boxID, request)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
savedFiles := make([]models.BoxFile, 0, len(files))
for index, file := range files {
savedFile, err := boxstore.SaveManifestUpload(boxID, manifestFiles[index].ID, file)
if err != nil { if err != nil {
_, _ = boxstore.MarkFileStatus(boxID, manifestFiles[index].ID, models.FileStatusFailed)
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }

View File

@@ -11,6 +11,10 @@ body {
display: grid; display: grid;
gap: 16px; gap: 16px;
padding: 16px; padding: 16px;
background-color: #ffffff;
background-image:
linear-gradient(180deg, rgba(255,255,255,.9), rgba(238,238,238,.58)),
repeating-linear-gradient(0deg, rgba(0,0,0,.025) 0 1px, transparent 1px 6px);
} }
.admin-nav { .admin-nav {
@@ -35,6 +39,12 @@ body {
padding: 12px; padding: 12px;
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
background: #dfdfdf;
border-top: 1px solid #ffffff;
border-left: 1px solid #ffffff;
border-right: 1px solid #808080;
border-bottom: 1px solid #808080;
box-shadow: inset 1px 1px 0 #f7f7f7, inset -1px -1px 0 #b0b0b0;
} }
.admin-link strong, .admin-link strong,
@@ -50,6 +60,10 @@ body {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
background: #fff; background: #fff;
border-top: 2px solid #808080;
border-left: 2px solid #808080;
border-right: 2px solid #ffffff;
border-bottom: 2px solid #ffffff;
} }
.admin-table th, .admin-table th,
@@ -74,7 +88,14 @@ body {
.admin-form-row textarea, .admin-form-row textarea,
.admin-form-row select { .admin-form-row select {
width: 100%; width: 100%;
box-sizing: border-box; min-height: 24px;
color: #000000;
background: #ffffff;
border-top: 1px solid #808080;
border-left: 1px solid #808080;
border-right: 1px solid #ffffff;
border-bottom: 1px solid #ffffff;
font-family: inherit;
} }
.admin-checks { .admin-checks {
@@ -103,4 +124,9 @@ body {
.admin-summary span { .admin-summary span {
padding: 6px 8px; padding: 6px 8px;
background: #dfdfdf;
border-top: 1px solid #ffffff;
border-left: 1px solid #ffffff;
border-right: 1px solid #808080;
border-bottom: 1px solid #808080;
} }

View File

@@ -15,82 +15,183 @@
} }
@font-face { @font-face {
font-family: 'PixelOperatorMono'; font-family: 'MonoCraft';
src: url('/static/fonts/pixel_operator/PixelOperatorMono-Bold.ttf'); src: url('/static/fonts/Monocraft.ttf');
font-weight: bold;
}
@font-face {
font-family: 'PixeloidSans';
src: url('/static/fonts/pixeloid_sans/PixeloidSans.ttf');
}
@font-face {
font-family: 'PixeloidSans';
src: url('/static/fonts/pixeloid_sans/PixeloidSans-Bold.ttf');
font-weight: bold;
} }
:root { :root {
font-family: 'PixeloidSans', 'PixelOperator', sans-serif, Arial, Helvetica; font-family: 'PixelOperator', 'MS Sans Serif', Arial, sans-serif;
font-smooth: never; font-smooth: never;
image-rendering: pixelated; image-rendering: pixelated;
cursor: url('/static/cursors/vaporwave-hotline-white-plus/Normal\ Select.cur'), auto; cursor: url('/static/cursors/vaporwave-hotline-white-plus/Normal\ Select.cur'), auto;
--base-font-size: 14px; --base-font-size: 14px;
/* Colours */
--w98-blue: #000078; --w98-blue: #000078;
--w98-blue-gradient: linear-gradient(to right, #000078, 80%, #0f80cd); --w98-blue-gradient: linear-gradient(90deg, #000078 0%, #000078 28%, #0f80cd 50%, #000078 72%, #000078 100%);
--w98-gray: #c0c0c0; --w98-gray: #c0c0c0;
--w98-gray2: #a6a6a6; --w98-gray2: #a6a6a6;
--w98-gray-gradient: linear-gradient(to bottom, #fff, 95%, #c0c0c0); --ok: #008000;
--danger: #800000;
scroll-behavior: smooth;
} }
a, * {
button, box-sizing: border-box;
label[for], scrollbar-width: auto;
.win98-button:not(:disabled) { scrollbar-color: #c0c0c0 #808080;
cursor: url('/static/cursors/vaporwave-hotline-white-plus/Link\ Select.cur'), auto;
}
input[type="text"],
input[type="password"],
input[type="file"],
textarea,
[contenteditable="true"] {
cursor: url('/static/cursors/vaporwave-hotline-white-plus/Hotline\ Black\ Handwriting.cur'), text;
} }
html { html {
min-height: 100%;
font-size: var(--base-font-size); font-size: var(--base-font-size);
color: white; color: #ffffff;
background-color: #000; background: #000000;
} }
html, html,
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow-x: hidden;
} }
body { body {
width: 100vw;
min-height: 100vh; min-height: 100vh;
height: auto; overflow-x: hidden;
background-color: #000000; background-color: #000000;
background-image: url('/static/img/bg/stars1.gif'); background-image: url('/static/img/bg/stars1.gif');
background-repeat: repeat; background-repeat: repeat;
background-size: auto;
font-family: 'PixelOperator', 'MS Sans Serif', Arial, sans-serif;
} }
main { main {
min-height: 100vh;
display: grid; display: grid;
place-items: center; place-items: center;
width: 100vw; padding: 18px;
min-height: 100vh; }
button,
label[for],
.menu-button,
.win98-button:not(:disabled),
a {
cursor: url('/static/cursors/vaporwave-hotline-white-plus/Link\ Select.cur'), pointer;
}
button,
input,
select,
textarea {
font-family: inherit;
}
input[type="text"],
input[type="password"],
input[type="number"],
input[type="file"],
textarea {
cursor: url('/static/cursors/vaporwave-hotline-white-plus/Hotline\ Black\ Handwriting.cur'), text;
}
:focus-visible {
outline: 2px dotted #000078;
outline-offset: 2px;
}
::-webkit-scrollbar {
width: 17px;
height: 17px;
background: #c0c0c0;
}
::-webkit-scrollbar-track {
background: repeating-linear-gradient(45deg, #c0c0c0 0 2px, #b5b5b5 2px 4px);
border-top: 1px solid #808080;
border-left: 1px solid #808080;
border-right: 1px solid #ffffff;
border-bottom: 1px solid #ffffff;
}
::-webkit-scrollbar-thumb,
::-webkit-scrollbar-button:single-button {
background: #c0c0c0;
border-top: 2px solid #ffffff;
border-left: 2px solid #ffffff;
border-right: 2px solid #000000;
border-bottom: 2px solid #000000;
box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #dfdfdf;
}
::-webkit-scrollbar-corner {
background: #c0c0c0;
}
.win98-button {
min-width: 92px;
height: 28px;
display: grid;
place-items: center;
margin: 0;
padding: 0 10px;
color: #000000;
background: var(--w98-gray);
border-top: 2px solid #ffffff;
border-left: 2px solid #ffffff;
border-right: 2px solid #000000;
border-bottom: 2px solid #000000;
box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #dfdfdf;
font-size: 13px;
line-height: 13px;
text-align: center;
text-decoration: none;
appearance: none;
}
.win98-button:disabled,
button:disabled,
input:disabled,
select:disabled,
textarea:disabled {
cursor: not-allowed;
}
.win98-button:disabled {
color: #808080;
text-shadow: 1px 1px 0 #ffffff;
}
.win98-button:active:not(:disabled),
.win98-control:active,
.menu-button[aria-expanded="true"] {
border-top-color: #000000;
border-left-color: #000000;
border-right-color: #ffffff;
border-bottom-color: #ffffff;
box-shadow: inset -1px -1px 0 #dfdfdf, inset 1px 1px 0 #808080;
padding-top: 1px;
}
@media (min-width: 1800px) {
:root { --base-font-size: 15px; }
.desktop-wrap { zoom: 1.2; }
}
@media (min-width: 2048px) {
:root { --base-font-size: 16px; }
.desktop-wrap { zoom: 1.36; }
}
@media (min-width: 2560px) {
:root { --base-font-size: 18px; }
.desktop-wrap { zoom: 1.58; }
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 1ms !important;
animation-iteration-count: 1 !important;
scroll-behavior: auto !important;
}
} }

View File

@@ -1,13 +1,12 @@
.box-window { .box-window {
width: 640px; width: min(760px, calc(100vw - 36px));
height: 460px; height: min(560px, calc(100vh - 36px));
} }
.box-toolbar { .box-toolbar {
display: flex; display: flex;
gap: 8px; gap: 8px;
height: 40px; height: 40px;
box-sizing: border-box;
padding: 6px 8px; padding: 6px 8px;
} }
@@ -20,7 +19,6 @@
grid-template-columns: 58px minmax(0, 1fr); grid-template-columns: 58px minmax(0, 1fr);
align-items: center; align-items: center;
height: 28px; height: 28px;
box-sizing: border-box;
padding: 0 8px 6px; padding: 0 8px 6px;
gap: 6px; gap: 6px;
font-size: 13px; font-size: 13px;
@@ -32,7 +30,6 @@
grid-template-columns: 58px minmax(0, 1fr); grid-template-columns: 58px minmax(0, 1fr);
align-items: center; align-items: center;
height: 24px; height: 24px;
box-sizing: border-box;
padding: 0 8px 6px; padding: 0 8px 6px;
gap: 6px; gap: 6px;
color: #333333; color: #333333;
@@ -45,7 +42,6 @@
height: 22px; height: 22px;
display: flex; display: flex;
align-items: center; align-items: center;
box-sizing: border-box;
padding: 0 6px; padding: 0 6px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -64,6 +60,10 @@
min-height: 0; min-height: 0;
margin: 0 8px 8px; margin: 0 8px 8px;
overflow: auto; overflow: auto;
background-color: #ffffff;
background-image:
linear-gradient(180deg, rgba(255,255,255,.9), rgba(238,238,238,.58)),
repeating-linear-gradient(0deg, rgba(0,0,0,.025) 0 1px, transparent 1px 6px);
} }
.box-file-grid { .box-file-grid {
@@ -81,7 +81,6 @@
grid-template-rows: 34px 18px 28px; grid-template-rows: 34px 18px 28px;
justify-items: center; justify-items: center;
align-items: center; align-items: center;
box-sizing: border-box;
padding: 8px 6px; padding: 8px 6px;
color: #000000; color: #000000;
text-decoration: none; text-decoration: none;
@@ -185,6 +184,7 @@
main { main {
display: block; display: block;
min-height: 100dvh; min-height: 100dvh;
padding: 0;
} }
.box-window { .box-window {

View File

@@ -14,7 +14,12 @@
flex: 1; flex: 1;
margin: 8px; margin: 8px;
padding: 12px; padding: 12px;
background: #c0c0c0; background-color: #dfdfdf;
background-image: repeating-linear-gradient(45deg, rgba(255,255,255,.18) 0 1px, transparent 1px 5px);
border-top: 1px solid #ffffff;
border-left: 1px solid #ffffff;
border-right: 1px solid #808080;
border-bottom: 1px solid #808080;
} }
.login-alert { .login-alert {
@@ -52,7 +57,6 @@
.login-input { .login-input {
width: 100%; width: 100%;
height: 24px; height: 24px;
box-sizing: border-box;
padding: 2px 5px; padding: 2px 5px;
color: #000000; color: #000000;
background: #ffffff; background: #ffffff;
@@ -82,7 +86,6 @@
justify-content: flex-end; justify-content: flex-end;
gap: 8px; gap: 8px;
height: 40px; height: 40px;
box-sizing: border-box;
padding: 0 8px 8px; padding: 0 8px 8px;
} }
@@ -98,6 +101,7 @@
main { main {
display: block; display: block;
min-height: 100dvh; min-height: 100dvh;
padding: 0;
} }
.login-window { .login-window {

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
.win98-window { .win98-window {
box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
color: #000000; color: #000000;
background: var(--w98-gray); background-color: #c0c0c0;
border-top: 2px solid #ffffff; background-image:
border-left: 2px solid #ffffff; linear-gradient(180deg, rgba(255,255,255,.34), rgba(0,0,0,.06)),
border-right: 2px solid #000000; repeating-linear-gradient(45deg, rgba(255,255,255,.12) 0 1px, transparent 1px 5px);
border-bottom: 2px solid #000000; border-top: 1px solid #ffffff;
box-shadow: border-left: 1px solid #ffffff;
inset -1px -1px 0 #808080, border-right: 1px solid #000000;
inset 1px 1px 0 #dfdfdf; border-bottom: 1px solid #000000;
box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #dfdfdf, 5px 6px 0 rgba(0,0,0,.5);
} }
.win98-titlebar { .win98-titlebar {
@@ -18,14 +18,23 @@
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
height: 22px; height: 22px;
box-sizing: border-box;
margin: 2px; margin: 2px;
padding: 2px 3px 2px 6px; padding: 2px 3px 2px 6px;
color: #ffffff; color: #ffffff;
background: var(--w98-blue-gradient); background: var(--w98-blue-gradient);
background-size: 240% 100%;
box-shadow: inset 0 1px 0 rgba(255,255,255,.35), inset 0 -1px 0 rgba(0,0,0,.35);
user-select: none;
animation: titlebar-center-drift 34s ease-in-out infinite alternate;
} }
.win98-titlebar h1 { @keyframes titlebar-center-drift {
0% { background-position: 0% 50%; }
100% { background-position: 100% 50%; }
}
.win98-titlebar h1,
.win98-titlebar h2 {
min-width: 0; min-width: 0;
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
@@ -60,36 +69,28 @@
.win98-control { .win98-control {
width: 16px; width: 16px;
height: 14px; height: 14px;
box-sizing: border-box;
display: grid; display: grid;
place-items: center; place-items: center;
padding: 0;
color: #000000; color: #000000;
background: var(--w98-gray); background: var(--w98-gray);
border-top: 1px solid #ffffff; border-top: 1px solid #ffffff;
border-left: 1px solid #ffffff; border-left: 1px solid #ffffff;
border-right: 1px solid #000000; border-right: 1px solid #000000;
border-bottom: 1px solid #000000; border-bottom: 1px solid #000000;
box-shadow: box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #dfdfdf;
inset -1px -1px 0 #808080,
inset 1px 1px 0 #dfdfdf;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
font-size: 12px; font-size: 12px;
line-height: 12px; line-height: 12px;
} }
.win98-menu { .win98-minimize {
display: flex; align-items: start;
align-items: center; padding-top: 0;
gap: 18px; line-height: 8px;
height: 22px;
box-sizing: border-box;
padding: 0 8px;
font-size: 13px;
line-height: 13px;
} }
.win98-panel { .win98-panel {
box-sizing: border-box;
background: #ffffff; background: #ffffff;
border-top: 2px solid #808080; border-top: 2px solid #808080;
border-left: 2px solid #808080; border-left: 2px solid #808080;
@@ -97,51 +98,10 @@
border-bottom: 2px solid #ffffff; border-bottom: 2px solid #ffffff;
} }
.win98-button {
width: 92px;
height: 28px;
box-sizing: border-box;
display: grid;
place-items: center;
margin: 0;
padding: 0 10px;
color: #000000;
background: var(--w98-gray);
border-top: 2px solid #ffffff;
border-left: 2px solid #ffffff;
border-right: 2px solid #000000;
border-bottom: 2px solid #000000;
box-shadow:
inset -1px -1px 0 #808080,
inset 1px 1px 0 #dfdfdf;
font-family: inherit;
font-size: 13px;
line-height: 13px;
text-align: center;
appearance: none;
}
.win98-button:active {
border-top-color: #000000;
border-left-color: #000000;
border-right-color: #ffffff;
border-bottom-color: #ffffff;
box-shadow:
inset -1px -1px 0 #dfdfdf,
inset 1px 1px 0 #808080;
padding: 1px 9px 0 11px;
}
.win98-button:focus-visible {
outline: 1px dotted #000000;
outline-offset: -5px;
}
.win98-statusbar { .win98-statusbar {
display: grid; display: grid;
gap: 4px; gap: 4px;
height: 22px; height: 22px;
box-sizing: border-box;
padding: 0 4px 4px; padding: 0 4px 4px;
font-size: 12px; font-size: 12px;
line-height: 12px; line-height: 12px;
@@ -152,7 +112,6 @@
align-items: center; align-items: center;
min-width: 0; min-width: 0;
padding: 0 5px; padding: 0 5px;
box-sizing: border-box;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@@ -161,3 +120,13 @@
border-right: 1px solid #ffffff; border-right: 1px solid #ffffff;
border-bottom: 1px solid #ffffff; border-bottom: 1px solid #ffffff;
} }
.win98-menu {
display: flex;
align-items: center;
gap: 18px;
height: 22px;
padding: 0 8px;
font-size: 13px;
line-height: 13px;
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,107 +3,244 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Warpbox</title> <title>WarpBox</title>
<link rel="icon" type="image/png" href="/static/WarpBoxLogo.png"> <link rel="icon" type="image/png" href="/static/WarpBoxLogo.png">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/app.css"> <link rel="stylesheet" href="/static/css/app.css">
<link rel="stylesheet" href="/static/css/window.css"> <link rel="stylesheet" href="/static/css/window.css">
<link rel="stylesheet" href="/static/css/upload.css"> <link rel="stylesheet" href="/static/css/upload.css">
</head> </head>
<body> <body>
<main> <main class="upload-main">
<section class="win98-window upload-window" aria-labelledby="upload-window-title"> <div class="desktop-wrap">
<header class="win98-titlebar upload-titlebar"> <section class="win98-window upload-window" aria-label="WarpBox upload window">
<div class="win98-titlebar-label"> <div class="win98-titlebar upload-titlebar">
<img class="win98-titlebar-icon" src="/static/WarpBoxLogo.png" alt="" aria-hidden="true"> <div class="win98-titlebar-label">
<h1 id="upload-window-title">WarpBox Upload</h1> <img class="win98-titlebar-icon" src="/static/WarpBoxLogo.png" alt="" aria-hidden="true">
</div> <h1>WarpBox</h1>
<div class="win98-window-controls" aria-hidden="true"> </div>
<span class="win98-control">_</span> <div class="win98-window-controls" aria-label="Window controls">
<span class="win98-control"></span> <button class="win98-control win98-minimize" type="button" data-action="minimize" title="Minimize" aria-label="Minimize">_</button>
<span class="win98-control">×</span> <button class="win98-control" type="button" data-action="toggle-fit" title="Fit window" aria-label="Maximize"></button>
</div> <button class="win98-control" type="button" data-action="fake-close" title="Close" aria-label="Close">×</button>
</header> </div>
<form class="upload-form" action="/upload" method="post" enctype="multipart/form-data" data-uploads-enabled="{{ if .UploadsEnabled }}true{{ else }}false{{ end }}">
<div class="win98-menu upload-menu" aria-hidden="true">
<span class="win98-menu-option">File</span>
<span class="win98-menu-option">Edit</span>
<span class="win98-menu-option">View</span>
<span class="win98-menu-option">Help</span>
</div> </div>
<div class="win98-panel upload-panel"> <nav class="menu-bar" aria-label="Upload menu">
<label class="upload-dropzone" for="file-upload"> <div class="menu-item">
<span class="upload-icon" aria-hidden="true"></span> <button class="menu-button" type="button" aria-expanded="false"><u>F</u>ile</button>
<span class="upload-primary">Drop file here</span> <div class="menu-popup" role="menu">
<span class="upload-secondary">or click Browse to choose one</span> <button class="menu-action" type="button" data-action="browse"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Add files...</span><span class="shortcut">Ctrl+O</span></button>
</label> <button class="menu-action" type="button" data-action="start-upload"><img src="/static/img/icons/check_mark_pixel.png" alt="" aria-hidden="true"><span>Start upload</span><span class="shortcut">Ctrl+U</span></button>
<button class="menu-action" type="button" data-action="copy-link"><img src="/static/img/sprites/frame_web-0.png" alt="" aria-hidden="true"><span>Copy share URL</span><span class="shortcut">Ctrl+L</span></button>
<div class="menu-separator"></div>
<button class="menu-action" type="button" data-action="clear"><img src="/static/img/icons/x_mark_pixel.png" alt="" aria-hidden="true"><span>Clear queue</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>B</u>ox</button>
<div class="menu-popup" role="menu">
{{ range .RetentionOptions }}
<button class="menu-action" type="button" data-expiry="{{ .Key }}"><span class="menu-check" data-expiry-check="{{ .Key }}">{{ if eq .Key $.DefaultRetention }}✓{{ end }}</span><span>{{ .Label }}</span><span></span></button>
{{ end }}
<div class="menu-separator"></div>
<button class="menu-action" type="button" data-action="toggle-delete-once"><span class="menu-check" data-delete-once-check></span><span>One-time download</span><span></span></button>
<button class="menu-action" type="button" data-doc="dailyQuota"><img src="/static/img/icons/scanner_alt-3.png" alt="" aria-hidden="true"><span>Upload limits...</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>O</u>ptions</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="random-password"><img src="/static/img/sprites/file_padlock.png" alt="" aria-hidden="true"><span>Generate password</span><span></span></button>
<button class="menu-action" type="button" data-action="random-box-name"><img src="/static/img/icons/directory_closed-2.png" alt="" aria-hidden="true"><span>Random box name</span><span></span></button>
<button class="menu-action" type="button" data-action="clear-password"><span></span><span>Clear password</span><span></span></button>
<button class="menu-action" type="button" data-action="toggle-page"><span class="menu-check" data-download-page-check></span><span>Download page</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>H</u>elp</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="help"><img src="/static/img/icons/tip.png" alt="" aria-hidden="true"><span>Show quick help</span><span>F1</span></button>
<button class="menu-action" type="button" data-action="terminal-help"><span>&gt;</span><span>Show cURL command</span><span></span></button>
<button class="menu-action" type="button" data-doc="about"><span>i</span><span>About WarpBox</span><span></span></button>
</div>
</div>
</nav>
<input id="file-upload" class="upload-input" type="file" name="files" multiple {{ if not .UploadsEnabled }}disabled{{ end }}> <form class="upload-form" id="upload-form" action="/box" method="post" data-uploads-enabled="{{ if .UploadsEnabled }}true{{ else }}false{{ end }}" data-max-file-bytes="{{ .MaxFileSizeBytes }}" data-max-box-bytes="{{ .MaxBoxSizeBytes }}" data-default-retention="{{ .DefaultRetention }}">
<div class="win98-panel upload-panel" id="drop-surface">
<header class="upload-header">
<div>
<p class="upload-heading">Upload files</p>
<p class="upload-subtext">Drop files into this window or browse from your computer. WarpBox creates a temporary share link when the upload finishes.</p>
</div>
<aside class="upload-quota" aria-label="Box space">
<strong>Box space</strong>
<span id="box-space-text">0 B</span>
<span class="upload-quota-track" aria-hidden="true"><span class="upload-quota-bar" id="box-space-bar"></span></span>
</aside>
</header>
<fieldset class="upload-options"> <label class="upload-dropzone" for="file-upload" tabindex="0" id="dropzone">
<legend>Box options</legend> <img class="upload-icon-img" src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true">
<label class="upload-option-row" for="upload-retention"> <span class="upload-primary">{{ if .UploadsEnabled }}Drop files here{{ else }}Guest uploads disabled{{ end }}</span>
<span>Keep files</span> <span class="upload-secondary">or <span class="upload-linklike">click to browse</span> from your computer</span>
<select id="upload-retention" class="upload-select" name="retention"> <span class="upload-secondary" id="limit-hint">Links expire automatically</span>
{{ range .RetentionOptions }} <input class="upload-input" id="file-upload" name="files" type="file" multiple {{ if not .UploadsEnabled }}disabled{{ end }} data-disabled-reason="Guest uploads are disabled.">
<option value="{{ .Key }}" {{ if eq .Key $.DefaultRetention }}selected{{ end }}>{{ .Label }}</option>
{{ end }}
</select>
</label> </label>
<label class="upload-check-row" for="upload-password-enabled">
<input id="upload-password-enabled" type="checkbox">
<span>Password protect this box</span>
</label>
<input id="upload-password" class="upload-text-input" type="password" autocomplete="new-password" placeholder="Password" disabled>
<label class="upload-check-row" for="upload-zip-enabled">
<input id="upload-zip-enabled" type="checkbox" checked>
<span>Allow Download Zip</span>
</label>
</fieldset>
<div class="upload-details"> <div class="upload-details">
<span class="upload-detail-label">Selected Files</span> <span class="upload-detail-label">Queue:</span>
<span id="upload-file-count" class="upload-file-count">0 files</span> <span id="queue-label">{{ if .UploadsEnabled }}No files selected{{ else }}Guest uploads are disabled{{ end }}</span>
<span class="upload-file-count" id="queue-size">0 B total</span>
</div>
<div class="upload-file-list" aria-label="Upload queue" id="file-list">
<p class="upload-empty-state">{{ if .UploadsEnabled }}No files in the box yet. Drop files here, use File &gt; Add files, or click the dropzone.{{ else }}Guest uploads are disabled.{{ end }}</p>
</div>
<div class="upload-result">
<span class="upload-result-label">Share URL:</span>
<a class="upload-result-link is-empty" id="share-link" href="#" aria-disabled="true">Not created yet</a>
<button class="win98-button upload-share-button" type="button" id="copy-button" disabled data-disabled-reason="There is no share URL yet. Start an upload first.">Copy</button>
</div>
</div> </div>
<div class="upload-result is-hidden" aria-live="polite"> <div class="upload-overall">
<span class="upload-result-label">Folder link</span> <span class="upload-overall-track" aria-label="Overall upload progress"><span class="upload-overall-bar" id="overall-bar"></span></span>
<a id="upload-box-link" class="upload-result-link is-empty" href="#" aria-disabled="true">Waiting for upload</a> <span class="upload-overall-percent" id="overall-percent">0%</span>
<button id="upload-share-button" class="win98-button upload-share-button" type="button" disabled>Share</button>
</div> </div>
<div class="upload-file-list" aria-live="polite" aria-label="Selected files"> <div class="upload-actions">
{{ if .UploadsEnabled }} <button class="win98-button" type="button" data-action="clear">Clear</button>
<p class="upload-empty-state">No files selected</p> <button class="win98-button start-upload-cta" type="submit" id="start-button" {{ if not .UploadsEnabled }}disabled{{ end }} data-disabled-reason="Start upload is unavailable right now.">Start upload</button>
{{ else }}
<p class="upload-empty-state">Guest uploads are disabled.</p>
{{ end }}
</div> </div>
</div> </form>
<footer class="upload-actions"> <div class="win98-statusbar upload-statusbar">
<label class="win98-button" for="file-upload">Browse...</label> <span id="status-text">{{ if .UploadsEnabled }}Ready · drag files anywhere onto the window{{ else }}Guest uploads are disabled{{ end }}</span>
<button class="win98-button" type="submit" {{ if not .UploadsEnabled }}disabled{{ end }}>Upload</button>
</footer>
<div class="upload-overall" aria-live="polite">
<div class="upload-overall-track" aria-hidden="true">
<span class="upload-overall-bar"></span>
</div>
<span class="upload-overall-percent">0%</span>
</div>
<div class="win98-statusbar upload-statusbar" aria-live="polite">
<span>Ready</span>
<span>WarpBox</span> <span>WarpBox</span>
</div> </div>
</form> </section>
</section>
<aside class="side-stack" aria-label="Secondary upload panels">
<section class="win98-window side-panel">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/scanner_alt-3.png" alt="" aria-hidden="true">
<h2>Box Options</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-close" title="Close-ish">×</button></div>
</div>
<div class="win98-panel side-body">
<div class="box-options-form" id="box-options-form">
<label class="option-row">
<span>Expires:</span>
<select class="upload-select" id="expiry-select" name="retention_key">
{{ range .RetentionOptions }}
<option value="{{ .Key }}" {{ if eq .Key $.DefaultRetention }}selected{{ end }}>{{ .Label }}</option>
{{ end }}
</select>
</label>
<label class="option-row">
<span>Password:</span>
<input class="upload-text-input" id="password-input" type="text" placeholder="optional" autocomplete="off">
</label>
<label class="option-row">
<span>Max views:</span>
<input class="upload-text-input" id="max-views" type="number" min="1" max="9999" placeholder="local note">
</label>
<label class="option-row">
<span>Box name:</span>
<input class="upload-text-input" id="box-name" type="text" maxlength="42" placeholder="local note">
</label>
<label class="option-row">
<span>Custom slug:</span>
<input class="upload-text-input" id="custom-slug" type="text" maxlength="32" placeholder="local note">
</label>
<label class="option-check">
<input type="checkbox" id="download-page" checked>
<span>Generate download page</span>
</label>
<label class="option-check">
<input type="checkbox" id="allow-zip" checked>
<span>Allow Download Zip</span>
</label>
<label class="option-check">
<input type="checkbox" id="allow-preview" checked>
<span>Allow previews when possible</span>
</label>
<label class="option-check">
<input type="checkbox" id="keep-filenames" checked>
<span>Keep original filenames</span>
</label>
<label class="option-check">
<input type="checkbox" id="private-box">
<span>Hide from public listings</span>
</label>
<label class="option-check">
<input type="checkbox" id="api-key-mode">
<span>Use API key for larger quota</span>
</label>
<label class="option-row api-key-row" id="api-key-row">
<span>API key:</span>
<span class="api-key-field">
<input class="upload-text-input" id="api-key-input" type="password" placeholder="paste key when enabled" autocomplete="off" disabled data-disabled-reason="Enable Use API key for larger quota before typing an API key.">
<span class="api-key-state" id="api-key-state" aria-live="polite"></span>
</span>
</label>
</div>
</div>
</section>
<section class="win98-window side-panel">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/sprites/computer_explorer-4.png" alt="" aria-hidden="true">
<h2>Terminal Upload</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-help" title="Help-ish">?</button></div>
</div>
<div class="win98-panel side-body">
<div class="terminal-box" id="terminal-box" tabindex="0" aria-label="Terminal upload command"></div>
<div class="terminal-actions">
<button class="win98-button terminal-copy-button" type="button" id="copy-curl-button">Copy cURL command</button>
</div>
</div>
</section>
<section class="win98-window helper-window" aria-label="WarpBox help folder">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/tip.png" alt="" aria-hidden="true">
<h2>WarpBox Help Folder</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-folder-close" title="Nope">×</button></div>
</div>
<div class="win98-panel helper-body">
<button class="folder-icon-button" type="button" data-doc="cli"><img src="/static/img/icons/directory_closed-2.png" alt="" aria-hidden="true"><span>CLI Guide</span></button>
<button class="folder-icon-button" type="button" data-doc="faq"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Help &amp; FAQ</span></button>
<button class="folder-icon-button" type="button" data-doc="examples"><img src="/static/img/icons/shell_window1.png" alt="" aria-hidden="true"><span>Examples</span></button>
<button class="folder-icon-button folder-icon-button-disabled" type="button" data-action="coming-soon"><img src="/static/img/sprites/eject_pc_cool-5.png" alt="" aria-hidden="true"><span>WarpBox.exe</span></button>
</div>
</section>
</aside>
</div>
</main> </main>
<div class="modal-backdrop" id="modal-backdrop"></div>
<section class="win98-window popup-window" id="doc-popup" aria-modal="true" role="dialog" aria-labelledby="doc-popup-title">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/tip.png" alt="" aria-hidden="true">
<h2 id="doc-popup-title">WarpBox Help</h2>
</div>
<div class="win98-window-controls"><button class="win98-control popup-close" type="button" id="doc-popup-close" title="Close">×</button></div>
</div>
<div class="win98-panel popup-body" id="doc-popup-body"></div>
</section>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="/static/js/app.js"></script> <script src="/static/js/app.js"></script>
</body> </body>
</html> </html>