mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: Reset fallback sharing state
This commit is contained in:
@@ -654,7 +654,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
||||
title: device.platformName.isNotEmpty
|
||||
? device.platformName
|
||||
: 'Unknown Device',
|
||||
subtitle: 'Signal $rssi dBm',
|
||||
subtitle: AppLocalizations.of(context)!.signalDbm(rssi.toString()),
|
||||
trailing: isConnecting
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
@@ -665,7 +665,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
||||
)
|
||||
: FilledButton.tonal(
|
||||
onPressed: connectBle,
|
||||
child: const Text('Connect'),
|
||||
child: Text(AppLocalizations.of(context)!.connect),
|
||||
),
|
||||
onTap: isConnecting ? null : connectBle,
|
||||
enabled: !isConnecting,
|
||||
@@ -721,7 +721,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
||||
: _discoveredServers.isEmpty
|
||||
? _buildEmptyState(
|
||||
icon: Icons.wifi_off_rounded,
|
||||
title: 'No servers found',
|
||||
title: AppLocalizations.of(context)!.noServersFound,
|
||||
actionLabel: 'Scan Again',
|
||||
onAction: _startNetworkScan,
|
||||
)
|
||||
@@ -792,7 +792,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
||||
onPressed: isAnyConnectionInProgress
|
||||
? null
|
||||
: connectServer,
|
||||
child: const Text('Connect'),
|
||||
child: Text(AppLocalizations.of(context)!.connect),
|
||||
),
|
||||
enabled: !isAnyConnectionInProgress,
|
||||
onTap: isAnyConnectionInProgress ? null : connectServer,
|
||||
@@ -885,7 +885,7 @@ class _ManualTcpHostDialogState extends State<_ManualTcpHostDialog> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Connect by IP address'),
|
||||
title: Text(AppLocalizations.of(context)!.connectByIpAddress),
|
||||
content: TextField(
|
||||
controller: _controller,
|
||||
autofocus: true,
|
||||
@@ -910,11 +910,11 @@ class _ManualTcpHostDialogState extends State<_ManualTcpHostDialog> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: _submit,
|
||||
child: const Text('Connect'),
|
||||
child: Text(AppLocalizations.of(context)!.connect),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -1053,7 +1053,7 @@ class _SerialDeviceListState extends State<_SerialDeviceList> {
|
||||
if (!mounted) return;
|
||||
setState(() => _isConnecting = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Failed to connect via serial')),
|
||||
SnackBar(content: Text(AppLocalizations.of(context)!.failedToConnectViaSerial)),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -1061,7 +1061,7 @@ class _SerialDeviceListState extends State<_SerialDeviceList> {
|
||||
setState(() => _isConnecting = false);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Serial error: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(AppLocalizations.of(context)!.serialError(e.toString()))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,7 +1127,7 @@ class _SerialDeviceListState extends State<_SerialDeviceList> {
|
||||
onPressed: _isConnecting
|
||||
? null
|
||||
: () => _connectToDevice(device),
|
||||
child: const Text('Connect'),
|
||||
child: Text(AppLocalizations.of(context)!.connect),
|
||||
),
|
||||
enabled: !_isConnecting,
|
||||
onTap: _isConnecting ? null : () => _connectToDevice(device),
|
||||
|
||||
@@ -320,7 +320,7 @@ class _ContactRouteDialogState extends State<ContactRouteDialog> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Selected relays', style: Theme.of(context).textTheme.titleSmall),
|
||||
Text(AppLocalizations.of(context)!.selectedRelays, style: Theme.of(context).textTheme.titleSmall),
|
||||
const SizedBox(height: 8),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
@@ -355,11 +355,11 @@ class _ContactRouteDialogState extends State<ContactRouteDialog> {
|
||||
TextField(
|
||||
controller: _relaySearchController,
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: const InputDecoration(
|
||||
prefixIcon: Icon(Icons.search),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
labelText: 'Find relay',
|
||||
hintText: 'Search by name or token',
|
||||
border: OutlineInputBorder(),
|
||||
hintText: AppLocalizations.of(context)!.searchByNameOrToken,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@@ -509,7 +509,7 @@ class _ContactRouteDialogState extends State<ContactRouteDialog> {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text('Path size', style: Theme.of(context).textTheme.labelLarge),
|
||||
Text(AppLocalizations.of(context)!.pathSize, style: Theme.of(context).textTheme.labelLarge),
|
||||
const Spacer(),
|
||||
SegmentedButton<int>(
|
||||
segments: [
|
||||
@@ -621,7 +621,7 @@ class _ContactRouteDialogState extends State<ContactRouteDialog> {
|
||||
length: 2,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Set Path for ${widget.contact.displayName}'),
|
||||
title: Text(AppLocalizations.of(context)!.setPathForContact(widget.contact.displayName)),
|
||||
bottom: const TabBar(
|
||||
tabs: [
|
||||
Tab(text: 'Build'),
|
||||
|
||||
@@ -437,6 +437,7 @@ class ContactTile extends StatelessWidget {
|
||||
final result = await context.read<AppProvider>().setChannelLocationSharingEnabled(
|
||||
channelIdx,
|
||||
enabled,
|
||||
l10n: AppLocalizations.of(context),
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
ToastLogger.success(context, result.message);
|
||||
@@ -655,7 +656,7 @@ class ContactTile extends StatelessWidget {
|
||||
if (contact.type == ContactType.repeater)
|
||||
_ContactSheetAction(
|
||||
icon: Icons.hub_outlined,
|
||||
label: 'View Neighbours',
|
||||
label: AppLocalizations.of(context)!.viewNeighbours,
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
_showNeighbours(context, contact);
|
||||
@@ -665,7 +666,7 @@ class ContactTile extends StatelessWidget {
|
||||
contact.type == ContactType.room)
|
||||
_ContactSheetAction(
|
||||
icon: Icons.network_ping,
|
||||
label: 'Ping',
|
||||
label: AppLocalizations.of(context)!.ping,
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
_pingRelay(context, contact);
|
||||
@@ -2395,7 +2396,7 @@ class _NeighboursSheetState extends State<_NeighboursSheet> {
|
||||
),
|
||||
)
|
||||
: _neighbours.isEmpty
|
||||
? const Center(child: Text('No neighbours found'))
|
||||
? Center(child: Text(AppLocalizations.of(context)!.noNeighboursFound))
|
||||
: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
|
||||
child: Column(
|
||||
@@ -2768,7 +2769,7 @@ class _PingRelaySheetState extends State<_PingRelaySheet> {
|
||||
IconButton(
|
||||
onPressed: () => setState(() => _history.clear()),
|
||||
icon: const Icon(Icons.delete_outline, size: 20),
|
||||
tooltip: 'Clear history',
|
||||
tooltip: AppLocalizations.of(context)!.clearHistory,
|
||||
style: IconButton.styleFrom(
|
||||
foregroundColor: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter_map/flutter_map.dart' as flutter_map;
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../models/contact.dart';
|
||||
import '../../providers/connection_provider.dart';
|
||||
import '../../providers/contacts_provider.dart';
|
||||
@@ -84,7 +85,7 @@ class _ContactTraceSheetState extends State<ContactTraceSheet> {
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text('Failed to load trace: ${snapshot.error}'),
|
||||
child: Text(AppLocalizations.of(context)!.failedToLoadTrace(snapshot.error.toString())),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -179,7 +179,7 @@ class DrawingMarkersLayer extends StatelessWidget {
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(AppLocalizations.of(context)!.deleteDrawing),
|
||||
content: Text('Delete this ${drawing.type.name}?'),
|
||||
content: Text(AppLocalizations.of(context)!.deleteThisDrawing(drawing.type.name)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
|
||||
@@ -398,7 +398,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
},
|
||||
tooltip: 'Share',
|
||||
tooltip: AppLocalizations.of(context)!.share,
|
||||
color: Colors.blue,
|
||||
padding: const EdgeInsets.all(4),
|
||||
constraints: const BoxConstraints(),
|
||||
@@ -415,7 +415,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
drawing,
|
||||
);
|
||||
},
|
||||
tooltip: 'Delete',
|
||||
tooltip: AppLocalizations.of(context)!.delete,
|
||||
color: Colors.red,
|
||||
padding: const EdgeInsets.all(4),
|
||||
constraints: const BoxConstraints(),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../providers/offline_tiles_provider.dart';
|
||||
|
||||
/// Renders polygon/rectangle drawing interaction on the map.
|
||||
@@ -199,7 +200,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
children: [
|
||||
_ToolButton(
|
||||
icon: Icons.crop_square,
|
||||
label: 'Rectangle',
|
||||
label: AppLocalizations.of(context)!.rectangle,
|
||||
isActive: provider.drawingMode == DrawingMode.rectangle,
|
||||
onTap: () => provider.setDrawingMode(
|
||||
provider.drawingMode == DrawingMode.rectangle
|
||||
@@ -210,7 +211,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_ToolButton(
|
||||
icon: Icons.pentagon_outlined,
|
||||
label: 'Polygon',
|
||||
label: AppLocalizations.of(context)!.polygon,
|
||||
isActive: provider.drawingMode == DrawingMode.polygon,
|
||||
onTap: () => provider.setDrawingMode(
|
||||
provider.drawingMode == DrawingMode.polygon
|
||||
@@ -223,7 +224,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_ToolButton(
|
||||
icon: Icons.check,
|
||||
label: 'Finish',
|
||||
label: AppLocalizations.of(context)!.finish,
|
||||
isActive: false,
|
||||
color: Colors.green,
|
||||
onTap: () => provider.finishPolygon(),
|
||||
@@ -234,7 +235,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_ToolButton(
|
||||
icon: Icons.undo,
|
||||
label: 'Undo',
|
||||
label: AppLocalizations.of(context)!.undo,
|
||||
isActive: false,
|
||||
onTap: () => provider.undoLastVertex(),
|
||||
),
|
||||
@@ -243,7 +244,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_ToolButton(
|
||||
icon: Icons.delete_outline,
|
||||
label: 'Clear',
|
||||
label: AppLocalizations.of(context)!.clear,
|
||||
isActive: false,
|
||||
color: Colors.red,
|
||||
onTap: () => provider.clearPolygons(),
|
||||
|
||||
@@ -394,7 +394,7 @@ class _CustomMapSarUpdateSheetState extends State<CustomMapSarUpdateSheet> {
|
||||
controller: _notesController,
|
||||
maxLines: 3,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Add additional details',
|
||||
hintText: AppLocalizations.of(context)!.addAdditionalDetails,
|
||||
filled: true,
|
||||
fillColor: colorScheme.surfaceContainerHighest,
|
||||
border: OutlineInputBorder(
|
||||
|
||||
@@ -11,6 +11,7 @@ import '../../providers/contacts_provider.dart';
|
||||
import '../../providers/image_provider.dart' as ip;
|
||||
import '../../providers/messages_provider.dart';
|
||||
import '../../utils/image_message_parser.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../utils/transmission_target_resolver.dart';
|
||||
import 'transfer_timeout.dart';
|
||||
|
||||
@@ -237,7 +238,7 @@ class _ImageMessageBubbleState extends State<ImageMessageBubble> {
|
||||
onPressed: () => _cancelReceive(envelope.sessionId),
|
||||
icon: const Icon(Icons.close, size: 20),
|
||||
color: Colors.white70,
|
||||
tooltip: 'Cancel image receive',
|
||||
tooltip: AppLocalizations.of(context)!.cancelImageReceive,
|
||||
),
|
||||
),
|
||||
] else if (_errorText != null) ...[
|
||||
@@ -255,7 +256,7 @@ class _ImageMessageBubbleState extends State<ImageMessageBubble> {
|
||||
pathLen: pathLen,
|
||||
),
|
||||
icon: const Icon(Icons.refresh, size: 18),
|
||||
label: const Text('Retry'),
|
||||
label: Text(AppLocalizations.of(context)!.retry),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.white70,
|
||||
),
|
||||
@@ -657,7 +658,7 @@ class _ImageMessageBubbleState extends State<ImageMessageBubble> {
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
icon: const Icon(Icons.close),
|
||||
color: Colors.white,
|
||||
tooltip: 'Close',
|
||||
tooltip: AppLocalizations.of(context)!.close,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart' as flutter_map;
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../models/ble_packet_log.dart';
|
||||
import '../../models/message.dart';
|
||||
import '../../providers/connection_provider.dart';
|
||||
@@ -133,7 +134,7 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text('Failed to load trace: ${snapshot.error}'),
|
||||
child: Text(AppLocalizations.of(context)!.failedToLoadTrace(snapshot.error.toString())),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -602,7 +602,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return PopupMenuButton<_RecipientSortMode>(
|
||||
tooltip: 'Sort',
|
||||
tooltip: AppLocalizations.of(context)!.sort,
|
||||
initialValue: _sortMode,
|
||||
onSelected: (sortMode) {
|
||||
setState(() {
|
||||
@@ -642,13 +642,13 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
|
||||
],
|
||||
),
|
||||
),
|
||||
const PopupMenuItem<_RecipientSortMode>(
|
||||
PopupMenuItem<_RecipientSortMode>(
|
||||
value: _RecipientSortMode.alphabetical,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.sort_by_alpha_rounded, size: 18),
|
||||
SizedBox(width: 8),
|
||||
Text('A-Z'),
|
||||
const Icon(Icons.sort_by_alpha_rounded, size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Text(AppLocalizations.of(context)!.aToZ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -176,7 +176,7 @@ class _PermissionRequestDialogState extends State<PermissionRequestDialog> {
|
||||
Navigator.of(context).pop();
|
||||
widget.onPermissionsDenied?.call();
|
||||
},
|
||||
child: const Text('Skip'),
|
||||
child: Text(AppLocalizations.of(context)!.skip),
|
||||
),
|
||||
if (_errorMessage != null && !_isRequesting)
|
||||
ElevatedButton(
|
||||
@@ -184,13 +184,13 @@ class _PermissionRequestDialogState extends State<PermissionRequestDialog> {
|
||||
// Open app settings
|
||||
await Geolocator.openLocationSettings();
|
||||
},
|
||||
child: const Text('Open Settings'),
|
||||
child: Text(AppLocalizations.of(context)!.openSettings),
|
||||
),
|
||||
if (_errorMessage != null && !_isRequesting &&
|
||||
!_errorMessage!.contains('permanently denied'))
|
||||
ElevatedButton(
|
||||
onPressed: _checkAndRequestPermissions,
|
||||
child: const Text('Retry'),
|
||||
child: Text(AppLocalizations.of(context)!.retry),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'package:meshcore_client/meshcore_client.dart' show Message;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -233,7 +234,7 @@ class _BTHomeMetHistorySheetState extends State<_BTHomeMetHistorySheet> {
|
||||
),
|
||||
),
|
||||
icon: const Icon(Icons.chevron_left),
|
||||
label: const Text('Newer'),
|
||||
label: Text(AppLocalizations.of(context)!.newer),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
OutlinedButton.icon(
|
||||
@@ -249,7 +250,7 @@ class _BTHomeMetHistorySheetState extends State<_BTHomeMetHistorySheet> {
|
||||
),
|
||||
),
|
||||
icon: const Icon(Icons.chevron_right),
|
||||
label: const Text('Older'),
|
||||
label: Text(AppLocalizations.of(context)!.older),
|
||||
),
|
||||
const Spacer(),
|
||||
if (_loading)
|
||||
@@ -276,13 +277,13 @@ class _BTHomeMetHistorySheetState extends State<_BTHomeMetHistorySheet> {
|
||||
if (_error != null)
|
||||
_HistoryMessageCard(
|
||||
icon: Icons.error_outline,
|
||||
title: 'Could not load MET history',
|
||||
title: AppLocalizations.of(context)!.couldNotLoadMetHistory,
|
||||
body: _error!,
|
||||
)
|
||||
else if (_loading && history == null)
|
||||
const _HistoryMessageCard(
|
||||
_HistoryMessageCard(
|
||||
icon: Icons.hourglass_top,
|
||||
title: 'Loading',
|
||||
title: AppLocalizations.of(context)!.loading,
|
||||
body: 'Waiting for the sensor to reply.',
|
||||
)
|
||||
else if (history != null) ...[
|
||||
@@ -362,19 +363,19 @@ class _HistoryStatsGrid extends StatelessWidget {
|
||||
final compact = constraints.maxWidth < 520;
|
||||
final tiles = <Widget>[
|
||||
_HistoryStatTile(
|
||||
label: 'Latest',
|
||||
label: AppLocalizations.of(context)!.latest,
|
||||
value: _formatMeasurementValue(measurement, history.latest),
|
||||
),
|
||||
_HistoryStatTile(
|
||||
label: 'Min',
|
||||
label: AppLocalizations.of(context)!.min,
|
||||
value: _formatMeasurementValue(measurement, history.minimum),
|
||||
),
|
||||
_HistoryStatTile(
|
||||
label: 'Max',
|
||||
label: AppLocalizations.of(context)!.max,
|
||||
value: _formatMeasurementValue(measurement, history.maximum),
|
||||
),
|
||||
_HistoryStatTile(
|
||||
label: 'Samples',
|
||||
label: AppLocalizations.of(context)!.samples,
|
||||
value: history.values.length.toString(),
|
||||
),
|
||||
];
|
||||
|
||||
@@ -1140,7 +1140,7 @@ class SensorTelemetryCard extends StatelessWidget {
|
||||
await Clipboard.setData(ClipboardData(text: rawTelemetry));
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Raw response copied')),
|
||||
SnackBar(content: Text(AppLocalizations.of(context)!.rawResponseCopied)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1173,13 +1173,13 @@ class SensorTelemetryCard extends StatelessWidget {
|
||||
if (onPing != null)
|
||||
_SensorSheetAction(
|
||||
icon: Icons.network_ping,
|
||||
label: 'Ping',
|
||||
label: AppLocalizations.of(context)!.ping,
|
||||
onTap: () => _handleAction(context, 'ping'),
|
||||
),
|
||||
if (_rawTelemetryHex(contact?.telemetry) != null)
|
||||
_SensorSheetAction(
|
||||
icon: Icons.copy_all_outlined,
|
||||
label: 'Copy raw response',
|
||||
label: AppLocalizations.of(context)!.copyRawResponse,
|
||||
onTap: () => _handleAction(context, 'copy_raw'),
|
||||
),
|
||||
if (onCustomize != null)
|
||||
@@ -1193,7 +1193,7 @@ class SensorTelemetryCard extends StatelessWidget {
|
||||
supportsBTHomeMetHistory(contact))
|
||||
_SensorSheetAction(
|
||||
icon: Icons.show_chart,
|
||||
label: 'MET history',
|
||||
label: AppLocalizations.of(context)!.metHistory,
|
||||
onTap: () => _handleAction(context, 'met_history'),
|
||||
),
|
||||
if (onRemove != null)
|
||||
@@ -1309,10 +1309,10 @@ class SensorTelemetryCard extends StatelessWidget {
|
||||
tooltip: l10n.refreshing,
|
||||
),
|
||||
if (state == SensorRefreshState.success)
|
||||
const _InlineStateMeta(
|
||||
_InlineStateMeta(
|
||||
color: Color(0xFF218B63),
|
||||
icon: Icons.check_circle,
|
||||
tooltip: 'Updated',
|
||||
tooltip: AppLocalizations.of(context)!.updated,
|
||||
),
|
||||
if (state == SensorRefreshState.unavailable)
|
||||
_InlineStateMeta(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../services/traffic_stats_reporting_service.dart';
|
||||
|
||||
class TrafficStatsReportingSection extends StatelessWidget {
|
||||
@@ -18,7 +19,7 @@ class TrafficStatsReportingSection extends StatelessWidget {
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
secondary: const Icon(Icons.cloud_upload_outlined, size: 20),
|
||||
title: const Text('Anonymous RX stats'),
|
||||
title: Text(AppLocalizations.of(context)!.anonymousRxStats),
|
||||
subtitle: const Text(
|
||||
'Upload packet totals every 5 min',
|
||||
),
|
||||
@@ -43,7 +44,7 @@ class TrafficStatsReportingSection extends StatelessWidget {
|
||||
TextButton.icon(
|
||||
onPressed: _openStatsDashboard,
|
||||
icon: const Icon(Icons.open_in_new, size: 16),
|
||||
label: const Text('View'),
|
||||
label: Text(AppLocalizations.of(context)!.view),
|
||||
style: TextButton.styleFrom(
|
||||
visualDensity: VisualDensity.compact,
|
||||
textStyle: theme.textTheme.labelSmall,
|
||||
|
||||
@@ -170,7 +170,7 @@ class UpdateDialog extends StatelessWidget {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Error opening download: $e'),
|
||||
content: Text(AppLocalizations.of(context)!.errorOpeningDownload(e.toString())),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user