mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-14 22:55:12 +10:00
Refactor: move Contact UI labels to l10n extension; rename raw getter to typeLabelRaw
This commit is contained in:
@@ -3997,7 +3997,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
);
|
||||
} else {
|
||||
appLogger.info(
|
||||
"Discovered contact ${contact.name} (type ${contact.typeLabel}) not added due to auto-add settings",
|
||||
"Discovered contact ${contact.name} (type ${contact.typeLabelRaw}) not added due to auto-add settings",
|
||||
tag: 'Connector',
|
||||
);
|
||||
return;
|
||||
@@ -4019,7 +4019,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
if (settings.notificationsEnabled && settings.notifyOnNewAdvert) {
|
||||
_notificationService.showAdvertNotification(
|
||||
contactName: contact.name,
|
||||
contactType: contact.typeLabel,
|
||||
contactType: contact.typeLabelRaw,
|
||||
contactId: contact.publicKeyHex,
|
||||
);
|
||||
}
|
||||
@@ -4094,7 +4094,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
if (settings.notificationsEnabled && settings.notifyOnNewAdvert) {
|
||||
_notificationService.showAdvertNotification(
|
||||
contactName: contact.name,
|
||||
contactType: contact.typeLabel,
|
||||
contactType: contact.typeLabelRaw,
|
||||
contactId: contact.publicKeyHex,
|
||||
);
|
||||
}
|
||||
@@ -6025,7 +6025,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
if (settings.notificationsEnabled && settings.notifyOnNewAdvert) {
|
||||
_notificationService.showAdvertNotification(
|
||||
contactName: contact.name,
|
||||
contactType: contact.typeLabel,
|
||||
contactType: contact.typeLabelRaw,
|
||||
contactId: contact.publicKeyHex,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
import '../models/contact.dart';
|
||||
import 'app_localizations.dart';
|
||||
|
||||
/// UI-level localization helpers for [Contact].
|
||||
///
|
||||
/// Kept out of the model layer so `Contact` does not depend on
|
||||
/// `AppLocalizations`. Use these from widgets/screens; for logs and
|
||||
/// non-UI export use `Contact.typeLabelRaw`.
|
||||
extension ContactLocalization on Contact {
|
||||
String typeLabel(AppLocalizations l10n) {
|
||||
switch (type) {
|
||||
case advTypeChat:
|
||||
return l10n.contact_typeChat;
|
||||
case advTypeRepeater:
|
||||
return l10n.contact_typeRepeater;
|
||||
case advTypeRoom:
|
||||
return l10n.contact_typeRoom;
|
||||
case advTypeSensor:
|
||||
return l10n.contact_typeSensor;
|
||||
default:
|
||||
return l10n.contact_typeUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
String pathLabel(AppLocalizations l10n) {
|
||||
if (pathOverride != null) {
|
||||
if (pathOverride! < 0) return l10n.chat_floodForced;
|
||||
if (pathOverride == 0) return l10n.chat_directForced;
|
||||
return l10n.chat_hopsForced(pathOverride!);
|
||||
}
|
||||
if (pathLength < 0) return l10n.channelPath_floodPath;
|
||||
if (pathLength == 0) return l10n.chat_direct;
|
||||
return l10n.chat_hopsCount(pathLength);
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,9 @@ void main() async {
|
||||
final notificationService = NotificationService();
|
||||
await notificationService.initialize();
|
||||
await backgroundService.initialize();
|
||||
backgroundService.setLanguageOverrideProvider(
|
||||
() => appSettingsService.settings.languageOverride,
|
||||
);
|
||||
_registerThirdPartyLicenses();
|
||||
|
||||
await chatTextScaleService.initialize();
|
||||
|
||||
+4
-28
@@ -2,7 +2,6 @@ import 'dart:typed_data';
|
||||
import 'package:meshcore_open/utils/app_logger.dart';
|
||||
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
||||
class Contact {
|
||||
final Uint8List publicKey;
|
||||
@@ -42,7 +41,10 @@ class Contact {
|
||||
|
||||
String get publicKeyHex => pubKeyToHex(publicKey);
|
||||
|
||||
String get typeLabel {
|
||||
/// Non-localized type label, intended for logs and non-UI exports
|
||||
/// (e.g. GPX). For UI use the `typeLabel(l10n)` extension in
|
||||
/// `lib/l10n/contact_localization.dart`.
|
||||
String get typeLabelRaw {
|
||||
switch (type) {
|
||||
case advTypeChat:
|
||||
return 'Chat';
|
||||
@@ -57,32 +59,6 @@ class Contact {
|
||||
}
|
||||
}
|
||||
|
||||
String typeLabelLocalized(AppLocalizations l10n) {
|
||||
switch (type) {
|
||||
case advTypeChat:
|
||||
return l10n.contact_typeChat;
|
||||
case advTypeRepeater:
|
||||
return l10n.contact_typeRepeater;
|
||||
case advTypeRoom:
|
||||
return l10n.contact_typeRoom;
|
||||
case advTypeSensor:
|
||||
return l10n.contact_typeSensor;
|
||||
default:
|
||||
return l10n.contact_typeUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
String pathLabel(AppLocalizations l10n) {
|
||||
if (pathOverride != null) {
|
||||
if (pathOverride! < 0) return l10n.chat_floodForced;
|
||||
if (pathOverride == 0) return l10n.chat_directForced;
|
||||
return l10n.chat_hopsForced(pathOverride!);
|
||||
}
|
||||
if (pathLength < 0) return l10n.channelPath_floodPath;
|
||||
if (pathLength == 0) return l10n.chat_direct;
|
||||
return l10n.chat_hopsCount(pathLength);
|
||||
}
|
||||
|
||||
bool get hasLocation {
|
||||
const double epsilon = 1e-6;
|
||||
final lat = latitude ?? 0.0;
|
||||
|
||||
@@ -20,6 +20,7 @@ import '../helpers/gif_helper.dart';
|
||||
import '../helpers/path_helper.dart';
|
||||
import '../models/channel_message.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../models/message.dart';
|
||||
import '../models/path_history.dart';
|
||||
import '../models/translation_support.dart';
|
||||
@@ -1168,7 +1169,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoRow(context.l10n.chat_type, contact.typeLabelLocalized(context.l10n)),
|
||||
_buildInfoRow(context.l10n.chat_type, contact.typeLabel(context.l10n)),
|
||||
_buildInfoRow(context.l10n.chat_path, contact.pathLabel(context.l10n)),
|
||||
_buildInfoRow(
|
||||
context.l10n.contact_lastSeen,
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../connector/meshcore_connector.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../models/contact_group.dart';
|
||||
import '../services/ui_view_state_service.dart';
|
||||
import '../utils/contact_search.dart';
|
||||
@@ -1123,7 +1124,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
value: isSelected,
|
||||
title: Text(contact.name),
|
||||
subtitle: Text(
|
||||
contact.typeLabelLocalized(context.l10n),
|
||||
contact.typeLabel(context.l10n),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setDialogState(() {
|
||||
|
||||
@@ -16,6 +16,7 @@ import '../connector/meshcore_protocol.dart';
|
||||
import '../models/app_settings.dart';
|
||||
import '../models/channel.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../services/app_settings_service.dart';
|
||||
import '../services/path_history_service.dart';
|
||||
import '../services/map_marker_service.dart';
|
||||
@@ -1425,7 +1426,7 @@ class _MapScreenState extends State<MapScreen> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoRow(context.l10n.map_type, contact.typeLabelLocalized(context.l10n)),
|
||||
_buildInfoRow(context.l10n.map_type, contact.typeLabel(context.l10n)),
|
||||
_buildInfoRow(context.l10n.map_path, contact.pathLabel(context.l10n)),
|
||||
if (contact.hasLocation)
|
||||
_buildInfoRow(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../services/app_settings_service.dart';
|
||||
import 'repeater_status_screen.dart';
|
||||
import 'repeater_cli_screen.dart';
|
||||
|
||||
@@ -6,6 +6,14 @@ import '../utils/platform_info.dart';
|
||||
|
||||
class BackgroundService {
|
||||
bool _initialized = false;
|
||||
String? Function()? _languageOverrideProvider;
|
||||
|
||||
/// Allows the app to expose its current language override (e.g. from
|
||||
/// AppSettingsService) so the foreground notification matches the app UI
|
||||
/// language instead of only the system locale.
|
||||
void setLanguageOverrideProvider(String? Function()? provider) {
|
||||
_languageOverrideProvider = provider;
|
||||
}
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (!PlatformInfo.isAndroid || _initialized) return;
|
||||
@@ -47,6 +55,10 @@ class BackgroundService {
|
||||
|
||||
Future<AppLocalizations> _loadLocalizations() async {
|
||||
final supported = AppLocalizations.supportedLocales;
|
||||
final override = _languageOverrideProvider?.call();
|
||||
if (override != null && override.isNotEmpty) {
|
||||
return AppLocalizations.delegate.load(Locale(override));
|
||||
}
|
||||
final system =
|
||||
WidgetsBinding.instance.platformDispatcher.locale;
|
||||
final match = basicLocaleListResolution(
|
||||
|
||||
@@ -72,7 +72,7 @@ class GpxExport {
|
||||
contact.name,
|
||||
contact.latitude!,
|
||||
contact.longitude!,
|
||||
"Type: ${contact.typeLabel}\nPublic Key: ${contact.publicKeyHex}",
|
||||
"Type: ${contact.typeLabelRaw}\nPublic Key: ${contact.publicKeyHex}",
|
||||
url,
|
||||
);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ class GpxExport {
|
||||
contact.name,
|
||||
contact.latitude!,
|
||||
contact.longitude!,
|
||||
"Type: ${contact.typeLabel}\nPublic Key: ${contact.publicKeyHex}",
|
||||
"Type: ${contact.typeLabelRaw}\nPublic Key: ${contact.publicKeyHex}",
|
||||
url,
|
||||
);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class GpxExport {
|
||||
contact.name,
|
||||
contact.latitude ?? 0.0,
|
||||
contact.longitude ?? 0.0,
|
||||
"Type: ${contact.typeLabel}\nPublic Key: ${contact.publicKeyHex}",
|
||||
"Type: ${contact.typeLabelRaw}\nPublic Key: ${contact.publicKeyHex}",
|
||||
url,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:provider/provider.dart';
|
||||
import '../connector/meshcore_connector.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../helpers/path_helper.dart';
|
||||
import '../services/path_history_service.dart';
|
||||
import '../helpers/snack_bar_builder.dart';
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../helpers/snack_bar_builder.dart';
|
||||
|
||||
class PathSelectionDialog extends StatefulWidget {
|
||||
@@ -311,7 +312,7 @@ class _PathSelectionDialogState extends State<PathSelectionDialog> {
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
subtitle: Text(
|
||||
'${contact.typeLabelLocalized(l10n)} • ${contact.publicKeyHex.substring(0, 2)}',
|
||||
'${contact.typeLabel(l10n)} • ${contact.publicKeyHex.substring(0, 2)}',
|
||||
style: const TextStyle(fontSize: 10),
|
||||
),
|
||||
trailing: isSelected
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../services/storage_service.dart';
|
||||
import '../connector/meshcore_connector.dart';
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../l10n/contact_localization.dart';
|
||||
import '../services/storage_service.dart';
|
||||
import '../connector/meshcore_connector.dart';
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
|
||||
Reference in New Issue
Block a user