diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index b4986bd..3818689 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -489,7 +489,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -511,7 +511,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.meshcore.sar.meshcoreSarApp.RunnerTests;
@@ -529,7 +529,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.meshcore.sar.meshcoreSarApp.RunnerTests;
@@ -545,7 +545,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.meshcore.sar.meshcoreSarApp.RunnerTests;
@@ -676,7 +676,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -699,7 +699,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 0e9a6e7..3614340 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -21,7 +21,7 @@
CFBundleSignature
????
CFBundleVersion
- 18
+ 19
LSRequiresIPhoneOS
UILaunchStoryboardName
diff --git a/ios/fastlane/report.xml b/ios/fastlane/report.xml
index 6b73287..b078525 100644
--- a/ios/fastlane/report.xml
+++ b/ios/fastlane/report.xml
@@ -5,17 +5,22 @@
-
+
-
+
-
+
+
+
+
+
+
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 6b66536..a0f10e4 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -1097,6 +1097,11 @@
"description": "Filter option for contacts"
},
+ "repeatersFilter": "Repeaters",
+ "@repeatersFilter": {
+ "description": "Filter option for repeaters"
+ },
+
"sarMarkers": "SAR Markers",
"@sarMarkers": {
"description": "SAR markers section header"
diff --git a/lib/l10n/app_hr.arb b/lib/l10n/app_hr.arb
index 8370aa8..46ea40e 100644
--- a/lib/l10n/app_hr.arb
+++ b/lib/l10n/app_hr.arb
@@ -371,6 +371,8 @@
"contactsFilter": "Kontakti",
+ "repeatersFilter": "Repetitori",
+
"sarMarkers": "SAR markeri",
"foundPerson": "Pronađena osoba",
diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart
index 80dfa47..a47db9f 100644
--- a/lib/l10n/app_localizations.dart
+++ b/lib/l10n/app_localizations.dart
@@ -1215,6 +1215,12 @@ abstract class AppLocalizations {
/// **'Contacts'**
String get contactsFilter;
+ /// Filter option for repeaters
+ ///
+ /// In en, this message translates to:
+ /// **'Repeaters'**
+ String get repeatersFilter;
+
/// SAR markers section header
///
/// In en, this message translates to:
diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart
index afc1933..7640bcb 100644
--- a/lib/l10n/app_localizations_en.dart
+++ b/lib/l10n/app_localizations_en.dart
@@ -643,6 +643,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get contactsFilter => 'Contacts';
+ @override
+ String get repeatersFilter => 'Repeaters';
+
@override
String get sarMarkers => 'SAR Markers';
diff --git a/lib/l10n/app_localizations_hr.dart b/lib/l10n/app_localizations_hr.dart
index 21ac909..ded3274 100644
--- a/lib/l10n/app_localizations_hr.dart
+++ b/lib/l10n/app_localizations_hr.dart
@@ -643,6 +643,9 @@ class AppLocalizationsHr extends AppLocalizations {
@override
String get contactsFilter => 'Kontakti';
+ @override
+ String get repeatersFilter => 'Repetitori';
+
@override
String get sarMarkers => 'SAR markeri';
diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart
index 73b103e..92f02d6 100644
--- a/lib/l10n/app_localizations_sl.dart
+++ b/lib/l10n/app_localizations_sl.dart
@@ -643,6 +643,9 @@ class AppLocalizationsSl extends AppLocalizations {
@override
String get contactsFilter => 'Stiki';
+ @override
+ String get repeatersFilter => 'Ponavljalniki';
+
@override
String get sarMarkers => 'SAR označevalci';
diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb
index f891f98..ffd185b 100644
--- a/lib/l10n/app_sl.arb
+++ b/lib/l10n/app_sl.arb
@@ -371,6 +371,8 @@
"contactsFilter": "Stiki",
+ "repeatersFilter": "Ponavljalniki",
+
"sarMarkers": "SAR označevalci",
"foundPerson": "Najdena oseba",
diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart
index 4d24918..8fab91d 100644
--- a/lib/screens/settings_screen.dart
+++ b/lib/screens/settings_screen.dart
@@ -772,6 +772,30 @@ class _SettingsScreenState extends State {
Navigator.pop(context);
},
),
+ RadioListTile(
+ title: Row(
+ children: [
+ const Text('SAR Navy Blue'),
+ const SizedBox(width: 8),
+ Container(
+ width: 16,
+ height: 16,
+ decoration: BoxDecoration(
+ color: const Color(0xFF5C9FFF),
+ shape: BoxShape.circle,
+ border: Border.all(color: Colors.black26),
+ ),
+ ),
+ ],
+ ),
+ subtitle: const Text('Professional/Operations Mode'),
+ value: AppThemeMode.sarNavyBlue,
+ groupValue: _selectedTheme,
+ onChanged: (value) {
+ _handleThemeChange(value);
+ Navigator.pop(context);
+ },
+ ),
const Divider(),
RadioListTile(
title: Text(AppLocalizations.of(context)!.autoSystem),
diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart
index 893f897..d942e93 100644
--- a/lib/theme/app_theme.dart
+++ b/lib/theme/app_theme.dart
@@ -5,6 +5,7 @@ enum AppThemeMode {
dark,
sarRed,
sarGreen,
+ sarNavyBlue,
system,
}
@@ -181,6 +182,65 @@ class AppTheme {
);
}
+ // SAR Navy Blue theme (Professional/Operations tones)
+ static ThemeData get sarNavyBlueTheme {
+ return ThemeData(
+ useMaterial3: true,
+ colorScheme: const ColorScheme.dark(
+ brightness: Brightness.dark,
+ primary: Color(0xFF5C9FFF), // Bright navy blue
+ onPrimary: Color(0xFF000000),
+ primaryContainer: Color(0xFF003366), // Dark navy
+ onPrimaryContainer: Color(0xFFBBDEFF),
+ secondary: Color(0xFF80B3FF),
+ onSecondary: Color(0xFF000000),
+ secondaryContainer: Color(0xFF002244),
+ onSecondaryContainer: Color(0xFFBBDEFF),
+ tertiary: Color(0xFF4DB8FF),
+ onTertiary: Color(0xFF000000),
+ error: Color(0xFFCF6679),
+ onError: Color(0xFF000000),
+ surface: Color(0xFF00111C), // Very dark blue-tinted
+ onSurface: Color(0xFFE3F2FD),
+ surfaceContainerHighest: Color(0xFF001A2D),
+ onSurfaceVariant: Color(0xFFBBDEFF),
+ outline: Color(0xFF5C9FFF),
+ ),
+ scaffoldBackgroundColor: const Color(0xFF00111C),
+ appBarTheme: const AppBarTheme(
+ centerTitle: true,
+ elevation: 0,
+ backgroundColor: Color(0xFF001A2D),
+ foregroundColor: Color(0xFFE3F2FD),
+ ),
+ cardTheme: CardThemeData(
+ elevation: 2,
+ color: const Color(0xFF001A2D),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ side: const BorderSide(
+ color: Color(0xFF5C9FFF),
+ width: 1,
+ ),
+ ),
+ ),
+ inputDecorationTheme: InputDecorationTheme(
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(12),
+ borderSide: const BorderSide(color: Color(0xFF5C9FFF)),
+ ),
+ filled: true,
+ fillColor: const Color(0xFF001A2D),
+ ),
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ElevatedButton.styleFrom(
+ backgroundColor: const Color(0xFF5C9FFF),
+ foregroundColor: const Color(0xFF000000),
+ ),
+ ),
+ );
+ }
+
// Get theme by mode
static ThemeData getTheme(AppThemeMode mode, Brightness systemBrightness) {
switch (mode) {
@@ -192,6 +252,8 @@ class AppTheme {
return sarRedTheme;
case AppThemeMode.sarGreen:
return sarGreenTheme;
+ case AppThemeMode.sarNavyBlue:
+ return sarNavyBlueTheme;
case AppThemeMode.system:
return systemBrightness == Brightness.dark ? darkTheme : lightTheme;
}
@@ -208,6 +270,8 @@ class AppTheme {
return 'SAR Red (Alert)';
case AppThemeMode.sarGreen:
return 'SAR Green (Safe)';
+ case AppThemeMode.sarNavyBlue:
+ return 'SAR Navy Blue (Ops)';
case AppThemeMode.system:
return 'Auto (System)';
}
diff --git a/lib/widgets/map/compass/compass_contact_list.dart b/lib/widgets/map/compass/compass_contact_list.dart
index d119412..1af2a5f 100644
--- a/lib/widgets/map/compass/compass_contact_list.dart
+++ b/lib/widgets/map/compass/compass_contact_list.dart
@@ -6,11 +6,14 @@ import '../../../models/contact.dart';
/// Contact list section for the compass dialog.
/// Shows all contacts with location sorted by distance with bearing information.
+/// Splits contacts by type: Persons/Team, Repeaters, and Rooms.
class CompassContactList extends StatelessWidget {
final List contacts;
final Position? position;
final double? heading;
final Contact? selectedContact;
+ final bool showContacts;
+ final bool showRepeaters;
final ValueChanged onContactTap;
const CompassContactList({
@@ -19,6 +22,8 @@ class CompassContactList extends StatelessWidget {
required this.position,
this.heading,
required this.selectedContact,
+ required this.showContacts,
+ required this.showRepeaters,
required this.onContactTap,
});
@@ -32,9 +37,16 @@ class CompassContactList extends StatelessWidget {
return Text(AppLocalizations.of(context)!.locationUnavailable);
}
- // Calculate bearings and distances
- final contactsWithBearing = contacts.map((contact) {
- if (contact.displayLocation == null) return null;
+ final l10n = AppLocalizations.of(context)!;
+
+ // Split contacts by type
+ final persons =