From 517e493b5e442efb2e6cc37d92178df6c2e87d6d Mon Sep 17 00:00:00 2001 From: misha Date: Wed, 24 Sep 2025 15:23:01 +0300 Subject: [PATCH] feat(pushNotifications): added anonymous token for push notifications --- lib/core/app_router.dart | 21 ++++++--- lib/core/firebase_api.dart | 16 +++++++ lib/core/locator_service.dart | 8 +++- lib/core/prefs.dart | 43 +++++++++++++++++++ lib/core/prefs_keys.dart | 1 + .../presentation/pages/welcome_screen.dart | 8 ++-- 6 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 lib/core/prefs.dart create mode 100644 lib/core/prefs_keys.dart diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index cc028255..9b94b818 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -1,6 +1,8 @@ import 'package:dio/dio.dart'; import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/firebase_api.dart'; +import 'package:eatvio_app/core/prefs.dart'; +import 'package:eatvio_app/core/prefs_keys.dart'; import 'package:eatvio_app/core/token_storage.dart'; import 'package:eatvio_app/core/websockets/ws_manager.dart'; import 'package:eatvio_app/core/locator_service.dart'; @@ -72,7 +74,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:go_router/go_router.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:version/version.dart'; import 'dart:developer'; @@ -111,6 +112,10 @@ class AppRouter { path: '/auth-screen', name: 'authScreen', builder: (context, state) => const AuthScreen(), + redirect: (context, state) async { + await sl().registerAnonymousPushToken(); + return null; + }, routes: [ GoRoute(path: 'registration-screen', name: 'registrationScreen', builder: (context, state) => const RegistrationScreen()), GoRoute( @@ -196,14 +201,20 @@ class AppRouter { builder: (context, state) => const WelcomeScreen(), redirect: (context, state) async { try { - final sharedPreferences = await SharedPreferences.getInstance(); - final welcomeScreenWasShowed = sharedPreferences.getBool('welcomeScreenWasShowed') ?? false; - await sl().registerPushToken(); - if (welcomeScreenWasShowed == false) { + final prefs = sl(); + final firebaseApi = sl(); + final welcomeScreenWasShowed = prefs.getBool(PrefsKeys.welcomeScreenWasShowed) ?? false; + await firebaseApi.registerPushToken(); + if (!welcomeScreenWasShowed) { return null; } else if (await TokenStorage.haveTokenInStorage()) { return '/feed-screen'; } else { + final hasAnonymousTokenBeenSent = prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false; + if (!hasAnonymousTokenBeenSent) { + await firebaseApi.registerAnonymousPushToken(); + prefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true); + } return '/auth-screen'; } } catch (e) { diff --git a/lib/core/firebase_api.dart b/lib/core/firebase_api.dart index 2ba89290..cd0c4d12 100644 --- a/lib/core/firebase_api.dart +++ b/lib/core/firebase_api.dart @@ -26,6 +26,22 @@ class FirebaseApi { return token; } + Future registerAnonymousPushToken() async { + try { + final deviceInfo = DeviceInfoPlugin(); + await sl().post( + '/api/anonymous_token', + data: { + 'platform': Platform.isIOS ? 'ios' : 'android', + 'hw_id': Platform.isIOS ? (await deviceInfo.iosInfo).identifierForVendor : (await deviceInfo.androidInfo).id, + 'token': await getToken(), + }, + ); + } catch (e, st) { + log(e.toString(), stackTrace: st); + } + } + Future registerPushToken() async { if (await TokenStorage.haveTokenInStorage()) { try { diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index 37713f29..4ac7e003 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -5,6 +5,7 @@ import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/dio/phone_verify_error_interceptor.dart'; import 'package:eatvio_app/core/firebase_api.dart'; import 'package:eatvio_app/core/interceptors/token_interceptor.dart'; +import 'package:eatvio_app/core/prefs.dart'; import 'package:eatvio_app/core/views/cubit/views_cubit.dart'; import 'package:eatvio_app/core/views/repository/views_repository.dart'; import 'package:eatvio_app/core/views/service/views_service.dart'; @@ -118,10 +119,14 @@ import 'package:eatvio_app/features/settings/services/settings_service.dart'; import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart'; import 'package:get_it/get_it.dart'; import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profile_plans; +import 'package:shared_preferences/shared_preferences.dart'; final sl = GetIt.instance; Future init() async { + // Prefs + sl.registerLazySingletonAsync(() async=> Prefs(await SharedPreferences.getInstance())); + // Cubit singletons sl.registerLazySingleton(() => WsManager(wsService: sl())); sl.registerLazySingleton(() => NewMessagesCubit()); @@ -216,8 +221,7 @@ Future init() async { sl.registerLazySingleton(() => CommentsRepository(service: sl())); sl.registerLazySingleton(() => NotificationSettingsRepository(sl())); sl.registerFactory(() => ConsultantRatingRepository(sl())); - sl.registerFactory(() => ViewsRepository(viewsService: sl())); - + sl.registerFactory(() => ViewsRepository(viewsService: sl())); // Services sl.registerLazySingleton(() => ChatService(sl())); sl.registerLazySingleton(() => FeedService(sl())); diff --git a/lib/core/prefs.dart b/lib/core/prefs.dart new file mode 100644 index 00000000..14ed7812 --- /dev/null +++ b/lib/core/prefs.dart @@ -0,0 +1,43 @@ +import 'package:eatvio_app/core/prefs_keys.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + + +class Prefs { + final SharedPreferences _prefs; + + Prefs(this._prefs); + + String _key(PrefsKeys key) => key.name; + + Future setString(PrefsKeys key, String value) async { + await _prefs.setString(_key(key), value); + } + + String? getString(PrefsKeys key) { + return _prefs.getString(_key(key)); + } + + Future setInt(PrefsKeys key, int value) async { + await _prefs.setInt(_key(key), value); + } + + int? getInt(PrefsKeys key) { + return _prefs.getInt(_key(key)); + } + + Future setBool(PrefsKeys key, bool value) async { + await _prefs.setBool(_key(key), value); + } + + bool? getBool(PrefsKeys key) { + return _prefs.getBool(_key(key)); + } + + Future remove(PrefsKeys key) async { + await _prefs.remove(_key(key)); + } + + Future clear() async { + await _prefs.clear(); + } +} diff --git a/lib/core/prefs_keys.dart b/lib/core/prefs_keys.dart new file mode 100644 index 00000000..0ba552d5 --- /dev/null +++ b/lib/core/prefs_keys.dart @@ -0,0 +1 @@ +enum PrefsKeys { hasAnonymousTokenBeenSent, welcomeScreenWasShowed } diff --git a/lib/features/welcome/presentation/pages/welcome_screen.dart b/lib/features/welcome/presentation/pages/welcome_screen.dart index 31b4bf0f..887e2d9e 100644 --- a/lib/features/welcome/presentation/pages/welcome_screen.dart +++ b/lib/features/welcome/presentation/pages/welcome_screen.dart @@ -1,9 +1,11 @@ +import 'package:eatvio_app/core/locator_service.dart'; +import 'package:eatvio_app/core/prefs.dart'; +import 'package:eatvio_app/core/prefs_keys.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/core/token_storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; class WelcomeScreen extends StatefulWidget { @@ -80,8 +82,8 @@ class _WelcomeScreenState extends State { const SizedBox(height: 24), InkWell( onTap: () async { - final sharedPreferences = await SharedPreferences.getInstance(); - await sharedPreferences.setBool('welcomeScreenWasShowed', true); + final sharedPreferences = sl(); + await sharedPreferences.setBool(PrefsKeys.welcomeScreenWasShowed, true); if (await TokenStorage.haveTokenInStorage()) { goRouter.go('/feed-screen'); } else {