diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-06 08:09:30 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-06 08:09:30 +0300 |
| commit | ad6f2ae6f6aa14926ef63a7fe124093dcceb024b (patch) | |
| tree | 515309f431add4fe9d9b2bf2909bbc89fced12e5 | |
| parent | 885dd0912dd0e4f9df86b6676a6c467bdb367660 (diff) | |
fix(scanner, browse): fallback to original image when thumbnail generation fails for cover.jpg
When scanning image files (e.g. cover.jpg in audiobook folders),
thumbnailForImage can fail or produce a missing .thumbnails/cover.jpg.
This caused broken thumbnails in the grid.
- scanner.go buildThumbnailPath: after generating an image thumbnail,
verify the output file exists via fs.Stat. If it does not exist,
fall back to using the original image path as the thumbnail_path.
- browse.go GetThumbnail: if os.Stat(ThumbnailPath) fails and the
media type is image, fall back to serving the original AbsPath.
All tests pass.
| -rw-r--r-- | internal/scanner/scanner.go | 11 | ||||
| -rw-r--r-- | internal/service/browse.go | 26 |
2 files changed, 29 insertions, 8 deletions
diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go index 30b20d1..34e0ca5 100644 --- a/internal/scanner/scanner.go +++ b/internal/scanner/scanner.go @@ -202,7 +202,16 @@ func (s *FSScanner) buildThumbnailPath(ctx context.Context, path, setPath string if ext == ".svg" { return path, nil } - return s.thumbnailForImage(ctx, path, setPath) + thumbPath, err := s.thumbnailForImage(ctx, path, setPath) + if err != nil { + return "", err + } + if thumbPath != "" { + if _, statErr := s.fs.Stat(thumbPath); statErr == nil { + return thumbPath, nil + } + } + return path, nil } return "", nil } diff --git a/internal/service/browse.go b/internal/service/browse.go index b420d70..0df399b 100644 --- a/internal/service/browse.go +++ b/internal/service/browse.go @@ -183,14 +183,26 @@ func (s *browseService) GetThumbnail(ctx context.Context, mediaID, userID int64) return nil, errors.New("thumbnail not found") } info, err := os.Stat(media.ThumbnailPath) - if err != nil { - return nil, fmt.Errorf("stat thumbnail: %w", err) + if err == nil { + return &FileResult{ + Path: media.ThumbnailPath, + FileName: filepath.Base(media.ThumbnailPath), + FileSize: info.Size(), + }, nil } - return &FileResult{ - Path: media.ThumbnailPath, - FileName: filepath.Base(media.ThumbnailPath), - FileSize: info.Size(), - }, nil + // If the generated thumbnail is missing, fall back to the original file + // for image media so that cover.jpg and similar files still render. + if media.Type == model.MediaTypeImage { + info, err = os.Stat(media.AbsPath) + if err == nil { + return &FileResult{ + Path: media.AbsPath, + FileName: filepath.Base(media.AbsPath), + FileSize: info.Size(), + }, nil + } + } + return nil, fmt.Errorf("stat thumbnail: %w", err) } func (s *browseService) RegenerateThumbnail(ctx context.Context, mediaID, userID int64) error { |
