From e938f6d9a98770fd58e581dee6bc54a501f9550d Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 23 Mar 2026 11:16:18 -0700 Subject: [PATCH] feat: Native previews for video, audio, and PDF files Use presigned R2 URLs with native HTML elements instead of generic icons for all previewable file types on the download page. Co-Authored-By: Claude Opus 4.6 --- internal/handler/download.go | 17 +++++++++-------- web/download.html | 25 ++++--------------------- web/static/style.css | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/internal/handler/download.go b/internal/handler/download.go index 56220fb..9411481 100644 --- a/internal/handler/download.go +++ b/internal/handler/download.go @@ -57,15 +57,11 @@ func (h *Handler) Download(w http.ResponseWriter, r *http.Request) { } } - // Determine thumbnail type + // Determine preview type and generate presigned URL for inline rendering thumbType := "" // "image", "video", "audio", "pdf", or "" - thumbnailURL := "" + previewURL := "" if strings.HasPrefix(rec.ContentType, "image/") { thumbType = "image" - // Generate inline presigned URL for the image thumbnail - if url, err := h.r2.PresignGet(r.Context(), rec.R2Key, rec.Filename, true); err == nil { - thumbnailURL = url - } } else if strings.HasPrefix(rec.ContentType, "video/") { thumbType = "video" } else if strings.HasPrefix(rec.ContentType, "audio/") { @@ -73,6 +69,11 @@ func (h *Handler) Download(w http.ResponseWriter, r *http.Request) { } else if rec.ContentType == "application/pdf" { thumbType = "pdf" } + if thumbType != "" { + if url, err := h.r2.PresignGet(r.Context(), rec.R2Key, rec.Filename, true); err == nil { + previewURL = url + } + } data := map[string]any{ "ID": rec.ID, @@ -84,8 +85,8 @@ func (h *Handler) Download(w http.ResponseWriter, r *http.Request) { "Previewable": isPreviewable(rec.ContentType), "ViewURL": "/f/" + id + "/view", "DownloadURL": "/f/" + id + "/dl", - "ThumbType": thumbType, - "ThumbnailURL": thumbnailURL, + "ThumbType": thumbType, + "PreviewURL": previewURL, } if rec.ExpiresAt != nil { data["ExpiresAt"] = rec.ExpiresAt.Format("Jan 2, 2006 at 3:04 PM") diff --git a/web/download.html b/web/download.html index 72c463d..862fbe6 100644 --- a/web/download.html +++ b/web/download.html @@ -11,30 +11,13 @@
{{if eq .ThumbType "image"}} - {{.Filename}} + {{.Filename}} {{else if eq .ThumbType "video"}} -
- - - -
+ {{else if eq .ThumbType "audio"}} -
- - - - - -
+ {{else if eq .ThumbType "pdf"}} -
- - - - - - -
+ {{else}}
diff --git a/web/static/style.css b/web/static/style.css index 80a6684..cccdfa9 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -277,6 +277,21 @@ footer a:hover { color: var(--accent); } margin: 0 auto; } +.audio-preview { + width: 100%; + border-radius: 8px; + background: var(--bg); + padding: 1rem; +} + +.pdf-preview { + width: 100%; + height: 360px; + border: none; + border-radius: 8px; + background: var(--bg); +} + .thumb-icon { display: flex; align-items: center;