From 8759783ebb3e6c7b54a25da43ae129d9973bcf6f Mon Sep 17 00:00:00 2001 From: wisplite Date: Sun, 23 Nov 2025 02:30:07 -0600 Subject: [PATCH] Add first metadata values and vastly improve gallery tiling --- backend/internal/services/media.go | 34 +++++++++-- frontend/src/gallery/components/MediaList.jsx | 57 ++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/backend/internal/services/media.go b/backend/internal/services/media.go index ff0859f..3559a01 100644 --- a/backend/internal/services/media.go +++ b/backend/internal/services/media.go @@ -1,11 +1,17 @@ package services import ( + "encoding/json" "fmt" + "image" + _ "image/jpeg" + _ "image/png" + "mime/multipart" + "github.com/google/uuid" "github.com/wisplite/raster/internal/db" "github.com/wisplite/raster/internal/models" - "mime/multipart" + "gorm.io/datatypes" ) func UploadMedia(file *multipart.FileHeader, albumID string, accessToken string) (models.Media, error) { @@ -24,13 +30,31 @@ func UploadMedia(file *multipart.FileHeader, albumID string, accessToken string) if albumID == "" { albumPath = "root" } + + // Extract metadata (dimensions) + var meta datatypes.JSON + src, err := file.Open() + if err == nil { + defer src.Close() + cfg, _, err := image.DecodeConfig(src) + if err == nil { + m := map[string]int{ + "width": cfg.Width, + "height": cfg.Height, + } + b, _ := json.Marshal(m) + meta = datatypes.JSON(b) + } + } + mediaID := uuid.New().String() mediaPath := fmt.Sprintf("media/%s/%s.%s", albumPath, mediaID, file.Filename) media := models.Media{ - ID: mediaID, - AlbumID: albumID, - Path: mediaPath, - Type: file.Header.Get("Content-Type"), + ID: mediaID, + AlbumID: albumID, + Path: mediaPath, + Type: file.Header.Get("Content-Type"), + Metadata: meta, } result := db.GetDB().Create(&media) if result.Error != nil { diff --git a/frontend/src/gallery/components/MediaList.jsx b/frontend/src/gallery/components/MediaList.jsx index 28ab796..0ea4cd9 100644 --- a/frontend/src/gallery/components/MediaList.jsx +++ b/frontend/src/gallery/components/MediaList.jsx @@ -10,13 +10,12 @@ export default function MediaList({ albumId, albumName }) { const { getAccessToken } = useAccount() const [open, setOpen] = useState(false) const [media, setMedia] = useState([]) + const [aspectRatios, setAspectRatios] = useState({}) const { showError } = useNotifier() useEffect(() => { let ignore = false; const getMedia = async () => { - // TODO: Implement media fetching from API - // const response = await fetch(...) const response = await fetch(`${getServerUrl()}/api/media/getAllMediaInAlbum?albumId=${albumId}`, { method: 'GET', headers: { @@ -28,7 +27,6 @@ export default function MediaList({ albumId, albumName }) { if (data.error) { showError(data.error) } else { - console.log("data.media", data.media) setMedia(data.media) } } @@ -36,6 +34,16 @@ export default function MediaList({ albumId, albumName }) { return () => { ignore = true; } }, [albumId]) + const handleImageLoad = (id, event) => { + const { naturalWidth, naturalHeight } = event.target + if (naturalWidth && naturalHeight) { + setAspectRatios(prev => ({ + ...prev, + [id]: naturalWidth / naturalHeight + })) + } + } + return (
@@ -44,20 +52,41 @@ export default function MediaList({ albumId, albumName }) {
{/* Media Grid */} -
+
{media.length === 0 && (

No media in this album

)} - {media.map((media) => ( -
- -
- ))} + {media.map((item) => { + let ar = 1; + // Try to get aspect ratio from metadata (new uploads) or fallback to loaded state (old uploads) + if (item.Metadata && item.Metadata.width && item.Metadata.height) { + ar = item.Metadata.width / item.Metadata.height; + } else if (aspectRatios[item.ID]) { + ar = aspectRatios[item.ID]; + } + + return ( +
+ handleImageLoad(item.ID, e)} + /> +
+ ) + })} + {/* Spacer to prevent the last row from expanding to fill width if it has few items */} +