fix(studio): Welcome layout exception, drop awkward header, Store at slot 2 (v0.39.1)
Three fixes against the v0.39.0 user feedback. - Layout exception "BoxConstraints forces an infinite height". `_PillarRow`'s wide-window path used `Row(crossAxisAlignment: CrossAxisAlignment.stretch)` inside a `Column` inside a `SingleChildScrollView` — Row inherits unbounded height, can't stretch to anything, Flutter throws. Wrapped the Row in `IntrinsicHeight` so the Row's height is bounded to the tallest child first. Same shape `_DocsRow`'s narrow-window path was triggering with `Wrap` + `SizedBox(width: double.infinity)` — replaced with a plain `Column` for that path; the wide path keeps the Wrap with the proper finite cardWidth. - Dropped the "WIE ES ZUSAMMENPASST" / "HOW IT FITS TOGETHER" section header. Operator-feedback was that the label sounded like a question without an answer. The hero already establishes the page; the three Hub/Module/Flow cards are self-explaining beneath it. Header was visual clutter and the underlying ARB keys are gone. - Reordered the sidebar: Welcome, **Store**, Doctor, Flows, Audit, Approvals. Store is the operator's daily-use surface and belongs above Doctor (which is a diagnostics page). Welcome stays slot 0 as the first-launch landing. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
930e246649
commit
eb447c6ec0
8 changed files with 47 additions and 40 deletions
|
|
@ -6,7 +6,6 @@
|
||||||
"navWelcome": "Willkommen",
|
"navWelcome": "Willkommen",
|
||||||
"welcomeHeroTitle": "F∆I Platform",
|
"welcomeHeroTitle": "F∆I Platform",
|
||||||
"welcomeHeroSubtitle": "Deterministische Workflow-Engine für KI-gestützte Dokumentenverarbeitung in regulierten Umgebungen.",
|
"welcomeHeroSubtitle": "Deterministische Workflow-Engine für KI-gestützte Dokumentenverarbeitung in regulierten Umgebungen.",
|
||||||
"welcomePillarsHeader": "WIE ES ZUSAMMENPASST",
|
|
||||||
"welcomePillarHubTitle": "Hub",
|
"welcomePillarHubTitle": "Hub",
|
||||||
"welcomePillarHubBody": "Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den State. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.",
|
"welcomePillarHubBody": "Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den State. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.",
|
||||||
"welcomePillarModuleTitle": "Modul",
|
"welcomePillarModuleTitle": "Modul",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
"navWelcome": "Welcome",
|
"navWelcome": "Welcome",
|
||||||
"welcomeHeroTitle": "F∆I Platform",
|
"welcomeHeroTitle": "F∆I Platform",
|
||||||
"welcomeHeroSubtitle": "Deterministic workflow engine for AI-assisted document processing in regulated environments.",
|
"welcomeHeroSubtitle": "Deterministic workflow engine for AI-assisted document processing in regulated environments.",
|
||||||
"welcomePillarsHeader": "HOW IT FITS TOGETHER",
|
|
||||||
"welcomePillarHubTitle": "Hub",
|
"welcomePillarHubTitle": "Hub",
|
||||||
"welcomePillarHubBody": "One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.",
|
"welcomePillarHubBody": "One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.",
|
||||||
"welcomePillarModuleTitle": "Module",
|
"welcomePillarModuleTitle": "Module",
|
||||||
|
|
|
||||||
|
|
@ -122,12 +122,6 @@ abstract class AppLocalizations {
|
||||||
/// **'Deterministic workflow engine for AI-assisted document processing in regulated environments.'**
|
/// **'Deterministic workflow engine for AI-assisted document processing in regulated environments.'**
|
||||||
String get welcomeHeroSubtitle;
|
String get welcomeHeroSubtitle;
|
||||||
|
|
||||||
/// No description provided for @welcomePillarsHeader.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'HOW IT FITS TOGETHER'**
|
|
||||||
String get welcomePillarsHeader;
|
|
||||||
|
|
||||||
/// No description provided for @welcomePillarHubTitle.
|
/// No description provided for @welcomePillarHubTitle.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get welcomeHeroSubtitle =>
|
String get welcomeHeroSubtitle =>
|
||||||
'Deterministische Workflow-Engine für KI-gestützte Dokumentenverarbeitung in regulierten Umgebungen.';
|
'Deterministische Workflow-Engine für KI-gestützte Dokumentenverarbeitung in regulierten Umgebungen.';
|
||||||
|
|
||||||
@override
|
|
||||||
String get welcomePillarsHeader => 'WIE ES ZUSAMMENPASST';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarHubTitle => 'Hub';
|
String get welcomePillarHubTitle => 'Hub';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
String get welcomeHeroSubtitle =>
|
String get welcomeHeroSubtitle =>
|
||||||
'Deterministic workflow engine for AI-assisted document processing in regulated environments.';
|
'Deterministic workflow engine for AI-assisted document processing in regulated environments.';
|
||||||
|
|
||||||
@override
|
|
||||||
String get welcomePillarsHeader => 'HOW IT FITS TOGETHER';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarHubTitle => 'Hub';
|
String get welcomePillarHubTitle => 'Hub';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import 'widgets/widgets.dart';
|
||||||
/// Studio's own build version. Bump on every UI commit so the
|
/// Studio's own build version. Bump on every UI commit so the
|
||||||
/// running app self-identifies — visible in the sidebar header
|
/// running app self-identifies — visible in the sidebar header
|
||||||
/// and quick-glance proof that you're seeing the current build.
|
/// and quick-glance proof that you're seeing the current build.
|
||||||
const String kStudioVersion = '0.39.0';
|
const String kStudioVersion = '0.39.1';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
@ -146,6 +146,15 @@ class _StudioShellState extends State<StudioShell> {
|
||||||
selectedIcon: Icons.waving_hand,
|
selectedIcon: Icons.waving_hand,
|
||||||
page: WelcomePage(),
|
page: WelcomePage(),
|
||||||
),
|
),
|
||||||
|
// Store moved to slot 2 in v0.39.1 — it's the
|
||||||
|
// operator's daily-use surface and belongs above Doctor,
|
||||||
|
// which is a diagnostics page.
|
||||||
|
_NavPage(
|
||||||
|
id: 'store',
|
||||||
|
icon: Icons.storefront_outlined,
|
||||||
|
selectedIcon: Icons.storefront,
|
||||||
|
page: StorePage(),
|
||||||
|
),
|
||||||
_NavPage(
|
_NavPage(
|
||||||
id: 'doctor',
|
id: 'doctor',
|
||||||
icon: Icons.health_and_safety_outlined,
|
icon: Icons.health_and_safety_outlined,
|
||||||
|
|
@ -157,12 +166,6 @@ class _StudioShellState extends State<StudioShell> {
|
||||||
// the Store's detail sheet, and the Store with the
|
// the Store's detail sheet, and the Store with the
|
||||||
// "Installed" filter covers the listing role. Cmd+K still
|
// "Installed" filter covers the listing role. Cmd+K still
|
||||||
// opens FaiModuleSheet for quick info.
|
// opens FaiModuleSheet for quick info.
|
||||||
_NavPage(
|
|
||||||
id: 'store',
|
|
||||||
icon: Icons.storefront_outlined,
|
|
||||||
selectedIcon: Icons.storefront,
|
|
||||||
page: StorePage(),
|
|
||||||
),
|
|
||||||
_NavPage(
|
_NavPage(
|
||||||
id: 'flows',
|
id: 'flows',
|
||||||
icon: Icons.account_tree_outlined,
|
icon: Icons.account_tree_outlined,
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,6 @@ class WelcomePage extends StatelessWidget {
|
||||||
// path beats educational content. Auto-hides
|
// path beats educational content. Auto-hides
|
||||||
// once the operator dismisses it.
|
// once the operator dismisses it.
|
||||||
_OnboardingChecklist(),
|
_OnboardingChecklist(),
|
||||||
_SectionLabel(textKey: _SectionLabelKey.pillars),
|
|
||||||
SizedBox(height: FaiSpace.md),
|
|
||||||
_PillarRow(),
|
_PillarRow(),
|
||||||
SizedBox(height: FaiSpace.xxl),
|
SizedBox(height: FaiSpace.xxl),
|
||||||
_SectionLabel(textKey: _SectionLabelKey.trust),
|
_SectionLabel(textKey: _SectionLabelKey.trust),
|
||||||
|
|
@ -143,7 +141,7 @@ class _Hero extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _SectionLabelKey { pillars, trust, docs }
|
enum _SectionLabelKey { trust, docs }
|
||||||
|
|
||||||
class _SectionLabel extends StatelessWidget {
|
class _SectionLabel extends StatelessWidget {
|
||||||
final _SectionLabelKey textKey;
|
final _SectionLabelKey textKey;
|
||||||
|
|
@ -154,7 +152,6 @@ class _SectionLabel extends StatelessWidget {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final l = AppLocalizations.of(context)!;
|
final l = AppLocalizations.of(context)!;
|
||||||
final text = switch (textKey) {
|
final text = switch (textKey) {
|
||||||
_SectionLabelKey.pillars => l.welcomePillarsHeader,
|
|
||||||
_SectionLabelKey.trust => l.welcomeTrustHeader,
|
_SectionLabelKey.trust => l.welcomeTrustHeader,
|
||||||
_SectionLabelKey.docs => l.welcomeDocsHeader,
|
_SectionLabelKey.docs => l.welcomeDocsHeader,
|
||||||
};
|
};
|
||||||
|
|
@ -210,20 +207,28 @@ class _PillarRow extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Row(
|
// IntrinsicHeight bounds the Row's height so
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
// `crossAxisAlignment: stretch` has something to
|
||||||
children: [
|
// stretch against. Without it the Row inherits the
|
||||||
for (var i = 0; i < pillars.length; i++) ...[
|
// unbounded height of the surrounding
|
||||||
if (i > 0) const SizedBox(width: FaiSpace.md),
|
// `SingleChildScrollView` and Flutter throws
|
||||||
Expanded(
|
// "BoxConstraints forces an infinite height".
|
||||||
child: _Pillar(
|
return IntrinsicHeight(
|
||||||
icon: pillars[i].$1,
|
child: Row(
|
||||||
title: pillars[i].$2,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
body: pillars[i].$3,
|
children: [
|
||||||
|
for (var i = 0; i < pillars.length; i++) ...[
|
||||||
|
if (i > 0) const SizedBox(width: FaiSpace.md),
|
||||||
|
Expanded(
|
||||||
|
child: _Pillar(
|
||||||
|
icon: pillars[i].$1,
|
||||||
|
title: pillars[i].$2,
|
||||||
|
body: pillars[i].$3,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -683,8 +688,21 @@ class _DocsRow extends StatelessWidget {
|
||||||
LayoutBuilder(
|
LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final twoCols = constraints.maxWidth >= 640;
|
final twoCols = constraints.maxWidth >= 640;
|
||||||
final cardWidth =
|
// Narrow windows stack to a single column. Putting
|
||||||
twoCols ? (constraints.maxWidth - FaiSpace.md) / 2 : double.infinity;
|
// `width: double.infinity` SizedBoxes into a Wrap
|
||||||
|
// breaks Wrap's intrinsic-width math; a Column with
|
||||||
|
// unconstrained child widths is the correct fit.
|
||||||
|
if (!twoCols) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
for (var i = 0; i < _kDocs.length; i++) ...[
|
||||||
|
if (i > 0) const SizedBox(height: FaiSpace.md),
|
||||||
|
_DocCard(entry: _kDocs[i]),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final cardWidth = (constraints.maxWidth - FaiSpace.md) / 2;
|
||||||
return Wrap(
|
return Wrap(
|
||||||
spacing: FaiSpace.md,
|
spacing: FaiSpace.md,
|
||||||
runSpacing: FaiSpace.md,
|
runSpacing: FaiSpace.md,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
name: fai_studio
|
name: fai_studio
|
||||||
description: "F∆I Studio — desktop GUI for the F∆I hub"
|
description: "F∆I Studio — desktop GUI for the F∆I hub"
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.39.0
|
version: 0.39.1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.11.0-200.1.beta
|
sdk: ^3.11.0-200.1.beta
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue