Added Line Of Sight Feature for repeater placement, Added app wide Units Setting (#198)

* feat: add LOS workflow, global units, l10n cleanup, and mobile UI overflow fixes

Squashes prior PR commits into one changeset including: LOS map/service/tests, global metric/imperial unit system adoption, notification/BLE safety fixes, app-wide localization backfill/mojibake cleanup, and responsive UI title/overflow hardening.

* l10n: revert unrelated locale churn for LOS feature

* feat: keep LOS with app-wide unit settings

* fix: resolve post-merge app bar/import analyzer errors

* style: format screen files for CI
This commit is contained in:
just_stuff_tm
2026-02-21 01:08:23 -05:00
committed by GitHub
parent d2b693e5ce
commit f4b18d97a1
52 changed files with 6078 additions and 214 deletions
+28
View File
@@ -1,3 +1,16 @@
enum UnitSystem { metric, imperial }
extension UnitSystemValue on UnitSystem {
String get value {
switch (this) {
case UnitSystem.imperial:
return 'imperial';
case UnitSystem.metric:
return 'metric';
}
}
}
class AppSettings {
static const Object _unset = Object();
@@ -21,6 +34,7 @@ class AppSettings {
final String? languageOverride; // null = system default
final bool appDebugLogEnabled;
final Map<String, String> batteryChemistryByDeviceId;
final UnitSystem unitSystem;
AppSettings({
this.clearPathOnMaxRetry = false,
@@ -43,6 +57,7 @@ class AppSettings {
this.languageOverride,
this.appDebugLogEnabled = false,
Map<String, String>? batteryChemistryByDeviceId,
this.unitSystem = UnitSystem.metric,
}) : batteryChemistryByDeviceId = batteryChemistryByDeviceId ?? {};
Map<String, dynamic> toJson() {
@@ -67,10 +82,18 @@ class AppSettings {
'language_override': languageOverride,
'app_debug_log_enabled': appDebugLogEnabled,
'battery_chemistry_by_device_id': batteryChemistryByDeviceId,
'unit_system': unitSystem.value,
};
}
factory AppSettings.fromJson(Map<String, dynamic> json) {
UnitSystem parseUnitSystem(dynamic value) {
if (value is String && value.toLowerCase() == 'imperial') {
return UnitSystem.imperial;
}
return UnitSystem.metric;
}
return AppSettings(
clearPathOnMaxRetry: json['clear_path_on_max_retry'] as bool? ?? false,
mapShowRepeaters: json['map_show_repeaters'] as bool? ?? true,
@@ -101,6 +124,9 @@ class AppSettings {
(key, value) => MapEntry(key.toString(), value.toString()),
) ??
{},
unitSystem: parseUnitSystem(
json['unit_system'] ?? json['los_unit_system'],
),
);
}
@@ -125,6 +151,7 @@ class AppSettings {
Object? languageOverride = _unset,
bool? appDebugLogEnabled,
Map<String, String>? batteryChemistryByDeviceId,
UnitSystem? unitSystem,
}) {
return AppSettings(
clearPathOnMaxRetry: clearPathOnMaxRetry ?? this.clearPathOnMaxRetry,
@@ -154,6 +181,7 @@ class AppSettings {
appDebugLogEnabled: appDebugLogEnabled ?? this.appDebugLogEnabled,
batteryChemistryByDeviceId:
batteryChemistryByDeviceId ?? this.batteryChemistryByDeviceId,
unitSystem: unitSystem ?? this.unitSystem,
);
}
}