From 4e4b5614e0a4316319b2cba9f289e47f2fe06382 Mon Sep 17 00:00:00 2001 From: Dominic Ferrando Date: Mon, 21 Apr 2025 00:57:35 -0400 Subject: [PATCH] Add file info at top of post images --- internal/util/posts.go | 60 ++++++++++++++++++++++++++++++++++++++++++ web/static/index.css | 8 +++++- web/views/board.templ | 2 +- web/views/thread.templ | 12 ++++++++- 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/internal/util/posts.go b/internal/util/posts.go index 614d603..4dcaf66 100644 --- a/internal/util/posts.go +++ b/internal/util/posts.go @@ -8,6 +8,7 @@ import ( "log" "mime/multipart" "os" + "path" "path/filepath" "strings" @@ -111,3 +112,62 @@ func SumUniquePostIps(posts []database.Post) int { } return len(uniqueIpHashes) } + +type PostImageInfo struct { + Size int64 + Height int + Width int +} + +func GetPostImageInfo(mediaPath string) PostImageInfo { + var result PostImageInfo + + imagePath := path.Join(POST_IMG_FULL_PATH, mediaPath) + + fileInfo, err := os.Stat(imagePath) + if err != nil { + log.Printf("Failed to get image file info at %s: %v", mediaPath, err) + return PostImageInfo{} + } + + file, err := os.Open(imagePath) + if err != nil { + log.Printf("Failed to open image at %s: %v", mediaPath, err) + return PostImageInfo{} + } + defer file.Close() + + cfg, _, err := image.DecodeConfig(file) + if err != nil { + log.Printf("Failed to decode image at %s: %v", mediaPath, err) + return PostImageInfo{} + } + + result.Size = fileInfo.Size() + result.Width = cfg.Width + result.Height = cfg.Height + + return result +} + +func FormatBytes(bytes int64) string { + const ( + KB = 1 << 10 // 1024 + MB = 1 << 20 + GB = 1 << 30 + TB = 1 << 40 + ) + + switch { + case bytes >= TB: + return fmt.Sprintf("%.2f TB", float64(bytes)/float64(TB)) + case bytes >= GB: + return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB)) + case bytes >= MB: + return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB)) + case bytes >= KB: + return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB)) + default: + return fmt.Sprintf("%d B", bytes) + } +} diff --git a/web/static/index.css b/web/static/index.css index 5e4ad15..ab280d7 100644 --- a/web/static/index.css +++ b/web/static/index.css @@ -216,6 +216,12 @@ body { max-width: 100%; } +.post-img-info { + display: inline-block; + font-size: 10px; + margin-left: 5px; +} + .post-body { margin-top: 10px; margin-left: 5px; @@ -253,7 +259,7 @@ body { color: rgb(52, 52, 92); text-decoration: underline; cursor: pointer; - margin-left: 8px; + margin-left: 4px; } .reply-link-header:hover { diff --git a/web/views/board.templ b/web/views/board.templ index 4559b0f..21cdbe8 100644 --- a/web/views/board.templ +++ b/web/views/board.templ @@ -75,7 +75,7 @@ templ Board(board database.Board) { - +
File: { post.MediaPath } +
+ ({ util.FormatBytes(imgInfo.Size) }, + { strconv.Itoa(imgInfo.Width) }x{ strconv.Itoa(imgInfo.Height) }) +
-
+

{ thread.Subject } -

@@ -36,6 +41,7 @@ templ PostOriginal(post database.Post, thread *database.Thread) { } templ PostReply(post database.Post) { +{{ imgInfo := util.GetPostImageInfo(post.MediaPath) }}
@@ -54,6 +60,10 @@ templ PostReply(post database.Post) { { post.MediaPath } +
+ ({ util.FormatBytes(imgInfo.Size) }, + { strconv.Itoa(imgInfo.Width) }x{ strconv.Itoa(imgInfo.Height) }) +