diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 36869a1..89cf28f 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -9,7 +9,8 @@
"Bash(dart pub global run intl_utils:generate:*)",
"Bash(dart pub global deactivate:*)",
"Bash(flutter precache:*)",
- "Bash(flutter analyze:*)"
+ "Bash(flutter analyze:*)",
+ "Bash(flutter pub get:*)"
],
"deny": [],
"ask": []
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c2ae9b8..c513bc6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
dev.flutter.background.refresh
+ UIUserNotificationSettings
+
+ UIUserNotificationTypesEnabled
+
+ UIUserNotificationTypeAlert
+ UIUserNotificationTypeBadge
+ UIUserNotificationTypeSound
+
+
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index dfdb6c1..308edb5 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -1698,5 +1698,40 @@
"failed": "Failed",
"@failed": {
"description": "Delivery status: failed"
+ },
+
+ "sarMarkerFoundPerson": "Found Person",
+ "@sarMarkerFoundPerson": {
+ "description": "SAR marker type: found person"
+ },
+
+ "sarMarkerFire": "Fire Location",
+ "@sarMarkerFire": {
+ "description": "SAR marker type: fire"
+ },
+
+ "sarMarkerStagingArea": "Staging Area",
+ "@sarMarkerStagingArea": {
+ "description": "SAR marker type: staging area"
+ },
+
+ "sarMarkerObject": "Object Found",
+ "@sarMarkerObject": {
+ "description": "SAR marker type: object"
+ },
+
+ "from": "From",
+ "@from": {
+ "description": "Sender label in notifications"
+ },
+
+ "coordinates": "Coordinates",
+ "@coordinates": {
+ "description": "Coordinates label"
+ },
+
+ "tapToViewOnMap": "Tap to view on map",
+ "@tapToViewOnMap": {
+ "description": "Notification action text"
}
}
diff --git a/lib/l10n/app_hr.arb b/lib/l10n/app_hr.arb
index 6e4024a..566b01e 100644
--- a/lib/l10n/app_hr.arb
+++ b/lib/l10n/app_hr.arb
@@ -567,5 +567,19 @@
"messageDeleted": "Poruka izbrisana",
- "refreshedContacts": "Kontakti osvježeni"
+ "refreshedContacts": "Kontakti osvježeni",
+
+ "sarMarkerFoundPerson": "Pronađena osoba",
+
+ "sarMarkerFire": "Lokacija požara",
+
+ "sarMarkerStagingArea": "Zbirno mjesto",
+
+ "sarMarkerObject": "Pronađen objekt",
+
+ "from": "Od",
+
+ "coordinates": "Koordinate",
+
+ "tapToViewOnMap": "Dodirnite za prikaz na karti"
}
diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart
index 9ecdb22..39a94a2 100644
--- a/lib/l10n/app_localizations.dart
+++ b/lib/l10n/app_localizations.dart
@@ -1808,6 +1808,48 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Failed'**
String get failed;
+
+ /// SAR marker type: found person
+ ///
+ /// In en, this message translates to:
+ /// **'Found Person'**
+ String get sarMarkerFoundPerson;
+
+ /// SAR marker type: fire
+ ///
+ /// In en, this message translates to:
+ /// **'Fire Location'**
+ String get sarMarkerFire;
+
+ /// SAR marker type: staging area
+ ///
+ /// In en, this message translates to:
+ /// **'Staging Area'**
+ String get sarMarkerStagingArea;
+
+ /// SAR marker type: object
+ ///
+ /// In en, this message translates to:
+ /// **'Object Found'**
+ String get sarMarkerObject;
+
+ /// Sender label in notifications
+ ///
+ /// In en, this message translates to:
+ /// **'From'**
+ String get from;
+
+ /// Coordinates label
+ ///
+ /// In en, this message translates to:
+ /// **'Coordinates'**
+ String get coordinates;
+
+ /// Notification action text
+ ///
+ /// In en, this message translates to:
+ /// **'Tap to view on map'**
+ String get tapToViewOnMap;
}
class _AppLocalizationsDelegate
diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart
index a336d27..1b19817 100644
--- a/lib/l10n/app_localizations_en.dart
+++ b/lib/l10n/app_localizations_en.dart
@@ -988,4 +988,25 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get failed => 'Failed';
+
+ @override
+ String get sarMarkerFoundPerson => 'Found Person';
+
+ @override
+ String get sarMarkerFire => 'Fire Location';
+
+ @override
+ String get sarMarkerStagingArea => 'Staging Area';
+
+ @override
+ String get sarMarkerObject => 'Object Found';
+
+ @override
+ String get from => 'From';
+
+ @override
+ String get coordinates => 'Coordinates';
+
+ @override
+ String get tapToViewOnMap => 'Tap to view on map';
}
diff --git a/lib/l10n/app_localizations_hr.dart b/lib/l10n/app_localizations_hr.dart
index 47f310a..63c1606 100644
--- a/lib/l10n/app_localizations_hr.dart
+++ b/lib/l10n/app_localizations_hr.dart
@@ -990,4 +990,25 @@ class AppLocalizationsHr extends AppLocalizations {
@override
String get failed => 'Neuspjelo';
+
+ @override
+ String get sarMarkerFoundPerson => 'Pronađena osoba';
+
+ @override
+ String get sarMarkerFire => 'Lokacija požara';
+
+ @override
+ String get sarMarkerStagingArea => 'Zbirno mjesto';
+
+ @override
+ String get sarMarkerObject => 'Pronađen objekt';
+
+ @override
+ String get from => 'Od';
+
+ @override
+ String get coordinates => 'Koordinate';
+
+ @override
+ String get tapToViewOnMap => 'Dodirnite za prikaz na karti';
}
diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart
index c5dee63..c516629 100644
--- a/lib/l10n/app_localizations_sl.dart
+++ b/lib/l10n/app_localizations_sl.dart
@@ -990,4 +990,25 @@ class AppLocalizationsSl extends AppLocalizations {
@override
String get failed => 'Neuspešno';
+
+ @override
+ String get sarMarkerFoundPerson => 'Najdena oseba';
+
+ @override
+ String get sarMarkerFire => 'Lokacija ognja';
+
+ @override
+ String get sarMarkerStagingArea => 'Zbirališče';
+
+ @override
+ String get sarMarkerObject => 'Najden predmet';
+
+ @override
+ String get from => 'Od';
+
+ @override
+ String get coordinates => 'Koordinate';
+
+ @override
+ String get tapToViewOnMap => 'Tapnite za prikaz na zemljevidu';
}
diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb
index ea4ae9e..e43b2c3 100644
--- a/lib/l10n/app_sl.arb
+++ b/lib/l10n/app_sl.arb
@@ -567,5 +567,19 @@
"messageDeleted": "Sporočilo izbrisano",
- "refreshedContacts": "Stiki osveženi"
+ "refreshedContacts": "Stiki osveženi",
+
+ "sarMarkerFoundPerson": "Najdena oseba",
+
+ "sarMarkerFire": "Lokacija ognja",
+
+ "sarMarkerStagingArea": "Zbirališče",
+
+ "sarMarkerObject": "Najden predmet",
+
+ "from": "Od",
+
+ "coordinates": "Koordinate",
+
+ "tapToViewOnMap": "Tapnite za prikaz na zemljevidu"
}
diff --git a/lib/main.dart b/lib/main.dart
index 1c23f07..6f7cddf 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,6 +9,7 @@ import 'providers/map_provider.dart';
import 'providers/drawing_provider.dart';
import 'providers/app_provider.dart';
import 'services/tile_cache_service.dart';
+import 'services/notification_service.dart';
import 'services/locale_preferences.dart';
import 'screens/home_screen.dart';
import 'theme/app_theme.dart';
@@ -39,6 +40,8 @@ class _MeshCoreSarAppState extends State {
Future _initializeApp() async {
await _loadThemePreference();
await _loadLocalePreference();
+ // Initialize notification service
+ await NotificationService().initialize();
setState(() {
_isInitialized = true;
});
diff --git a/lib/providers/messages_provider.dart b/lib/providers/messages_provider.dart
index 855f0dc..0ff7997 100644
--- a/lib/providers/messages_provider.dart
+++ b/lib/providers/messages_provider.dart
@@ -4,14 +4,18 @@ import 'package:flutter/foundation.dart';
import '../models/message.dart';
import '../models/sar_marker.dart';
import '../services/message_storage_service.dart';
+import '../services/notification_service.dart';
import '../utils/sar_message_parser.dart';
+import '../l10n/app_localizations.dart';
/// Messages Provider - manages message history and SAR markers
class MessagesProvider with ChangeNotifier {
final List _messages = [];
final Map _sarMarkers = {};
final MessageStorageService _storageService = MessageStorageService();
+ final NotificationService _notificationService = NotificationService();
bool _isInitialized = false;
+ AppLocalizations? _localizations;
// Track pending sent messages by expected ACK/TAG
final Map _pendingSentMessages = {};
@@ -49,6 +53,11 @@ class MessagesProvider with ChangeNotifier {
bool get isInitialized => _isInitialized;
+ /// Set localizations for notifications
+ void setLocalizations(AppLocalizations localizations) {
+ _localizations = localizations;
+ }
+
/// Get count of unread messages (excluding sent messages and system messages)
int get unreadCount => _messages
.where((m) =>
@@ -146,6 +155,11 @@ class MessagesProvider with ChangeNotifier {
final marker = finalMessage.toSarMarker();
if (marker != null) {
_sarMarkers[marker.id] = marker;
+
+ // Trigger urgent notification for received SAR messages (not sent by user)
+ if (!finalMessage.isSentMessage) {
+ _triggerSarNotification(finalMessage, marker);
+ }
}
}
@@ -231,6 +245,31 @@ class MessagesProvider with ChangeNotifier {
notifyListeners();
}
+ /// Trigger urgent notification for SAR marker
+ Future _triggerSarNotification(Message message, SarMarker marker) async {
+ try {
+ // Format coordinates
+ final coords = '${marker.location.latitude.toStringAsFixed(5)}, ${marker.location.longitude.toStringAsFixed(5)}';
+
+ // Get sender name from message
+ final senderName = message.senderName ?? message.senderKeyShort ?? 'Unknown';
+
+ print('🔔 [MessagesProvider] Triggering SAR notification for ${marker.type.displayName}');
+ print(' Sender: $senderName');
+ print(' Coordinates: $coords');
+
+ await _notificationService.showSarNotification(
+ type: marker.type,
+ senderName: senderName,
+ coordinates: coords,
+ notes: marker.notes,
+ localizations: _localizations,
+ );
+ } catch (e) {
+ print('❌ [MessagesProvider] Error triggering SAR notification: $e');
+ }
+ }
+
/// Persist messages to storage (async, non-blocking)
Future _persistMessages() async {
try {
diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart
index 49533f6..94b03c3 100644
--- a/lib/screens/home_screen.dart
+++ b/lib/screens/home_screen.dart
@@ -451,6 +451,13 @@ class _HomeScreenState extends State
@override
Widget build(BuildContext context) {
+ // Set localizations for notifications
+ final messagesProvider = context.read();
+ final localizations = AppLocalizations.of(context);
+ if (localizations != null) {
+ messagesProvider.setLocalizations(localizations);
+ }
+
// Determine if we should hide the UI (only in fullscreen on map tab)
final shouldHideUI = _isMapFullscreen && _currentIndex == 2;
diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart
new file mode 100644
index 0000000..16d57d6
--- /dev/null
+++ b/lib/services/notification_service.dart
@@ -0,0 +1,353 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:timezone/timezone.dart' as tz;
+import 'package:timezone/data/latest_all.dart' as tz;
+import '../models/sar_marker.dart';
+import '../l10n/app_localizations.dart';
+
+/// Notification Service - manages urgent notifications for SAR messages
+/// Provides critical alert functionality for SAR marker events
+class NotificationService {
+ static final NotificationService _instance = NotificationService._internal();
+ factory NotificationService() => _instance;
+ NotificationService._internal();
+
+ final FlutterLocalNotificationsPlugin _notificationsPlugin =
+ FlutterLocalNotificationsPlugin();
+
+ bool _isInitialized = false;
+ bool _permissionGranted = false;
+
+ // Notification IDs
+ static const int _sarNotificationId = 1000;
+
+ // Notification channels
+ static const String _urgentChannelId = 'sar_urgent';
+ static const String _urgentChannelName = 'SAR Urgent Alerts';
+ static const String _urgentChannelDescription =
+ 'Critical alerts for SAR markers (found persons, fires, staging areas)';
+
+ /// Initialize notification service
+ Future initialize() async {
+ if (_isInitialized) return;
+
+ try {
+ print('📬 [NotificationService] Initializing...');
+
+ // Initialize timezone data
+ tz.initializeTimeZones();
+
+ // Android initialization settings
+ const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
+
+ // iOS initialization settings
+ final darwinSettings = DarwinInitializationSettings(
+ requestAlertPermission: true,
+ requestBadgePermission: true,
+ requestSoundPermission: true,
+ requestCriticalPermission: true, // For urgent SAR notifications
+ );
+
+ // Combined initialization settings
+ final initSettings = InitializationSettings(
+ android: androidSettings,
+ iOS: darwinSettings,
+ );
+
+ // Initialize plugin
+ await _notificationsPlugin.initialize(
+ initSettings,
+ onDidReceiveNotificationResponse: _onNotificationResponse,
+ );
+
+ // Request permissions
+ await _requestPermissions();
+
+ // Create notification channels (Android)
+ await _createNotificationChannels();
+
+ _isInitialized = true;
+ print('✅ [NotificationService] Initialized successfully');
+ print(' Permission granted: $_permissionGranted');
+ } catch (e) {
+ print('❌ [NotificationService] Initialization error: $e');
+ }
+ }
+
+ /// Request notification permissions
+ Future _requestPermissions() async {
+ try {
+ // iOS permissions
+ final iosPlugin = _notificationsPlugin
+ .resolvePlatformSpecificImplementation();
+ if (iosPlugin != null) {
+ final granted = await iosPlugin.requestPermissions(
+ alert: true,
+ badge: true,
+ sound: true,
+ critical: true, // Request critical alert permission for urgent SAR notifications
+ );
+ _permissionGranted = granted ?? false;
+ print('📱 [NotificationService] iOS permissions granted: $_permissionGranted');
+ }
+
+ // Android 13+ permissions
+ final androidPlugin = _notificationsPlugin
+ .resolvePlatformSpecificImplementation();
+ if (androidPlugin != null) {
+ final granted = await androidPlugin.requestNotificationsPermission();
+ _permissionGranted = granted ?? false;
+ print('🤖 [NotificationService] Android permissions granted: $_permissionGranted');
+ }
+ } catch (e) {
+ print('⚠️ [NotificationService] Error requesting permissions: $e');
+ }
+ }
+
+ /// Create notification channels for Android
+ Future _createNotificationChannels() async {
+ try {
+ final androidPlugin = _notificationsPlugin
+ .resolvePlatformSpecificImplementation();
+
+ if (androidPlugin == null) return;
+
+ // Urgent SAR channel with maximum priority
+ const urgentChannel = AndroidNotificationChannel(
+ _urgentChannelId,
+ _urgentChannelName,
+ description: _urgentChannelDescription,
+ importance: Importance.max,
+ playSound: true,
+ enableVibration: true,
+ enableLights: true,
+ showBadge: true,
+ sound: RawResourceAndroidNotificationSound('notification'),
+ );
+
+ await androidPlugin.createNotificationChannel(urgentChannel);
+ print('✅ [NotificationService] Created urgent notification channel');
+ } catch (e) {
+ print('⚠️ [NotificationService] Error creating channels: $e');
+ }
+ }
+
+ /// Handle notification tap (foreground)
+ void _onNotificationResponse(NotificationResponse response) {
+ print('🔔 [NotificationService] Notification tapped: ${response.payload}');
+ // TODO: Navigate to map tab and show SAR marker
+ // This would require a callback to the app layer
+ }
+
+ /// Show urgent notification for SAR marker
+ Future showSarNotification({
+ required SarMarkerType type,
+ required String senderName,
+ required String coordinates,
+ String? notes,
+ AppLocalizations? localizations,
+ }) async {
+ if (!_isInitialized) {
+ print('⚠️ [NotificationService] Not initialized, skipping notification');
+ return;
+ }
+
+ if (!_permissionGranted) {
+ print('⚠️ [NotificationService] Permission not granted, skipping notification');
+ return;
+ }
+
+ try {
+ // Generate unique notification ID based on timestamp
+ final notificationId = _sarNotificationId + (DateTime.now().millisecondsSinceEpoch % 1000);
+
+ // Build notification title and body
+ final title = _buildNotificationTitle(type, localizations);
+ final body = _buildNotificationBody(
+ type: type,
+ senderName: senderName,
+ coordinates: coordinates,
+ notes: notes,
+ localizations: localizations,
+ );
+
+ // Android notification details
+ final androidDetails = AndroidNotificationDetails(
+ _urgentChannelId,
+ _urgentChannelName,
+ channelDescription: _urgentChannelDescription,
+ importance: Importance.max,
+ priority: Priority.high,
+ ticker: title,
+ playSound: true,
+ enableVibration: true,
+ enableLights: true,
+ color: Color(_getNotificationColor(type)),
+ colorized: true,
+ showWhen: true,
+ when: DateTime.now().millisecondsSinceEpoch,
+ category: AndroidNotificationCategory.alarm, // High priority category
+ fullScreenIntent: true, // Show as full screen on some devices
+ styleInformation: BigTextStyleInformation(
+ body,
+ contentTitle: title,
+ summaryText: _getSummaryText(type, localizations),
+ ),
+ );
+
+ // iOS notification details
+ final darwinDetails = DarwinNotificationDetails(
+ presentAlert: true,
+ presentBadge: true,
+ presentSound: true,
+ sound: 'default',
+ badgeNumber: 1,
+ threadIdentifier: 'sar_markers',
+ categoryIdentifier: 'SAR_ALERT',
+ interruptionLevel: InterruptionLevel.critical, // Critical alert (bypasses silent mode)
+ );
+
+ // Combined notification details
+ final notificationDetails = NotificationDetails(
+ android: androidDetails,
+ iOS: darwinDetails,
+ );
+
+ // Show notification
+ await _notificationsPlugin.show(
+ notificationId,
+ title,
+ body,
+ notificationDetails,
+ payload: 'sar:${type.name}:$coordinates',
+ );
+
+ print('✅ [NotificationService] Showed SAR notification: $title');
+ print(' Type: ${type.displayName}');
+ print(' Sender: $senderName');
+ print(' Coordinates: $coordinates');
+ } catch (e) {
+ print('❌ [NotificationService] Error showing notification: $e');
+ }
+ }
+
+ /// Build notification title based on SAR marker type
+ String _buildNotificationTitle(SarMarkerType type, AppLocalizations? localizations) {
+ if (localizations == null) {
+ return '🚨 ${type.displayName} Detected';
+ }
+
+ switch (type) {
+ case SarMarkerType.foundPerson:
+ return '🚨 ${localizations.sarMarkerFoundPerson}';
+ case SarMarkerType.fire:
+ return '🚨 ${localizations.sarMarkerFire}';
+ case SarMarkerType.stagingArea:
+ return '🚨 ${localizations.sarMarkerStagingArea}';
+ case SarMarkerType.object:
+ return '🚨 ${localizations.sarMarkerObject}';
+ case SarMarkerType.unknown:
+ return '🚨 SAR Alert';
+ }
+ }
+
+ /// Build notification body with all details
+ String _buildNotificationBody({
+ required SarMarkerType type,
+ required String senderName,
+ required String coordinates,
+ String? notes,
+ AppLocalizations? localizations,
+ }) {
+ final buffer = StringBuffer();
+
+ // Sender
+ if (localizations != null) {
+ buffer.write('${localizations.from}: $senderName\n');
+ buffer.write('${localizations.coordinates}: $coordinates');
+ } else {
+ buffer.write('From: $senderName\n');
+ buffer.write('Coordinates: $coordinates');
+ }
+
+ // Optional notes
+ if (notes != null && notes.isNotEmpty) {
+ buffer.write('\n\n$notes');
+ }
+
+ return buffer.toString();
+ }
+
+ /// Get summary text for notification
+ String _getSummaryText(SarMarkerType type, AppLocalizations? localizations) {
+ if (localizations == null) {
+ return 'Tap to view on map';
+ }
+ return localizations.tapToViewOnMap;
+ }
+
+ /// Get notification color based on SAR marker type
+ int _getNotificationColor(SarMarkerType type) {
+ // Return ARGB color codes
+ switch (type) {
+ case SarMarkerType.foundPerson:
+ return 0xFF4CAF50; // Green
+ case SarMarkerType.fire:
+ return 0xFFF44336; // Red
+ case SarMarkerType.stagingArea:
+ return 0xFFFF9800; // Orange
+ case SarMarkerType.object:
+ return 0xFF2196F3; // Blue
+ case SarMarkerType.unknown:
+ return 0xFF9E9E9E; // Gray
+ }
+ }
+
+ /// Cancel all notifications
+ Future cancelAll() async {
+ try {
+ await _notificationsPlugin.cancelAll();
+ print('✅ [NotificationService] Cancelled all notifications');
+ } catch (e) {
+ print('❌ [NotificationService] Error canceling notifications: $e');
+ }
+ }
+
+ /// Cancel specific notification
+ Future cancel(int id) async {
+ try {
+ await _notificationsPlugin.cancel(id);
+ print('✅ [NotificationService] Cancelled notification: $id');
+ } catch (e) {
+ print('❌ [NotificationService] Error canceling notification: $e');
+ }
+ }
+
+ /// Check if notifications are enabled
+ Future areNotificationsEnabled() async {
+ try {
+ final androidPlugin = _notificationsPlugin
+ .resolvePlatformSpecificImplementation();
+ if (androidPlugin != null) {
+ final enabled = await androidPlugin.areNotificationsEnabled();
+ return enabled ?? false;
+ }
+
+ // For iOS, assume enabled if permission was granted
+ return _permissionGranted;
+ } catch (e) {
+ print('⚠️ [NotificationService] Error checking notification status: $e');
+ return false;
+ }
+ }
+
+ /// Get pending notifications
+ Future> getPendingNotifications() async {
+ try {
+ return await _notificationsPlugin.pendingNotificationRequests();
+ } catch (e) {
+ print('⚠️ [NotificationService] Error getting pending notifications: $e');
+ return [];
+ }
+ }
+}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 11ab6c9..dc9b76e 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -6,6 +6,7 @@ import FlutterMacOS
import Foundation
import flutter_blue_plus_darwin
+import flutter_local_notifications
import geolocator_apple
import objectbox_flutter_libs
import package_info_plus
@@ -15,6 +16,7 @@ import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterBluePlusPlugin.register(with: registry.registrar(forPlugin: "FlutterBluePlusPlugin"))
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index cf5418d..023f654 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -246,6 +246,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.0.0"
+ flutter_local_notifications:
+ dependency: "direct main"
+ description:
+ name: flutter_local_notifications
+ sha256: ef41ae901e7529e52934feba19ed82827b11baa67336829564aeab3129460610
+ url: "https://pub.dev"
+ source: hosted
+ version: "18.0.1"
+ flutter_local_notifications_linux:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_linux
+ sha256: "8f685642876742c941b29c32030f6f4f6dacd0e4eaecb3efbb187d6a3812ca01"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.0"
+ flutter_local_notifications_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_platform_interface
+ sha256: "6c5b83c86bf819cdb177a9247a3722067dd8cc6313827ce7c77a4b238a26fd52"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@@ -794,6 +818,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.6"
+ timezone:
+ dependency: transitive
+ description:
+ name: timezone
+ sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.1"
typed_data:
dependency: transitive
description: