View switching feature
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// handleSettings persists the listing view/sort/order to the folder's
|
||||
// .page-settings file. Values are validated against the allowed sets (unknown
|
||||
// values fall back to defaults). Triggered by POST /{path}?settings.
|
||||
func (h *handler) handleSettings(w http.ResponseWriter, r *http.Request, urlPath, fsPath string) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, "bad request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
view := validateView(r.FormValue("view"))
|
||||
sortKey := validateSort(r.FormValue("sort"))
|
||||
order := validateOrder(r.FormValue("order"))
|
||||
|
||||
if err := writePageSettings(fsPath, view, sortKey, order); err != nil {
|
||||
http.Error(w, "write failed: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, urlPath, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// writePageSettings performs a read-modify-write of <dir>/.page-settings,
|
||||
// updating the view/sort/order lines while preserving every other line
|
||||
// (other keys, comments, blank lines, ordering) verbatim. Missing keys are
|
||||
// appended. The write is atomic (temp file + rename).
|
||||
func writePageSettings(dir, view, sortKey, order string) error {
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
p := filepath.Join(dir, ".page-settings")
|
||||
existing, err := os.ReadFile(p)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
updated := updateSettingsLines(existing, view, sortKey, order)
|
||||
return writeFileAtomic(p, updated, 0644)
|
||||
}
|
||||
|
||||
// updateSettingsLines rewrites the view/sort/order lines in existing while
|
||||
// leaving all other lines untouched. Every occurrence of a known key is
|
||||
// updated (so the reader's last-wins parse stays consistent); keys absent from
|
||||
// the file are appended in a stable order. The result always ends in a newline.
|
||||
func updateSettingsLines(existing []byte, view, sortKey, order string) []byte {
|
||||
targets := map[string]string{"view": view, "sort": sortKey, "order": order}
|
||||
appendOrder := []string{"view", "sort", "order"}
|
||||
seen := map[string]bool{}
|
||||
|
||||
var lines []string
|
||||
if len(existing) > 0 {
|
||||
s := string(existing)
|
||||
s = strings.TrimSuffix(s, "\n")
|
||||
lines = strings.Split(s, "\n")
|
||||
}
|
||||
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if trimmed == "" || strings.HasPrefix(trimmed, "#") {
|
||||
continue
|
||||
}
|
||||
eq := strings.IndexByte(line, '=')
|
||||
if eq < 0 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(line[:eq])
|
||||
if val, ok := targets[key]; ok {
|
||||
lines[i] = key + " = " + val
|
||||
seen[key] = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, k := range appendOrder {
|
||||
if !seen[k] {
|
||||
lines = append(lines, k+" = "+targets[k])
|
||||
}
|
||||
}
|
||||
|
||||
out := strings.Join(lines, "\n")
|
||||
if out != "" {
|
||||
out += "\n"
|
||||
}
|
||||
return []byte(out)
|
||||
}
|
||||
Reference in New Issue
Block a user