summaryrefslogtreecommitdiff
path: root/internal/scanner
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-01 12:40:30 +0300
committerPaul Buetow <paul@buetow.org>2026-05-01 12:40:30 +0300
commit27dbaf2b2d5895a091d04aa1c852abb91a619e2d (patch)
tree846ba964ee6f0fba52ccb2b1750d44b21c454efb /internal/scanner
parentbadc2543eaa319657ecc97453fbdca58679ecb87 (diff)
Minimalist UI: hide all elements until activated; add help modal and keyboard shortcuts
- Redesign UI to be invisible by default: only header + '?' button shown - Press m to show sidebar, t for toolbar, / for search, ? for help - Add help modal with all keyboard shortcuts - Fix scanner to skip corrupt/unprobeable files instead of aborting - Fix scanner to skip thumbnail errors instead of aborting - Fix rescan to use background context so it completes after HTTP response - Rename project from KISS Media Player to Player
Diffstat (limited to 'internal/scanner')
-rw-r--r--internal/scanner/scanner.go14
-rw-r--r--internal/scanner/scanner_test.go13
2 files changed, 21 insertions, 6 deletions
diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go
index a1effd7..2e82fbe 100644
--- a/internal/scanner/scanner.go
+++ b/internal/scanner/scanner.go
@@ -132,7 +132,9 @@ func (s *FSScanner) scanSet(ctx context.Context, root, setPath string) error {
meta, err := s.prober.Probe(ctx, path)
if err != nil {
- return fmt.Errorf("probe %q: %w", path, err)
+ // Skip unprobeable/corrupt files instead of aborting the whole scan.
+ fmt.Printf("[scanner] skipping unprobeable file %q: %v\n", path, err)
+ return nil
}
meta.FileSizeBytes = info.Size()
@@ -146,7 +148,10 @@ func (s *FSScanner) scanSet(ctx context.Context, root, setPath string) error {
thumbName := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) + ".jpg"
thumbnailPath = filepath.Join(thumbDir, thumbName)
if err := s.thumbGen.Generate(ctx, path, thumbnailPath, meta.Duration); err != nil {
- return fmt.Errorf("thumbnail %q: %w", path, err)
+ // Skip thumbnail generation errors (e.g., corrupt or audio-only video files)
+ // and continue scanning without a thumbnail.
+ fmt.Printf("[scanner] skipping thumbnail for %q: %v\n", path, err)
+ thumbnailPath = ""
}
}
@@ -182,6 +187,11 @@ var mediaExtensions = map[string]struct{}{
}
func isMediaFile(path string) bool {
+ base := filepath.Base(path)
+ // Skip macOS resource fork files (._*)
+ if strings.HasPrefix(base, "._") {
+ return false
+ }
ext := strings.ToLower(filepath.Ext(path))
_, ok := mediaExtensions[ext]
return ok
diff --git a/internal/scanner/scanner_test.go b/internal/scanner/scanner_test.go
index 8da32a4..f6299dd 100644
--- a/internal/scanner/scanner_test.go
+++ b/internal/scanner/scanner_test.go
@@ -345,9 +345,13 @@ func TestFSScanner_Scan(t *testing.T) {
}
s := newTestScanner(store, prober, &thumb.MockGenerator{}, clk, mfs)
+ // Unprobeable files are skipped with a log instead of failing the whole scan.
err := s.Scan(ctx, "/media")
- if err == nil {
- t.Fatal("expected error for probe failure")
+ if err != nil {
+ t.Fatalf("unexpected error for probe failure; expected skip, got: %v", err)
+ }
+ if store.MediaRepo.CreateMediaFunc != nil {
+ // no media should have been created for the bad file
}
})
@@ -381,9 +385,10 @@ func TestFSScanner_Scan(t *testing.T) {
}
s := newTestScanner(store, prober, gen, clk, mfs)
+ // Thumbnail generation errors are skipped so the scan continues.
err := s.Scan(ctx, "/media")
- if err == nil {
- t.Fatal("expected error for thumbnail failure")
+ if err != nil {
+ t.Fatalf("unexpected error for thumbnail failure; expected skip, got: %v", err)
}
})