Add shared UI components for mesh application

- Introduced `mesh_ui.dart` with reusable widgets including SectionHeader, MeshCard, StatusChip, StatTile, AvatarCircle, SignalBars, RouteChip, PulseDot, BottomSheetHeader, ErrorRetryCard, and ListEntrance.
- Implemented `path_map_ui.dart` for path map screens, featuring path distance calculations, playback controls, and a summary list of observed paths.
- Created `themed_map_tile_layer.dart` for shared cached map tiles with automatic dark-mode treatment.
This commit is contained in:
zjs81
2026-06-12 21:04:02 -07:00
parent 6a31d304d3
commit 51d6210920
72 changed files with 16778 additions and 7110 deletions
+39 -54
View File
@@ -19,6 +19,8 @@ import '../utils/battery_utils.dart';
import '../helpers/snack_bar_builder.dart';
import '../widgets/sync_progress_overlay.dart';
import '../widgets/telemetry_location_map.dart';
import '../theme/mesh_theme.dart';
import '../widgets/mesh_ui.dart';
class TelemetryScreen extends StatefulWidget {
final Contact contact;
@@ -319,6 +321,7 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final scheme = Theme.of(context).colorScheme;
final connector = context.watch<MeshCoreConnector>();
final settings = context.watch<AppSettingsService>().settings;
final isImperialUnits = settings.unitSystem == UnitSystem.imperial;
@@ -387,7 +390,7 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
l10n.telemetry_noData,
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: scheme.onSurfaceVariant,
),
),
),
@@ -415,34 +418,21 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
int channel,
bool isImperialUnits,
) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.info_outline,
color: Theme.of(context).textTheme.headlineSmall?.color,
),
const SizedBox(width: 8),
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const Divider(),
for (final entry in channelData.entries)
_buildTelemetryField(entry, channel, isImperialUnits),
],
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SectionHeader(title, padding: const EdgeInsets.fromLTRB(16, 16, 16, 8)),
MeshCard(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final entry in channelData.entries)
_buildTelemetryField(entry, channel, isImperialUnits),
],
),
),
),
],
);
}
@@ -601,30 +591,19 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
final l10n = context.l10n;
final counterText = _autoRefreshCounterText();
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Icon(
Icons.autorenew,
color: Theme.of(context).textTheme.headlineSmall?.color,
),
const SizedBox(width: 8),
Text(
l10n.common_autoRefresh,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const Divider(),
_buildAutoRefreshNumberField(
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SectionHeader(
l10n.common_autoRefresh,
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
),
MeshCard(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildAutoRefreshNumberField(
controller: _autoRefreshIntervalController,
label: l10n.common_interval,
min: _autoRefreshMinIntervalSeconds,
@@ -684,6 +663,7 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
],
),
),
],
);
}
@@ -913,6 +893,7 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
}
Widget _buildInfoRow(String label, String value) {
final scheme = Theme.of(context).colorScheme;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Row(
@@ -922,7 +903,8 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
child: Text(
label,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: scheme.onSurfaceVariant,
fontSize: 13,
fontWeight: FontWeight.w500,
),
),
@@ -930,7 +912,10 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
const SizedBox(width: 8),
Text(
value,
style: const TextStyle(fontWeight: FontWeight.w400),
style: MeshTheme.mono(
fontSize: 13,
color: scheme.onSurface,
),
textAlign: TextAlign.end,
),
],