refactor: rename internal Fai* design system + fai_ helpers to chain
Some checks failed
Security / Security check (push) Failing after 2s

The Studio design system, widgets and helpers carried a Fai* / fai_
prefix (FaiSpace, FaiColors, FaiTheme, FaiLog, 17 fai_*.dart files, the
faiBinary* l10n keys). Studio is the Ch∆In product, so rename them to
Chain* / chain_ — carefully preserving English fail/failure/failed.
Also fix stale references: the 'fai' binary in l10n strings -> 'chain',
FAI_* env vars (FAI_BIN/DATA_DIR/MODULES_DIR/TODAY/BOOTSTRAP_TOKEN) ->
CHAIN_*, fai_platform -> fai_chain, fai_hub -> chain_hub. Vendor
security-hook tooling (FAI_BANNED_TERMS_FILE) + the .fai bundle ext left.
flutter analyze + test: clean (20 passed).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-16 17:53:17 +02:00
parent 68d23ab7dd
commit 891acd2ba2
52 changed files with 1225 additions and 1225 deletions

View file

@ -35,14 +35,14 @@ class WelcomePage extends StatelessWidget {
final hubDown = StudioShellState.of(context)?.connected == false;
return Scaffold(
backgroundColor: theme.scaffoldBackgroundColor,
appBar: AppBar(titleSpacing: FaiSpace.xl, title: Text(l.navWelcome)),
appBar: AppBar(titleSpacing: ChainSpace.xl, title: Text(l.navWelcome)),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(
FaiSpace.xl,
FaiSpace.lg,
FaiSpace.xl,
FaiSpace.xxl,
ChainSpace.xl,
ChainSpace.lg,
ChainSpace.xl,
ChainSpace.xxl,
),
// Center the 960-px content column on wide windows
// so the right margin matches the left rather than
@ -59,24 +59,24 @@ class WelcomePage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const _Hero(),
const SizedBox(height: FaiSpace.xxl),
const SizedBox(height: ChainSpace.xxl),
// When the hub is down the onboarding checklist
// would render dead (all-unchecked, nothing to
// probe). Lead with a "start the hub" card
// instead; restore the checklist once connected.
if (hubDown) ...[
const _HubDownHero(),
const SizedBox(height: FaiSpace.xxl),
const SizedBox(height: ChainSpace.xxl),
] else
const _OnboardingChecklist(),
const _PillarRow(),
const SizedBox(height: FaiSpace.xxl),
const SizedBox(height: ChainSpace.xxl),
const _SectionLabel(textKey: _SectionLabelKey.trust),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
const _TrustPosture(),
const SizedBox(height: FaiSpace.xxl),
const SizedBox(height: ChainSpace.xxl),
const _SectionLabel(textKey: _SectionLabelKey.docs),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
const _DocsRow(),
],
),
@ -100,9 +100,9 @@ class _Hero extends StatelessWidget {
final l = AppLocalizations.of(context)!;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(FaiSpace.xxl),
padding: const EdgeInsets.all(ChainSpace.xxl),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
gradient: LinearGradient(
colors: [
theme.colorScheme.primary.withValues(alpha: 0.18),
@ -123,7 +123,7 @@ class _Hero extends StatelessWidget {
Row(
children: [
Container(
padding: const EdgeInsets.all(FaiSpace.md),
padding: const EdgeInsets.all(ChainSpace.md),
decoration: BoxDecoration(
color: theme.colorScheme.primary.withValues(alpha: 0.14),
shape: BoxShape.circle,
@ -134,7 +134,7 @@ class _Hero extends StatelessWidget {
color: theme.colorScheme.primary,
),
),
const SizedBox(width: FaiSpace.lg),
const SizedBox(width: ChainSpace.lg),
Expanded(
child: Text(
l.welcomeHeroTitle,
@ -145,7 +145,7 @@ class _Hero extends StatelessWidget {
),
],
),
const SizedBox(height: FaiSpace.lg),
const SizedBox(height: ChainSpace.lg),
Text(
l.welcomeHeroSubtitle,
style: theme.textTheme.titleMedium?.copyWith(
@ -189,13 +189,13 @@ class _HubDownHeroState extends State<_HubDownHero> {
final l = AppLocalizations.of(context)!;
// No `fai` binary "Start hub" cannot work; lead the
// operator to the install guide instead.
final canStart = SystemActions.faiBinaryExists();
final canStart = SystemActions.chainBinaryExists();
return Container(
width: double.infinity,
padding: const EdgeInsets.all(FaiSpace.xl),
padding: const EdgeInsets.all(ChainSpace.xl),
decoration: BoxDecoration(
color: theme.colorScheme.errorContainer.withValues(alpha: 0.35),
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(
color: theme.colorScheme.error.withValues(alpha: 0.4),
),
@ -210,7 +210,7 @@ class _HubDownHeroState extends State<_HubDownHero> {
size: 24,
color: theme.colorScheme.error,
),
const SizedBox(width: FaiSpace.md),
const SizedBox(width: ChainSpace.md),
Expanded(
child: Text(
l.welcomeHubDownTitle,
@ -221,7 +221,7 @@ class _HubDownHeroState extends State<_HubDownHero> {
),
],
),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
Text(
l.welcomeHubDownBody,
style: theme.textTheme.bodyMedium?.copyWith(
@ -229,15 +229,15 @@ class _HubDownHeroState extends State<_HubDownHero> {
height: 1.45,
),
),
const SizedBox(height: FaiSpace.xs),
const SizedBox(height: ChainSpace.xs),
Text(
l.welcomeHubDownEndpoint(HubService.instance.endpointLabel),
style: FaiTheme.mono(
style: ChainTheme.mono(
size: 11,
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: FaiSpace.lg),
const SizedBox(height: ChainSpace.lg),
if (canStart)
FilledButton.icon(
onPressed: _starting ? null : _start,
@ -253,8 +253,8 @@ class _HubDownHeroState extends State<_HubDownHero> {
),
)
else
const FaiBinaryRecovery(),
const SizedBox(height: FaiSpace.sm),
const ChainBinaryRecovery(),
const SizedBox(height: ChainSpace.sm),
TextButton.icon(
icon: const Icon(Icons.open_in_new, size: 16),
label: Text(l.welcomeHubDownDocsLink),
@ -323,7 +323,7 @@ class _PillarRow extends StatelessWidget {
children: [
for (final p in pillars) ...[
_Pillar(icon: p.$1, title: p.$2, body: p.$3),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
],
],
);
@ -339,7 +339,7 @@ class _PillarRow extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
for (var i = 0; i < pillars.length; i++) ...[
if (i > 0) const SizedBox(width: FaiSpace.md),
if (i > 0) const SizedBox(width: ChainSpace.md),
Expanded(
child: _Pillar(
icon: pillars[i].$1,
@ -367,24 +367,24 @@ class _Pillar extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
padding: const EdgeInsets.all(FaiSpace.lg),
padding: const EdgeInsets.all(ChainSpace.lg),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(color: theme.colorScheme.outlineVariant),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 28, color: theme.colorScheme.primary),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
Text(
title,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: FaiSpace.sm),
const SizedBox(height: ChainSpace.sm),
Text(
body,
style: theme.textTheme.bodyMedium?.copyWith(
@ -427,7 +427,7 @@ class _TrustPosture extends StatelessWidget {
return Column(
children: [
for (var i = 0; i < rows.length; i++) ...[
if (i > 0) const SizedBox(height: FaiSpace.sm),
if (i > 0) const SizedBox(height: ChainSpace.sm),
_TrustRow(icon: rows[i].$1, title: rows[i].$2, body: rows[i].$3),
],
],
@ -450,17 +450,17 @@ class _TrustRow extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
padding: const EdgeInsets.all(FaiSpace.lg),
padding: const EdgeInsets.all(ChainSpace.lg),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(color: theme.colorScheme.outlineVariant),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 22, color: theme.colorScheme.primary),
const SizedBox(width: FaiSpace.lg),
const SizedBox(width: ChainSpace.lg),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -601,13 +601,13 @@ class _OnboardingChecklistState extends State<_OnboardingChecklist> {
_aiOk,
l.welcomeChecklistAi,
l.welcomeChecklistAiHint,
() => FaiSettingsDialog.show(context),
() => ChainSettingsDialog.show(context),
),
(
_mcpOk,
l.welcomeChecklistMcp,
l.welcomeChecklistMcpHint,
() => FaiSettingsDialog.show(context),
() => ChainSettingsDialog.show(context),
),
(
_moduleOk,
@ -623,7 +623,7 @@ class _OnboardingChecklistState extends State<_OnboardingChecklist> {
),
];
return Padding(
padding: const EdgeInsets.only(bottom: FaiSpace.xxl),
padding: const EdgeInsets.only(bottom: ChainSpace.xxl),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -661,11 +661,11 @@ class _OnboardingChecklistState extends State<_OnboardingChecklist> {
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
Container(
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(color: theme.colorScheme.outlineVariant),
),
child: Column(
@ -684,7 +684,7 @@ class _OnboardingChecklistState extends State<_OnboardingChecklist> {
),
),
if (allDone) ...[
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
_AllDoneCelebration(onDismiss: _dismiss),
],
],
@ -707,19 +707,19 @@ class _AllDoneCelebration extends StatelessWidget {
final theme = Theme.of(context);
final l = AppLocalizations.of(context)!;
return Container(
padding: const EdgeInsets.all(FaiSpace.lg),
padding: const EdgeInsets.all(ChainSpace.lg),
decoration: BoxDecoration(
color: FaiColors.success.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(FaiRadius.md),
border: Border.all(color: FaiColors.success.withValues(alpha: 0.35)),
color: ChainColors.success.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(color: ChainColors.success.withValues(alpha: 0.35)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.celebration_outlined, color: FaiColors.success),
const SizedBox(width: FaiSpace.sm),
Icon(Icons.celebration_outlined, color: ChainColors.success),
const SizedBox(width: ChainSpace.sm),
Expanded(
child: Text(
l.welcomeChecklistAllSetTitle,
@ -741,7 +741,7 @@ class _AllDoneCelebration extends StatelessWidget {
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
_NextStepRow(
icon: Icons.timeline_outlined,
title: l.welcomeChecklistNextAuditTitle,
@ -797,12 +797,12 @@ class _NextStepRow extends StatelessWidget {
final theme = Theme.of(context);
final canActivate = doc != null && onOpenDoc != null;
return Padding(
padding: const EdgeInsets.only(bottom: FaiSpace.sm),
padding: const EdgeInsets.only(bottom: ChainSpace.sm),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 18, color: theme.colorScheme.primary),
const SizedBox(width: FaiSpace.md),
const SizedBox(width: ChainSpace.md),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -823,7 +823,7 @@ class _NextStepRow extends StatelessWidget {
],
),
),
const SizedBox(width: FaiSpace.md),
const SizedBox(width: ChainSpace.md),
OutlinedButton(
onPressed: canActivate ? () => onOpenDoc!(doc!) : null,
child: Text(buttonLabel),
@ -856,16 +856,16 @@ class _ChecklistRow extends StatelessWidget {
final theme = Theme.of(context);
final l = AppLocalizations.of(context)!;
final row = Padding(
padding: const EdgeInsets.all(FaiSpace.lg),
padding: const EdgeInsets.all(ChainSpace.lg),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
done ? Icons.check_circle : Icons.radio_button_unchecked,
size: 20,
color: done ? FaiColors.success : theme.colorScheme.outline,
color: done ? ChainColors.success : theme.colorScheme.outline,
),
const SizedBox(width: FaiSpace.lg),
const SizedBox(width: ChainSpace.lg),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -890,10 +890,10 @@ class _ChecklistRow extends StatelessWidget {
],
),
),
const SizedBox(width: FaiSpace.md),
FaiPill(
const SizedBox(width: ChainSpace.md),
ChainPill(
label: done ? l.welcomeChecklistDone : l.welcomeChecklistTodo,
tone: done ? FaiPillTone.success : FaiPillTone.neutral,
tone: done ? ChainPillTone.success : ChainPillTone.neutral,
),
],
),
@ -985,7 +985,7 @@ class _DocsRow extends StatelessWidget {
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
LayoutBuilder(
builder: (context, constraints) {
final twoCols = constraints.maxWidth >= 640;
@ -997,16 +997,16 @@ class _DocsRow extends StatelessWidget {
return Column(
children: [
for (var i = 0; i < _kDocs.length; i++) ...[
if (i > 0) const SizedBox(height: FaiSpace.md),
if (i > 0) const SizedBox(height: ChainSpace.md),
_DocCard(entry: _kDocs[i]),
],
],
);
}
final cardWidth = (constraints.maxWidth - FaiSpace.md) / 2;
final cardWidth = (constraints.maxWidth - ChainSpace.md) / 2;
return Wrap(
spacing: FaiSpace.md,
runSpacing: FaiSpace.md,
spacing: ChainSpace.md,
runSpacing: ChainSpace.md,
children: [
for (final d in _kDocs)
SizedBox(
@ -1045,30 +1045,30 @@ class _DocCardState extends State<_DocCard> {
onEnter: (_) => setState(() => _hovered = true),
onExit: (_) => setState(() => _hovered = false),
child: AnimatedContainer(
duration: FaiMotion.base,
curve: FaiMotion.easing,
duration: ChainMotion.base,
curve: ChainMotion.easing,
transform: Matrix4.translationValues(0, _hovered ? -2 : 0, 0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(FaiRadius.md),
boxShadow: _hovered ? FaiElevation.medium(theme.brightness) : null,
borderRadius: BorderRadius.circular(ChainRadius.md),
boxShadow: _hovered ? ChainElevation.medium(theme.brightness) : null,
),
child: Material(
color: theme.colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
child: InkWell(
onTap: () => _DocReaderSheet.show(context, entry),
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
child: Container(
padding: const EdgeInsets.all(FaiSpace.lg),
padding: const EdgeInsets.all(ChainSpace.lg),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(FaiRadius.md),
borderRadius: BorderRadius.circular(ChainRadius.md),
border: Border.all(color: theme.colorScheme.outlineVariant),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(entry.icon, size: 22, color: theme.colorScheme.primary),
const SizedBox(width: FaiSpace.lg),
const SizedBox(width: ChainSpace.lg),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -1159,7 +1159,7 @@ class _DocReaderSheet extends StatefulWidget {
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(FaiRadius.md)),
borderRadius: BorderRadius.vertical(top: Radius.circular(ChainRadius.md)),
),
builder: (_) => _DocReaderSheet(entry: entry),
);
@ -1191,7 +1191,7 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
// the .dart_tool asset manifest can be inconsistent with
// the compiled binary surface "rebuild Studio" as a
// first-class hint rather than just dumping the raw
// PlatformException string into FaiErrorBox.
// PlatformException string into ChainErrorBox.
try {
return await rootBundle.loadString(localised);
} catch (firstErr) {
@ -1219,7 +1219,7 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: FaiSpace.sm),
padding: const EdgeInsets.symmetric(vertical: ChainSpace.sm),
child: Container(
width: 40,
height: 4,
@ -1231,10 +1231,10 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
),
Padding(
padding: const EdgeInsets.fromLTRB(
FaiSpace.xxl,
FaiSpace.sm,
FaiSpace.lg,
FaiSpace.sm,
ChainSpace.xxl,
ChainSpace.sm,
ChainSpace.lg,
ChainSpace.sm,
),
child: Row(
children: [
@ -1243,7 +1243,7 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
size: 20,
color: theme.colorScheme.primary,
),
const SizedBox(width: FaiSpace.sm),
const SizedBox(width: ChainSpace.sm),
Expanded(
child: Text(
widget.entry.title(l),
@ -1268,7 +1268,7 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
builder: (context, snap) {
if (snap.connectionState == ConnectionState.waiting) {
return const Padding(
padding: EdgeInsets.all(FaiSpace.xxl),
padding: EdgeInsets.all(ChainSpace.xxl),
child: Center(child: CircularProgressIndicator()),
);
}
@ -1276,7 +1276,7 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
final err = snap.error;
final structured = err is _DocReaderError ? err : null;
return Padding(
padding: const EdgeInsets.all(FaiSpace.xxl),
padding: const EdgeInsets.all(ChainSpace.xxl),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -1286,21 +1286,21 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
color: theme.colorScheme.error,
),
),
const SizedBox(height: FaiSpace.sm),
const SizedBox(height: ChainSpace.sm),
if (structured != null)
FaiErrorBox(
ChainErrorBox(
text: structured.localizedBody(l),
isError: true,
maxHeight: 200,
)
else
FaiErrorBox(
ChainErrorBox(
error: err,
isError: true,
maxHeight: 200,
),
if (structured != null) ...[
const SizedBox(height: FaiSpace.md),
const SizedBox(height: ChainSpace.md),
TextButton.icon(
icon: const Icon(Icons.open_in_new, size: 16),
label: Text(structured.forgejoUrl),
@ -1314,14 +1314,14 @@ class _DocReaderSheetState extends State<_DocReaderSheet> {
}
return Markdown(
data: snap.data ?? '',
padding: const EdgeInsets.all(FaiSpace.xxl),
padding: const EdgeInsets.all(ChainSpace.xxl),
selectable: true,
onTapLink: (text, href, title) async {
if (href != null && href.isNotEmpty) {
await SystemActions.openInOs(href);
}
},
styleSheet: FaiTheme.markdownStyle(theme),
styleSheet: ChainTheme.markdownStyle(theme),
);
},
),