feat(ground-suite): add system glass themes
This commit is contained in:
1 parent
01fb9f7292
commit
fd26a0bd14
9 files changed
+422
-136
No files matched your search
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../core/observations/observed_event.dart';
|
||||
import '../../../shared/widgets/severity_badge.dart';
|
||||
import '../../../shared/widgets/glass_panel.dart';
|
||||
import '../../observability/presentation/observability_controller.dart';
|
||||
|
||||
enum _DiagnosticFilter { all, logs, errors, shutdowns }
|
||||
@@ -23,50 +24,74 @@ class _DiagnosticsPageState extends ConsumerState<DiagnosticsPage> {
|
||||
final state = ref.watch(observabilityControllerProvider);
|
||||
final events = state.events.where(_matches).toList(growable: false);
|
||||
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
children: [
|
||||
Text('Diagnostics', style: Theme.of(context).textTheme.headlineMedium),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Messages remain distinct by protocol class. A configuration result '
|
||||
'will remain authoritative when configuration support is added.',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: _DiagnosticFilter.values
|
||||
.map(
|
||||
(filter) => ChoiceChip(
|
||||
label: Text(_labelFor(filter)),
|
||||
selected: _filter == filter,
|
||||
onSelected: (_) => setState(() => _filter = filter),
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 16),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Diagnostics',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
)
|
||||
.toList(growable: false),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Filter diagnostics',
|
||||
prefixIcon: Icon(Icons.search),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Messages remain distinct by protocol class. A configuration '
|
||||
'result will remain authoritative when configuration support '
|
||||
'is added.',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: _DiagnosticFilter.values
|
||||
.map(
|
||||
(filter) => ChoiceChip(
|
||||
label: Text(_labelFor(filter)),
|
||||
selected: _filter == filter,
|
||||
onSelected: (_) => setState(() => _filter = filter),
|
||||
),
|
||||
)
|
||||
.toList(growable: false),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Filter diagnostics',
|
||||
prefixIcon: Icon(Icons.search),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() => _query = value.trim().toLowerCase());
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() => _query = value.trim().toLowerCase());
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (events.isEmpty)
|
||||
const Card(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text('No diagnostic observations match this filter.'),
|
||||
const SliverPadding(
|
||||
padding: EdgeInsets.fromLTRB(24, 0, 24, 24),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: GlassPanel(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text('No diagnostic observations match this filter.'),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
...events.map((event) => _DiagnosticCard(event: event)),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: events.length,
|
||||
itemBuilder: (context, index) =>
|
||||
_DiagnosticCard(event: events[index]),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -119,37 +144,39 @@ class _DiagnosticCard extends StatelessWidget {
|
||||
return Semantics(
|
||||
container: true,
|
||||
label: content.semanticLabel,
|
||||
child: Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
content.leading,
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: SelectionArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(content.title, style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: 4),
|
||||
Text(content.detail),
|
||||
if (content.additionalDetail case final detail?) ...[
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: GlassListItem(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
content.leading,
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: SelectionArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(content.title, style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: 4),
|
||||
Text(content.detail),
|
||||
if (content.additionalDetail case final detail?) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(detail),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
Text(detail),
|
||||
Text(
|
||||
event.receivedAt.toIso8601String(),
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
event.receivedAt.toIso8601String(),
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user