feat(studio): central error helpers + inline log viewer + Today CTAs
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
Bundles the error-UX overhaul and the inline log viewer:
- New `FaiLog` (`~/.fai/logs/studio-errors.log`, 256 KiB rotation,
JSON-per-line). Every operator-visible failure is appended so
`fai admin doctor` and the new viewer can show the trail
without the operator having to reproduce the failure.
- New `showFaiErrorSnack` / `showFaiErrorDialog` helpers wrap
`FaiErrorBox` in copyable surfaces; 27 ad-hoc
`SnackBar(content: Text(e.toString()))` sites swept to use
them (settings, doctor, audit, store, module sheet, system-AI
editor, flow output).
- New `FaiLogViewer` modal (`showFaiLogViewer`) renders log
files inline with line numbers, JSON-key + `[level]` token
colouring, Copy-all, Refresh, Open-externally. Doctor's
daemon-paths panel grows a "View" button next to "Open" for
every `.log` row and now also lists the Studio errors log.
- Today carousel: CTAs now actually re-run search after a
`filterCategory` / `runQuery` story is tapped (was only
flipping the chip state). Fallback story list bumped to 8.
- Editor bumped to git ref carrying 0.15.0 (type-token
colouring + analyzer diagnostics).
Studio bumped to 0.62.0.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
2731062a13
commit
8f5cd2528b
22 changed files with 1087 additions and 134 deletions
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../data/error_presentation.dart';
|
||||
import '../data/fai_log.dart';
|
||||
import '../data/hub.dart';
|
||||
import '../data/system_actions.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
|
@ -343,6 +345,12 @@ class _DaemonPathsPanel extends StatelessWidget {
|
|||
// Explorer instead of failing the OS "open" handler.
|
||||
final entries = <(String, String, IconData, bool)>[
|
||||
(l.doctorPathLog, paths.logPath, Icons.description_outlined, false),
|
||||
(
|
||||
l.doctorPathStudioErrors,
|
||||
FaiLog.instance.path,
|
||||
Icons.report_problem_outlined,
|
||||
false,
|
||||
),
|
||||
(l.doctorPathConfig, paths.configPath, Icons.settings_outlined, false),
|
||||
(l.doctorPathDb, paths.dbPath, Icons.storage_outlined, false),
|
||||
(l.doctorPathModules, paths.modulesDir, Icons.extension_outlined, true),
|
||||
|
|
@ -387,6 +395,8 @@ class _PathRow extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l = AppLocalizations.of(context)!;
|
||||
final isLog = !isDirectory && path.toLowerCase().endsWith('.log');
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
|
|
@ -412,6 +422,18 @@ class _PathRow extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(width: FaiSpace.sm),
|
||||
if (isLog) ...[
|
||||
OutlinedButton.icon(
|
||||
onPressed: () =>
|
||||
showFaiLogViewer(context, path: path, title: label),
|
||||
icon: const Icon(Icons.visibility_outlined, size: 14),
|
||||
label: Text(l.buttonView),
|
||||
style: OutlinedButton.styleFrom(
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: FaiSpace.xs),
|
||||
],
|
||||
OutlinedButton.icon(
|
||||
onPressed: () async {
|
||||
final r = await SystemActions.openOrReveal(
|
||||
|
|
@ -420,9 +442,10 @@ class _PathRow extends StatelessWidget {
|
|||
);
|
||||
if (!context.mounted) return;
|
||||
if (!r.ok) {
|
||||
final l = AppLocalizations.of(context)!;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(l.doctorOpenError(r.stderr))),
|
||||
showFaiErrorSnack(
|
||||
context,
|
||||
'doctor.open-path',
|
||||
r.stderr.isEmpty ? 'open failed' : r.stderr,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -430,7 +453,7 @@ class _PathRow extends StatelessWidget {
|
|||
isDirectory ? Icons.folder_open : Icons.open_in_new,
|
||||
size: 14,
|
||||
),
|
||||
label: Text(AppLocalizations.of(context)!.buttonOpen),
|
||||
label: Text(l.buttonOpen),
|
||||
style: OutlinedButton.styleFrom(
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue