Count row depth the way group_by_depth does — levels, not boundaries

The EXPAND buttons did nothing because their 0..3 were written against
view.set_depth(), which is 0-based, while the config field is 1-based.
server.cpp does

    ctx1->set_depth(row_pivot_depth - 1)     // one-sided
    ctx2->set_depth(HEADER_ROW, row_pivot_depth - 1)

for both contexts, so group_by_depth counts the levels to show. Passing 0
asked the engine for set_depth(-1), and every other button was off by one
level. The fork's own depth_test.mjs uses group_by_depth: 1 as its working
control, which is the same arithmetic seen from the outside.

So the toolbar sends d + 1, and subtracts one again when reading a saved
layout back for the button state.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Trowbridge 2026-09-17 03:22:42 -04:00
parent 02a0db386e
commit 744342d519

View File

@ -676,7 +676,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
// restore() has already applied group_by_depth; this only syncs the
// toolbar. expand_depth is the legacy key, from when depth was imperative
// and had to be stored beside the config rather than in it.
if (cfg.group_by_depth != null) setExpandDepth(cfg.group_by_depth)
if (cfg.group_by_depth != null) setExpandDepth(cfg.group_by_depth - 1)
else if (cfg.expand_depth != null) await applyDepth(cfg.expand_depth)
} else {
const sourceDefault = sources.find(s => String(s.id) === String(sid))?.default_layout
@ -832,11 +832,18 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
async function applyDepth(d) {
const viewer = viewerRef.current
if (!viewer) return
// A partial restore({ group_by_depth }) on its own did nothing, so the whole
// config goes back with the field changed. table is dropped: it is loaded by
// reference, and a stale name in the config fails the lookup.
// group_by_depth counts levels, where view.set_depth() counts the boundary
// below them -- server.cpp does ctx->set_depth(row_pivot_depth - 1) for both
// the one- and two-sided contexts. So the toolbar's 0..3, which were written
// against the imperative call, are one less than the config wants: depth 0
// (grand total only) is group_by_depth 1, and passing 0 asked the engine for
// set_depth(-1).
//
// The whole config goes back rather than a partial update, which had no
// effect on its own. table is dropped: it is loaded by reference, and a stale
// name in a restored config fails the lookup.
const { table: _t, ...cfg } = await viewer.save()
await viewer.restore({ ...cfg, group_by_depth: d })
await viewer.restore({ ...cfg, group_by_depth: d + 1 })
setExpandDepth(d)
}
@ -906,7 +913,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
cfg.plugin_config = { ...(cfg.plugin_config || {}), edit_mode: 'SELECT_REGION' }
await viewer.restore(cfg)
adoptSplit(cfg.split_full?.length ? cfg.split_full : cfg.split_by, (cfg.split_by || []).length)
if (cfg.group_by_depth != null) setExpandDepth(cfg.group_by_depth)
if (cfg.group_by_depth != null) setExpandDepth(cfg.group_by_depth - 1)
else if (cfg.expand_depth != null) await applyDepth(cfg.expand_depth)
setActiveLayoutId(layout.id)
await persistLayout(versionId, cfg)