// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 package admin import ( "fmt" "net/http" "strings" "sourcedock.dev/petrbalvin/volumen/internal/store" ) func (a *Admin) registerMediaRoutes(mux *http.ServeMux) { mux.HandleFunc("GET /admin/media", a.requireLogin(a.handleMediaLibrary)) mux.HandleFunc("POST /admin/media/{name}/delete", a.requireLogin(a.handleMediaDelete)) } func (a *Admin) handleMediaLibrary(w http.ResponseWriter, r *http.Request) { data := a.pageData(r) items := a.deps.Store.ListMedia() data.MediaItems = mediaRows(items) data.MediaTotal = humanSize(totalSize(items)) data.Crumbs = []Crumb{{Label: "Media", IsLast: true, UI: true}} a.renderPage(w, r, "media.html", data, http.StatusOK) } // totalSize sums the byte sizes of the media library. func totalSize(items []store.Media) int64 { var total int64 for _, item := range items { total += item.Size } return total } // humanSize formats a byte count for the library summary: kilobytes // below a megabyte (rounded up, so nothing reads as zero), megabytes // above it, empty for an empty library. func humanSize(total int64) string { switch { case total <= 0: return "" case total < 1024*1024: kb := (total + 1023) / 1024 return fmt.Sprintf("%d kB", kb) default: return fmt.Sprintf("%.1f MB", float64(total)/(1024*1024)) } } func (a *Admin) handleMediaDelete(w http.ResponseWriter, r *http.Request) { if !a.requireCSRF(w, r) { return } name := r.PathValue("name") if !a.deps.Store.DeleteMedia("/media/" + strings.TrimPrefix(name, "/")) { http.Error(w, "File not found", http.StatusNotFound) return } a.record(r, "media.deleted", fmt.Sprintf("/media/%s", name), nil) http.Redirect(w, r, "/admin/media", http.StatusSeeOther) }