Narrow the mode switch's persist to the one key it changes

A switch wrote all seven ext-state keys to record that view_state moved,
re-serializing the bank book and the tracking ledger for nothing. Both entry
surfaces now take saveViewStateOnly; every other caller keeps the full save.
This commit is contained in:
2026-08-03 12:39:28 -04:00
parent 0eb2c67875
commit 82a8d51004
4 changed files with 74 additions and 35 deletions
+15 -8
View File
@@ -133,11 +133,17 @@ std::vector<RetagItem> selectedRetagItems() {
return items;
}
// Which keys the following persist has to write. A mode switch changes `view_state`
// and nothing else, and it is the one action here a user fires repeatedly — so it
// alone narrows, and pays neither the bank-book nor the tracking-ledger
// serialization. Every other action keeps the full save.
enum class PersistScope { Full, ViewOnly };
// Persists the bank + Design-View model after every state-changing action so the
// view model is not lost across save/close/reopen. If membership is non-empty and
// the project is unsaved, prompts Save-As first (mirrors the flow capture uses) —
// DAW-ONLY: Main_SaveProject(proj, true) blocks until the dialog is dismissed.
void persistViewState() {
void persistViewState(PersistScope scope) {
if (!g_session->view().membership().empty()) {
ReaProject* proj = EnumProjects(-1, nullptr, 0);
if (proj) {
@@ -158,7 +164,8 @@ void persistViewState() {
}
}
}
g_session->saveToActiveProject();
if (scope == PersistScope::ViewOnly) g_session->saveViewStateOnly();
else g_session->saveToActiveProject();
}
// The footer segment already reads disabled while the transport runs, but an action can
@@ -178,7 +185,7 @@ void doToggleMode() {
nextModeId(g_session->view().modes(), g_session->view().activeModeId());
if (target.empty()) return; // no modes to cycle to (degenerate)
if (!applyMode(g_session->view(), target, nullptr)) { reportModeSwitchRefused(); return; }
persistViewState();
persistViewState(PersistScope::ViewOnly);
bankPanelInvalidate(); // repaint the footer [Arrange|Design] toggle immediately
}
@@ -186,7 +193,7 @@ void doToggleMode() {
// the id is unregistered or the transport is running, so both fail safe.
void doActivateMode(const std::string& modeId) {
if (!applyMode(g_session->view(), modeId, nullptr)) { reportModeSwitchRefused(); return; }
persistViewState();
persistViewState(PersistScope::ViewOnly);
bankPanelInvalidate(); // repaint the footer [Arrange|Design] toggle immediately
}
@@ -196,7 +203,7 @@ void doTag(const std::string& modeId) {
for (const std::string& g : selectedTrackGuids())
g_session->view().membership().tag(g, modeId);
reapplyActiveMode();
persistViewState();
persistViewState(PersistScope::Full);
}
// Shared body behind "Untag selected" and "Tag -> Arrange" — Arrange is the absence
@@ -205,7 +212,7 @@ void doUntag() {
for (const std::string& g : selectedTrackGuids())
g_session->view().membership().untag(g);
reapplyActiveMode();
persistViewState();
persistViewState(PersistScope::Full);
}
// Flips each track's pin independently — the honest semantics of a toggle on a
@@ -215,7 +222,7 @@ void doShowBoth() {
for (const std::string& g : selectedTrackGuids())
m.setShowBoth(g, !m.isShowBoth(g));
reapplyActiveMode();
persistViewState();
persistViewState(PersistScope::Full);
}
// Retag the current ITEM selection to `targetMode` (empty => untag -> Arrange
@@ -247,7 +254,7 @@ void doMoveItems(const std::string& targetMode) {
: std::string("ReaSampler: move selected items -> ") + targetMode;
Undo_EndBlock2(nullptr, label.c_str(), -1);
persistViewState();
persistViewState(PersistScope::Full);
}
} // namespace