feat(#18): flatten App Settings + add top-level Message Settings category

Split the monolithic AppSettingsScreen (reached via a redundant tile->push from the App Settings category) into two embeddable views rendered directly in the shell panes: AppSettingsView (appearance, translation, battery, map, Cyr2Lat, debug) and MessageSettingsView (notifications + message handling, a new top-level 'Message Settings' category after Contacts). Removes the category->tile->separate-screen layer; each category now lands directly on its settings. Deletes app_settings_screen.dart (no remaining refs). Adds settings_messageSettings(+Subtitle) l10n keys (en template; other locales fall back pending the l10n sweep). Card bodies moved verbatim -- behavior preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/36/head
Strycher 1 month ago
parent 7708155597
commit 3fb798ca7f

@ -143,6 +143,14 @@
"settings_deviceInfo": "Device Info",
"settings_appSettings": "App Settings",
"settings_appSettingsSubtitle": "Notifications, messaging, and map preferences",
"settings_messageSettings": "Message Settings",
"@settings_messageSettings": {
"description": "Settings category title for notification and message-handling preferences"
},
"settings_messageSettingsSubtitle": "Notifications and message handling",
"@settings_messageSettingsSubtitle": {
"description": "Settings category subtitle for the message settings pane"
},
"settings_nodeSettings": "Node Settings",
"settings_nodeName": "Node Name",
"settings_nodeNameNotSet": "Not set",

@ -694,6 +694,18 @@ abstract class AppLocalizations {
/// **'Notifications, messaging, and map preferences'**
String get settings_appSettingsSubtitle;
/// Settings category title for notification and message-handling preferences
///
/// In en, this message translates to:
/// **'Message Settings'**
String get settings_messageSettings;
/// Settings category subtitle for the message settings pane
///
/// In en, this message translates to:
/// **'Notifications and message handling'**
String get settings_messageSettingsSubtitle;
/// No description provided for @settings_nodeSettings.
///
/// In en, this message translates to:

@ -319,6 +319,13 @@ class AppLocalizationsBg extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Уведомления, съобщения и предпочитания за карта';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Настройки на възела';

@ -322,6 +322,13 @@ class AppLocalizationsDe extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Benachrichtigungen, Messaging und Kartenwahrnehmung';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Knoten-Einstellungen';

@ -316,6 +316,13 @@ class AppLocalizationsEn extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notifications, messaging, and map preferences';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Node Settings';

@ -320,6 +320,13 @@ class AppLocalizationsEs extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notificaciones, mensajes y preferencias de mapa';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Configuración del Nodo';

@ -322,6 +322,13 @@ class AppLocalizationsFr extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notifications, messagerie et préférences de carte';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Paramètres du nœud';

@ -319,6 +319,13 @@ class AppLocalizationsHu extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Értesítések, üzenetküldés és térképi beállítások';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Műközép beállítások';

@ -322,6 +322,13 @@ class AppLocalizationsIt extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notifiche, messaggi e preferenze della mappa';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Impostazioni Nodo';

@ -308,6 +308,13 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get settings_appSettingsSubtitle => '通知、メッセージング、および地図の表示設定';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'ノード設定';

@ -307,6 +307,13 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get settings_appSettingsSubtitle => '알림, 메시징, 지도 설정';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => '노드 설정';

@ -318,6 +318,13 @@ class AppLocalizationsNl extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notificaties, berichten en kaartinstellingen';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Node Instellingen';

@ -323,6 +323,13 @@ class AppLocalizationsPl extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Powiadomienia, wiadomości i preferencje mapy';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Ustawienia węzła';

@ -321,6 +321,13 @@ class AppLocalizationsPt extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Notificações, mensagens e preferências de mapa';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Configurações do Nó';

@ -321,6 +321,13 @@ class AppLocalizationsRu extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Уведомления, сообщения и настройки карты';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Настройки ноды';

@ -320,6 +320,13 @@ class AppLocalizationsSk extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Upozornenia, správy a nastavenia mapy';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Nastavenia uzla';

@ -318,6 +318,13 @@ class AppLocalizationsSl extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Obveščanja, sporoščanje in zemljevidi.';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Nastavitev časa';

@ -317,6 +317,13 @@ class AppLocalizationsSv extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Meddelanden, notiser och kartinställningar';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Nodinställningar';

@ -320,6 +320,13 @@ class AppLocalizationsUk extends AppLocalizations {
String get settings_appSettingsSubtitle =>
'Сповіщення, повідомлення та налаштування карти';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => 'Налаштування вузла';

@ -305,6 +305,13 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get settings_appSettingsSubtitle => '通知、消息和地图偏好';
@override
String get settings_messageSettings => 'Message Settings';
@override
String get settings_messageSettingsSubtitle =>
'Notifications and message handling';
@override
String get settings_nodeSettings => '节点设置';

@ -3,74 +3,50 @@ import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../connector/meshcore_connector.dart';
import '../l10n/l10n.dart';
import '../models/app_settings.dart';
import '../models/translation_support.dart';
import '../services/app_settings_service.dart';
import '../services/notification_service.dart';
import '../services/translation_service.dart';
import '../widgets/adaptive_app_bar_title.dart';
import '../widgets/sync_progress_overlay.dart';
import '../helpers/snack_bar_builder.dart';
import 'map_cache_screen.dart';
import '../../connector/meshcore_connector.dart';
import '../../l10n/l10n.dart';
import '../../models/app_settings.dart';
import '../../models/translation_support.dart';
import '../../services/app_settings_service.dart';
import '../../services/translation_service.dart';
import '../../helpers/snack_bar_builder.dart';
import '../map_cache_screen.dart';
class AppSettingsScreen extends StatelessWidget {
const AppSettingsScreen({super.key});
/// Embeddable view (no Scaffold) for the App Settings shell pane.
///
/// Renders appearance, translation, battery, map, Cyr2Lat, and debug cards.
/// Notifications and message-handling settings live in [MessageSettingsView].
class AppSettingsView extends StatelessWidget {
const AppSettingsView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: AdaptiveAppBarTitle(context.l10n.appSettings_title),
centerTitle: true,
bottom: const SyncProgressAppBarBottom(),
),
body: SafeArea(
top: false,
child:
Consumer3<
AppSettingsService,
MeshCoreConnector,
TranslationService
>(
builder:
(
return Consumer3<AppSettingsService, MeshCoreConnector, TranslationService>(
builder:
(context, settingsService, connector, translationService, child) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
_buildAppearanceCard(context, settingsService),
const SizedBox(height: 16),
if (!kIsWeb) ...[
_buildTranslationCard(
context,
settingsService,
connector,
translationService,
child,
) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
_buildAppearanceCard(context, settingsService),
const SizedBox(height: 16),
_buildNotificationsCard(context, settingsService),
const SizedBox(height: 16),
_buildMessagingCard(context, settingsService),
const SizedBox(height: 16),
if (!kIsWeb) ...[
_buildTranslationCard(
context,
settingsService,
translationService,
),
const SizedBox(height: 16),
],
_buildBatteryCard(context, settingsService, connector),
const SizedBox(height: 16),
_buildMapSettingsCard(context, settingsService),
const SizedBox(height: 16),
_buildCyr2LatCard(context, settingsService),
const SizedBox(height: 16),
_buildDebugCard(context, settingsService),
],
);
},
),
),
),
const SizedBox(height: 16),
],
_buildBatteryCard(context, settingsService, connector),
const SizedBox(height: 16),
_buildMapSettingsCard(context, settingsService),
const SizedBox(height: 16),
_buildCyr2LatCard(context, settingsService),
const SizedBox(height: 16),
_buildDebugCard(context, settingsService),
],
);
},
);
}
@ -128,338 +104,6 @@ class AppSettingsScreen extends StatelessWidget {
);
}
Widget _buildNotificationsCard(
BuildContext context,
AppSettingsService settingsService,
) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
context.l10n.appSettings_notifications,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
SwitchListTile(
secondary: const Icon(Icons.notifications_outlined),
title: Text(context.l10n.appSettings_enableNotifications),
subtitle: Text(
context.l10n.appSettings_enableNotificationsSubtitle,
),
value: settingsService.settings.notificationsEnabled,
onChanged: (value) async {
if (value) {
// Request permission when enabling
final granted = await NotificationService()
.requestPermissions();
if (!granted) {
if (context.mounted) {
showDismissibleSnackBar(
context,
content: Text(
context.l10n.appSettings_notificationPermissionDenied,
),
duration: const Duration(seconds: 2),
);
}
return;
}
}
await settingsService.setNotificationsEnabled(value);
if (context.mounted) {
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_notificationsEnabled
: context.l10n.appSettings_notificationsDisabled,
),
duration: const Duration(seconds: 2),
);
}
},
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.message_outlined,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_messageNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_messageNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewMessage,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewMessage(value);
}
: null,
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.forum_outlined,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_channelMessageNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_channelMessageNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewChannelMessage,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewChannelMessage(value);
}
: null,
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.cell_tower,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_advertisementNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_advertisementNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewAdvert,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewAdvert(value);
}
: null,
),
],
),
);
}
Widget _buildMessagingCard(
BuildContext context,
AppSettingsService settingsService,
) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
context.l10n.appSettings_messaging,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
SwitchListTile(
secondary: const Icon(Icons.refresh_outlined),
title: Text(context.l10n.appSettings_clearPathOnMaxRetry),
subtitle: Text(
context.l10n.appSettings_clearPathOnMaxRetrySubtitle,
),
value: settingsService.settings.clearPathOnMaxRetry,
onChanged: (value) {
settingsService.setClearPathOnMaxRetry(value);
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_pathsWillBeCleared
: context.l10n.appSettings_pathsWillNotBeCleared,
),
duration: const Duration(seconds: 2),
);
},
),
const Divider(height: 1),
SwitchListTile(
secondary: const Icon(Icons.vertical_align_top),
title: Text(context.l10n.appSettings_jumpToOldestUnread),
subtitle: Text(context.l10n.appSettings_jumpToOldestUnreadSubtitle),
value: settingsService.settings.jumpToOldestUnread,
onChanged: settingsService.setJumpToOldestUnread,
),
const Divider(height: 1),
SwitchListTile(
secondary: const Icon(Icons.alt_route),
title: Text(context.l10n.appSettings_autoRouteRotation),
subtitle: Text(context.l10n.appSettings_autoRouteRotationSubtitle),
value: settingsService.settings.autoRouteRotationEnabled,
onChanged: (value) {
settingsService.setAutoRouteRotationEnabled(value);
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_autoRouteRotationEnabled
: context.l10n.appSettings_autoRouteRotationDisabled,
),
duration: const Duration(seconds: 2),
);
},
),
if (settingsService.settings.autoRouteRotationEnabled) ...[
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),
),
],
),
),
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,
),
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_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()),
),
],
),
),
],
],
),
);
}
Widget _buildMapSettingsCard(
BuildContext context,
AppSettingsService settingsService,

@ -0,0 +1,363 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../l10n/l10n.dart';
import '../../services/app_settings_service.dart';
import '../../services/notification_service.dart';
import '../../helpers/snack_bar_builder.dart';
/// Embeddable view (no Scaffold) for the Message Settings shell pane.
///
/// Renders notification toggles and message-handling settings. Both cards read
/// and write only [AppSettingsService].
class MessageSettingsView extends StatelessWidget {
const MessageSettingsView({super.key});
@override
Widget build(BuildContext context) {
return Consumer<AppSettingsService>(
builder: (context, settingsService, child) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
_buildNotificationsCard(context, settingsService),
const SizedBox(height: 16),
_buildMessagingCard(context, settingsService),
],
);
},
);
}
Widget _buildNotificationsCard(
BuildContext context,
AppSettingsService settingsService,
) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
context.l10n.appSettings_notifications,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
SwitchListTile(
secondary: const Icon(Icons.notifications_outlined),
title: Text(context.l10n.appSettings_enableNotifications),
subtitle: Text(
context.l10n.appSettings_enableNotificationsSubtitle,
),
value: settingsService.settings.notificationsEnabled,
onChanged: (value) async {
if (value) {
// Request permission when enabling
final granted = await NotificationService()
.requestPermissions();
if (!granted) {
if (context.mounted) {
showDismissibleSnackBar(
context,
content: Text(
context.l10n.appSettings_notificationPermissionDenied,
),
duration: const Duration(seconds: 2),
);
}
return;
}
}
await settingsService.setNotificationsEnabled(value);
if (context.mounted) {
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_notificationsEnabled
: context.l10n.appSettings_notificationsDisabled,
),
duration: const Duration(seconds: 2),
);
}
},
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.message_outlined,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_messageNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_messageNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewMessage,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewMessage(value);
}
: null,
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.forum_outlined,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_channelMessageNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_channelMessageNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewChannelMessage,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewChannelMessage(value);
}
: null,
),
const Divider(height: 1),
SwitchListTile(
secondary: Icon(
Icons.cell_tower,
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
title: Text(
context.l10n.appSettings_advertisementNotifications,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
subtitle: Text(
context.l10n.appSettings_advertisementNotificationsSubtitle,
style: TextStyle(
color: settingsService.settings.notificationsEnabled
? null
: Colors.grey,
),
),
value: settingsService.settings.notifyOnNewAdvert,
onChanged: settingsService.settings.notificationsEnabled
? (value) {
settingsService.setNotifyOnNewAdvert(value);
}
: null,
),
],
),
);
}
Widget _buildMessagingCard(
BuildContext context,
AppSettingsService settingsService,
) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
context.l10n.appSettings_messaging,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
SwitchListTile(
secondary: const Icon(Icons.refresh_outlined),
title: Text(context.l10n.appSettings_clearPathOnMaxRetry),
subtitle: Text(
context.l10n.appSettings_clearPathOnMaxRetrySubtitle,
),
value: settingsService.settings.clearPathOnMaxRetry,
onChanged: (value) {
settingsService.setClearPathOnMaxRetry(value);
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_pathsWillBeCleared
: context.l10n.appSettings_pathsWillNotBeCleared,
),
duration: const Duration(seconds: 2),
);
},
),
const Divider(height: 1),
SwitchListTile(
secondary: const Icon(Icons.vertical_align_top),
title: Text(context.l10n.appSettings_jumpToOldestUnread),
subtitle: Text(context.l10n.appSettings_jumpToOldestUnreadSubtitle),
value: settingsService.settings.jumpToOldestUnread,
onChanged: settingsService.setJumpToOldestUnread,
),
const Divider(height: 1),
SwitchListTile(
secondary: const Icon(Icons.alt_route),
title: Text(context.l10n.appSettings_autoRouteRotation),
subtitle: Text(context.l10n.appSettings_autoRouteRotationSubtitle),
value: settingsService.settings.autoRouteRotationEnabled,
onChanged: (value) {
settingsService.setAutoRouteRotationEnabled(value);
showDismissibleSnackBar(
context,
content: Text(
value
? context.l10n.appSettings_autoRouteRotationEnabled
: context.l10n.appSettings_autoRouteRotationDisabled,
),
duration: const Duration(seconds: 2),
);
},
),
if (settingsService.settings.autoRouteRotationEnabled) ...[
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),
),
],
),
),
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,
),
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_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()),
),
],
),
),
],
],
),
);
}
}

