feat(studio): rich theme picker (presets + custom colour) + editor 0.11.0
Some checks failed
Security / Security check (push) Failing after 1s

Settings dialog's Theme Plugin section is now a grid of
swatched tiles:

- Built-in (none) — falls back to FaiTheme.light/.dark
- One tile per installed studio.theme.* plugin, each
  showing the plugin's primary/secondary/tertiary as
  live colour dots. Tile loads its preview lazily so a
  dozen installed themes don't block the picker.
- Custom — opens a colour-picker dialog with 12 curated
  Material presets + a hex input + live preview. Selecting
  applies ColorScheme.fromSeed for both brightnesses.

main.dart's _pluginThemes parses a 'custom:#RRGGBB' sigil
in the same notifier slot as plugin capability ids, so the
existing persistence + restoration paths cover the custom
case with no new state.

Bumps editor to 0.11.0 (type-checked port connections +
dynamic card width fix + card-height border allowance) and
Studio to 0.58.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-02 01:29:34 +02:00
parent 69864da934
commit c1c60d5434
30 changed files with 1280 additions and 846 deletions

View file

@ -126,10 +126,7 @@ class _CodeBlock extends StatelessWidget {
),
child: SelectableText(
text,
style: FaiTheme.mono(
size: 12,
color: theme.colorScheme.onSurface,
),
style: FaiTheme.mono(size: 12, color: theme.colorScheme.onSurface),
),
);
}
@ -170,14 +167,14 @@ class _BytesView extends StatelessWidget {
try {
await File(path).writeAsBytes(bytes, flush: true);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l.flowsOutputSavedAt(path))),
);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(l.flowsOutputSavedAt(path))));
} catch (e) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l.flowsOutputSaveFailed('$e'))),
);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(l.flowsOutputSaveFailed('$e'))));
}
}
@ -239,9 +236,9 @@ class _FileView extends StatelessWidget {
final r = await SystemActions.openInOs(target);
if (!context.mounted || r.ok) return;
final l = AppLocalizations.of(context)!;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l.flowsOutputOpenFailed(r.stderr))),
);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(l.flowsOutputOpenFailed(r.stderr))));
}
@override
@ -261,10 +258,7 @@ class _FileView extends StatelessWidget {
children: [
SelectableText(
uri,
style: FaiTheme.mono(
size: 11,
color: theme.colorScheme.primary,
),
style: FaiTheme.mono(size: 11, color: theme.colorScheme.primary),
),
if (mimeType.isNotEmpty) ...[
const SizedBox(height: 4),