fix(actions): persist Design View state after every mutating action

Design View actions mutated the model but never pushed it to ext-state, so
tags/active-mode/snapshots were lost on save/reopen. Add persistViewState()
(saveToActiveProject) after each handler's apply/reapply.
This commit is contained in:
2026-07-23 14:10:31 -04:00
parent bcd7def7c8
commit cde8feda57
+14
View File
@@ -111,6 +111,15 @@ void reapplyActiveMode() {
applyMode(g_session->view(), g_session->view().activeModeId(), nullptr); applyMode(g_session->view(), g_session->view().activeModeId(), nullptr);
} }
// Persists both the bank and the Design-View model to the active project's ext
// state. Called after every state-changing Design View action so the view model
// is not lost across save/close/reopen. Marking the project dirty is correct —
// a Design View mutation is a project-level change the user should be prompted
// to save. Safe when there is no active/saved project (saveToActiveProject no-ops).
void persistViewState() {
g_session->saveToActiveProject();
}
// -- Action bodies --------------------------------------------------------- // -- Action bodies ---------------------------------------------------------
// Toggle: cycle to the next mode in ordinal order (Arrange <-> Design with two // Toggle: cycle to the next mode in ordinal order (Arrange <-> Design with two
@@ -121,12 +130,14 @@ void doToggleMode() {
nextModeId(g_session->view().modes(), g_session->view().activeModeId()); nextModeId(g_session->view().modes(), g_session->view().activeModeId());
if (target.empty()) return; // no modes to cycle to (degenerate) if (target.empty()) return; // no modes to cycle to (degenerate)
applyMode(g_session->view(), target, nullptr); applyMode(g_session->view(), target, nullptr);
persistViewState();
} }
// Direct jump to a named mode. applyMode is a no-op (returns false, no mutation) if // Direct jump to a named mode. applyMode is a no-op (returns false, no mutation) if
// the id is unregistered, so an absent mode fails safe. // the id is unregistered, so an absent mode fails safe.
void doActivateMode(const std::string& modeId) { void doActivateMode(const std::string& modeId) {
applyMode(g_session->view(), modeId, nullptr); applyMode(g_session->view(), modeId, nullptr);
persistViewState();
} }
// Tag the selection's leaves into `modeId`, then reapply so the change is immediate. // Tag the selection's leaves into `modeId`, then reapply so the change is immediate.
@@ -136,6 +147,7 @@ void doTag(const std::string& modeId) {
for (const std::string& g : selectedTrackGuids()) for (const std::string& g : selectedTrackGuids())
g_session->view().membership().tag(g, modeId); g_session->view().membership().tag(g, modeId);
reapplyActiveMode(); reapplyActiveMode();
persistViewState();
} }
// Untag the selection entirely (return each to the Arrange default). This is the // Untag the selection entirely (return each to the Arrange default). This is the
@@ -145,6 +157,7 @@ void doUntag() {
for (const std::string& g : selectedTrackGuids()) for (const std::string& g : selectedTrackGuids())
g_session->view().membership().untag(g); g_session->view().membership().untag(g);
reapplyActiveMode(); reapplyActiveMode();
persistViewState();
} }
// Toggle the per-track show-both pin for the selection. Read the CURRENT pin of each // Toggle the per-track show-both pin for the selection. Read the CURRENT pin of each
@@ -157,6 +170,7 @@ void doShowBoth() {
for (const std::string& g : selectedTrackGuids()) for (const std::string& g : selectedTrackGuids())
m.setShowBoth(g, !m.isShowBoth(g)); m.setShowBoth(g, !m.isShowBoth(g));
reapplyActiveMode(); reapplyActiveMode();
persistViewState();
} }
} // namespace } // namespace