Complete remaining TODO: image upload, spinners, drag-to-trash, sort
- Image upload: drag-drop images into editor, stored in .assets/ - Serve images via /api/files/image/ endpoint - Loading spinner bar in sidebar during file operations - Sort files by name/date buttons - Drag files onto Trash button to delete - All code TODO items complete
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -417,6 +418,48 @@ func (s *Server) handleSharedFiles(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, 200, []files.FileInfo{})
|
||||
}
|
||||
|
||||
func (s *Server) handleUploadImage(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 10*1024*1024)
|
||||
if err := r.ParseMultipartForm(10 << 20); err != nil {
|
||||
writeJSON(w, 413, map[string]string{"error": "file too large (max 10MB)"})
|
||||
return
|
||||
}
|
||||
file, header, err := r.FormFile("image")
|
||||
if err != nil {
|
||||
writeJSON(w, 400, map[string]string{"error": "image field required"})
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
userID := getUserID(r)
|
||||
assetsDir := filepath.Join(files.UserDir(s.dataDir, userID), ".assets")
|
||||
os.MkdirAll(assetsDir, 0755)
|
||||
|
||||
filename := header.Filename
|
||||
dest := filepath.Join(assetsDir, filename)
|
||||
out, err := os.Create(dest)
|
||||
if err != nil {
|
||||
writeJSON(w, 500, map[string]string{"error": "save failed"})
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
io.Copy(out, file)
|
||||
|
||||
url := "/api/files/image/" + filename
|
||||
writeJSON(w, 200, map[string]string{"url": url, "filename": filename})
|
||||
}
|
||||
|
||||
func (s *Server) handleServeImage(w http.ResponseWriter, r *http.Request) {
|
||||
userID := getUserID(r)
|
||||
filename := filepath.Base(r.URL.Path)
|
||||
if filename == "" || filename == "." {
|
||||
http.Error(w, "not found", 404)
|
||||
return
|
||||
}
|
||||
p := filepath.Join(files.UserDir(s.dataDir, userID), ".assets", filename)
|
||||
http.ServeFile(w, r, p)
|
||||
}
|
||||
|
||||
func (s *Server) handleListTrash(w http.ResponseWriter, r *http.Request) {
|
||||
userID := getUserID(r)
|
||||
items, err := files.ListTrash(s.dataDir, userID)
|
||||
|
||||
@@ -43,6 +43,8 @@ func NewRouter(db *sql.DB, dataDir, secret string) http.Handler {
|
||||
mux.HandleFunc("POST /api/files/trash/empty", s.requireAuth(s.handleEmptyTrash))
|
||||
mux.HandleFunc("POST /api/files/search", s.requireAuth(s.handleSearchFiles))
|
||||
mux.HandleFunc("POST /api/files/shared", s.requireAuth(s.handleListSharedFiles))
|
||||
mux.HandleFunc("POST /api/files/upload-image", s.requireAuth(s.handleUploadImage))
|
||||
mux.HandleFunc("GET /api/files/image/", s.requireAuth(s.handleServeImage))
|
||||
|
||||
// Sharing
|
||||
mux.HandleFunc("POST /api/share", s.requireAuth(s.handleShareFile))
|
||||
|
||||
Reference in New Issue
Block a user