@ -12,7 +12,8 @@ import '../models/radio_settings.dart';
import '../services/app_debug_log_service.dart';
import '../helpers/snack_bar_builder.dart';
import 'settings/settings_shell.dart';
import 'app_settings_screen.dart';
import 'settings/app_settings_view.dart';
import 'settings/message_settings_view.dart';
import 'app_debug_log_screen.dart';
import 'ble_debug_log_screen.dart';
import '../widgets/radio_stats_entry.dart';
@ -94,6 +95,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
subtitle: l10n.settings_contactSettingsSubtitle,
builder: _messagesContactsPane,
),
SettingsCategory(
icon: Icons.sms_outlined,
title: l10n.settings_messageSettings,
subtitle: l10n.settings_messageSettingsSubtitle,
builder: _messageSettingsPane,
),
SettingsCategory(
icon: Icons.info_outline,
title: l10n.settings_deviceInfo,
@ -273,12 +280,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
}
Widget _appPane(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: [_buildAppSettingsCard(context)],
);
}
Widget _appPane(BuildContext context) => const AppSettingsView();
Widget _messageSettingsPane(BuildContext context) =>
const MessageSettingsView();
Widget _actionsPane(BuildContext context) {
final connector = context.watch<MeshCoreConnector>();
@ -444,24 +449,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
}
Widget _buildAppSettingsCard(BuildContext context) {
final l10n = context.l10n;
return Card(
child: ListTile(
leading: const Icon(Icons.settings_outlined),
title: Text(l10n.settings_appSettings),
subtitle: Text(l10n.settings_appSettingsSubtitle),
trailing: const Icon(Icons.chevron_right),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AppSettingsScreen()),
);
},
),
);
}
Widget _buildActionsCard(BuildContext context, MeshCoreConnector connector) {
final l10n = context.l10n;
return Card(

@ -1 +1,86 @@
{}
{
"bg": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"de": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"es": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"fr": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"hu": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"it": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"ja": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"ko": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"nl": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"pl": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"pt": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"ru": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"sk": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"sl": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"sv": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"uk": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
],
"zh": [
"settings_messageSettings",
"settings_messageSettingsSubtitle"
]
}

Loading…
Cancel
Save

Powered by TurnKey Linux.