fix runtime exceptions surfaced when the editor opens
Now that the editor split actually opens (T-197), it exposed latent
issues, plus a coincidental Claude-session crash in the same log:
- T-203: the _EditorDragHandle's slider Semantics had value +
onIncrease/onDecrease but no increased/decreasedValue, so Flutter
asserted on every semantics flush — add them. And opening the split
reparented the Claude pane (direct child → Column/Expanded), tearing
down its SelectableRegion mid selection-update ('selectable not in
this registrar' / 'inactive element'); a stable GlobalKey on the
workspace primary makes Flutter move the element instead.
- T-202: rate_limit_event.resetsAt arrives as a unix-epoch number but
was cast `as String?`, throwing in the stream-json line parser. Accept
a num (epoch) or an ISO string.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+19
-3
@@ -923,6 +923,15 @@ class _SidebarSlot extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// Stable identity for the workspace's primary pane (Claude). Opening the
|
||||
// editor reparents it from a direct child into a Column/Expanded; without a
|
||||
// stable key Flutter disposes + rebuilds the subtree, and the Claude
|
||||
// conversation's SelectableRegion then runs a pending selection update
|
||||
// against now-inactive elements ("selectable not in this registrar" /
|
||||
// "renderObject of inactive element"). The GlobalKey makes Flutter MOVE the
|
||||
// element instead, preserving the selection subtree.
|
||||
final GlobalKey _kWorkspacePrimary = GlobalKey(debugLabel: 'workspace.primary');
|
||||
|
||||
class _WorkspaceSlot extends StatelessWidget {
|
||||
const _WorkspaceSlot({required this.tabs, required this.active});
|
||||
|
||||
@@ -944,9 +953,10 @@ class _WorkspaceSlot extends StatelessWidget {
|
||||
|
||||
final claude = tabs.where((t) => t.id == _claudeTabId).firstOrNull;
|
||||
final primary = claude ?? active;
|
||||
final primaryPane = KeyedSubtree(key: _kWorkspacePrimary, child: primary.build(ctx));
|
||||
|
||||
if (!editorOpen || editorTab == null) {
|
||||
return Container(color: tokens.panelBackground, child: primary.build(ctx));
|
||||
return Container(color: tokens.panelBackground, child: primaryPane);
|
||||
}
|
||||
|
||||
final ratio = kernel.arrangement.editorRatio;
|
||||
@@ -960,7 +970,7 @@ class _WorkspaceSlot extends StatelessWidget {
|
||||
children: [
|
||||
SizedBox(height: editorHeight, child: editorTab.build(ctx)),
|
||||
_EditorDragHandle(arrangement: kernel.arrangement, totalHeight: totalHeight),
|
||||
Expanded(child: primary.build(ctx)),
|
||||
Expanded(child: primaryPane),
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -998,11 +1008,17 @@ class _EditorDragHandleState extends State<_EditorDragHandle> {
|
||||
final tokens = ClideTheme.of(context).surface;
|
||||
final lineColor = (_hovered || _focused) ? tokens.panelActiveBorder : tokens.panelBorder;
|
||||
|
||||
final ratio = widget.arrangement.editorRatio;
|
||||
String pct(double r) => '${(r.clamp(0.15, 0.70) * 100).round()}%';
|
||||
return Semantics(
|
||||
container: true,
|
||||
slider: true,
|
||||
label: 'Editor split',
|
||||
value: '${(widget.arrangement.editorRatio * 100).round()}%',
|
||||
value: pct(ratio),
|
||||
// increase/decrease actions require matching increased/decreased
|
||||
// values, or Flutter asserts on every semantics flush.
|
||||
increasedValue: pct(ratio + _stepFine),
|
||||
decreasedValue: pct(ratio - _stepFine),
|
||||
onIncrease: () => _bump(_stepFine),
|
||||
onDecrease: () => _bump(-_stepFine),
|
||||
child: FocusableActionDetector(
|
||||
|
||||
Reference in New Issue
Block a user