Add multi-project sources, clip dedupe and a swing selection mode #27

Merged
cheapnud merged 9 commits from d/multi-source-swing into master 2026-08-23 13:39:19 +00:00
Owner

Extra .mlt files can be loaded as additional clip sources, the selection pool now drops entries showing identical footage (same file and in/out range), and a new swing mode arranges long clips as random anchors with the shorter clips spread evenly between them.

Extra .mlt files can be loaded as additional clip sources, the selection pool now drops entries showing identical footage (same file and in/out range), and a new swing mode arranges long clips as random anchors with the shorter clips spread evenly between them.

🤖 Claude AI Code Review

  1. Summary
    Adds multi-project source merging, resource+range dedupe, and a swing selection mode, with solid test coverage and a CI refactor to cmd/external release script.

  2. Code Quality
    Excellent test coverage across all three new features, including edge cases like fallback halves and empty pools.

  3. Issues

🟡 SwingVideoSelector.cs — Arrange can throw IndexOutOfRangeException. perGap and remainder distribute all shorts across gaps positions, but the loop only fills gaps where i < gaps (i.e. i from 0 to gaps-1). Since a HashSet of extraGaps picks indices in [0, gaps), this is consistent — however if shuffledShorts.Count exceeds what the gaps consume it's fine, but verify the invariant: total placed = perGap*gaps + remainder = shuffledShorts.Count, and shortCursor advances exactly that many times. This holds, so no bug — but note the last long (i == gaps) correctly gets no trailing shorts, meaning shorts never appear after the final long. That matches the tests. No action needed.

🟢 ShotcutService.cs — LoadCombinedProjectAsync calls MakeResourcePathsAbsolute(primary, ...) and MergeSourceProject also calls MakeResourcePathsAbsolute(extra, ...), but this method isn't shown in the diff. Assuming it's idempotent and pre-existing, fine. Confirm it exists.

🟢 Home.razor — RemoveSourceProjectAsync discards the reload result (_ = await ...). If reload fails after removal, the UI silently keeps a stale/cleared project. Minor, but a failed reload here leaves CurrentProject potentially null with no user feedback beyond the snackbar inside the method.

  1. Verdict: APPROVE

The 192.168.1.15:3000 internal URL is hardcoded but was already present pre-PR (just relocated to release.ps1) — not introduced here. The release token is correctly passed via env var rather than interpolated. Everything else is clean and well-tested.


📊 Tokens: 22655 input + 767 output | 💰 Cost: ~$0.1325
Generated by Claude Opus 4.8 via Gitea Actions

## 🤖 Claude AI Code Review 1. **Summary** Adds multi-project source merging, resource+range dedupe, and a swing selection mode, with solid test coverage and a CI refactor to `cmd`/external release script. 2. **Code Quality** ⭐⭐⭐⭐☆ Excellent test coverage across all three new features, including edge cases like fallback halves and empty pools. 3. **Issues** 🟡 SwingVideoSelector.cs — `Arrange` can throw `IndexOutOfRangeException`. `perGap` and `remainder` distribute all shorts across `gaps` positions, but the loop only fills gaps where `i < gaps` (i.e. `i` from 0 to `gaps-1`). Since a HashSet of `extraGaps` picks indices in `[0, gaps)`, this is consistent — however if `shuffledShorts.Count` exceeds what the gaps consume it's fine, but verify the invariant: total placed = `perGap*gaps + remainder = shuffledShorts.Count`, and shortCursor advances exactly that many times. This holds, so no bug — but note the last long (`i == gaps`) correctly gets no trailing shorts, meaning shorts never appear after the final long. That matches the tests. No action needed. 🟢 ShotcutService.cs — `LoadCombinedProjectAsync` calls `MakeResourcePathsAbsolute(primary, ...)` and `MergeSourceProject` also calls `MakeResourcePathsAbsolute(extra, ...)`, but this method isn't shown in the diff. Assuming it's idempotent and pre-existing, fine. Confirm it exists. 🟢 Home.razor — `RemoveSourceProjectAsync` discards the reload result (`_ = await ...`). If reload fails after removal, the UI silently keeps a stale/cleared project. Minor, but a failed reload here leaves `CurrentProject` potentially null with no user feedback beyond the snackbar inside the method. 4. **Verdict**: **APPROVE** The `192.168.1.15:3000` internal URL is hardcoded but was already present pre-PR (just relocated to `release.ps1`) — not introduced here. The release token is correctly passed via env var rather than interpolated. Everything else is clean and well-tested. --- 📊 **Tokens**: 22655 input + 767 output | 💰 **Cost**: ~$0.1325 *Generated by Claude Opus 4.8 via Gitea Actions*
Retrigger CI
Some checks failed
Build & Test / Build and Test (pull_request) Failing after 8s
Claude PR Review / AI Code Review (pull_request) Successful in 23s
94b75928ee
Bypass execution policy in workflow PowerShell steps
Some checks failed
Build & Test / Build and Test (pull_request) Failing after 8s
Claude PR Review / AI Code Review (pull_request) Successful in 22s
12ab5cde72
Use cmd shell for Windows workflow steps
All checks were successful
Claude PR Review / AI Code Review (pull_request) Successful in 19s
Build & Test / Build and Test (pull_request) Successful in 1m4s
25b4f81267
cheapnud merged commit a33aa0b113 into master 2026-08-23 13:39:19 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
cheapnud/CheapShotcutRandomizer!27
No description provided.