diff options
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 109 |
1 files changed, 99 insertions, 10 deletions
@@ -17,6 +17,7 @@ import ( "os/exec" "path/filepath" "regexp" + "strconv" "strings" "time" @@ -53,11 +54,11 @@ func dbCollectStrings(query string) ([]string, error) { var result []string for rows.Next() { - var sha1 string - if err := rows.Scan(&sha1); err != nil { + var s string + if err := rows.Scan(&s); err != nil { return nil, err } - result = append(result, sha1) + result = append(result, s) } if err := rows.Err(); err != nil { return nil, err @@ -103,6 +104,74 @@ func (dm *directoryManager) IDForDirectoryPath(path string) (int64, error) { return parent.Int64, nil } +// XXX: This is preliminary. +type entry struct { + Parent int64 + Name string + Mtime int64 + Sha1 string + + Thumbw int + Thumbh int + Dhash int64 +} + +// XXX: This is preliminary. +type directory struct { + Id int64 + Name string + Parent int64 + Children []int64 + Entries []entry +} + +func dbCollectDirectory(id int64) (directory, error) { + d := directory{Id: id} + dbID := sql.NullInt64{Int64: id, Valid: id != 0} + if id != 0 { + err := db.QueryRow(`SELECT name, IFNULL(parent, 0) + FROM directory WHERE id IS ?`, dbID).Scan(&d.Name, &d.Parent) + if err != nil { + return d, err + } + } + + rows1, err := db.Query(`SELECT id FROM directory WHERE parent IS ?`, dbID) + if err != nil { + return d, err + } + defer rows1.Close() + for rows1.Next() { + var child int64 + if err := rows1.Scan(&child); err != nil { + return d, err + } + d.Children = append(d.Children, child) + } + if err := rows1.Err(); err != nil { + return d, err + } + + rows2, err := db.Query(`SELECT IFNULL(entry.parent, 0), + entry.name, entry.mtime, entry.sha1, + IFNULL(image.thumbw, 0), IFNULL(image.thumbh, 0), IFNULL(image.dhash, 0) + FROM entry JOIN image ON entry.sha1 = image.sha1 + WHERE entry.parent IS ?`, dbID) + if err != nil { + return d, err + } + defer rows2.Close() + for rows2.Next() { + var e entry + if err := rows2.Scan(&e.Parent, &e.Name, &e.Mtime, &e.Sha1, + &e.Thumbw, &e.Thumbh, &e.Dhash); err != nil { + return d, err + } + d.Entries = append(d.Entries, e) + } + return d, rows2.Err() +} + // cmdInit initializes a "gallery directory" that contains gallery.sqlite, // images, thumbs. func cmdInit(args []string) error { @@ -137,8 +206,21 @@ var page = template.Must(template.New("/").Parse(`<!DOCTYPE html><html><head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel=stylesheet href=style.css> </head><body> + <h1>{{ .Name }}</h1> + <ul> + {{ range .Children }} + <li><a href="?id={{ . }}">{{ . }}</a></li> + {{ end }} + </ul> + + {{ range .Entries }} + <a href="/image/{{ .Sha1 }}"> + <img width={{ .Thumbw }} height={{ .Thumbh }} src="/thumb/{{ .Sha1 }}" + title="{{ .Name }}"> + </a> + {{ end }} + <script src=gallery.js></script> - {{ . }} </body></html>`)) func handleRequest(w http.ResponseWriter, r *http.Request) { @@ -147,10 +229,14 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { return } - // TODO: Include the most elementary contents first. - - if err := page.Execute(w, "Hello world"); err != nil { + id, _ := strconv.ParseInt(r.URL.Query().Get("id"), 10, 64) + d, err := dbCollectDirectory(id) + if err != nil { http.Error(w, err.Error(), 500) + return + } + if err := page.Execute(w, d); err != nil { + log.Println(err) } } @@ -186,8 +272,8 @@ func cmdRun(args []string) error { staticHandler = http.FileServer(http.Dir("public")) http.HandleFunc("/", handleRequest) - http.HandleFunc("/images/", handleImages) - http.HandleFunc("/thumbs/", handleThumbs) + http.HandleFunc("/image/", handleImages) + http.HandleFunc("/thumb/", handleThumbs) // TODO: Add a few API endpoints. host, port, err := net.SplitHostPort(address) @@ -357,11 +443,14 @@ func makeThumbnail(pathImage, pathThumb string) (int, int, error) { // - https://www.imagemagick.org/Usage/thumbnails/ // - https://imagemagick.org/script/command-line-options.php#layers // + // "info:" output is written for each frame, which is why we delete + // all of them but the first one beforehands. + // // TODO: See if we can optimize resulting WebP animations. // (Do -layers optimize* apply to this format at all?) cmd := exec.Command("convert", pathImage, "-coalesce", "-colorspace", "RGB", "-auto-orient", "-strip", "-resize", "256x128>", "-colorspace", "sRGB", - "-format", "%w %h", "+write", "info:", pathThumb) + "-format", "%w %h", "+write", pathThumb, "-delete", "1--1", "info:") stdout, err := cmd.StdoutPipe() if err != nil { |