diff --git a/lib/app/app.dart b/lib/app/app.dart index eed9bbe..9b83731 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -46,7 +46,13 @@ class UnionFlowApp extends StatelessWidget { ], child: Consumer2( builder: (context, locale, theme, child) { - return MaterialApp( + return BlocListener( + listenWhen: (prev, curr) => + curr is AuthAuthenticated && prev is! AuthAuthenticated, + listener: (context, _) { + context.read().add(const OrgSwitcherLoadRequested()); + }, + child: MaterialApp( title: 'UnionFlow', debugShowCheckedModeBanner: false, scaffoldMessengerKey: UnionFlowApp.scaffoldMessengerKey, @@ -79,7 +85,8 @@ class UnionFlowApp extends StatelessWidget { child: child ?? const SizedBox(), ); }, - ); + ), + ); }, ), ); diff --git a/lib/app/router/app_router.dart b/lib/app/router/app_router.dart index fd3ec98..b0be867 100644 --- a/lib/app/router/app_router.dart +++ b/lib/app/router/app_router.dart @@ -20,7 +20,7 @@ import '../../features/adhesions/presentation/pages/adhesions_page_wrapper.dart' import '../../features/settings/presentation/pages/system_settings_page.dart'; import '../../features/dashboard/presentation/pages/advanced_dashboard_page.dart'; import '../../features/admin/presentation/pages/user_management_page.dart'; -import '../../features/communication/presentation/pages/conversations_page.dart'; +import '../../features/communication/presentation/pages/conversations_page_wrapper.dart'; import '../../features/finance_workflow/presentation/pages/pending_approvals_page.dart'; import '../../features/finance_workflow/presentation/pages/budgets_list_page.dart'; import '../../core/navigation/main_navigation_layout.dart'; @@ -86,7 +86,7 @@ class AppRouter { '/reports': (context) => const ReportsPageWrapper(), '/finances': (context) => const CotisationsPageWrapper(), '/adhesions': (context) => const AdhesionsPageWrapper(), - '/messages': (context) => const ConversationsPage(), + '/messages': (context) => const ConversationsPageWrapper(), '/settings': (context) => const SystemSettingsPage(), '/analytics': (context) { final authState = context.read().state; diff --git a/lib/core/navigation/main_navigation_layout.dart b/lib/core/navigation/main_navigation_layout.dart index f8e13d8..7971fab 100644 --- a/lib/core/navigation/main_navigation_layout.dart +++ b/lib/core/navigation/main_navigation_layout.dart @@ -118,7 +118,7 @@ class _MainNavigationLayoutState extends State { statusBarIconBrightness: Brightness.dark, ), child: Scaffold( - backgroundColor: ColorTokens.background, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: SafeArea( top: true, bottom: false, @@ -199,12 +199,13 @@ class _PillNavigationBar extends StatelessWidget { @override Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; return Container( decoration: BoxDecoration( - color: ColorTokens.surface, + color: scheme.surface, boxShadow: [ BoxShadow( - color: ColorTokens.shadow, + color: scheme.shadow.withOpacity(0.12), blurRadius: 12, offset: const Offset(0, -2), ), diff --git a/lib/core/network/api_client.dart b/lib/core/network/api_client.dart index e4a5065..a379749 100644 --- a/lib/core/network/api_client.dart +++ b/lib/core/network/api_client.dart @@ -1,6 +1,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import '../../shared/design_system/tokens/app_colors.dart'; import 'package:injectable/injectable.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../../app/app.dart'; @@ -35,17 +36,7 @@ class ApiClient { ), ); - // Intercepteur de Log (Uniquement en Dev) - if (AppConfig.enableLogging) { - _dio.interceptors.add(LogInterceptor( - requestHeader: true, - requestBody: true, - responseBody: true, - logPrint: (obj) => print('🌐 [API] $obj'), - )); - } - - // Intercepteur de Token & Refresh automatique + // Intercepteur de Token & Refresh automatique (doit Γͺtre AVANT le logger) _dio.interceptors.add( InterceptorsWrapper( onRequest: (options, handler) async { @@ -112,6 +103,16 @@ class ApiClient { }, ), ); + + // Intercepteur de Log (aprΓ¨s le token pour voir le Bearer dans les logs) + if (AppConfig.enableLogging) { + _dio.interceptors.add(LogInterceptor( + requestHeader: true, + requestBody: true, + responseBody: true, + logPrint: (obj) => print('🌐 [API] $obj'), + )); + } } void _forceLogout() { @@ -132,7 +133,7 @@ class ApiClient { ), ], ), - backgroundColor: Colors.orange.shade700, + backgroundColor: AppColors.warning, duration: const Duration(seconds: 4), behavior: SnackBarBehavior.floating, ), diff --git a/lib/core/websocket/websocket_service.dart b/lib/core/websocket/websocket_service.dart index db26673..b58a431 100644 --- a/lib/core/websocket/websocket_service.dart +++ b/lib/core/websocket/websocket_service.dart @@ -77,6 +77,17 @@ abstract class WebSocketEvent { organizationId: json['organizationId'] as String?, ); + case 'NOUVEAU_MESSAGE': + case 'MESSAGE_SUPPRIME': + case 'CONVERSATION_LUE': + return ChatMessageEvent( + eventType: eventType, + timestamp: timestamp, + data: data, + conversationId: json['conversationId'] as String?, + organizationId: json['organizationId'] as String?, + ); + default: return GenericEvent( eventType: eventType, @@ -144,6 +155,19 @@ class ContributionEvent extends WebSocketEvent { }); } +class ChatMessageEvent extends WebSocketEvent { + final String? conversationId; + final String? organizationId; + + ChatMessageEvent({ + required super.eventType, + required super.timestamp, + required super.data, + this.conversationId, + this.organizationId, + }); +} + class GenericEvent extends WebSocketEvent { GenericEvent({ required super.eventType, diff --git a/pubspec.lock b/pubspec.lock index f023472..70a0840 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.4.1" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" archive: dependency: transitive description: @@ -177,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -249,6 +265,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" csv: dependency: "direct main" description: @@ -451,6 +475,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -488,6 +520,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_native_splash: + dependency: "direct dev" + description: + name: flutter_native_splash + sha256: "7062602e0dbd29141fb8eb19220b5871ca650be5197ab9c1f193a28b17537bc7" + url: "https://pub.dev" + source: hosted + version: "2.4.4" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -623,6 +663,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" http: dependency: "direct main" description: @@ -1489,6 +1537,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" + source: hosted + version: "2.3.1" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index a41a959..6a53b9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -83,12 +83,49 @@ dev_dependencies: bloc_test: ^9.1.7 integration_test: sdk: flutter + flutter_launcher_icons: ^0.13.1 + flutter_native_splash: ^2.4.1 + +# ─── GΓ©nΓ©ration des icΓ΄nes d'application (launcher) ────────────────────────── +# Source unique : assets/images/unionflow-logo.png +# RΓ©gΓ©nΓ©rer : dart run flutter_launcher_icons +flutter_launcher_icons: + android: "ic_launcher" + ios: true + remove_alpha_ios: true + image_path: "assets/images/unionflow-logo.png" + background_color_ios: "#FFFFFF" + min_sdk_android: 21 + adaptive_icon_background: "#FFFFFF" + adaptive_icon_foreground: "assets/images/unionflow-logo.png" + web: + generate: false + windows: + generate: false + macos: + generate: false + +# ─── GΓ©nΓ©ration du splash screen natif (Android + iOS) ─────────────────────── +# RΓ©gΓ©nΓ©rer : dart run flutter_native_splash:create +flutter_native_splash: + color: "#FFFFFF" + color_dark: "#0A0D1A" + image: "assets/images/unionflow-logo.png" + android_12: + image: "assets/images/unionflow-logo.png" + color: "#FFFFFF" + color_dark: "#0A0D1A" + android: true + ios: true + web: false + fullscreen: false flutter: uses-material-design: true generate: true assets: - assets/images/ + - assets/images/branding/ - assets/images/payment_methods/wave/ - assets/images/payment_methods/orange_money/ - assets/images/payment_methods/free_money/