feat(studio): first-run UX, recovery affordances, l10n, bundled fonts
- Connection-aware Welcome: when the hub is down, show a hero with a primary "Start hub" CTA + install fallback instead of a dead, all-unchecked onboarding checklist (the first-run cliff). - Actionable binary-not-found (file picker + install link, not a "set FAI_BIN" dead end) and a connect-failure banner after repeated failed health polls. - Localize six hardcoded English error/toast clusters (DE+EN ARB). - Bundle Inter + JetBrains Mono as assets; drop the runtime google_fonts fetch (air-gap / KRITIS safe, no font-swap flash). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
7511867774
commit
5313266cc4
25 changed files with 1231 additions and 234 deletions
|
|
@ -86,6 +86,26 @@ class _ProviderPreset {
|
|||
static _ProviderPreset byWire(String wire) {
|
||||
return all.firstWhere((p) => p.wire == wire, orElse: () => all.first);
|
||||
}
|
||||
|
||||
/// Localized help body for this provider. Falls back to the
|
||||
/// const English [description] for any future wire that has no
|
||||
/// ARB key yet.
|
||||
String descriptionFor(AppLocalizations l) {
|
||||
switch (wire) {
|
||||
case 'ollama':
|
||||
return l.providerDescOllama;
|
||||
case 'openai':
|
||||
return l.providerDescOpenai;
|
||||
case 'lmstudio':
|
||||
return l.providerDescLmstudio;
|
||||
case 'vllm':
|
||||
return l.providerDescVllm;
|
||||
case 'custom':
|
||||
return l.providerDescCustom;
|
||||
default:
|
||||
return description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FaiSystemAiEditor extends StatefulWidget {
|
||||
|
|
@ -372,7 +392,7 @@ class _FaiSystemAiEditorState extends State<FaiSystemAiEditor> {
|
|||
_ProviderDropdown(value: _preset, onChanged: _onProviderChanged),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_preset.description,
|
||||
_preset.descriptionFor(l),
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
|
@ -634,10 +654,10 @@ class _TestResultPanel extends StatelessWidget {
|
|||
ok ? l.systemAiReplyPrefix(result.text) : result.text,
|
||||
style: FaiTheme.mono(size: 11, color: theme.colorScheme.onSurface),
|
||||
),
|
||||
if (!ok && result.fixHint.isNotEmpty) ...[
|
||||
if (!ok && result.fixHint(l).isNotEmpty) ...[
|
||||
const SizedBox(height: FaiSpace.xs),
|
||||
Text(
|
||||
result.fixHint,
|
||||
result.fixHint(l),
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurface,
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue