fix(view): lane-separate a content-bearing folder's own media when it's derived-visible in >1 mode

planLaneMinting now takes the model + folder tree and splits a track visible in
2+ modes that carries own media (own-item span OR folder derived-visibility),
fixing an item dropped on a cross-mode folder leaking into every mode. Show-both
tracks are never force-split.
This commit is contained in:
2026-07-24 05:08:18 -04:00
parent 960c5166ee
commit 78a31ff215
5 changed files with 298 additions and 50 deletions
+11 -5
View File
@@ -543,13 +543,19 @@ bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject
bool mintManagedLanes(ViewModeModel& model, ReaProject* proj) {
std::vector<std::pair<std::string, MediaTrack*>> handleByGuid;
readFolderEntries(proj, handleByGuid); // populates handleByGuid (tree unused here)
std::vector<TrackFolderEntry> entries = readFolderEntries(proj, handleByGuid);
// The minting decision is now folder-tree / visibility aware: it needs the tree to
// detect a content-bearing folder derived-visible in >1 mode (which must lane-separate
// its own media even when that media is single-mode). Build it exactly as applyMode does.
const FolderTree tree = buildFolderTree(entries);
// Build the live per-track item picture and run the PURE decision. A single-mode
// track produces no split; a track that now holds >1 mode's content produces mints
// + assignments. Manual-lane items are reported exempt inside readLaneTracks.
// Build the live per-track item picture and run the PURE decision. A track visible in
// exactly one mode produces no split; a track visible in >1 mode while carrying its own
// media (own items span modes, OR a folder derived-visible across modes) produces mints
// + assignments. Manual-lane items are reported exempt inside readLaneTracks; show-both
// tracks are skipped inside the decision.
const std::vector<LaneTrack> tracks = readLaneTracks(model, handleByGuid);
const LaneMintPlan plan = planLaneMinting(tracks);
const LaneMintPlan plan = planLaneMinting(model, tree, tracks);
if (plan.empty()) return false; // nothing to mint — no Undo point for a no-op tick
// Wrap the structural mutation in ONE Undo block (unlike the invisible membership