Stop the pivot snapping when its settings sidebar is opened
Two causes, both mine, both triggered by adjusting the layout. A zero size was being treated as the viewer going away, and opening Perspective's settings sidebar collapses the datagrid for a frame. The return then re-applied the stored row depth over whatever had been expanded by hand. Only lost intersection counts as a departure now; a zero size is a transient of layout, not an absence. And perspective-config-update fires for anything in the config, the settings flag included -- not only for split_by. While collapsed the live split_by is a truncation of the full hierarchy, so adopting it recorded the truncation as the hierarchy and put the deeper levels out of reach. A genuine rearrangement is not a prefix of what we already hold, which is the difference the handler now tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7cfd0068e7
commit
8aa0ae2ece
@ -346,14 +346,14 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
let settle = null
|
let settle = null
|
||||||
const onObserved = (ev) => {
|
const onObserved = (ev) => {
|
||||||
const d = ev.detail || {}
|
const d = ev.detail || {}
|
||||||
// Losing intersection, or collapsing to zero size, is the element going
|
// Only intersection counts as going away. A zero size is a transient of
|
||||||
// away: record it, because that is when the view gets discarded.
|
// layout -- opening Perspective's own settings sidebar collapses the
|
||||||
const leaving = d.entries?.some(e =>
|
// datagrid for a frame -- and treating it as a departure meant the return
|
||||||
e.isIntersecting === false || (e.width === 0 && e.height === 0))
|
// re-applied depth, so adjusting the layout snapped the tree back.
|
||||||
|
const leaving = d.entries?.some(e => e.isIntersecting === false)
|
||||||
if (leaving) { wentAwayRef.current = true; return dbg(`observer ${d.kind} -> viewer went away`) }
|
if (leaving) { wentAwayRef.current = true; return dbg(`observer ${d.kind} -> viewer went away`) }
|
||||||
|
|
||||||
// A resize with a non-zero size is an ordinary reflow. It is not a
|
// Everything else is a reflow. Not a restoration, so it restores nothing.
|
||||||
// restoration, so it must not re-apply anything.
|
|
||||||
if (!wentAwayRef.current) return
|
if (!wentAwayRef.current) return
|
||||||
|
|
||||||
clearTimeout(settle)
|
clearTimeout(settle)
|
||||||
@ -875,7 +875,17 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
// it redefines the hierarchy. Ours is a collapse, and must not overwrite it.
|
// it redefines the hierarchy. Ours is a collapse, and must not overwrite it.
|
||||||
if (!collapsingRef.current) {
|
if (!collapsingRef.current) {
|
||||||
const live = await viewer.save()
|
const live = await viewer.save()
|
||||||
adoptSplit(live.split_by || [], (live.split_by || []).length)
|
const next = live.split_by || []
|
||||||
|
const full = splitFullRef.current || []
|
||||||
|
// This event fires for anything in the config -- opening the settings
|
||||||
|
// sidebar included -- not only for split_by. While collapsed, the live
|
||||||
|
// split_by is a prefix of the full hierarchy, and adopting it would
|
||||||
|
// record the truncation as the hierarchy and make the deeper levels
|
||||||
|
// unreachable. A genuine rearrangement is not a prefix of what we hold.
|
||||||
|
const isCollapsedPrefix =
|
||||||
|
next.length < full.length && next.every((c, i) => c === full[i])
|
||||||
|
if (!isCollapsedPrefix) adoptSplit(next, next.length)
|
||||||
|
else dbg(`config-update: split_by is our collapse (${next.length}/${full.length}), keeping the full hierarchy`)
|
||||||
}
|
}
|
||||||
const cfg = await captureConfig()
|
const cfg = await captureConfig()
|
||||||
if (cfg) await persistLayout(vid, cfg)
|
if (cfg) await persistLayout(vid, cfg)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user