fix(studio): sidebar left-anchor + pull flow-editor 0.1.2
Some checks failed
Security / Security check (push) Failing after 2s

Two Stefan-reported fixes after the v0.51.x live test:

1. Sidebar icons appeared to shift between collapsed and
   expanded. Mathematically the icons stayed at x=24 (
   ListView padding + AC padding), but the Column's default
   crossAxisAlignment.center re-centered the brand mark
   AND the top indicators (version, connection, channel) on
   every expand → in a 72 px rail the brand sits at x≈36,
   in a 220 px rail it sits at x≈110. Stefan perceived this
   horizontal repositioning of the brand+pills as a shift
   of the icons below.

   Fix: Column.crossAxisAlignment = start + left-pad every
   top item (brand mark, "F∆I Studio" label, version,
   connection pill, channel pill, mini-version, connection
   dot, channel chip) by exactly the same offset the
   destinations use (ListView.padding + AC.padding =
   FaiSpace.md + FaiSpace.md). The whole rail now reads as
   one stable left edge through the expand animation.

2. Pull fai_studio_flow_editor 0.1.2 — fixes the
   "opening hello.yaml shows extract-with-approval content"
   bug by switching `_code.text = ...` to the canonical
   `_code.fullText = ...` setter in the package.

Version: 0.51.2 → 0.51.3
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-30 16:08:22 +02:00
parent 8ae9441e38
commit 1295675bd9
3 changed files with 88 additions and 34 deletions

View file

@ -27,7 +27,7 @@ import 'widgets/widgets.dart';
/// Studio's own build version. Bump on every UI commit so the
/// running app self-identifies visible in the sidebar header
/// and quick-glance proof that you're seeing the current build.
const String kStudioVersion = '0.51.2';
const String kStudioVersion = '0.51.3';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -479,29 +479,59 @@ class _SidebarState extends State<_Sidebar> {
padding: const EdgeInsets.symmetric(vertical: FaiSpace.xl),
child: ClipRect(
child: Column(
// Left-align every column child so brand mark + top
// indicators sit at the same X-pixel as the icons
// below. With the default `center`, the brand mark
// re-positioned itself horizontally on every expand
// animation (centered in 72 vs centered in 220),
// which the user perceived as the whole nav rail
// shifting even though the destination icons stayed
// put. Anchoring everything to the start eliminates
// the perceived shift.
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Brand mark always visible.
FaiDeltaMark(color: theme.colorScheme.primary, mode: mode),
// Brand mark always visible. Pad it to match the
// icon's left offset (ListView padding + AC padding
// = FaiSpace.md + FaiSpace.md), so the triangle's
// left edge aligns with the destination icons'
// left edges.
Padding(
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
),
child:
FaiDeltaMark(color: theme.colorScheme.primary, mode: mode),
),
if (expanded) ...[
const SizedBox(height: FaiSpace.md),
Text(
'F∆I Studio',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
const Padding(
padding: EdgeInsets.only(left: FaiSpace.md + FaiSpace.md),
child: Text(
'F∆I Studio',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
const SizedBox(height: 2),
Text(
'v$kStudioVersion',
style: FaiTheme.mono(
size: 10,
color: theme.colorScheme.primary,
Padding(
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
),
child: Text(
'v$kStudioVersion',
style: FaiTheme.mono(
size: 10,
color: theme.colorScheme.primary,
),
),
),
const SizedBox(height: FaiSpace.md),
// Connection pill full version when expanded.
// Connection pill left-aligned to the same
// x-anchor as the icons.
Padding(
padding: const EdgeInsets.symmetric(horizontal: FaiSpace.lg),
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
right: FaiSpace.md,
),
child: _ConnectionPill(
connected: widget.connected,
label: widget.endpointLabel,
@ -523,7 +553,10 @@ class _SidebarState extends State<_Sidebar> {
if (widget.activeChannel != null && widget.activeChannel!.isNotEmpty) ...[
const SizedBox(height: FaiSpace.sm),
Padding(
padding: const EdgeInsets.symmetric(horizontal: FaiSpace.lg),
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
right: FaiSpace.md,
),
child: _ChannelPill(channel: widget.activeChannel!),
),
],
@ -532,29 +565,50 @@ class _SidebarState extends State<_Sidebar> {
// most glance-able status indicators (version,
// connection dot, channel letter) so the rail
// still reads as FI Studio at-a-glance without
// hovering to expand.
// hovering to expand. All left-padded by the
// same offset as the destination icons (
// ListView.padding + AC.padding = 12 + 12)
// so the column reads as one stable left edge.
const SizedBox(height: FaiSpace.sm),
Text(
'v$kStudioVersion'.replaceFirst(RegExp(r'-.*'), ''),
style: FaiTheme.mono(
size: 9,
color: theme.colorScheme.primary,
Padding(
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
),
child: Text(
'v$kStudioVersion'.replaceFirst(RegExp(r'-.*'), ''),
style: FaiTheme.mono(
size: 9,
color: theme.colorScheme.primary,
),
),
),
const SizedBox(height: FaiSpace.md),
Tooltip(
message: widget.connected == true
? 'Connected · ${widget.endpointLabel}'
: widget.connected == false
? 'Disconnected · ${widget.endpointLabel}'
: 'Connecting · ${widget.endpointLabel}',
child: _CollapsedConnectionDot(connected: widget.connected),
Padding(
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
),
child: Tooltip(
message: widget.connected == true
? 'Connected · ${widget.endpointLabel}'
: widget.connected == false
? 'Disconnected · ${widget.endpointLabel}'
: 'Connecting · ${widget.endpointLabel}',
child:
_CollapsedConnectionDot(connected: widget.connected),
),
),
if (widget.activeChannel != null && widget.activeChannel!.isNotEmpty) ...[
const SizedBox(height: FaiSpace.sm),
Tooltip(
message: widget.activeChannel!,
child: _CollapsedChannelChip(channel: widget.activeChannel!),
Padding(
padding: const EdgeInsets.only(
left: FaiSpace.md + FaiSpace.md,
),
child: Tooltip(
message: widget.activeChannel!,
child: _CollapsedChannelChip(
channel: widget.activeChannel!,
),
),
),
],
],