diff --git a/internal/app/server.go b/internal/app/server.go index 5970989..953d410 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -9,38 +9,34 @@ import ( func (app *App) Routes() *http.ServeMux { mux := http.NewServeMux() - - fs := http.FileServer(http.Dir("./web/static")) - mux.Handle("GET /static/", http.StripPrefix("/static/", fs)) - + fs := http.FileServer(http.Dir("./web/static")) + mux.Handle("GET /static/", http.StripPrefix("/static/", fs)) mux.HandleFunc("GET /{$}", app.HandleHome) mux.HandleFunc("POST /{$}", app.HandleUpload) mux.HandleFunc("POST /upload/chunk", app.HandleChunk) mux.HandleFunc("POST /upload/finish", app.HandleFinish) mux.HandleFunc("GET /{slug}", app.HandleGetFile) - return mux } func (app *App) RespondWithLink(w http.ResponseWriter, r *http.Request, key []byte, originalName string) { keySlug := base64.RawURLEncoding.EncodeToString(key) ext := filepath.Ext(originalName) - link := fmt.Sprintf("%s/%s%s", r.Host, keySlug, ext) - if r.Header.Get("X-Requested-With") == "XMLHttpRequest" { fmt.Fprintf(w, ` -
-
Upload Complete:
+
+
Upload Complete:
- +
+ +
`, link) return } - scheme := "https" if r.TLS == nil { scheme = "http" @@ -51,7 +47,13 @@ func (app *App) RespondWithLink(w http.ResponseWriter, r *http.Request, key []by func (app *App) SendError(w http.ResponseWriter, r *http.Request, code int) { if r.Header.Get("X-Requested-With") == "XMLHttpRequest" { w.WriteHeader(code) - fmt.Fprintf(w, `
Error %d
`, code) + fmt.Fprintf(w, ` +
+
Error %d
+
+ +
+
`, code) return } http.Error(w, http.StatusText(code), code) diff --git a/web/static/css/style.css b/web/static/css/style.css index 3ccb2d4..8db3323 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -20,7 +20,7 @@ body { .container { width: 100%; - max-width: 600px; + max-width: 800px; padding: 20px; } @@ -28,16 +28,33 @@ body { margin-bottom: 30px; border-left: 3px solid var(--accent); padding-left: 16px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-title { + margin: 0; + color: var(--header-white); } .upload-area { border: 2px dashed var(--border); border-radius: 12px; - padding: 60px 20px; + padding: 20px; text-align: center; cursor: pointer; background: #161b22; - transition: 0.2s; + transition: + border-color 0.2s, + background 0.2s; + height: 220px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + box-sizing: border-box; + overflow: hidden; } .upload-area:hover, @@ -46,6 +63,17 @@ body { background: #1c2128; } +.upload-icon { + font-size: 32px; + color: var(--accent); + margin-bottom: 8px; +} + +.upload-text { + font-weight: 500; + color: var(--header-white); +} + .progress-bar { height: 6px; background: var(--border); @@ -53,6 +81,11 @@ body { margin: 25px 0; overflow: hidden; display: none; + width: 95%; +} + +.progress-bar.visible { + display: block; } .progress-fill { @@ -62,10 +95,37 @@ body { transition: width 0.3s; } +#busy-state { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +#result-state { + width: 100%; + display: flex; + justify-content: center; +} + +.result-container { + width: 100%; + max-width: 700px; + display: flex; + flex-direction: column; + padding: 0 20px; + box-sizing: border-box; +} + +.result-label { + text-align: left; + margin-bottom: 8px; +} + .copy-box { display: flex; - margin-top: 20px; gap: 8px; + width: 100%; } input[type="text"] { @@ -76,7 +136,10 @@ input[type="text"] { padding: 12px; border-radius: 6px; font-family: monospace; + font-size: 14px; outline: none; + min-width: 0; + width: 100%; } button { @@ -87,16 +150,27 @@ button { border-radius: 6px; cursor: pointer; font-weight: 600; + white-space: nowrap; +} + +.reset-wrapper { + margin-top: 20px; + display: flex; + justify-content: center; } .reset-btn { background: transparent; color: var(--fg); text-decoration: underline; - margin-top: 20px; border: none; cursor: pointer; opacity: 0.7; + font-size: 14px; +} + +.reset-btn:hover { + opacity: 1; } .dim { @@ -108,3 +182,66 @@ button { color: #f85149; margin-bottom: 10px; } + +.github-btn { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + background: #21262d; + border: 1px solid var(--border); + border-radius: 6px; + color: var(--header-white); + text-decoration: none; + font-size: 13px; + font-weight: 500; + transition: 0.2s; +} + +.github-btn:hover { + background: #30363d; + border-color: #8b949e; +} + +.github-btn svg { + opacity: 0.9; +} + +.cli-section { + margin-top: 40px; + padding-top: 24px; + border-top: 1px solid var(--border); +} + +.cli-label { + text-transform: uppercase; + font-size: 11px; + font-weight: 700; + letter-spacing: 1px; +} + +.cli-pre { + background: #161b22; + padding: 16px; + border-radius: 8px; + font-size: 13px; + overflow-x: auto; + border: 1px solid var(--border); +} + +.status-text { + font-weight: 500; +} + +.hidden { + display: none !important; +} + +@media (max-width: 400px) { + .github-btn span { + display: none; + } + .github-btn { + padding: 6px; + } +} diff --git a/web/static/js/app.js b/web/static/js/app.js index 75c329d..d9fa531 100644 --- a/web/static/js/app.js +++ b/web/static/js/app.js @@ -4,7 +4,7 @@ const fileInput = $("file-input"); if (dropZone) { dropZone.onclick = () => { - if ($("idle-state").style.display !== "none") fileInput.click(); + if (!$("idle-state").classList.contains("hidden")) fileInput.click(); }; fileInput.onchange = () => { @@ -32,8 +32,9 @@ if (dropZone) { } async function handleUpload(file) { - $("idle-state").style.display = "none"; - $("busy-state").style.display = "block"; + $("idle-state").classList.add("hidden"); + $("busy-state").classList.remove("hidden"); + $("p-bar-container").classList.add("visible"); const uploadID = Math.random().toString(36).substring(2, 15); const chunkSize = 1024 * 1024 * 8; @@ -61,11 +62,19 @@ async function handleUpload(file) { headers: { "X-Requested-With": "XMLHttpRequest" }, }); - $("busy-state").style.display = "none"; + $("busy-state").classList.add("hidden"); + $("result-state").classList.remove("hidden"); $("result-state").innerHTML = await res.text(); } catch (e) { - $("busy-state").style.display = "none"; - $("result-state").innerHTML = `
Upload Failed
`; + $("busy-state").classList.add("hidden"); + $("result-state").classList.remove("hidden"); + $("result-state").innerHTML = ` +
+
Upload Failed
+
+ +
+
`; } } diff --git a/web/templates/base.html b/web/templates/base.html index 7fb3571..28ead09 100644 --- a/web/templates/base.html +++ b/web/templates/base.html @@ -10,21 +10,26 @@
-

safebin

-
Encrypted Temporary File Storage
+
+

safebin

+
Encrypted Temporary File Storage
+
+ + + + + GitHub +
- {{template "content" .}} - -
-
CLI Usage
-
-curl -F file=@yourfile {{.Host}}
+
+
CLI Usage
+
curl -F file=@yourfile {{.Host}}
- - + diff --git a/web/templates/index.html b/web/templates/index.html index 1b79316..14bc67c 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -1,18 +1,16 @@ {{define "content"}}
-
-
Click or drag to upload
+
+
Click or drag to upload
Max size: {{.MaxMB}}MB
- -
{{end}}