aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-12-09 09:33:25 +0100
committerPřemysl Eric Janouch <p@janouch.name>2023-12-09 09:43:22 +0100
commitfb541e8e7e472e72595f89f7dd7c5a8eda48fcda (patch)
treed6f015a306e46c2c83d2fe3fd57a8e9537917d30
parentac2f065f9bbd12e9ffd9b60bf91a436129038263 (diff)
downloadgallery-fb541e8e7e472e72595f89f7dd7c5a8eda48fcda.tar.gz
gallery-fb541e8e7e472e72595f89f7dd7c5a8eda48fcda.tar.xz
gallery-fb541e8e7e472e72595f89f7dd7c5a8eda48fcda.zip
Elementary traversal
-rw-r--r--main.go109
1 files changed, 99 insertions, 10 deletions
diff --git a/main.go b/main.go
index b6ef3e0..34c0806 100644
--- a/main.go
+++ b/main.go
@@ -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 {