Refactor UI code for better readability and consistency

- Improved formatting of ListTile icons and text styles in settings_screen.dart, telemetry_screen.dart, usb_screen.dart, gif_picker.dart, path_editor_sheet.dart, repeater_login_dialog.dart, and room_login_dialog.dart for better readability.
- Consolidated TextStyle definitions into single lines where applicable.
- Updated notification_service.dart to enhance readability of notification ID assignment.
- Simplified function signatures in routing_sheet.dart for clarity.
- Cleaned up test assertions in usb_flow_test.dart for conciseness.
- Removed unused translations in untranslated.json to streamline localization files.
This commit is contained in:
zjs81
2026-06-11 00:28:13 -07:00
parent b1de1b4bf0
commit 26fdf74d69
66 changed files with 3436 additions and 2596 deletions
+9 -3
View File
@@ -75,7 +75,9 @@ class AppDebugLogScreen extends StatelessWidget {
entry.formattedTime,
style: TextStyle(
fontSize: 10,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
);
@@ -95,7 +97,9 @@ class AppDebugLogScreen extends StatelessWidget {
context.l10n.debugLog_noEntries,
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 8),
@@ -103,7 +107,9 @@ class AppDebugLogScreen extends StatelessWidget {
context.l10n.debugLog_enableInSettings,
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
+144 -108
View File
@@ -359,113 +359,129 @@ class AppSettingsScreen extends StatelessWidget {
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_maxRouteWeight),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.l10n.appSettings_maxRouteWeightSubtitle),
Slider(
value: settingsService.settings.maxRouteWeight,
min: 1,
max: 10,
divisions: 9,
label: settingsService.settings.maxRouteWeight
.round()
.toString(),
onChanged: (value) =>
settingsService.setMaxRouteWeight(value),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.l10n.appSettings_maxRouteWeightSubtitle),
Slider(
value: settingsService.settings.maxRouteWeight,
min: 1,
max: 10,
divisions: 9,
label: settingsService.settings.maxRouteWeight
.round()
.toString(),
onChanged: (value) =>
settingsService.setMaxRouteWeight(value),
),
],
),
),
],
),
),
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_initialRouteWeight),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.l10n.appSettings_initialRouteWeightSubtitle),
Slider(
value: settingsService.settings.initialRouteWeight,
min: 0.5,
max: 5.0,
divisions: 9,
label: settingsService.settings.initialRouteWeight
.toStringAsFixed(1),
onChanged: (value) =>
settingsService.setInitialRouteWeight(value),
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_initialRouteWeight),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.l10n.appSettings_initialRouteWeightSubtitle,
),
Slider(
value: settingsService.settings.initialRouteWeight,
min: 0.5,
max: 5.0,
divisions: 9,
label: settingsService.settings.initialRouteWeight
.toStringAsFixed(1),
onChanged: (value) =>
settingsService.setInitialRouteWeight(value),
),
],
),
),
],
),
),
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_routeWeightSuccessIncrement),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context
.l10n
.appSettings_routeWeightSuccessIncrementSubtitle,
const Divider(height: 1),
ListTile(
title: Text(
context.l10n.appSettings_routeWeightSuccessIncrement,
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context
.l10n
.appSettings_routeWeightSuccessIncrementSubtitle,
),
Slider(
value: settingsService
.settings
.routeWeightSuccessIncrement,
min: 0.1,
max: 2.0,
divisions: 19,
label: settingsService
.settings
.routeWeightSuccessIncrement
.toStringAsFixed(1),
onChanged: (value) => settingsService
.setRouteWeightSuccessIncrement(value),
),
],
),
),
Slider(
value: settingsService.settings.routeWeightSuccessIncrement,
min: 0.1,
max: 2.0,
divisions: 19,
label: settingsService.settings.routeWeightSuccessIncrement
.toStringAsFixed(1),
onChanged: (value) =>
settingsService.setRouteWeightSuccessIncrement(value),
const Divider(height: 1),
ListTile(
title: Text(
context.l10n.appSettings_routeWeightFailureDecrement,
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context
.l10n
.appSettings_routeWeightFailureDecrementSubtitle,
),
Slider(
value: settingsService
.settings
.routeWeightFailureDecrement,
min: 0.1,
max: 2.0,
divisions: 19,
label: settingsService
.settings
.routeWeightFailureDecrement
.toStringAsFixed(1),
onChanged: (value) => settingsService
.setRouteWeightFailureDecrement(value),
),
],
),
),
],
),
),
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_routeWeightFailureDecrement),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context
.l10n
.appSettings_routeWeightFailureDecrementSubtitle,
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_maxMessageRetries),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.l10n.appSettings_maxMessageRetriesSubtitle,
),
Slider(
value: settingsService.settings.maxMessageRetries
.toDouble(),
min: 2,
max: 10,
divisions: 8,
label: settingsService.settings.maxMessageRetries
.toString(),
onChanged: (value) => settingsService
.setMaxMessageRetries(value.toInt()),
),
],
),
),
Slider(
value: settingsService.settings.routeWeightFailureDecrement,
min: 0.1,
max: 2.0,
divisions: 19,
label: settingsService.settings.routeWeightFailureDecrement
.toStringAsFixed(1),
onChanged: (value) =>
settingsService.setRouteWeightFailureDecrement(value),
),
],
),
),
const Divider(height: 1),
ListTile(
title: Text(context.l10n.appSettings_maxMessageRetries),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.l10n.appSettings_maxMessageRetriesSubtitle),
Slider(
value: settingsService.settings.maxMessageRetries
.toDouble(),
min: 2,
max: 10,
divisions: 8,
label: settingsService.settings.maxMessageRetries
.toString(),
onChanged: (value) =>
settingsService.setMaxMessageRetries(value.toInt()),
),
],
),
),
],
),
),
@@ -610,15 +626,25 @@ class AppSettingsScreen extends StatelessWidget {
SwitchListTile(
secondary: Icon(
Icons.auto_awesome_outlined,
color: translationEnabled ? null : Theme.of(context).disabledColor,
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
title: Text(
context.l10n.translation_autoIncomingTitle,
style: TextStyle(color: translationEnabled ? null : Theme.of(context).disabledColor),
style: TextStyle(
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
),
subtitle: Text(
context.l10n.translation_autoIncomingSubtitle,
style: TextStyle(color: translationEnabled ? null : Theme.of(context).disabledColor),
style: TextStyle(
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
),
value: settings.autoTranslateIncomingMessages,
onChanged: translationEnabled
@@ -629,15 +655,25 @@ class AppSettingsScreen extends StatelessWidget {
SwitchListTile(
secondary: Icon(
Icons.outgoing_mail,
color: translationEnabled ? null : Theme.of(context).disabledColor,
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
title: Text(
context.l10n.translation_composerTitle,
style: TextStyle(color: translationEnabled ? null : Theme.of(context).disabledColor),
style: TextStyle(
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
),
subtitle: Text(
context.l10n.translation_composerSubtitle,
style: TextStyle(color: translationEnabled ? null : Theme.of(context).disabledColor),
style: TextStyle(
color: translationEnabled
? null
: Theme.of(context).disabledColor,
),
),
value: settings.composerTranslationEnabled,
onChanged: translationEnabled
+189 -180
View File
@@ -512,149 +512,133 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
const bodyFontSize = 14.0;
final messageBody = LayoutBuilder(
builder: (context, constraints) => Column(
crossAxisAlignment: isOutgoing
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: isOutgoing
? MainAxisAlignment.end
: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
_buildAvatar(message.senderName),
const SizedBox(width: 8),
],
Flexible(
child: GestureDetector(
onLongPress: () => _showMessageActions(message),
onSecondaryTapUp: PlatformInfo.isDesktop
? (_) => _showMessageActions(message)
: null,
child: Container(
padding: gifId != null
? const EdgeInsets.all(4)
: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.65,
),
decoration: BoxDecoration(
color: isOutgoing
? Theme.of(context).colorScheme.primaryContainer
: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
top: 4,
bottom: 4,
)
: EdgeInsets.zero,
child: Text(
crossAxisAlignment: isOutgoing
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: isOutgoing
? MainAxisAlignment.end
: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
_buildAvatar(message.senderName),
const SizedBox(width: 8),
],
Flexible(
child: GestureDetector(
onLongPress: () => _showMessageActions(message),
onSecondaryTapUp: PlatformInfo.isDesktop
? (_) => _showMessageActions(message)
: null,
child: Container(
padding: gifId != null
? const EdgeInsets.all(4)
: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.65,
),
decoration: BoxDecoration(
color: isOutgoing
? Theme.of(context).colorScheme.primaryContainer
: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
top: 4,
bottom: 4,
)
: EdgeInsets.zero,
child: Text(
message.senderName,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
),
if (gifId == null) const SizedBox(height: 4),
],
if (message.replyToMessageId != null) ...[
_buildReplyPreview(message, textScale),
const SizedBox(height: 8),
],
if (poi != null)
_buildPoiMessage(
context,
poi,
isOutgoing,
textScale,
message.senderName,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
),
if (gifId == null) const SizedBox(height: 4),
],
if (message.replyToMessageId != null) ...[
_buildReplyPreview(message, textScale),
const SizedBox(height: 8),
],
if (poi != null)
_buildPoiMessage(
context,
poi,
isOutgoing,
textScale,
message.senderName,
)
else if (gifId != null)
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: GifMessage(
url:
'https://media.giphy.com/media/$gifId/giphy.gif',
backgroundColor: Colors.transparent,
fallbackTextColor: isOutgoing
? Theme.of(context)
.colorScheme
.onPrimaryContainer
.withValues(alpha: 0.7)
: Theme.of(context).colorScheme.onSurface
.withValues(alpha: 0.6),
),
),
],
)
else
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TranslatedMessageContent(
displayText: translatedDisplayText,
originalText: originalDisplayText,
style: TextStyle(
fontSize: bodyFontSize * textScale,
),
originalStyle: TextStyle(
fontSize: bodyFontSize * textScale,
fontStyle: FontStyle.italic,
color: Theme.of(context).colorScheme.onSurface
.withValues(alpha: 0.72),
)
else if (gifId != null)
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: GifMessage(
url:
'https://media.giphy.com/media/$gifId/giphy.gif',
backgroundColor: Colors.transparent,
fallbackTextColor: isOutgoing
? Theme.of(context)
.colorScheme
.onPrimaryContainer
.withValues(alpha: 0.7)
: Theme.of(context).colorScheme.onSurface
.withValues(alpha: 0.6),
),
),
),
],
),
if (enableTracing && displayPath.isNotEmpty) ...[
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.symmetric(horizontal: 8)
: EdgeInsets.zero,
child: Text(
context.l10n.channels_via(
_formatPathPrefixes(displayPath),
),
style: TextStyle(
fontSize: 11 * textScale,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
],
)
else
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TranslatedMessageContent(
displayText: translatedDisplayText,
originalText: originalDisplayText,
style: TextStyle(
fontSize: bodyFontSize * textScale,
),
originalStyle: TextStyle(
fontSize: bodyFontSize * textScale,
fontStyle: FontStyle.italic,
color: Theme.of(context)
.colorScheme
.onSurface
.withValues(alpha: 0.72),
),
),
),
],
),
),
],
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
right: 8,
bottom: 4,
)
: EdgeInsets.zero,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_formatTime(context, message.timestamp),
if (enableTracing && displayPath.isNotEmpty) ...[
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.symmetric(horizontal: 8)
: EdgeInsets.zero,
child: Text(
context.l10n.channels_via(
_formatPathPrefixes(displayPath),
),
style: TextStyle(
fontSize: 11 * textScale,
color: Theme.of(
@@ -662,18 +646,22 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
).colorScheme.onSurfaceVariant,
),
),
if (enableTracing && message.repeatCount > 0) ...[
const SizedBox(width: 6),
Icon(
Icons.repeat,
size: 12 * textScale,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 2),
),
],
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
right: 8,
bottom: 4,
)
: EdgeInsets.zero,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${message.repeatCount}',
_formatTime(context, message.timestamp),
style: TextStyle(
fontSize: 11 * textScale,
color: Theme.of(
@@ -681,43 +669,62 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
).colorScheme.onSurfaceVariant,
),
),
if (enableTracing && message.repeatCount > 0) ...[
const SizedBox(width: 6),
Icon(
Icons.repeat,
size: 12 * textScale,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 2),
Text(
'${message.repeatCount}',
style: TextStyle(
fontSize: 11 * textScale,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
if (isOutgoing) ...[
const SizedBox(width: 4),
MessageStatusIcon(
isAcked:
message.status ==
ChannelMessageStatus.sent,
isRepeated:
message.status ==
ChannelMessageStatus.sent &&
displayPath.isNotEmpty,
isPending:
message.status ==
ChannelMessageStatus.pending,
isFailed:
message.status ==
ChannelMessageStatus.failed,
),
],
],
if (isOutgoing) ...[
const SizedBox(width: 4),
MessageStatusIcon(
isAcked:
message.status ==
ChannelMessageStatus.sent,
isRepeated:
message.status ==
ChannelMessageStatus.sent &&
displayPath.isNotEmpty,
isPending:
message.status ==
ChannelMessageStatus.pending,
isFailed:
message.status ==
ChannelMessageStatus.failed,
),
],
],
),
),
),
],
],
),
),
),
),
],
),
if (message.reactions.isNotEmpty) ...[
const SizedBox(height: 4),
Padding(
padding: EdgeInsets.only(left: isOutgoing ? 0 : 48),
child: _buildReactionsDisplay(message),
),
],
),
if (message.reactions.isNotEmpty) ...[
const SizedBox(height: 4),
Padding(
padding: EdgeInsets.only(left: isOutgoing ? 0 : 48),
child: _buildReactionsDisplay(message),
),
],
],
),
);
@@ -922,7 +929,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 40, minHeight: 40),
onPressed: () {
final selfName = context.read<MeshCoreConnector>().selfName ?? context.l10n.chat_me;
final selfName =
context.read<MeshCoreConnector>().selfName ??
context.l10n.chat_me;
final fromName = isOutgoing ? selfName : senderName;
final key = buildSharedMarkerKey(
sourceId: 'channel:${widget.channel.index}',
+34 -11
View File
@@ -106,7 +106,9 @@ class ChannelMessagePathScreen extends StatelessWidget {
if (!hasHopDetails)
Text(
l10n.channelPath_noHopDetails,
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
)
else
..._buildHopTiles(context, hops),
@@ -131,7 +133,11 @@ class ChannelMessagePathScreen extends StatelessWidget {
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 8),
_buildDetailRow(context, l10n.channelPath_senderLabel, message.senderName),
_buildDetailRow(
context,
l10n.channelPath_senderLabel,
message.senderName,
),
_buildDetailRow(
context,
l10n.channelPath_timeLabel,
@@ -149,7 +155,11 @@ class ChannelMessagePathScreen extends StatelessWidget {
_formatPathLabel(message.pathLength, l10n),
),
if (observedLabel != null)
_buildDetailRow(context, l10n.channelPath_observedLabel, observedLabel),
_buildDetailRow(
context,
l10n.channelPath_observedLabel,
observedLabel,
),
],
),
),
@@ -261,7 +271,12 @@ class ChannelMessagePathScreen extends StatelessWidget {
children: [
SizedBox(
width: 70,
child: Text(label, style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant)),
child: Text(
label,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
Expanded(child: Text(value)),
],
@@ -596,7 +611,9 @@ class _ChannelMessagePathMapScreenState
if (points.isEmpty)
Center(
child: Card(
color: Theme.of(context).colorScheme.surface.withValues(alpha: 0.9),
color: Theme.of(
context,
).colorScheme.surface.withValues(alpha: 0.9),
child: Padding(
padding: EdgeInsets.all(12),
child: Text(
@@ -667,7 +684,10 @@ class _ChannelMessagePathMapScreenState
label,
_formatPathPrefixes(selectedPath.pathBytes),
),
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 12),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 12,
),
),
],
),
@@ -816,10 +836,10 @@ class _ChannelMessagePathMapScreenState
}
Widget _colorDot(Color color) => Container(
width: 10,
height: 10,
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
);
width: 10,
height: 10,
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
);
Widget _buildLegendCard(
BuildContext context,
@@ -855,7 +875,10 @@ class _ChannelMessagePathMapScreenState
children: [
_colorDot(Colors.green),
const SizedBox(width: 4),
Text(l10n.pathTrace_legendGpsConfirmed, style: const TextStyle(fontSize: 11)),
Text(
l10n.pathTrace_legendGpsConfirmed,
style: const TextStyle(fontSize: 11),
),
],
),
],
+11 -5
View File
@@ -253,8 +253,7 @@ class _ChannelsScreenState extends State<ChannelsScreen>
),
child: EmptyState(
icon: Icons.search_off,
title:
context.l10n.channels_noChannelsFound,
title: context.l10n.channels_noChannelsFound,
),
),
],
@@ -953,7 +952,11 @@ class _ChannelsScreenState extends State<ChannelsScreen>
Channel.publicChannelPsk,
);
Navigator.pop(dialogContext);
connector.setChannel(nextIndex, context.l10n.channels_public, psk);
connector.setChannel(
nextIndex,
context.l10n.channels_public,
psk,
);
if (context.mounted) {
showDismissibleSnackBar(
context,
@@ -1240,7 +1243,8 @@ class _ChannelsScreenState extends State<ChannelsScreen>
child: FilledButton(
onPressed: () async {
final name = nameController.text.trim();
final publicLabel = context.l10n.channels_public;
final publicLabel =
context.l10n.channels_public;
if (name.isEmpty) {
showDismissibleSnackBar(
context,
@@ -1727,7 +1731,9 @@ class _ChannelsScreenState extends State<ChannelsScreen>
),
title: Text(community.name),
subtitle: Text(
context.l10n.channels_communityShortId(community.shortCommunityId),
context.l10n.channels_communityShortId(
community.shortCommunityId,
),
style: TextStyle(
fontSize: 12,
color: Theme.of(
+183 -177
View File
@@ -187,7 +187,11 @@ class _ChatScreenState extends State<ChatScreen> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(contact.name, maxLines: 1, overflow: TextOverflow.ellipsis),
Text(
contact.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () =>
@@ -1251,202 +1255,202 @@ class _MessageBubble extends StatelessWidget {
children: [
LayoutBuilder(
builder: (context, constraints) => GestureDetector(
onLongPress: onLongPress,
onSecondaryTapUp: PlatformInfo.isDesktop
? (_) => onLongPress?.call()
: null,
child: Row(
mainAxisAlignment: isOutgoing
? MainAxisAlignment.end
: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
_buildAvatar(senderName, colorScheme),
const SizedBox(width: 8),
],
Flexible(
child: Container(
padding: gifId != null
? const EdgeInsets.all(4)
: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.65,
),
decoration: BoxDecoration(
color: bubbleColor,
borderRadius: BorderRadius.circular(16),
border: isFailed
? Border.all(color: colorScheme.error)
: null,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
onLongPress: onLongPress,
onSecondaryTapUp: PlatformInfo.isDesktop
? (_) => onLongPress?.call()
: null,
child: Row(
mainAxisAlignment: isOutgoing
? MainAxisAlignment.end
: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
_buildAvatar(senderName, colorScheme),
const SizedBox(width: 8),
],
Flexible(
child: Container(
padding: gifId != null
? const EdgeInsets.all(4)
: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.65,
),
decoration: BoxDecoration(
color: bubbleColor,
borderRadius: BorderRadius.circular(16),
border: isFailed
? Border.all(color: colorScheme.error)
: null,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isOutgoing) ...[
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
top: 4,
bottom: 4,
)
: EdgeInsets.zero,
child: Text(
senderName,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: colorScheme.primary,
),
),
),
if (gifId == null) const SizedBox(height: 4),
],
if (poi != null)
_buildPoiMessage(
context,
poi,
textColor,
metaColor,
textScale,
senderName,
)
else if (gifId != null)
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: GifMessage(
url:
'https://media.giphy.com/media/$gifId/giphy.gif',
backgroundColor: Colors.transparent,
fallbackTextColor: textColor.withValues(
alpha: 0.7,
),
),
),
],
)
else
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TranslatedMessageContent(
displayText: translatedDisplayText,
originalText: originalDisplayText,
style: TextStyle(
color: textColor,
fontSize: bodyFontSize * textScale,
),
originalStyle: TextStyle(
color: textColor.withValues(alpha: 0.78),
fontSize: bodyFontSize * textScale,
),
),
),
],
),
if (enableTracing &&
isOutgoing &&
message.retryCount > 0) ...[
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.symmetric(horizontal: 8)
: EdgeInsets.zero,
child: Text(
context.l10n.chat_retryCount(
message.retryCount,
context
.read<AppSettingsService>()
.settings
.maxMessageRetries,
),
style: TextStyle(
fontSize: 10 * textScale,
color: metaColor,
fontWeight: FontWeight.w500,
),
),
),
],
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
top: 4,
right: 8,
bottom: 4,
)
: EdgeInsets.zero,
child: Text(
senderName,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: colorScheme.primary,
),
),
),
if (gifId == null) const SizedBox(height: 4),
],
if (poi != null)
_buildPoiMessage(
context,
poi,
textColor,
metaColor,
textScale,
senderName,
)
else if (gifId != null)
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: GifMessage(
url:
'https://media.giphy.com/media/$gifId/giphy.gif',
backgroundColor: Colors.transparent,
fallbackTextColor: textColor.withValues(
alpha: 0.7,
),
),
),
],
)
else
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TranslatedMessageContent(
displayText: translatedDisplayText,
originalText: originalDisplayText,
style: TextStyle(
color: textColor,
fontSize: bodyFontSize * textScale,
),
originalStyle: TextStyle(
color: textColor.withValues(alpha: 0.78),
fontSize: bodyFontSize * textScale,
),
),
),
],
),
if (enableTracing &&
isOutgoing &&
message.retryCount > 0) ...[
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.symmetric(horizontal: 8)
: EdgeInsets.zero,
child: Text(
context.l10n.chat_retryCount(
message.retryCount,
context
.read<AppSettingsService>()
.settings
.maxMessageRetries,
),
style: TextStyle(
fontSize: 10 * textScale,
color: metaColor,
fontWeight: FontWeight.w500,
),
),
),
],
const SizedBox(height: 4),
Padding(
padding: gifId != null
? const EdgeInsets.only(
left: 8,
right: 8,
bottom: 4,
)
: EdgeInsets.zero,
child: Wrap(
spacing: 4,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text(
_formatTime(message.timestamp),
style: TextStyle(
fontSize: 10 * textScale,
color: metaColor,
),
),
if (isOutgoing) ...[
const SizedBox(width: 4),
MessageStatusIcon(
size: 12 * textScale,
onColor: metaColor,
isAcked:
message.status ==
MessageStatus.delivered,
isPending:
message.status == MessageStatus.pending,
isFailed:
message.status == MessageStatus.failed,
),
],
if (enableTracing &&
message.tripTimeMs != null &&
message.status ==
MessageStatus.delivered) ...[
const SizedBox(width: 4),
Icon(
Icons.speed,
size: 10 * textScale,
color: isOutgoing
? metaColor
: Theme.of(
context,
).colorScheme.tertiary,
),
child: Wrap(
spacing: 4,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text(
'${(message.tripTimeMs! / 1000).toStringAsFixed(1)}s',
_formatTime(message.timestamp),
style: TextStyle(
fontSize: 9 * textScale,
fontSize: 10 * textScale,
color: metaColor,
),
),
if (isOutgoing) ...[
const SizedBox(width: 4),
MessageStatusIcon(
size: 12 * textScale,
onColor: metaColor,
isAcked:
message.status ==
MessageStatus.delivered,
isPending:
message.status == MessageStatus.pending,
isFailed:
message.status == MessageStatus.failed,
),
],
if (enableTracing &&
message.tripTimeMs != null &&
message.status ==
MessageStatus.delivered) ...[
const SizedBox(width: 4),
Icon(
Icons.speed,
size: 10 * textScale,
color: isOutgoing
? metaColor
: Theme.of(
context,
).colorScheme.tertiary,
),
),
Text(
'${(message.tripTimeMs! / 1000).toStringAsFixed(1)}s',
style: TextStyle(
fontSize: 9 * textScale,
color: isOutgoing
? metaColor
: Theme.of(
context,
).colorScheme.tertiary,
),
),
],
],
],
),
),
),
],
],
),
),
),
),
],
],
),
),
),
),
if (message.reactions.isNotEmpty) ...[
const SizedBox(height: 4),
Padding(
@@ -1476,7 +1480,9 @@ class _MessageBubble extends StatelessWidget {
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 40, minHeight: 40),
onPressed: () async {
final selfName = context.read<MeshCoreConnector>().selfName ?? context.l10n.chat_me;
final selfName =
context.read<MeshCoreConnector>().selfName ??
context.l10n.chat_me;
final fromName = message.isOutgoing ? selfName : senderName;
final key = buildSharedMarkerKey(
sourceId: sourceId,
+8 -2
View File
@@ -55,12 +55,18 @@ class ChromeRequiredScreen extends StatelessWidget {
decoration: BoxDecoration(
color: colorScheme.secondaryContainer.withValues(alpha: 0.4),
borderRadius: BorderRadius.circular(30),
border: Border.all(color: colorScheme.outline.withValues(alpha: 0.4)),
border: Border.all(
color: colorScheme.outline.withValues(alpha: 0.4),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.info_outline, size: 20, color: colorScheme.secondary),
Icon(
Icons.info_outline,
size: 20,
color: colorScheme.secondary,
),
const SizedBox(width: 12),
Text(
l10n.chrome_bluetoothRequiresChromium,
+2 -6
View File
@@ -705,9 +705,7 @@ class _ContactsScreenState extends State<ContactsScreen>
action: FilledButton.icon(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DiscoveryScreen(),
),
MaterialPageRoute(builder: (context) => const DiscoveryScreen()),
),
icon: const Icon(Icons.person_add_rounded),
label: Text(context.l10n.discoveredContacts_Title),
@@ -1496,9 +1494,7 @@ class _ContactsScreenState extends State<ContactsScreen>
),
title: Text(
context.l10n.contacts_deleteContact,
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
onTap: () {
Navigator.pop(sheetContext);
+1 -3
View File
@@ -189,8 +189,7 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
),
action: SnackBarAction(
label: context.l10n.common_undo,
onPressed: () =>
connector.removeContact(contact),
onPressed: () => connector.removeContact(contact),
),
);
},
@@ -444,7 +443,6 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
}
}
String _formatLastSeen(BuildContext context, DateTime lastSeen) {
final now = DateTime.now();
final diff = now.difference(lastSeen);
+25 -7
View File
@@ -507,7 +507,9 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
bottom: 12,
child: DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues(alpha: 0.85),
color: Theme.of(
context,
).colorScheme.surfaceContainerHighest.withValues(alpha: 0.85),
borderRadius: BorderRadius.circular(8),
),
child: Padding(
@@ -517,7 +519,10 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
),
child: Text(
context.l10n.losElevationAttribution,
style: TextStyle(fontSize: 10, color: Theme.of(context).colorScheme.onSurface),
style: TextStyle(
fontSize: 10,
color: Theme.of(context).colorScheme.onSurface,
),
),
),
),
@@ -631,7 +636,10 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
const SizedBox(height: 4),
Text(
context.l10n.losBlockedSpotsHint,
style: TextStyle(fontSize: 11, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 6),
Wrap(
@@ -700,7 +708,9 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
'${_selectedObstruction!.point.longitude.toStringAsFixed(5)}',
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
@@ -726,7 +736,10 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
const SizedBox(width: 8),
Text(
'${displayFrequencyMHz.toStringAsFixed(3)} MHz',
style: TextStyle(fontSize: 11, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
if (kFactorUsed != null) ...[
const SizedBox(width: 8),
@@ -734,7 +747,9 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
'k=${kFactorUsed.toStringAsFixed(3)}',
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
const SizedBox(width: 4),
@@ -758,7 +773,10 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
),
Text(
context.l10n.losElevationAttribution,
style: TextStyle(fontSize: 10, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 10,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 6),
ExpansionTile(
+3 -1
View File
@@ -458,7 +458,9 @@ class _MapCacheScreenState extends State<MapCacheScreen> {
padding: const EdgeInsets.only(top: 8),
child: Text(
l10n.mapCache_failedDownloads(_failedTiles),
style: TextStyle(color: Theme.of(context).colorScheme.error),
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
),
),
],
+71 -53
View File
@@ -486,7 +486,10 @@ class _MapScreenState extends State<MapScreen> {
PopupMenuItem(
child: Row(
children: [
Icon(Icons.logout, color: Theme.of(context).colorScheme.error),
Icon(
Icons.logout,
color: Theme.of(context).colorScheme.error,
),
const SizedBox(width: 8),
Text(context.l10n.common_disconnect),
],
@@ -1223,7 +1226,9 @@ class _MapScreenState extends State<MapScreen> {
Icon(
Icons.location_on,
size: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
Text(
": $nodeCount",
@@ -1239,7 +1244,9 @@ class _MapScreenState extends State<MapScreen> {
Icon(
Icons.wrong_location,
size: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
Text(
": ${nodeCountAll - nodeCount}",
@@ -1255,7 +1262,9 @@ class _MapScreenState extends State<MapScreen> {
Icon(
Icons.add_outlined,
size: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
Text(
": $nodeCountAll",
@@ -1612,51 +1621,56 @@ class _MapScreenState extends State<MapScreen> {
return SafeArea(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
_getNodeIcon(contact.type),
color: _getNodeColor(contact.type),
),
const SizedBox(width: 8),
Expanded(child: SelectableText(contact.name)),
],
),
const SizedBox(height: 8),
_buildInfoRow(
context.l10n.map_type,
contact.typeLabel(context.l10n),
),
_buildInfoRow(
context.l10n.map_path,
contact.pathLabel(context.l10n),
),
if (contact.hasLocation)
_buildInfoRow(
context.l10n.map_location,
'${contact.latitude!.toStringAsFixed(6)}, ${contact.longitude!.toStringAsFixed(6)}',
)
else if (guessedPosition != null)
_buildInfoRow(
context.l10n.map_estLocation,
'~${guessedPosition.latitude.toStringAsFixed(6)}, ${guessedPosition.longitude.toStringAsFixed(6)}',
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
_getNodeIcon(contact.type),
color: _getNodeColor(contact.type),
),
const SizedBox(width: 8),
Expanded(child: SelectableText(contact.name)),
],
),
_buildInfoRow(
context.l10n.map_lastSeen,
_formatLastSeen(contact.lastSeen),
),
_buildInfoRow(context.l10n.map_publicKey, contact.publicKeyHex),
const SizedBox(height: 16),
...actions,
TextButton(
onPressed: () => Navigator.pop(sheetContext),
child: Text(context.l10n.common_close),
),
],
const SizedBox(height: 8),
_buildInfoRow(
context.l10n.map_type,
contact.typeLabel(context.l10n),
),
_buildInfoRow(
context.l10n.map_path,
contact.pathLabel(context.l10n),
),
if (contact.hasLocation)
_buildInfoRow(
context.l10n.map_location,
'${contact.latitude!.toStringAsFixed(6)}, ${contact.longitude!.toStringAsFixed(6)}',
)
else if (guessedPosition != null)
_buildInfoRow(
context.l10n.map_estLocation,
'~${guessedPosition.latitude.toStringAsFixed(6)}, ${guessedPosition.longitude.toStringAsFixed(6)}',
),
_buildInfoRow(
context.l10n.map_lastSeen,
_formatLastSeen(contact.lastSeen),
),
_buildInfoRow(
context.l10n.map_publicKey,
contact.publicKeyHex,
),
const SizedBox(height: 16),
...actions,
TextButton(
onPressed: () => Navigator.pop(sheetContext),
child: Text(context.l10n.common_close),
),
],
),
),
),
);
@@ -1844,9 +1858,7 @@ class _MapScreenState extends State<MapScreen> {
);
await connector.refreshDeviceInfo();
if (!mounted) return;
messenger.showSnackBar(
SnackBar(content: Text(successMsg)),
);
messenger.showSnackBar(SnackBar(content: Text(successMsg)));
},
),
ListTile(
@@ -2235,7 +2247,10 @@ class _MapScreenState extends State<MapScreen> {
const SizedBox(height: 8),
Text(
_getTimeFilterLabel(settings.mapTimeFilterHours),
style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
Slider(
value: _hoursToSliderValue(settings.mapTimeFilterHours),
@@ -2387,7 +2402,10 @@ class _MapScreenState extends State<MapScreen> {
if (_pathTrace.isNotEmpty)
Text(
"${l10n.path_currentPathLabel} ${formatDistance(getPathDistanceMeters(_points), isImperial: isImperial)}",
style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
SelectableText(
_pathTrace
+1 -4
View File
@@ -326,10 +326,7 @@ class _NeighborsScreenState extends State<NeighborsScreen> {
if (!_isLoaded &&
!_hasData &&
(_parsedNeighbors == null || _parsedNeighbors!.isEmpty))
EmptyState(
icon: Icons.wifi_find,
title: l10n.neighbors_noData,
),
EmptyState(icon: Icons.wifi_find, title: l10n.neighbors_noData),
if (_isLoaded ||
_hasData &&
!(_parsedNeighbors == null || _parsedNeighbors!.isEmpty))
+23 -10
View File
@@ -274,8 +274,8 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
final frame = buildTraceReq(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
0, //flags
0, //auth
0, //flag
payload: path,
);
connector.sendFrame(frame);
@@ -350,11 +350,16 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
try {
buffer.skipBytes(2); // Skip push code and reserved byte
int pathLength = buffer.readUInt8();
buffer.skipBytes(5); // Skip Flag byte and tag data
final int flags = buffer
.readUInt8(); // path_sz = flags & 0x03 (path-hash mode, fw v1.11+)
buffer.skipBytes(4); // Skip tag data
buffer.skipBytes(4); // Skip auth code
final int pathSz = flags & 0x03;
Uint8List pathData = buffer.readBytes(pathLength);
// Firmware emits (path_len >> path_sz) hop SNRs plus 1 final SNR (to this node).
final int snrCount = (pathLength >> pathSz) + 1;
List<double> snrData = buffer
.readRemainingBytes()
.readBytes(snrCount)
.map((snr) => snr.toSigned(8).toDouble() / 4)
.toList();
@@ -616,7 +621,9 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
!_failed2Loaded)
Center(
child: Card(
color: Theme.of(context).colorScheme.surface.withValues(alpha: 0.9),
color: Theme.of(
context,
).colorScheme.surface.withValues(alpha: 0.9),
child: Padding(
padding: EdgeInsets.all(12),
child: Text(
@@ -963,10 +970,10 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
}
Widget _colorDot(Color color) => Container(
width: 10,
height: 10,
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
);
width: 10,
height: 10,
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
);
Widget _buildLegendCard(
BuildContext context,
@@ -1002,11 +1009,17 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
children: [
_colorDot(Colors.green),
const SizedBox(width: 4),
Text(l10n.pathTrace_legendGpsConfirmed, style: const TextStyle(fontSize: 11)),
Text(
l10n.pathTrace_legendGpsConfirmed,
style: const TextStyle(fontSize: 11),
),
const SizedBox(width: 12),
_colorDot(Colors.orange),
const SizedBox(width: 4),
Text(l10n.pathTrace_legendInferred, style: const TextStyle(fontSize: 11)),
Text(
l10n.pathTrace_legendInferred,
style: const TextStyle(fontSize: 11),
),
],
),
],
+13 -3
View File
@@ -385,16 +385,26 @@ class _RepeaterCliScreenState extends State<RepeaterCliScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.terminal, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant),
Icon(
Icons.terminal,
size: 64,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(height: 16),
Text(
l10n.repeater_noCommandsSent,
style: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 8),
Text(
l10n.repeater_typeCommandOrUseQuick,
style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
+28 -8
View File
@@ -72,11 +72,15 @@ class RepeaterHubScreen extends StatelessWidget {
children: [
CircleAvatar(
radius: 40,
backgroundColor: Theme.of(context).colorScheme.tertiaryContainer,
backgroundColor: Theme.of(
context,
).colorScheme.tertiaryContainer,
child: Icon(
Icons.cell_tower,
size: 40,
color: Theme.of(context).colorScheme.onTertiaryContainer,
color: Theme.of(
context,
).colorScheme.onTertiaryContainer,
),
),
const SizedBox(height: 16),
@@ -90,12 +94,18 @@ class RepeaterHubScreen extends StatelessWidget {
const SizedBox(height: 8),
Text(
repeater.shortPubKeyHex,
style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 8),
Text(
repeater.pathLabel(context.l10n),
style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
if (repeater.hasLocation) ...[
const SizedBox(height: 4),
@@ -105,14 +115,18 @@ class RepeaterHubScreen extends StatelessWidget {
Icon(
Icons.location_on,
size: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
const SizedBox(width: 4),
Text(
'${repeater.latitude?.toStringAsFixed(4)}, ${repeater.longitude?.toStringAsFixed(4)}',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
@@ -329,12 +343,18 @@ class RepeaterHubScreen extends StatelessWidget {
const SizedBox(height: 4),
Text(
subtitle,
style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
),
Icon(Icons.chevron_right, color: Theme.of(context).colorScheme.onSurfaceVariant),
Icon(
Icons.chevron_right,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
),
),
+6 -2
View File
@@ -459,7 +459,9 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
? l10n.repeater_refreshed(label)
: l10n.repeater_errorRefreshing(label),
),
backgroundColor: successCount > 0 ? null : Theme.of(context).colorScheme.error,
backgroundColor: successCount > 0
? null
: Theme.of(context).colorScheme.error,
);
setState(() => setRefreshing(false));
}
@@ -2229,7 +2231,9 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
onConfirm();
},
style: isDestructive
? FilledButton.styleFrom(backgroundColor: Theme.of(context).colorScheme.error)
? FilledButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.error,
)
: null,
child: Text(l10n.repeater_confirm),
),
+10 -9
View File
@@ -113,9 +113,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
'USB selected, opening UsbScreen',
tag: 'ScannerScreen',
);
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const UsbScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const UsbScreen()));
},
),
if (!PlatformInfo.isWeb)
@@ -123,9 +123,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
icon: const Icon(Icons.lan),
tooltip: context.l10n.connectionChoiceTcpLabel,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const TcpScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (_) => const TcpScreen()));
},
),
],
@@ -167,7 +167,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
)
: const Icon(Icons.bluetooth_searching),
label: Text(
isScanning ? context.l10n.scanner_stop : context.l10n.scanner_scan,
isScanning
? context.l10n.scanner_stop
: context.l10n.scanner_scan,
),
);
},
@@ -256,8 +258,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
);
}
final isConnecting =
connector.state == MeshCoreConnectionState.connecting;
final isConnecting = connector.state == MeshCoreConnectionState.connecting;
return ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: connector.scanResults.length,
+8 -2
View File
@@ -343,7 +343,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
),
ListTile(
leading: Icon(Icons.delete_outline, color: Theme.of(context).colorScheme.error),
leading: Icon(
Icons.delete_outline,
color: Theme.of(context).colorScheme.error,
),
title: Text(l10n.settings_deleteAllPaths),
subtitle: Text(
l10n.settings_deleteAllPathsSubtitle,
@@ -367,7 +370,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
const Divider(height: 1),
ListTile(
leading: Icon(Icons.restart_alt, color: Theme.of(context).colorScheme.tertiary),
leading: Icon(
Icons.restart_alt,
color: Theme.of(context).colorScheme.tertiary,
),
title: Text(l10n.settings_rebootDevice),
subtitle: Text(l10n.settings_rebootDeviceSubtitle),
onTap: () => _confirmReboot(context, connector),
+1 -4
View File
@@ -224,10 +224,7 @@ class _TcpScreenState extends State<TcpScreen> {
statusText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: statusColor,
fontWeight: FontWeight.w500,
),
style: TextStyle(color: statusColor, fontWeight: FontWeight.w500),
),
),
],
+4 -1
View File
@@ -385,7 +385,10 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
Center(
child: Text(
l10n.telemetry_noData,
style: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
if ((_isLoaded || _hasData) &&
+19 -8
View File
@@ -203,10 +203,7 @@ class _UsbScreenState extends State<UsbScreen> {
statusText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: statusColor,
fontWeight: FontWeight.w500,
),
style: TextStyle(color: statusColor, fontWeight: FontWeight.w500),
),
),
],
@@ -222,11 +219,18 @@ class _UsbScreenState extends State<UsbScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.usb, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant),
Icon(
Icons.usb,
size: 64,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(height: 16),
Text(
l10n.usbStatus_searching,
style: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
@@ -238,12 +242,19 @@ class _UsbScreenState extends State<UsbScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.usb, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant),
Icon(
Icons.usb,
size: 64,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
const SizedBox(height: 16),
Text(
l10n.usbScreenEmptyState,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurfaceVariant),
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),