mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-22 16:51:05 +10:00
@@ -3,6 +3,7 @@ import 'package:flutter_linkify/flutter_linkify.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../utils/platform_info.dart';
|
import '../utils/platform_info.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class LinkHandler {
|
class LinkHandler {
|
||||||
static TextStyle defaultLinkStyle(BuildContext context, TextStyle base) {
|
static TextStyle defaultLinkStyle(BuildContext context, TextStyle base) {
|
||||||
@@ -93,21 +94,19 @@ class LinkHandler {
|
|||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_couldNotOpenLink(url)),
|
content: Text(context.l10n.chat_couldNotOpenLink(url)),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_invalidLink),
|
content: Text(context.l10n.chat_invalidLink),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// showDismissibleSnackBar shows a [SnackBar] with tap to dismiss
|
||||||
|
// all other properties are default and optional
|
||||||
|
void showDismissibleSnackBar(
|
||||||
|
BuildContext context, {
|
||||||
|
Key? key,
|
||||||
|
required Widget content,
|
||||||
|
Color? backgroundColor,
|
||||||
|
double? elevation,
|
||||||
|
EdgeInsetsGeometry? margin,
|
||||||
|
EdgeInsetsGeometry? padding,
|
||||||
|
double? width,
|
||||||
|
ShapeBorder? shape,
|
||||||
|
HitTestBehavior? hitTestBehavior,
|
||||||
|
SnackBarBehavior? behavior,
|
||||||
|
SnackBarAction? action,
|
||||||
|
double? actionOverflowThreshold,
|
||||||
|
bool? showCloseIcon,
|
||||||
|
Color? closeIconColor,
|
||||||
|
Duration? duration,
|
||||||
|
bool? persist,
|
||||||
|
Animation<double>? animation,
|
||||||
|
void Function()? onVisible,
|
||||||
|
DismissDirection? dismissDirection,
|
||||||
|
Clip? clipBehavior,
|
||||||
|
}) {
|
||||||
|
final messenger = ScaffoldMessenger.of(context);
|
||||||
|
messenger.showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
key: key,
|
||||||
|
content: GestureDetector(
|
||||||
|
onTap: () => messenger.hideCurrentSnackBar(),
|
||||||
|
child: content,
|
||||||
|
),
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
elevation: elevation,
|
||||||
|
margin: margin,
|
||||||
|
padding: padding,
|
||||||
|
width: width,
|
||||||
|
shape: shape,
|
||||||
|
hitTestBehavior: hitTestBehavior,
|
||||||
|
behavior: behavior,
|
||||||
|
action: action,
|
||||||
|
actionOverflowThreshold: actionOverflowThreshold,
|
||||||
|
showCloseIcon: showCloseIcon,
|
||||||
|
closeIconColor: closeIconColor,
|
||||||
|
duration: duration ?? const Duration(seconds: 4),
|
||||||
|
persist: persist,
|
||||||
|
animation: animation,
|
||||||
|
onVisible: onVisible,
|
||||||
|
dismissDirection: dismissDirection ?? DismissDirection.down,
|
||||||
|
clipBehavior: clipBehavior ?? Clip.hardEdge,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import 'package:provider/provider.dart';
|
|||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../services/app_debug_log_service.dart';
|
import '../services/app_debug_log_service.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class AppDebugLogScreen extends StatelessWidget {
|
class AppDebugLogScreen extends StatelessWidget {
|
||||||
const AppDebugLogScreen({super.key});
|
const AppDebugLogScreen({super.key});
|
||||||
@@ -34,8 +35,9 @@ class AppDebugLogScreen extends StatelessWidget {
|
|||||||
.join('\n');
|
.join('\n');
|
||||||
await Clipboard.setData(ClipboardData(text: text));
|
await Clipboard.setData(ClipboardData(text: text));
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.debugLog_copied)),
|
context,
|
||||||
|
content: Text(context.l10n.debugLog_copied),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import '../services/app_settings_service.dart';
|
|||||||
import '../services/notification_service.dart';
|
import '../services/notification_service.dart';
|
||||||
import '../services/translation_service.dart';
|
import '../services/translation_service.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'map_cache_screen.dart';
|
import 'map_cache_screen.dart';
|
||||||
|
|
||||||
class AppSettingsScreen extends StatelessWidget {
|
class AppSettingsScreen extends StatelessWidget {
|
||||||
@@ -151,13 +152,12 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
.requestPermissions();
|
.requestPermissions();
|
||||||
if (!granted) {
|
if (!granted) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.appSettings_notificationPermissionDenied,
|
context.l10n.appSettings_notificationPermissionDenied,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -166,15 +166,14 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
|
|
||||||
await settingsService.setNotificationsEnabled(value);
|
await settingsService.setNotificationsEnabled(value);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
value
|
value
|
||||||
? context.l10n.appSettings_notificationsEnabled
|
? context.l10n.appSettings_notificationsEnabled
|
||||||
: context.l10n.appSettings_notificationsDisabled,
|
: context.l10n.appSettings_notificationsDisabled,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -301,15 +300,14 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
value: settingsService.settings.clearPathOnMaxRetry,
|
value: settingsService.settings.clearPathOnMaxRetry,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
settingsService.setClearPathOnMaxRetry(value);
|
settingsService.setClearPathOnMaxRetry(value);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
value
|
value
|
||||||
? context.l10n.appSettings_pathsWillBeCleared
|
? context.l10n.appSettings_pathsWillBeCleared
|
||||||
: context.l10n.appSettings_pathsWillNotBeCleared,
|
: context.l10n.appSettings_pathsWillNotBeCleared,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -329,15 +327,14 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
value: settingsService.settings.autoRouteRotationEnabled,
|
value: settingsService.settings.autoRouteRotationEnabled,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
settingsService.setAutoRouteRotationEnabled(value);
|
settingsService.setAutoRouteRotationEnabled(value);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
value
|
value
|
||||||
? context.l10n.appSettings_autoRouteRotationEnabled
|
? context.l10n.appSettings_autoRouteRotationEnabled
|
||||||
: context.l10n.appSettings_autoRouteRotationDisabled,
|
: context.l10n.appSettings_autoRouteRotationDisabled,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -1164,8 +1161,9 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
String? id,
|
String? id,
|
||||||
}) async {
|
}) async {
|
||||||
if (sourceUrl.isEmpty) {
|
if (sourceUrl.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.translation_enterUrlFirst)),
|
context,
|
||||||
|
content: Text(context.l10n.translation_enterUrlFirst),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1176,22 +1174,23 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
id: id,
|
id: id,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.translation_modelDownloaded)),
|
context,
|
||||||
|
content: Text(context.l10n.translation_modelDownloaded),
|
||||||
);
|
);
|
||||||
await settingsService.setTranslationEnabled(true);
|
await settingsService.setTranslationEnabled(true);
|
||||||
} on TranslationDownloadCancelled {
|
} on TranslationDownloadCancelled {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.translation_downloadStopped)),
|
context,
|
||||||
|
content: Text(context.l10n.translation_downloadStopped),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.translation_downloadFailed(error.toString()),
|
context.l10n.translation_downloadFailed(error.toString()),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1236,16 +1235,16 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
try {
|
try {
|
||||||
await translationService.removeModel(model);
|
await translationService.removeModel(model);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
// TODO: l10n
|
// TODO: l10n
|
||||||
content: Text('Deleted ${translationModelFriendlyName(model)}.'),
|
content: Text('Deleted ${translationModelFriendlyName(model)}.'),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text('Delete failed: $error')),
|
context,
|
||||||
|
content: Text('Delete failed: $error'),
|
||||||
); // TODO: l10n
|
); // TODO: l10n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1279,15 +1278,14 @@ class AppSettingsScreen extends StatelessWidget {
|
|||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
await settingsService.setAppDebugLogEnabled(value);
|
await settingsService.setAppDebugLogEnabled(value);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
value
|
value
|
||||||
? context.l10n.appSettings_appDebugLoggingEnabled
|
? context.l10n.appSettings_appDebugLoggingEnabled
|
||||||
: context.l10n.appSettings_appDebugLoggingDisabled,
|
: context.l10n.appSettings_appDebugLoggingDisabled,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import '../l10n/l10n.dart';
|
|||||||
import '../services/ble_debug_log_service.dart';
|
import '../services/ble_debug_log_service.dart';
|
||||||
import '../connector/meshcore_protocol.dart';
|
import '../connector/meshcore_protocol.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
enum _BleLogView { frames, rawLogRx }
|
enum _BleLogView { frames, rawLogRx }
|
||||||
|
|
||||||
@@ -52,10 +53,9 @@ class _BleDebugLogScreenState extends State<BleDebugLogScreen> {
|
|||||||
.join('\n');
|
.join('\n');
|
||||||
await Clipboard.setData(ClipboardData(text: text));
|
await Clipboard.setData(ClipboardData(text: text));
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.debugLog_bleCopied),
|
content: Text(context.l10n.debugLog_bleCopied),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import '../connector/meshcore_protocol.dart';
|
|||||||
import '../helpers/gif_helper.dart';
|
import '../helpers/gif_helper.dart';
|
||||||
import '../helpers/reaction_helper.dart';
|
import '../helpers/reaction_helper.dart';
|
||||||
import '../helpers/utf8_length_limiter.dart';
|
import '../helpers/utf8_length_limiter.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../models/channel.dart';
|
import '../models/channel.dart';
|
||||||
import '../models/channel_message.dart';
|
import '../models/channel_message.dart';
|
||||||
@@ -144,11 +145,10 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
Future<void> _scrollToMessage(String messageId) async {
|
Future<void> _scrollToMessage(String messageId) async {
|
||||||
final key = _messageKeys[messageId];
|
final key = _messageKeys[messageId];
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_originalMessageNotFound),
|
content: Text(context.l10n.chat_originalMessageNotFound),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1151,9 +1151,10 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
if (_lastChannelSendAt != null &&
|
if (_lastChannelSendAt != null &&
|
||||||
now.difference(_lastChannelSendAt!) < const Duration(seconds: 1)) {
|
now.difference(_lastChannelSendAt!) < const Duration(seconds: 1)) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_sendCooldown)));
|
content: Text(context.l10n.chat_sendCooldown),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_lastChannelSendAt = now;
|
_lastChannelSendAt = now;
|
||||||
@@ -1195,8 +1196,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
|
|
||||||
final maxBytes = maxChannelMessageBytes(connector.selfName);
|
final maxBytes = maxChannelMessageBytes(connector.selfName);
|
||||||
if (utf8.encode(messageText).length > maxBytes) {
|
if (utf8.encode(messageText).length > maxBytes) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.chat_messageTooLong(maxBytes))),
|
context,
|
||||||
|
content: Text(context.l10n.chat_messageTooLong(maxBytes)),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1323,17 +1325,19 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
|||||||
|
|
||||||
void _copyMessageText(String text) {
|
void _copyMessageText(String text) {
|
||||||
Clipboard.setData(ClipboardData(text: text));
|
Clipboard.setData(ClipboardData(text: text));
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_messageCopied)));
|
content: Text(context.l10n.chat_messageCopied),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteMessage(ChannelMessage message) async {
|
Future<void> _deleteMessage(ChannelMessage message) async {
|
||||||
await context.read<MeshCoreConnector>().deleteChannelMessage(message);
|
await context.read<MeshCoreConnector>().deleteChannelMessage(message);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_messageDeleted)));
|
content: Text(context.l10n.chat_messageDeleted),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _formatPathPrefixes(Uint8List pathBytes) {
|
String _formatPathPrefixes(Uint8List pathBytes) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import '../widgets/empty_state.dart';
|
|||||||
import '../widgets/qr_code_display.dart';
|
import '../widgets/qr_code_display.dart';
|
||||||
import '../widgets/quick_switch_bar.dart';
|
import '../widgets/quick_switch_bar.dart';
|
||||||
import '../widgets/unread_badge.dart';
|
import '../widgets/unread_badge.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'channel_chat_screen.dart';
|
import 'channel_chat_screen.dart';
|
||||||
import 'community_qr_scanner_screen.dart';
|
import 'community_qr_scanner_screen.dart';
|
||||||
import 'contacts_screen.dart';
|
import 'contacts_screen.dart';
|
||||||
@@ -809,15 +810,12 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final name = nameController.text.trim();
|
final name = nameController.text.trim();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
context,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext
|
||||||
content: Text(
|
.l10n
|
||||||
dialogContext
|
.channels_enterChannelName,
|
||||||
.l10n
|
|
||||||
.channels_enterChannelName,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -837,13 +835,10 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
nextIndex,
|
nextIndex,
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_channelAdded(
|
context.l10n.channels_channelAdded(name),
|
||||||
name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -897,15 +892,12 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
final name = nameController.text.trim();
|
final name = nameController.text.trim();
|
||||||
final pskHex = pskController.text.trim();
|
final pskHex = pskController.text.trim();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
context,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext
|
||||||
content: Text(
|
.l10n
|
||||||
dialogContext
|
.channels_enterChannelName,
|
||||||
.l10n
|
|
||||||
.channels_enterChannelName,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -914,15 +906,12 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
try {
|
try {
|
||||||
psk = Channel.parsePskHex(pskHex);
|
psk = Channel.parsePskHex(pskHex);
|
||||||
} on FormatException {
|
} on FormatException {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
context,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext
|
||||||
content: Text(
|
.l10n
|
||||||
dialogContext
|
.channels_pskMustBe32Hex,
|
||||||
.l10n
|
|
||||||
.channels_pskMustBe32Hex,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -930,13 +919,10 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
Navigator.pop(dialogContext);
|
Navigator.pop(dialogContext);
|
||||||
connector.setChannel(nextIndex, name, psk);
|
connector.setChannel(nextIndex, name, psk);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_channelAdded(
|
context.l10n.channels_channelAdded(name),
|
||||||
name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -967,11 +953,10 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
Navigator.pop(dialogContext);
|
Navigator.pop(dialogContext);
|
||||||
connector.setChannel(nextIndex, 'Public', psk);
|
connector.setChannel(nextIndex, 'Public', psk);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_publicChannelAdded,
|
context.l10n.channels_publicChannelAdded,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1097,15 +1082,12 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
var hashtag = hashtagController.text.trim();
|
var hashtag = hashtagController.text.trim();
|
||||||
if (hashtag.isEmpty) {
|
if (hashtag.isEmpty) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
context,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext
|
||||||
content: Text(
|
.l10n
|
||||||
dialogContext
|
.channels_enterChannelName,
|
||||||
.l10n
|
|
||||||
.channels_enterChannelName,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -1125,15 +1107,12 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
} else {
|
} else {
|
||||||
// Community hashtag - HMAC derivation from community secret
|
// Community hashtag - HMAC derivation from community secret
|
||||||
if (selectedCommunity == null) {
|
if (selectedCommunity == null) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
dialogContext,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext
|
||||||
content: Text(
|
.l10n
|
||||||
dialogContext
|
.community_selectCommunity,
|
||||||
.l10n
|
|
||||||
.community_selectCommunity,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -1159,12 +1138,11 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
psk,
|
psk,
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_channelAdded(
|
context.l10n.channels_channelAdded(
|
||||||
channelName,
|
channelName,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -1259,13 +1237,10 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final name = nameController.text.trim();
|
final name = nameController.text.trim();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
dialogContext,
|
context,
|
||||||
).showSnackBar(
|
content: Text(
|
||||||
SnackBar(
|
dialogContext.l10n.community_enterName,
|
||||||
content: Text(
|
|
||||||
dialogContext.l10n.community_enterName,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -1301,11 +1276,10 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
_loadCommunities();
|
_loadCommunities();
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.community_created(name),
|
context.l10n.community_created(name),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1494,10 +1468,9 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
try {
|
try {
|
||||||
psk = Channel.parsePskHex(pskHex);
|
psk = Channel.parsePskHex(pskHex);
|
||||||
} on FormatException {
|
} on FormatException {
|
||||||
ScaffoldMessenger.of(dialogContext).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
dialogContext,
|
||||||
content: Text(dialogContext.l10n.channels_pskMustBe32Hex),
|
content: Text(dialogContext.l10n.channels_pskMustBe32Hex),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1510,16 +1483,16 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
smazEnabled,
|
smazEnabled,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.channels_channelUpdated(name)),
|
content: Text(context.l10n.channels_channelUpdated(name)),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
debugPrint(st.toString());
|
debugPrint(st.toString());
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text('Failed to update channel: $e')),
|
context,
|
||||||
|
content: Text('Failed to update channel: $e'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1559,21 +1532,19 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_channelDeleted(channel.name),
|
context.l10n.channels_channelDeleted(channel.name),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.channels_channelDeleteFailed(channel.name),
|
context.l10n.channels_channelDeleteFailed(channel.name),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1594,8 +1565,9 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
void _addPublicChannel(BuildContext context, MeshCoreConnector connector) {
|
void _addPublicChannel(BuildContext context, MeshCoreConnector connector) {
|
||||||
final psk = Channel.parsePskHex(Channel.publicChannelPsk);
|
final psk = Channel.parsePskHex(Channel.publicChannelPsk);
|
||||||
connector.setChannel(0, 'Public', psk);
|
connector.setChannel(0, 'Public', psk);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.channels_publicChannelAdded)),
|
context,
|
||||||
|
content: Text(context.l10n.channels_publicChannelAdded),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1810,12 +1782,9 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
_loadCommunities();
|
_loadCommunities();
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(context.l10n.community_deleted(community.name)),
|
||||||
context.l10n.community_deleted(community.name),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import '../widgets/radio_stats_entry.dart';
|
|||||||
import '../widgets/translated_message_content.dart';
|
import '../widgets/translated_message_content.dart';
|
||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'telemetry_screen.dart';
|
import 'telemetry_screen.dart';
|
||||||
|
|
||||||
class ChatScreen extends StatefulWidget {
|
class ChatScreen extends StatefulWidget {
|
||||||
@@ -633,9 +634,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
if (_lastTextSendAt != null &&
|
if (_lastTextSendAt != null &&
|
||||||
now.difference(_lastTextSendAt!) < const Duration(seconds: 1)) {
|
now.difference(_lastTextSendAt!) < const Duration(seconds: 1)) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_sendCooldown)));
|
content: Text(context.l10n.chat_sendCooldown),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_lastTextSendAt = now;
|
_lastTextSendAt = now;
|
||||||
@@ -671,8 +673,9 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
}
|
}
|
||||||
final maxBytes = maxContactMessageBytes();
|
final maxBytes = maxContactMessageBytes();
|
||||||
if (utf8.encode(outgoingText).length > maxBytes) {
|
if (utf8.encode(outgoingText).length > maxBytes) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.chat_messageTooLong(maxBytes))),
|
context,
|
||||||
|
content: Text(context.l10n.chat_messageTooLong(maxBytes)),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -860,15 +863,12 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
_showFullPathDialog(context, path.pathBytes),
|
_showFullPathDialog(context, path.pathBytes),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (path.pathBytes.isEmpty) {
|
if (path.pathBytes.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context
|
context.l10n.chat_pathDetailsNotAvailable,
|
||||||
.l10n
|
|
||||||
.chat_pathDetailsNotAvailable,
|
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -952,11 +952,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
_resolveContact(connector),
|
_resolveContact(connector),
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_pathCleared),
|
content: Text(context.l10n.chat_pathCleared),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
@@ -982,11 +981,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
pathLen: -1,
|
pathLen: -1,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_floodModeEnabled),
|
content: Text(context.l10n.chat_floodModeEnabled),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
@@ -1020,11 +1018,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
|
|
||||||
void _showFullPathDialog(BuildContext context, List<int> pathBytes) {
|
void _showFullPathDialog(BuildContext context, List<int> pathBytes) {
|
||||||
if (pathBytes.isEmpty) {
|
if (pathBytes.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_pathDetailsNotAvailable),
|
content: Text(context.l10n.chat_pathDetailsNotAvailable),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1137,11 +1134,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
: (verified
|
: (verified
|
||||||
? context.l10n.chat_pathDeviceConfirmed
|
? context.l10n.chat_pathDeviceConfirmed
|
||||||
: context.l10n.chat_pathDeviceNotConfirmed);
|
: context.l10n.chat_pathDeviceNotConfirmed);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.chat_pathSetHops(hopCount, status)),
|
content: Text(context.l10n.chat_pathSetHops(hopCount, status)),
|
||||||
duration: const Duration(seconds: 3),
|
duration: const Duration(seconds: 3),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1490,26 +1486,29 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
|
|
||||||
void _copyMessageText(String text) {
|
void _copyMessageText(String text) {
|
||||||
Clipboard.setData(ClipboardData(text: text));
|
Clipboard.setData(ClipboardData(text: text));
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_messageCopied)));
|
content: Text(context.l10n.chat_messageCopied),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteMessage(Message message) async {
|
Future<void> _deleteMessage(Message message) async {
|
||||||
await context.read<MeshCoreConnector>().deleteMessage(message);
|
await context.read<MeshCoreConnector>().deleteMessage(message);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_messageDeleted)));
|
content: Text(context.l10n.chat_messageDeleted),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _retryMessage(Message message) {
|
void _retryMessage(Message message) {
|
||||||
final connector = Provider.of<MeshCoreConnector>(context, listen: false);
|
final connector = Provider.of<MeshCoreConnector>(context, listen: false);
|
||||||
// Retry using the contact's current path override setting
|
// Retry using the contact's current path override setting
|
||||||
connector.sendMessage(_resolveContact(connector), message.text);
|
connector.sendMessage(_resolveContact(connector), message.text);
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.chat_retryingMessage)));
|
content: Text(context.l10n.chat_retryingMessage),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showEmojiPicker(Message message, Contact senderContact) {
|
void _showEmojiPicker(Message message, Contact senderContact) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../models/community.dart';
|
|||||||
import '../storage/community_store.dart';
|
import '../storage/community_store.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
import '../widgets/qr_scanner_widget.dart';
|
import '../widgets/qr_scanner_widget.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
/// Screen for scanning community QR codes to join communities.
|
/// Screen for scanning community QR codes to join communities.
|
||||||
///
|
///
|
||||||
@@ -76,11 +77,10 @@ class _CommunityQrScannerScreenState extends State<CommunityQrScannerScreen> {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.community_invalidQrCode),
|
content: Text(context.l10n.community_invalidQrCode),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -93,12 +93,11 @@ class _CommunityQrScannerScreenState extends State<CommunityQrScannerScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showInvalidQrError(BuildContext context) {
|
void _showInvalidQrError(BuildContext context) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.community_invalidQrCode),
|
content: Text(context.l10n.community_invalidQrCode),
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,11 +228,10 @@ class _CommunityQrScannerScreenState extends State<CommunityQrScannerScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.community_joined(community.name)),
|
content: Text(context.l10n.community_joined(community.name)),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Return to previous screen
|
// Return to previous screen
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import '../widgets/quick_switch_bar.dart';
|
|||||||
import '../widgets/repeater_login_dialog.dart';
|
import '../widgets/repeater_login_dialog.dart';
|
||||||
import '../widgets/room_login_dialog.dart';
|
import '../widgets/room_login_dialog.dart';
|
||||||
import '../widgets/unread_badge.dart';
|
import '../widgets/unread_badge.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'channels_screen.dart';
|
import 'channels_screen.dart';
|
||||||
import 'chat_screen.dart';
|
import 'chat_screen.dart';
|
||||||
import 'discovery_screen.dart';
|
import 'discovery_screen.dart';
|
||||||
@@ -150,9 +151,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showGroupsUnavailableMessage(BuildContext context) {
|
void _showGroupsUnavailableMessage(BuildContext context) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(context.l10n.common_loading)));
|
content: Text(context.l10n.common_loading),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setupFrameListener() {
|
void _setupFrameListener() {
|
||||||
@@ -169,10 +171,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
// Validate packet has expected minimum size (98+ bytes per protocol)
|
// Validate packet has expected minimum size (98+ bytes per protocol)
|
||||||
if (advertPacket.length < 98) {
|
if (advertPacket.length < 98) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_invalidAdvertFormat),
|
content: Text(context.l10n.contacts_invalidAdvertFormat),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_pendingOperations.remove(ContactOperationType.export);
|
_pendingOperations.remove(ContactOperationType.export);
|
||||||
@@ -187,24 +188,23 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
if (_pendingOperations.contains(ContactOperationType.import)) {
|
if (_pendingOperations.contains(ContactOperationType.import)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_contactImported)),
|
context,
|
||||||
|
content: Text(context.l10n.contacts_contactImported),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pendingOperations.contains(ContactOperationType.zeroHopShare)) {
|
if (_pendingOperations.contains(ContactOperationType.zeroHopShare)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_zeroHopContactAdvertSent),
|
content: Text(context.l10n.contacts_zeroHopContactAdvertSent),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pendingOperations.contains(ContactOperationType.export)) {
|
if (_pendingOperations.contains(ContactOperationType.export)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_contactAdvertCopied),
|
content: Text(context.l10n.contacts_contactAdvertCopied),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,25 +216,22 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
if (_pendingOperations.contains(ContactOperationType.import)) {
|
if (_pendingOperations.contains(ContactOperationType.import)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_contactImportFailed),
|
content: Text(context.l10n.contacts_contactImportFailed),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pendingOperations.contains(ContactOperationType.zeroHopShare)) {
|
if (_pendingOperations.contains(ContactOperationType.zeroHopShare)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_zeroHopContactAdvertFailed),
|
content: Text(context.l10n.contacts_zeroHopContactAdvertFailed),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (_pendingOperations.contains(ContactOperationType.export)) {
|
if (_pendingOperations.contains(ContactOperationType.export)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_contactAdvertCopyFailed),
|
content: Text(context.l10n.contacts_contactAdvertCopyFailed),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,8 +268,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
final clipboardData = await Clipboard.getData('text/plain');
|
final clipboardData = await Clipboard.getData('text/plain');
|
||||||
if (clipboardData == null || clipboardData.text == null) {
|
if (clipboardData == null || clipboardData.text == null) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_clipboardEmpty)),
|
context,
|
||||||
|
content: Text(context.l10n.contacts_clipboardEmpty),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -280,8 +278,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
final text = clipboardData.text!.trim();
|
final text = clipboardData.text!.trim();
|
||||||
if (!text.startsWith('meshcore://')) {
|
if (!text.startsWith('meshcore://')) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_invalidAdvertFormat)),
|
context,
|
||||||
|
content: Text(context.l10n.contacts_invalidAdvertFormat),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -294,8 +293,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
connector.importContact(importContactFrame);
|
connector.importContact(importContactFrame);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_invalidAdvertFormat)),
|
context,
|
||||||
|
content: Text(context.l10n.contacts_invalidAdvertFormat),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,10 +330,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
),
|
),
|
||||||
onTap: () => {
|
onTap: () => {
|
||||||
connector.sendSelfAdvert(flood: false),
|
connector.sendSelfAdvert(flood: false),
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.settings_advertisementSent),
|
content: Text(context.l10n.settings_advertisementSent),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -347,10 +346,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
),
|
),
|
||||||
onTap: () => {
|
onTap: () => {
|
||||||
connector.sendSelfAdvert(flood: true),
|
connector.sendSelfAdvert(flood: true),
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.settings_advertisementSent),
|
content: Text(context.l10n.settings_advertisementSent),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -1146,19 +1144,17 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final name = nameController.text.trim();
|
final name = nameController.text.trim();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_groupNameRequired),
|
content: Text(context.l10n.contacts_groupNameRequired),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (name.toLowerCase() ==
|
if (name.toLowerCase() ==
|
||||||
contactsAllGroupsValue.toLowerCase()) {
|
contactsAllGroupsValue.toLowerCase()) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.contacts_groupNameReserved),
|
content: Text(context.l10n.contacts_groupNameReserved),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1167,11 +1163,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
return g.name.toLowerCase() == name.toLowerCase();
|
return g.name.toLowerCase() == name.toLowerCase();
|
||||||
});
|
});
|
||||||
if (exists) {
|
if (exists) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.contacts_groupAlreadyExists(name),
|
context.l10n.contacts_groupAlreadyExists(name),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import '../utils/contact_search.dart';
|
|||||||
import '../utils/platform_info.dart';
|
import '../utils/platform_info.dart';
|
||||||
import '../widgets/app_bar.dart';
|
import '../widgets/app_bar.dart';
|
||||||
import '../widgets/list_filter_widget.dart';
|
import '../widgets/list_filter_widget.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
enum DiscoverySortOption { lastSeen, name, type }
|
enum DiscoverySortOption { lastSeen, name, type }
|
||||||
|
|
||||||
@@ -234,8 +235,9 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
|
|||||||
final hexString = pubKeyToHex(contact.rawPacket!);
|
final hexString = pubKeyToHex(contact.rawPacket!);
|
||||||
Clipboard.setData(ClipboardData(text: "meshcore://$hexString"));
|
Clipboard.setData(ClipboardData(text: "meshcore://$hexString"));
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_contactAdvertCopied)),
|
context,
|
||||||
|
content: Text(context.l10n.contacts_contactAdvertCopied),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'delete_contact':
|
case 'delete_contact':
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../l10n/l10n.dart';
|
|||||||
import '../services/app_settings_service.dart';
|
import '../services/app_settings_service.dart';
|
||||||
import '../services/map_tile_cache_service.dart';
|
import '../services/map_tile_cache_service.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class MapCacheScreen extends StatefulWidget {
|
class MapCacheScreen extends StatefulWidget {
|
||||||
const MapCacheScreen({super.key});
|
const MapCacheScreen({super.key});
|
||||||
@@ -112,15 +113,17 @@ class _MapCacheScreenState extends State<MapCacheScreen> {
|
|||||||
Future<void> _startDownload() async {
|
Future<void> _startDownload() async {
|
||||||
final bounds = _selectedBounds;
|
final bounds = _selectedBounds;
|
||||||
if (bounds == null) {
|
if (bounds == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.mapCache_selectAreaFirst)),
|
context,
|
||||||
|
content: Text(context.l10n.mapCache_selectAreaFirst),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_estimatedTiles == 0) {
|
if (_estimatedTiles == 0) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.mapCache_noTilesToDownload)),
|
context,
|
||||||
|
content: Text(context.l10n.mapCache_noTilesToDownload),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -182,9 +185,7 @@ class _MapCacheScreenState extends State<MapCacheScreen> {
|
|||||||
result.failed,
|
result.failed,
|
||||||
)
|
)
|
||||||
: context.l10n.mapCache_cachedTiles(result.downloaded);
|
: context.l10n.mapCache_cachedTiles(result.downloaded);
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(context, content: Text(message));
|
||||||
context,
|
|
||||||
).showSnackBar(SnackBar(content: Text(message)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _clearCache() async {
|
Future<void> _clearCache() async {
|
||||||
@@ -210,8 +211,9 @@ class _MapCacheScreenState extends State<MapCacheScreen> {
|
|||||||
final cacheService = context.read<MapTileCacheService>();
|
final cacheService = context.read<MapTileCacheService>();
|
||||||
await cacheService.clearCache();
|
await cacheService.clearCache();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.mapCache_offlineCacheCleared)),
|
context,
|
||||||
|
content: Text(context.l10n.mapCache_offlineCacheCleared),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import 'chat_screen.dart';
|
|||||||
import 'contacts_screen.dart';
|
import 'contacts_screen.dart';
|
||||||
import '../widgets/repeater_login_dialog.dart';
|
import '../widgets/repeater_login_dialog.dart';
|
||||||
import '../widgets/room_login_dialog.dart';
|
import '../widgets/room_login_dialog.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'repeater_hub_screen.dart';
|
import 'repeater_hub_screen.dart';
|
||||||
import 'settings_screen.dart';
|
import 'settings_screen.dart';
|
||||||
import 'line_of_sight_map_screen.dart';
|
import 'line_of_sight_map_screen.dart';
|
||||||
@@ -1659,7 +1660,10 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
);
|
);
|
||||||
await connector.refreshDeviceInfo();
|
await connector.refreshDeviceInfo();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
messenger.showSnackBar(SnackBar(content: Text(successMsg)));
|
showDismissibleSnackBar(
|
||||||
|
messenger.context,
|
||||||
|
content: Text(successMsg),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -1681,8 +1685,9 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
required String flags,
|
required String flags,
|
||||||
}) async {
|
}) async {
|
||||||
if (!connector.isConnected) {
|
if (!connector.isConnected) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.map_connectToShareMarkers)),
|
context,
|
||||||
|
content: Text(context.l10n.map_connectToShareMarkers),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2271,8 +2276,9 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
_points.clear();
|
_points.clear();
|
||||||
_polylines.clear();
|
_polylines.clear();
|
||||||
});
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.map_pathTraceCancelled)),
|
context,
|
||||||
|
content: Text(l10n.map_pathTraceCancelled),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
tooltip: l10n.common_cancel,
|
tooltip: l10n.common_cancel,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import '../connector/meshcore_protocol.dart';
|
|||||||
import '../services/repeater_command_service.dart';
|
import '../services/repeater_command_service.dart';
|
||||||
import '../widgets/path_management_dialog.dart';
|
import '../widgets/path_management_dialog.dart';
|
||||||
import '../widgets/snr_indicator.dart';
|
import '../widgets/snr_indicator.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class NeighborsScreen extends StatefulWidget {
|
class NeighborsScreen extends StatefulWidget {
|
||||||
final Contact repeater;
|
final Contact repeater;
|
||||||
@@ -163,11 +164,10 @@ class _NeighborsScreenState extends State<NeighborsScreen> {
|
|||||||
_neighborCount = neighborCount;
|
_neighborCount = neighborCount;
|
||||||
});
|
});
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.neighbors_receivedData),
|
content: Text(context.l10n.neighbors_receivedData),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_statusTimeout?.cancel();
|
_statusTimeout?.cancel();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
@@ -224,11 +224,10 @@ class _NeighborsScreenState extends State<NeighborsScreen> {
|
|||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
});
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.neighbors_requestTimedOut),
|
content: Text(context.l10n.neighbors_requestTimedOut),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_recordStatusResult(false);
|
_recordStatusResult(false);
|
||||||
});
|
});
|
||||||
@@ -239,11 +238,10 @@ class _NeighborsScreenState extends State<NeighborsScreen> {
|
|||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.neighbors_errorLoading(e.toString())),
|
content: Text(context.l10n.neighbors_errorLoading(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import '../connector/meshcore_protocol.dart';
|
|||||||
import '../widgets/debug_frame_viewer.dart';
|
import '../widgets/debug_frame_viewer.dart';
|
||||||
import '../services/repeater_command_service.dart';
|
import '../services/repeater_command_service.dart';
|
||||||
import '../widgets/path_management_dialog.dart';
|
import '../widgets/path_management_dialog.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class RepeaterCliScreen extends StatefulWidget {
|
class RepeaterCliScreen extends StatefulWidget {
|
||||||
final Contact repeater;
|
final Contact repeater;
|
||||||
@@ -336,8 +337,9 @@ class _RepeaterCliScreenState extends State<RepeaterCliScreen> {
|
|||||||
if (_commandController.text.trim().isNotEmpty) {
|
if (_commandController.text.trim().isNotEmpty) {
|
||||||
_sendCommand(showDebug: true);
|
_sendCommand(showDebug: true);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.repeater_enterCommandFirst)),
|
context,
|
||||||
|
content: Text(l10n.repeater_enterCommandFirst),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import '../services/app_debug_log_service.dart';
|
|||||||
import '../services/repeater_command_service.dart';
|
import '../services/repeater_command_service.dart';
|
||||||
import '../services/storage_service.dart';
|
import '../services/storage_service.dart';
|
||||||
import '../widgets/path_management_dialog.dart';
|
import '../widgets/path_management_dialog.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class RepeaterSettingsScreen extends StatefulWidget {
|
class RepeaterSettingsScreen extends StatefulWidget {
|
||||||
final Contact repeater;
|
final Contact repeater;
|
||||||
@@ -468,18 +469,16 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
if (successCount > 0) {
|
if (successCount > 0) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.repeater_refreshed(label)),
|
content: Text(l10n.repeater_refreshed(label)),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.repeater_errorRefreshing(label)),
|
content: Text(l10n.repeater_errorRefreshing(label)),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,11 +665,10 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.repeater_settingsSaved),
|
content: Text(context.l10n.repeater_settingsSaved),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -679,13 +677,12 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
context.l10n.repeater_errorSavingSettings(e.toString()),
|
context.l10n.repeater_errorSavingSettings(e.toString()),
|
||||||
),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1429,9 +1426,10 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
|
|
||||||
if (command == 'erase') {
|
if (command == 'erase') {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(l10n.repeater_eraseSerialOnly)));
|
content: Text(l10n.repeater_eraseSerialOnly),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1453,17 +1451,17 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
await connector.sendFrame(frame);
|
await connector.sendFrame(frame);
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.repeater_commandSent(command))),
|
context,
|
||||||
|
content: Text(l10n.repeater_commandSent(command)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.repeater_errorSendingCommand(e.toString())),
|
content: Text(l10n.repeater_errorSendingCommand(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import '../services/app_settings_service.dart';
|
|||||||
import '../services/repeater_command_service.dart';
|
import '../services/repeater_command_service.dart';
|
||||||
import '../utils/battery_utils.dart';
|
import '../utils/battery_utils.dart';
|
||||||
import '../widgets/path_management_dialog.dart';
|
import '../widgets/path_management_dialog.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class RepeaterStatusScreen extends StatefulWidget {
|
class RepeaterStatusScreen extends StatefulWidget {
|
||||||
final Contact repeater;
|
final Contact repeater;
|
||||||
@@ -309,11 +310,10 @@ class _RepeaterStatusScreenState extends State<RepeaterStatusScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.repeater_statusRequestTimeout),
|
content: Text(context.l10n.repeater_statusRequestTimeout),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_recordStatusResult(false);
|
_recordStatusResult(false);
|
||||||
});
|
});
|
||||||
@@ -323,13 +323,10 @@ class _RepeaterStatusScreenState extends State<RepeaterStatusScreen> {
|
|||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(context.l10n.repeater_errorLoadingStatus(e.toString())),
|
||||||
context.l10n.repeater_errorLoadingStatus(e.toString()),
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_recordStatusResult(false);
|
_recordStatusResult(false);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import '../services/linux_ble_error_classifier.dart';
|
|||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
import '../widgets/device_tile.dart';
|
import '../widgets/device_tile.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'contacts_screen.dart';
|
import 'contacts_screen.dart';
|
||||||
import 'tcp_screen.dart';
|
import 'tcp_screen.dart';
|
||||||
import 'usb_screen.dart';
|
import 'usb_screen.dart';
|
||||||
@@ -317,11 +318,10 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.scanner_connectionFailed(e.toString())),
|
content: Text(context.l10n.scanner_connectionFailed(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import '../l10n/l10n.dart';
|
|||||||
import '../models/radio_settings.dart';
|
import '../models/radio_settings.dart';
|
||||||
import '../services/app_debug_log_service.dart';
|
import '../services/app_debug_log_service.dart';
|
||||||
import '../widgets/app_bar.dart';
|
import '../widgets/app_bar.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'app_settings_screen.dart';
|
import 'app_settings_screen.dart';
|
||||||
import 'app_debug_log_screen.dart';
|
import 'app_debug_log_screen.dart';
|
||||||
import 'ble_debug_log_screen.dart';
|
import 'ble_debug_log_screen.dart';
|
||||||
@@ -513,8 +514,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
await connector.setNodeName(controller.text);
|
await connector.setNodeName(controller.text);
|
||||||
await connector.refreshDeviceInfo();
|
await connector.refreshDeviceInfo();
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_nodeNameUpdated)),
|
context,
|
||||||
|
content: Text(l10n.settings_nodeNameUpdated),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(l10n.common_save),
|
child: Text(l10n.common_save),
|
||||||
@@ -628,10 +630,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
final interval = int.tryParse(intervalText);
|
final interval = int.tryParse(intervalText);
|
||||||
if (interval == null || interval < 60 || interval >= 86400) {
|
if (interval == null || interval < 60 || interval >= 86400) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.settings_locationIntervalInvalid),
|
content: Text(l10n.settings_locationIntervalInvalid),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -639,8 +640,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
await connector.setCustomVar("gps_interval:$interval");
|
await connector.setCustomVar("gps_interval:$interval");
|
||||||
await connector.refreshDeviceInfo();
|
await connector.refreshDeviceInfo();
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_locationUpdated)),
|
context,
|
||||||
|
content: Text(l10n.settings_locationUpdated),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,15 +662,17 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
: currentLon;
|
: currentLon;
|
||||||
if (lat == null || lon == null) {
|
if (lat == null || lon == null) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_locationBothRequired)),
|
context,
|
||||||
|
content: Text(l10n.settings_locationBothRequired),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lat < -90 || lat > 90 || lon < -180 || lon > 180) {
|
if (lat < -90 || lat > 90 || lon < -180 || lon > 180) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_locationInvalid)),
|
context,
|
||||||
|
content: Text(l10n.settings_locationInvalid),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -676,8 +680,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
await connector.setNodeLocation(lat: lat, lon: lon);
|
await connector.setNodeLocation(lat: lat, lon: lon);
|
||||||
await connector.refreshDeviceInfo();
|
await connector.refreshDeviceInfo();
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_locationUpdated)),
|
context,
|
||||||
|
content: Text(l10n.settings_locationUpdated),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(l10n.common_save),
|
child: Text(l10n.common_save),
|
||||||
@@ -691,9 +696,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
void _syncTime(BuildContext context, MeshCoreConnector connector) {
|
void _syncTime(BuildContext context, MeshCoreConnector connector) {
|
||||||
final l10n = context.l10n;
|
final l10n = context.l10n;
|
||||||
connector.syncTime();
|
connector.syncTime();
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(l10n.settings_timeSynchronized)));
|
content: Text(l10n.settings_timeSynchronized),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _confirmReboot(BuildContext context, MeshCoreConnector connector) {
|
void _confirmReboot(BuildContext context, MeshCoreConnector connector) {
|
||||||
@@ -758,23 +764,27 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case gpxExportSuccess:
|
case gpxExportSuccess:
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(l10n.settings_gpxExportSuccess)));
|
content: Text(l10n.settings_gpxExportSuccess),
|
||||||
|
);
|
||||||
case gpxExportNoContacts:
|
case gpxExportNoContacts:
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_gpxExportNoContacts)),
|
context,
|
||||||
|
content: Text(l10n.settings_gpxExportNoContacts),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case gpxExportNotAvailable:
|
case gpxExportNotAvailable:
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_gpxExportNotAvailable)),
|
context,
|
||||||
|
content: Text(l10n.settings_gpxExportNotAvailable),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case gpxExportFailed:
|
case gpxExportFailed:
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(l10n.settings_gpxExportError)));
|
content: Text(l10n.settings_gpxExportError),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1077,8 +1087,9 @@ void _privacySettings(BuildContext context, MeshCoreConnector connector) {
|
|||||||
);
|
);
|
||||||
await connector.refreshDeviceInfo();
|
await connector.refreshDeviceInfo();
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_telemetryModeUpdated)),
|
context,
|
||||||
|
content: Text(l10n.settings_telemetryModeUpdated),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(l10n.common_save),
|
child: Text(l10n.common_save),
|
||||||
@@ -1410,18 +1421,18 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
|
|||||||
final txPower = int.tryParse(_txPowerController.text);
|
final txPower = int.tryParse(_txPowerController.text);
|
||||||
|
|
||||||
if (freqMHz == null || freqMHz < 300 || freqMHz > 2500) {
|
if (freqMHz == null || freqMHz < 300 || freqMHz > 2500) {
|
||||||
ScaffoldMessenger.of(
|
showDismissibleSnackBar(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(l10n.settings_frequencyInvalid)));
|
content: Text(l10n.settings_frequencyInvalid),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final maxTxPower = widget.connector.maxTxPower ?? 22;
|
final maxTxPower = widget.connector.maxTxPower ?? 22;
|
||||||
if (txPower == null || txPower < 0 || txPower > maxTxPower) {
|
if (txPower == null || txPower < 0 || txPower > maxTxPower) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text('${l10n.settings_txPowerInvalid} (0-$maxTxPower dBm)'),
|
content: Text('${l10n.settings_txPowerInvalid} (0-$maxTxPower dBm)'),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1441,8 +1452,9 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
|
|||||||
if (knownRepeat) {
|
if (knownRepeat) {
|
||||||
const validRepeatFreqsKHz = {433000, 869000, 918000};
|
const validRepeatFreqsKHz = {433000, 869000, 918000};
|
||||||
if (_clientRepeat && !validRepeatFreqsKHz.contains(freqHz)) {
|
if (_clientRepeat && !validRepeatFreqsKHz.contains(freqHz)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_clientRepeatFreqWarning)),
|
context,
|
||||||
|
content: Text(l10n.settings_clientRepeatFreqWarning),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1472,14 +1484,16 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
|
|||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
_logRadioSettingsState('Radio settings saved successfully');
|
_logRadioSettingsState('Radio settings saved successfully');
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_radioSettingsUpdated)),
|
context,
|
||||||
|
content: Text(l10n.settings_radioSettingsUpdated),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_appLog.warn('Radio settings save failed: $e', tag: 'RadioSettings');
|
_appLog.warn('Radio settings save failed: $e', tag: 'RadioSettings');
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(l10n.settings_error(e.toString()))),
|
context,
|
||||||
|
content: Text(l10n.settings_error(e.toString())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../l10n/l10n.dart';
|
|||||||
import '../services/app_settings_service.dart';
|
import '../services/app_settings_service.dart';
|
||||||
import '../utils/platform_info.dart';
|
import '../utils/platform_info.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'contacts_screen.dart';
|
import 'contacts_screen.dart';
|
||||||
import 'usb_screen.dart';
|
import 'usb_screen.dart';
|
||||||
|
|
||||||
@@ -270,8 +271,10 @@ class _TcpScreenState extends State<TcpScreen> {
|
|||||||
|
|
||||||
void _showError(String message) {
|
void _showError(String message) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(content: Text(message), backgroundColor: Colors.red),
|
context,
|
||||||
|
content: Text(message),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import '../utils/app_logger.dart';
|
|||||||
import '../widgets/path_management_dialog.dart';
|
import '../widgets/path_management_dialog.dart';
|
||||||
import '../helpers/cayenne_lpp.dart';
|
import '../helpers/cayenne_lpp.dart';
|
||||||
import '../utils/battery_utils.dart';
|
import '../utils/battery_utils.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class TelemetryScreen extends StatefulWidget {
|
class TelemetryScreen extends StatefulWidget {
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
@@ -86,11 +87,10 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
|
|||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
});
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.telemetry_requestTimeout),
|
content: Text(context.l10n.telemetry_requestTimeout),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_recordTelemetryResult(false);
|
_recordTelemetryResult(false);
|
||||||
});
|
});
|
||||||
@@ -137,11 +137,10 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
|
|||||||
_parsedTelemetry = parsedTelemetry;
|
_parsedTelemetry = parsedTelemetry;
|
||||||
});
|
});
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.telemetry_receivedData),
|
content: Text(context.l10n.telemetry_receivedData),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_statusTimeout?.cancel();
|
_statusTimeout?.cancel();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
@@ -182,11 +181,10 @@ class _TelemetryScreenState extends State<TelemetryScreen> {
|
|||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.telemetry_errorLoading(e.toString())),
|
content: Text(context.l10n.telemetry_errorLoading(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import '../utils/app_logger.dart';
|
|||||||
import '../utils/platform_info.dart';
|
import '../utils/platform_info.dart';
|
||||||
import '../utils/usb_port_labels.dart';
|
import '../utils/usb_port_labels.dart';
|
||||||
import '../widgets/adaptive_app_bar_title.dart';
|
import '../widgets/adaptive_app_bar_title.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'contacts_screen.dart';
|
import 'contacts_screen.dart';
|
||||||
import 'scanner_screen.dart';
|
import 'scanner_screen.dart';
|
||||||
import 'tcp_screen.dart';
|
import 'tcp_screen.dart';
|
||||||
@@ -383,11 +384,10 @@ class _UsbScreenState extends State<UsbScreen> {
|
|||||||
|
|
||||||
void _showError(Object error) {
|
void _showError(Object error) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(_friendlyErrorMessage(error)),
|
content: Text(_friendlyErrorMessage(error)),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import '../l10n/l10n.dart';
|
|||||||
import '../models/contact.dart';
|
import '../models/contact.dart';
|
||||||
import '../helpers/path_helper.dart';
|
import '../helpers/path_helper.dart';
|
||||||
import '../services/path_history_service.dart';
|
import '../services/path_history_service.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'path_selection_dialog.dart';
|
import 'path_selection_dialog.dart';
|
||||||
|
|
||||||
class PathManagementDialog {
|
class PathManagementDialog {
|
||||||
@@ -65,11 +66,10 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
void _showFullPathDialog(BuildContext context, List<int> pathBytes) {
|
void _showFullPathDialog(BuildContext context, List<int> pathBytes) {
|
||||||
final l10n = context.l10n;
|
final l10n = context.l10n;
|
||||||
if (pathBytes.isEmpty) {
|
if (pathBytes.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.chat_pathDetailsNotAvailable),
|
content: Text(l10n.chat_pathDetailsNotAvailable),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -159,11 +159,10 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.chat_hopsCount(result.length)),
|
content: Text(l10n.chat_hopsCount(result.length)),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,13 +336,12 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
_showFullPathDialog(context, path.pathBytes),
|
_showFullPathDialog(context, path.pathBytes),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (path.pathBytes.isEmpty) {
|
if (path.pathBytes.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
l10n.chat_pathDetailsNotAvailable,
|
l10n.chat_pathDetailsNotAvailable,
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -361,13 +359,12 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(
|
||||||
l10n.path_usingHopsPath(path.hopCount),
|
l10n.path_usingHopsPath(path.hopCount),
|
||||||
),
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
),
|
),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -459,11 +456,10 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
await connector.clearContactPath(currentContact);
|
await connector.clearContactPath(currentContact);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.chat_pathCleared),
|
content: Text(l10n.chat_pathCleared),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
@@ -489,11 +485,10 @@ class _PathManagementDialogState extends State<_PathManagementDialog> {
|
|||||||
pathLen: -1,
|
pathLen: -1,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.chat_floodModeEnabled),
|
content: Text(l10n.chat_floodModeEnabled),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../models/contact.dart';
|
import '../models/contact.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class PathSelectionDialog extends StatefulWidget {
|
class PathSelectionDialog extends StatefulWidget {
|
||||||
final List<Contact> availableContacts;
|
final List<Contact> availableContacts;
|
||||||
@@ -138,26 +139,22 @@ class _PathSelectionDialogState extends State<PathSelectionDialog> {
|
|||||||
|
|
||||||
// Show error for invalid prefixes
|
// Show error for invalid prefixes
|
||||||
if (invalidPrefixes.isNotEmpty) {
|
if (invalidPrefixes.isNotEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
content: Text(l10n.path_invalidHexPrefixes(invalidPrefixes.join(", "))),
|
||||||
l10n.path_invalidHexPrefixes(invalidPrefixes.join(", ")),
|
duration: const Duration(seconds: 3),
|
||||||
),
|
backgroundColor: Colors.red,
|
||||||
duration: const Duration(seconds: 3),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check max path length (64 hops)
|
// Check max path length (64 hops)
|
||||||
if (pathBytesList.length > 64) {
|
if (pathBytesList.length > 64) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(l10n.path_tooLong),
|
content: Text(l10n.path_tooLong),
|
||||||
duration: const Duration(seconds: 3),
|
duration: const Duration(seconds: 3),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import '../services/storage_service.dart';
|
|||||||
import '../connector/meshcore_connector.dart';
|
import '../connector/meshcore_connector.dart';
|
||||||
import '../connector/meshcore_protocol.dart';
|
import '../connector/meshcore_protocol.dart';
|
||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
|
import '../helpers/snack_bar_builder.dart';
|
||||||
import 'path_management_dialog.dart';
|
import 'path_management_dialog.dart';
|
||||||
|
|
||||||
class RoomLoginDialog extends StatefulWidget {
|
class RoomLoginDialog extends StatefulWidget {
|
||||||
@@ -175,11 +176,10 @@ class _RoomLoginDialogState extends State<RoomLoginDialog> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_isLoggingIn = false;
|
_isLoggingIn = false;
|
||||||
});
|
});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDismissibleSnackBar(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(context.l10n.login_failed(e.toString())),
|
content: Text(context.l10n.login_failed(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user