diff options
| author | Paul Buetow <paul@buetow.org> | 2025-10-01 23:32:19 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-10-01 23:32:19 +0300 |
| commit | e8342798e51d9678d6109cf4c62309f13b1269c4 (patch) | |
| tree | 01dd37e73c6ee0e4eaa99eedd4d1ef0276158297 | |
| parent | 1c7d78db93d177ae3142967603d8b76a464e3f56 (diff) | |
add readme
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | main.go | 87 | ||||
| -rw-r--r-- | yoga.png | bin | 0 -> 263358 bytes |
3 files changed, 83 insertions, 9 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ea7a30 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Yoga + +A yoga video selector. Fully vibe-coded. + + @@ -391,21 +391,90 @@ func progressTickerCmd(progress *loadProgress) tea.Cmd { }) } -func loadVideos(root string, cache *durationCache, progress *loadProgress) ([]video, []string, error) { +func collectVideoPaths(root string) ([]string, error) { + info, err := os.Stat(root) + if err != nil { + return nil, err + } + if !info.IsDir() { + if isVideo(root) { + return []string{root}, nil + } + return nil, nil + } + visited := make(map[string]struct{}) var paths []string - err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { + if err := traverseVideoPaths(root, root, visited, &paths); err != nil { + return nil, err + } + sort.Strings(paths) + return paths, nil +} + +func traverseVideoPaths(displayPath, realPath string, visited map[string]struct{}, acc *[]string) error { + resolved, err := filepath.EvalSymlinks(realPath) + if err != nil { + resolved = realPath + } + resolved = filepath.Clean(resolved) + if _, seen := visited[resolved]; seen { + return nil + } + visited[resolved] = struct{}{} + + entries, err := os.ReadDir(resolved) + if err != nil { + return err + } + for _, entry := range entries { + displayChild := filepath.Join(displayPath, entry.Name()) + realChild := filepath.Join(resolved, entry.Name()) + fi, err := entry.Info() if err != nil { return err } - if d.IsDir() { - return nil + mode := fi.Mode() + if mode&os.ModeSymlink != 0 { + targetPath, err := filepath.EvalSymlinks(realChild) + if err != nil { + if isVideo(displayChild) { + *acc = append(*acc, displayChild) + } + continue + } + targetInfo, err := os.Stat(targetPath) + if err != nil { + if isVideo(displayChild) { + *acc = append(*acc, displayChild) + } + continue + } + if targetInfo.IsDir() { + if err := traverseVideoPaths(displayChild, targetPath, visited, acc); err != nil { + return err + } + continue + } + if isVideo(displayChild) || isVideo(targetPath) { + *acc = append(*acc, displayChild) + } + continue + } + if fi.IsDir() { + if err := traverseVideoPaths(displayChild, realChild, visited, acc); err != nil { + return err + } + continue } - if !isVideo(path) { - return nil + if isVideo(displayChild) { + *acc = append(*acc, displayChild) } - paths = append(paths, path) - return nil - }) + } + return nil +} + +func loadVideos(root string, cache *durationCache, progress *loadProgress) ([]video, []string, error) { + paths, err := collectVideoPaths(root) if err != nil { return nil, nil, err } diff --git a/yoga.png b/yoga.png Binary files differnew file mode 100644 index 0000000..7ca195d --- /dev/null +++ b/yoga.png |
