diff --git a/analysis_options.yaml b/analysis_options.yaml
index 1d331a6..a69a437 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -14,6 +14,7 @@ analyzer:
invalid_annotation_target: ignore
use_build_context_synchronously: ignore
deprecated_member_use: ignore
+ depend_on_referenced_packages: ignore
exclude:
- test/generated/**
- "**/**.g.dart"
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index fd02140..a9884f6 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -6,7 +6,7 @@ plugins {
}
android {
- namespace = "com.apskel.apskel_owner"
+ namespace = "com.apskel.enaklo_owner"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
@@ -21,7 +21,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId = "com.apskel.apskel_owner"
+ applicationId = "com.apskel.enaklo_owner"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
diff --git a/android/app/google-services.json b/android/app/google-services.json
new file mode 100644
index 0000000..4ba90e6
--- /dev/null
+++ b/android/app/google-services.json
@@ -0,0 +1,48 @@
+{
+ "project_info": {
+ "project_number": "765730035527",
+ "project_id": "apskel-pos-v2",
+ "storage_bucket": "apskel-pos-v2.firebasestorage.app"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:765730035527:android:beffb797b781e715241e62",
+ "android_client_info": {
+ "package_name": "com.apskel.enaklo_owner"
+ }
+ },
+ "oauth_client": [],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAOZwVSQwUeeM9BjcyTOK9GUh8AmTWucuc"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": []
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:765730035527:android:498defd7071336dd241e62",
+ "android_client_info": {
+ "package_name": "com.apskel.pos"
+ }
+ },
+ "oauth_client": [],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAOZwVSQwUeeM9BjcyTOK9GUh8AmTWucuc"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": []
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0a0b209..7a2c596 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -5,9 +5,11 @@
+
+
+
+
+
+
+
+
+ UIBackgroundModes
+
+ fetch
+ remote-notification
+
diff --git a/lib/common/di/di_firebase.dart b/lib/common/di/di_firebase.dart
new file mode 100644
index 0000000..8ab3f0d
--- /dev/null
+++ b/lib/common/di/di_firebase.dart
@@ -0,0 +1,8 @@
+import 'package:firebase_core/firebase_core.dart';
+import 'package:injectable/injectable.dart';
+
+@module
+abstract class FirebaseDi {
+ @preResolve
+ Future get firebaseApp => Firebase.initializeApp();
+}
diff --git a/lib/common/utils/fcm_service.dart b/lib/common/utils/fcm_service.dart
new file mode 100644
index 0000000..2a1a17e
--- /dev/null
+++ b/lib/common/utils/fcm_service.dart
@@ -0,0 +1,150 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:firebase_messaging/firebase_messaging.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:injectable/injectable.dart';
+
+/// Background message handler — must be a top-level function.
+@pragma('vm:entry-point')
+Future firebaseMessagingBackgroundHandler(RemoteMessage message) async {
+ debugPrint('[FCM] Background message: ${message.messageId}');
+}
+
+@lazySingleton
+class FcmService {
+ final FirebaseMessaging _messaging = FirebaseMessaging.instance;
+
+ final FlutterLocalNotificationsPlugin _localNotifications =
+ FlutterLocalNotificationsPlugin();
+
+ static const _androidChannel = AndroidNotificationChannel(
+ 'high_importance_channel',
+ 'High Importance Notifications',
+ description: 'This channel is used for important notifications.',
+ importance: Importance.high,
+ );
+
+ /// Call this once during app startup (after Firebase.initializeApp).
+ Future initialize({
+ void Function(RemoteMessage message)? onMessageTap,
+ }) async {
+ // 1. Request permission (iOS + Android 13+)
+ await _requestPermission();
+
+ // 2. Setup local notifications (needed to show heads-up on Android)
+ await _setupLocalNotifications();
+
+ // 3. Register background handler
+ FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
+
+ // 4. Foreground message handler
+ FirebaseMessaging.onMessage.listen((message) {
+ debugPrint('[FCM] Foreground message: ${message.messageId}');
+ _showLocalNotification(message);
+ });
+
+ // 5. App opened from notification (background → foreground)
+ FirebaseMessaging.onMessageOpenedApp.listen((message) {
+ debugPrint('[FCM] Notification tapped (background): ${message.messageId}');
+ onMessageTap?.call(message);
+ });
+
+ // 6. App launched from terminated state via notification
+ final initialMessage = await _messaging.getInitialMessage();
+ if (initialMessage != null) {
+ debugPrint('[FCM] App launched from notification: ${initialMessage.messageId}');
+ onMessageTap?.call(initialMessage);
+ }
+
+ // 7. Print FCM token for debugging
+ final token = await getToken();
+ debugPrint('[FCM] Token: $token');
+ }
+
+ Future _requestPermission() async {
+ final settings = await _messaging.requestPermission(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+ debugPrint('[FCM] Permission status: ${settings.authorizationStatus}');
+ }
+
+ Future _setupLocalNotifications() async {
+ // Android init
+ const androidInit = AndroidInitializationSettings('@mipmap/launcher_icon');
+
+ // iOS init
+ const iosInit = DarwinInitializationSettings(
+ requestAlertPermission: false,
+ requestBadgePermission: false,
+ requestSoundPermission: false,
+ );
+
+ const initSettings = InitializationSettings(
+ android: androidInit,
+ iOS: iosInit,
+ );
+
+ await _localNotifications.initialize(
+ initSettings,
+ onDidReceiveNotificationResponse: (details) {
+ debugPrint('[FCM] Local notification tapped: ${details.payload}');
+ },
+ );
+
+ // Create Android notification channel
+ if (Platform.isAndroid) {
+ await _localNotifications
+ .resolvePlatformSpecificImplementation<
+ AndroidFlutterLocalNotificationsPlugin>()
+ ?.createNotificationChannel(_androidChannel);
+ }
+
+ // iOS: show notification even when app is in foreground
+ await _messaging.setForegroundNotificationPresentationOptions(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+ }
+
+ void _showLocalNotification(RemoteMessage message) {
+ final notification = message.notification;
+ if (notification == null) return;
+
+ _localNotifications.show(
+ notification.hashCode,
+ notification.title,
+ notification.body,
+ NotificationDetails(
+ android: AndroidNotificationDetails(
+ _androidChannel.id,
+ _androidChannel.name,
+ channelDescription: _androidChannel.description,
+ icon: '@mipmap/launcher_icon',
+ importance: Importance.high,
+ priority: Priority.high,
+ ),
+ iOS: const DarwinNotificationDetails(),
+ ),
+ payload: jsonEncode(message.data),
+ );
+ }
+
+ /// Returns the FCM registration token for this device.
+ Future getToken() => _messaging.getToken();
+
+ /// Subscribe to a topic (e.g. 'all', 'promo').
+ Future subscribeToTopic(String topic) =>
+ _messaging.subscribeToTopic(topic);
+
+ /// Unsubscribe from a topic.
+ Future unsubscribeFromTopic(String topic) =>
+ _messaging.unsubscribeFromTopic(topic);
+
+ /// Listen for token refresh.
+ Stream get onTokenRefresh => _messaging.onTokenRefresh;
+}
diff --git a/lib/injection.config.dart b/lib/injection.config.dart
index 046ae07..40b1d03 100644
--- a/lib/injection.config.dart
+++ b/lib/injection.config.dart
@@ -53,11 +53,13 @@ import 'package:apskel_owner_flutter/common/api/api_client.dart' as _i115;
import 'package:apskel_owner_flutter/common/di/di_auto_route.dart' as _i311;
import 'package:apskel_owner_flutter/common/di/di_connectivity.dart' as _i586;
import 'package:apskel_owner_flutter/common/di/di_dio.dart' as _i103;
+import 'package:apskel_owner_flutter/common/di/di_firebase.dart' as _i73;
import 'package:apskel_owner_flutter/common/di/di_package_info.dart' as _i227;
import 'package:apskel_owner_flutter/common/di/di_shared_preferences.dart'
as _i402;
import 'package:apskel_owner_flutter/common/network/network_client.dart'
as _i543;
+import 'package:apskel_owner_flutter/common/utils/fcm_service.dart' as _i179;
import 'package:apskel_owner_flutter/domain/analytic/repositories/i_analytic_repository.dart'
as _i477;
import 'package:apskel_owner_flutter/domain/auth/auth.dart' as _i49;
@@ -106,6 +108,7 @@ import 'package:apskel_owner_flutter/presentation/router/app_router.dart'
as _i258;
import 'package:connectivity_plus/connectivity_plus.dart' as _i895;
import 'package:dio/dio.dart' as _i361;
+import 'package:firebase_core/firebase_core.dart' as _i982;
import 'package:get_it/get_it.dart' as _i174;
import 'package:injectable/injectable.dart' as _i526;
import 'package:package_info_plus/package_info_plus.dart' as _i655;
@@ -121,22 +124,28 @@ extension GetItInjectableX on _i174.GetIt {
_i526.EnvironmentFilter? environmentFilter,
}) async {
final gh = _i526.GetItHelper(this, environment, environmentFilter);
+ final firebaseDi = _$FirebaseDi();
final sharedPreferencesDi = _$SharedPreferencesDi();
- final dioDi = _$DioDi();
final autoRouteDi = _$AutoRouteDi();
final connectivityDi = _$ConnectivityDi();
+ final dioDi = _$DioDi();
final packageInfoDi = _$PackageInfoDi();
+ await gh.factoryAsync<_i982.FirebaseApp>(
+ () => firebaseDi.firebaseApp,
+ preResolve: true,
+ );
await gh.factoryAsync<_i460.SharedPreferences>(
() => sharedPreferencesDi.prefs,
preResolve: true,
);
- gh.lazySingleton<_i361.Dio>(() => dioDi.dio);
gh.lazySingleton<_i258.AppRouter>(() => autoRouteDi.appRouter);
gh.lazySingleton<_i895.Connectivity>(() => connectivityDi.connectivity);
+ gh.lazySingleton<_i361.Dio>(() => dioDi.dio);
await gh.lazySingletonAsync<_i655.PackageInfo>(
() => packageInfoDi.packageInfo,
preResolve: true,
);
+ gh.lazySingleton<_i179.FcmService>(() => _i179.FcmService());
gh.lazySingleton<_i543.NetworkClient>(
() => _i543.NetworkClient(gh<_i895.Connectivity>()),
);
@@ -151,29 +160,29 @@ extension GetItInjectableX on _i174.GetIt {
() => _i115.ApiClient(gh<_i361.Dio>(), gh<_i6.Env>()),
);
gh.factory<_i6.Env>(() => _i6.ProdEnv(), registerFor: {_prod});
- gh.factory<_i130.OrderRemoteDataProvider>(
- () => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()),
- );
- gh.factory<_i333.CategoryRemoteDataProvider>(
- () => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()),
+ gh.factory<_i866.AnalyticRemoteDataProvider>(
+ () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i17.AuthRemoteDataProvider>(
() => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()),
);
- gh.factory<_i785.UserRemoteDataProvider>(
- () => _i785.UserRemoteDataProvider(gh<_i115.ApiClient>()),
+ gh.factory<_i333.CategoryRemoteDataProvider>(
+ () => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()),
);
- gh.factory<_i823.ProductRemoteDataProvider>(
- () => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()),
+ gh.factory<_i1006.CustomerRemoteDataProvider>(
+ () => _i1006.CustomerRemoteDataProvider(gh<_i115.ApiClient>()),
+ );
+ gh.factory<_i130.OrderRemoteDataProvider>(
+ () => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i27.OutletRemoteDataProvider>(
() => _i27.OutletRemoteDataProvider(gh<_i115.ApiClient>()),
);
- gh.factory<_i866.AnalyticRemoteDataProvider>(
- () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()),
+ gh.factory<_i823.ProductRemoteDataProvider>(
+ () => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()),
);
- gh.factory<_i1006.CustomerRemoteDataProvider>(
- () => _i1006.CustomerRemoteDataProvider(gh<_i115.ApiClient>()),
+ gh.factory<_i785.UserRemoteDataProvider>(
+ () => _i785.UserRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i48.ICustomerRepository>(
() => _i550.CustomerRepository(gh<_i1006.CustomerRemoteDataProvider>()),
@@ -220,17 +229,20 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i183.CategoryLoaderBloc>(
() => _i183.CategoryLoaderBloc(gh<_i1020.ICategoryRepository>()),
);
- gh.factory<_i473.HomeBloc>(
- () => _i473.HomeBloc(gh<_i477.IAnalyticRepository>()),
- );
gh.factory<_i889.SalesLoaderBloc>(
() => _i889.SalesLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
+ gh.factory<_i473.HomeBloc>(
+ () => _i473.HomeBloc(gh<_i477.IAnalyticRepository>()),
+ );
gh.factory<_i337.CurrentOutletLoaderBloc>(
() => _i337.CurrentOutletLoaderBloc(gh<_i197.IOutletRepository>()),
);
- gh.factory<_i221.ProductAnalyticLoaderBloc>(
- () => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
+ gh.factory<_i1038.CategoryAnalyticLoaderBloc>(
+ () => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
+ );
+ gh.factory<_i516.DashboardAnalyticLoaderBloc>(
+ () => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i785.InventoryAnalyticLoaderBloc>(
() => _i785.InventoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
@@ -240,41 +252,38 @@ extension GetItInjectableX on _i174.GetIt {
gh<_i477.IAnalyticRepository>(),
),
);
- gh.factory<_i1038.CategoryAnalyticLoaderBloc>(
- () => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
+ gh.factory<_i221.ProductAnalyticLoaderBloc>(
+ () => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i11.ProfitLossLoaderBloc>(
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
- gh.factory<_i516.DashboardAnalyticLoaderBloc>(
- () => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
+ gh.factory<_i945.AuthBloc>(
+ () => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
);
gh.factory<_i775.LoginFormBloc>(
() => _i775.LoginFormBloc(gh<_i49.IAuthRepository>()),
);
- gh.factory<_i945.AuthBloc>(
- () => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
- );
gh.factory<_i574.LogoutFormBloc>(
() => _i574.LogoutFormBloc(gh<_i49.IAuthRepository>()),
);
gh.factory<_i1058.OrderLoaderBloc>(
() => _i1058.OrderLoaderBloc(gh<_i219.IOrderRepository>()),
);
- gh.factory<_i147.UserEditFormBloc>(
- () => _i147.UserEditFormBloc(gh<_i635.IUserRepository>()),
- );
gh.factory<_i1030.ChangePasswordFormBloc>(
() => _i1030.ChangePasswordFormBloc(gh<_i635.IUserRepository>()),
);
- gh.factory<_i605.TransactionReportBloc>(
- () => _i605.TransactionReportBloc(
+ gh.factory<_i147.UserEditFormBloc>(
+ () => _i147.UserEditFormBloc(gh<_i635.IUserRepository>()),
+ );
+ gh.factory<_i346.InventoryReportBloc>(
+ () => _i346.InventoryReportBloc(
gh<_i477.IAnalyticRepository>(),
gh<_i197.IOutletRepository>(),
),
);
- gh.factory<_i346.InventoryReportBloc>(
- () => _i346.InventoryReportBloc(
+ gh.factory<_i605.TransactionReportBloc>(
+ () => _i605.TransactionReportBloc(
gh<_i477.IAnalyticRepository>(),
gh<_i197.IOutletRepository>(),
),
@@ -283,12 +292,14 @@ extension GetItInjectableX on _i174.GetIt {
}
}
-class _$SharedPreferencesDi extends _i402.SharedPreferencesDi {}
+class _$FirebaseDi extends _i73.FirebaseDi {}
-class _$DioDi extends _i103.DioDi {}
+class _$SharedPreferencesDi extends _i402.SharedPreferencesDi {}
class _$AutoRouteDi extends _i311.AutoRouteDi {}
class _$ConnectivityDi extends _i586.ConnectivityDi {}
+class _$DioDi extends _i103.DioDi {}
+
class _$PackageInfoDi extends _i227.PackageInfoDi {}
diff --git a/lib/main.dart b/lib/main.dart
index 826ecd4..c9b2e97 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:injectable/injectable.dart';
+import 'common/utils/fcm_service.dart';
import 'injection.dart';
import 'presentation/app_widget.dart';
@@ -24,5 +25,13 @@ void main() async {
kReleaseMode ? Environment.prod : Environment.dev,
);
+ // Initialize FCM after dependencies are ready
+ await getIt().initialize(
+ onMessageTap: (message) {
+ // TODO: handle navigation when notification is tapped
+ debugPrint('[FCM] Navigate based on: ${message.data}');
+ },
+ );
+
runApp(const AppWidget());
}
diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt
index 3779ef0..5643091 100644
--- a/linux/CMakeLists.txt
+++ b/linux/CMakeLists.txt
@@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "apskel_owner_flutter")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
-set(APPLICATION_ID "com.apskel.apskel_owner")
+set(APPLICATION_ID "com.apskel.enaklo_owner")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 00f5060..476a6ba 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -8,6 +8,9 @@ import Foundation
import connectivity_plus
import device_info_plus
import file_selector_macos
+import firebase_core
+import firebase_messaging
+import flutter_local_notifications
import open_file_mac
import package_info_plus
import path_provider_foundation
@@ -19,6 +22,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
+ FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
+ FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index daee97a..7a22179 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "85.0.0"
+ _flutterfire_internals:
+ dependency: transitive
+ description:
+ name: _flutterfire_internals
+ sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.59"
analyzer:
dependency: transitive
description:
@@ -205,10 +213,10 @@ packages:
dependency: transitive
description:
name: characters
- sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
+ sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
- version: "1.4.0"
+ version: "1.4.1"
checked_yaml:
dependency: transitive
description:
@@ -449,6 +457,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.3+4"
+ firebase_core:
+ dependency: "direct main"
+ description:
+ name: firebase_core
+ sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.15.2"
+ firebase_core_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_core_platform_interface
+ sha256: "0ecda14c1bfc9ed8cac303dd0f8d04a320811b479362a9a4efb14fd331a473ce"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.3"
+ firebase_core_web:
+ dependency: transitive
+ description:
+ name: firebase_core_web
+ sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.24.1"
+ firebase_messaging:
+ dependency: "direct main"
+ description:
+ name: firebase_messaging
+ sha256: "60be38574f8b5658e2f22b7e311ff2064bea835c248424a383783464e8e02fcc"
+ url: "https://pub.dev"
+ source: hosted
+ version: "15.2.10"
+ firebase_messaging_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_messaging_platform_interface
+ sha256: "685e1771b3d1f9c8502771ccc9f91485b376ffe16d553533f335b9183ea99754"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.10"
+ firebase_messaging_web:
+ dependency: transitive
+ description:
+ name: firebase_messaging_web
+ sha256: "0d1be17bc89ed3ff5001789c92df678b2e963a51b6fa2bdb467532cc9dbed390"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.10.10"
fixnum:
dependency: transitive
description:
@@ -518,6 +574,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.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
@@ -777,26 +857,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
- sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
+ sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
- version: "10.0.9"
+ version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
- sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
- version: "3.0.9"
+ version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
- sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
line_icons:
dependency: "direct main"
description:
@@ -833,26 +913,26 @@ packages:
dependency: transitive
description:
name: matcher
- sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
+ sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
- version: "0.12.17"
+ version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
- version: "0.11.1"
+ version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
- sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
+ sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
- version: "1.16.0"
+ version: "1.17.0"
mime:
dependency: transitive
description:
@@ -1422,10 +1502,10 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
+ sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
- version: "0.7.4"
+ version: "0.7.10"
time:
dependency: transitive
description:
@@ -1434,6 +1514,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.5"
+ timezone:
+ dependency: transitive
+ description:
+ name: timezone
+ sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.1"
timing:
dependency: transitive
description:
@@ -1550,10 +1638,10 @@ packages:
dependency: transitive
description:
name: vector_math
- sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
- version: "2.1.4"
+ version: "2.2.0"
vm_service:
dependency: transitive
description:
@@ -1635,5 +1723,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
- dart: ">=3.8.1 <4.0.0"
+ dart: ">=3.9.0-0 <4.0.0"
flutter: ">=3.29.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 3bf55bd..ad8712e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -48,6 +48,9 @@ dependencies:
pdf: ^3.11.3
open_file: ^3.5.10
permission_handler: ^12.0.1
+ firebase_core: ^3.13.1
+ firebase_messaging: ^15.2.5
+ flutter_local_notifications: ^18.0.1
dev_dependencies:
flutter_test:
diff --git a/web/favicon.png b/web/favicon.png
index 91b113e..c477ce0 100644
Binary files a/web/favicon.png and b/web/favicon.png differ
diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png
index 483f22e..ac5b619 100644
Binary files a/web/icons/Icon-192.png and b/web/icons/Icon-192.png differ
diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png
index 3d0d42e..d1e12cc 100644
Binary files a/web/icons/Icon-512.png and b/web/icons/Icon-512.png differ
diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png
index 483f22e..ac5b619 100644
Binary files a/web/icons/Icon-maskable-192.png and b/web/icons/Icon-maskable-192.png differ
diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png
index 3d0d42e..d1e12cc 100644
Binary files a/web/icons/Icon-maskable-512.png and b/web/icons/Icon-maskable-512.png differ
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index dbf8289..281ed4c 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -8,6 +8,7 @@
#include
#include
+#include
#include
#include
@@ -16,6 +17,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
+ FirebaseCorePluginCApiRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index c22844a..11c0100 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -5,6 +5,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus
file_selector_windows
+ firebase_core
permission_handler_windows
url_launcher_windows
)
diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico
index eba7b0f..53ae5ae 100644
Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