feat: enhance app functionality with connectivity monitoring and analytics integration#59
Merged
feat: enhance app functionality with connectivity monitoring and analytics integration#59
Conversation
…ytics integration - Added connectivity_plus and flutter_secure_storage dependencies to pubspec.yaml. - Implemented ConnectivityCubit for monitoring network status and displaying an offline banner. - Integrated analytics services for logging BLoC transitions and screen views. - Established crash reporting mechanisms to capture and log errors globally. - Introduced a developer console for debugging, featuring network and BLoC state inspection. - Added mock data for API responses and updated documentation for new features.
There was a problem hiding this comment.
Pull request overview
This PR adds connectivity monitoring, token refresh, caching/resilience mechanisms, analytics + crash reporting hooks, and an in-app developer console, plus new lifecycle/dynamic-forms features and associated tests.
Changes:
- Added connectivity-aware request handling (connectivity interceptor + offline banner) and introduced caching, token refresh, circuit breaker, and dev-console network logging.
- Integrated analytics (route + BLoC observers) and global crash reporting, plus a debug-only developer console with network/BLoC/storage/environment/time-travel tabs.
- Added lifecycle gating (maintenance/force update + feature flags) and dynamic forms rendering + routing, with expanded unit/widget test coverage.
Reviewed changes
Copilot reviewed 137 out of 142 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| test/shared/utils/icon_utils_test.dart | Adds unit coverage for string→Icon mappings. |
| test/mocks/mock_classes.dart | Adds dynamic forms BLoC mocks/fakes for tests. |
| test/infrastructure/http/interceptors/connectivity_interceptor_test.dart | Adds tests for connectivity interceptor/exception behavior. |
| test/infrastructure/config/environment_test.dart | Updates allowed paths test for token refresh endpoint. |
| test/infrastructure/cache/cache_storage_test.dart | Adds cache storage model/interface tests. |
| test/features/users/application/user_bloc_test.dart | Adds value-equality/props tests for User events. |
| test/features/lifecycle/domain/entities/app_config_entity_test.dart | Adds tests for lifecycle app config entity. |
| test/features/dynamic_forms/presentation/pages/dynamic_form_page_test.dart | Adds widget tests for dynamic form page UI states. |
| test/features/dynamic_forms/domain/entities/form_schema_entity_test.dart | Adds tests for dynamic form schema entities/enums. |
| test/features/dashboard/presentation/pages/home_screen_test.dart | Adjusts viewport to avoid overflow with new dashboard header. |
| test/features/dashboard/presentation/pages/dashboard_page_test.dart | Reworks dashboard page tests to new SystemDashboardCubit state. |
| test/features/dashboard/domain/entities/dashboard_entity_test.dart | Removes tests for deleted legacy dashboard domain entities. |
| test/features/dashboard/application/usecases/load_dashboard_usecase_test.dart | Removes tests for deleted legacy dashboard use case. |
| test/features/auth/data/models/jwt_token_test.dart | Updates JWTToken equality/hash/toString expectations for refresh token support. |
| test/features/auth/data/mappers/auth_mapper_test.dart | Configures logger in tests for new mapping behavior. |
| test/core/security/security_utils_test.dart | Activates token-expiry checks + adds getTokenExpiration tests. |
| test/core/result/result_test.dart | Adds tests for new Result implementation patterns. |
| test/core/feature_flags/feature_flag_service_test.dart | Adds unit tests for feature flag singleton/service. |
| test/core/errors/app_error_test.dart | Adds unit tests for AppError sealed hierarchy + equality/pattern matching. |
| test/core/analytics/log_analytics_service_test.dart | Adds tests for LogAnalyticsService no-throw behavior. |
| test/architecture/import_guard_test.dart | Updates cross-feature import exceptions for lifecycle usage in dashboard. |
| test/app/session/session_cubit_test.dart | Adds tests for session state transitions and restore logic. |
| test/app/router/app_router_factory_test.dart | Adjusts viewport for router widget tests. |
| test/app/di/repository_contracts_test.dart | Removes dashboard repository contract test (dashboard repo removed). |
| test/app/connectivity/connectivity_banner_test.dart | Adds widget tests for offline banner behavior/animations. |
| pubspec.yaml | Adds connectivity_plus + flutter_secure_storage; bumps app version. |
| macos/Flutter/GeneratedPluginRegistrant.swift | Registers new plugins for macOS build. |
| linux/flutter/generated_plugins.cmake | Registers flutter_secure_storage plugin for Linux build. |
| linux/flutter/generated_plugin_registrant.cc | Registers flutter_secure_storage plugin for Linux build. |
| lib/infrastructure/storage/secure_storage.dart | Introduces secure storage abstraction + FlutterSecureStorage adapter. |
| lib/infrastructure/storage/local_storage.dart | Adds refreshToken storage key. |
| lib/infrastructure/http/interceptors/token_refresh_interceptor.dart | Adds 401 token refresh flow with retry + logout callback. |
| lib/infrastructure/http/interceptors/dev_console_interceptor.dart | Adds debug-only interceptor to record requests for dev console. |
| lib/infrastructure/http/interceptors/connectivity_interceptor.dart | Adds interceptor rejecting requests immediately when offline. |
| lib/infrastructure/http/interceptors/cache_interceptor.dart | Adds caching interceptor (policies + TTL + offline fallback). |
| lib/infrastructure/http/dev_console_store.dart | Adds in-memory store for dev console network + BLoC entries. |
| lib/infrastructure/http/circuit_breaker.dart | Adds standalone circuit breaker implementation. |
| lib/infrastructure/http/api_client.dart | Expands Dio interceptor chain; adds session-expired callback. |
| lib/infrastructure/connectivity/connectivity_service.dart | Adds singleton connectivity service with optional DNS verification. |
| lib/infrastructure/config/template_config.dart | Updates prod API URL value (currently set to localhost). |
| lib/infrastructure/cache/shared_prefs_cache_storage.dart | Adds SharedPreferences-backed cache storage implementation. |
| lib/infrastructure/cache/cache_storage.dart | Adds cache policy, storage interface, and cache entry model. |
| lib/features/lifecycle/presentation/pages/maintenance_screen.dart | Adds maintenance UI. |
| lib/features/lifecycle/presentation/pages/lifecycle_gate.dart | Adds lifecycle gating wrapper for force-update/maintenance. |
| lib/features/lifecycle/presentation/pages/force_update_screen.dart | Adds force-update UI + store redirect. |
| lib/features/lifecycle/lifecycle.dart | Adds lifecycle feature barrel exports. |
| lib/features/lifecycle/domain/repositories/lifecycle_repository.dart | Adds lifecycle repository contract. |
| lib/features/lifecycle/domain/entities/app_config_entity.dart | Adds app config entity for lifecycle checks + flags. |
| lib/features/lifecycle/data/repositories/lifecycle_repository.dart | Adds repository implementation fetching /app/config. |
| lib/features/lifecycle/data/models/app_config_model.dart | Adds JSON model mapping for app config. |
| lib/features/lifecycle/application/lifecycle_state.dart | Adds lifecycle state model. |
| lib/features/lifecycle/application/lifecycle_event.dart | Adds lifecycle events. |
| lib/features/lifecycle/application/lifecycle_bloc.dart | Adds lifecycle bloc implementing checks + flags update. |
| lib/features/dynamic_forms/presentation/widgets/dynamic_form_renderer.dart | Adds JSON-driven form renderer using flutter_form_builder. |
| lib/features/dynamic_forms/presentation/pages/dynamic_form_page.dart | Adds page that loads/renders/submits dynamic forms. |
| lib/features/dynamic_forms/navigation/dynamic_forms_routes.dart | Adds GoRouter routes for dynamic forms. |
| lib/features/dynamic_forms/dynamic_forms.dart | Adds dynamic forms feature barrel exports. |
| lib/features/dynamic_forms/domain/entities/form_schema_entity.dart | Adds dynamic form schema entities + enums. |
| lib/features/dynamic_forms/data/models/form_schema_model.dart | Adds JSON parsing for dynamic form schema. |
| lib/features/dynamic_forms/application/dynamic_form_state.dart | Adds dynamic forms state. |
| lib/features/dynamic_forms/application/dynamic_form_event.dart | Adds dynamic forms events. |
| lib/features/dynamic_forms/application/dynamic_form_bloc.dart | Adds dynamic forms bloc (load + submit). |
| lib/features/dashboard/presentation/pages/dashboard_home_page.dart | Reworks home wrapper to use SystemDashboardCubit + lifecycle bridging. |
| lib/features/dashboard/domain/repositories/dashboard_repository.dart | Removes legacy dashboard repository abstraction. |
| lib/features/dashboard/domain/entities/dashboard_entity.dart | Removes legacy dashboard domain entities. |
| lib/features/dashboard/data/repositories/dashboard_mock_repository.dart | Removes legacy dashboard mock repository. |
| lib/features/dashboard/data/repositories/dashboard_api_repository.dart | Removes legacy dashboard API repository. |
| lib/features/dashboard/data/models/dashboard_model.dart | Removes legacy dashboard model mapping. |
| lib/features/dashboard/dashboard.dart | Updates dashboard exports to new page/cubit structure. |
| lib/features/dashboard/application/usecases/load_dashboard_usecase.dart | Removes legacy dashboard use case. |
| lib/features/dashboard/application/dashboard_state.dart | Replaces legacy dashboard state with SystemDashboardState model. |
| lib/features/dashboard/application/dashboard_cubit.dart | Replaces legacy cubit with SystemDashboardCubit metrics aggregator. |
| lib/features/auth/domain/entities/auth_entity.dart | Extends AuthTokenEntity to include refresh token + expiry. |
| lib/features/auth/data/models/jwt_token.dart | Extends JWTToken to include refresh_token field. |
| lib/features/auth/data/mappers/auth_mapper.dart | Maps JWT model to token entity + extracts exp into DateTime. |
| lib/features/auth/application/login_bloc.dart | Persists refresh token on login flows. |
| lib/core/security/security_utils.dart | Implements token expiry checking and adds getTokenExpiration. |
| lib/core/security/allowed_paths.dart | Adds refresh endpoint to allowed paths. |
| lib/core/feature_flags/feature_flag_service.dart | Adds singleton feature flag service based on ChangeNotifier. |
| lib/core/errors/app_api_exception.dart | Adds CircuitBreakerOpenException. |
| lib/core/analytics/log_analytics_service.dart | Adds logger-backed analytics provider. |
| lib/core/analytics/analytics_service.dart | Adds analytics interface. |
| lib/app/shell/app_shell.dart | Adds offline banner + dev console shortcut wrapper in shell layout. |
| lib/app/router/app_router.dart | Adds dynamic forms routes + supports navigator observers injection. |
| lib/app/di/app_scope.dart | Registers ConnectivityCubit + SystemDashboardCubit and new infra singletons. |
| lib/app/di/app_dependencies.dart | Removes dashboard repository creation wiring. |
| lib/app/dev_console/time_travel/time_travel_store.dart | Adds time-travel snapshot storage + rewind/export. |
| lib/app/dev_console/time_travel/time_travel_bloc_observer.dart | Adds combined observer feeding dev console + time travel. |
| lib/app/dev_console/tabs/storage_tab.dart | Adds local storage inspector tab for dev console. |
| lib/app/dev_console/tabs/network_tab.dart | Adds network inspector tab for dev console. |
| lib/app/dev_console/tabs/environment_tab.dart | Adds environment + route tree tab for dev console. |
| lib/app/dev_console/tabs/bloc_tab.dart | Adds BLoC transition inspector tab for dev console. |
| lib/app/dev_console/dev_console_overlay.dart | Adds Ctrl+Shift+D overlay panel with tabs. |
| lib/app/dev_console/dev_console_bloc_observer.dart | Adds observer for recording transitions to dev console store. |
| lib/app/dev_console/dev_console.dart | Adds dev console barrel exports. |
| lib/app/connectivity/connectivity_cubit.dart | Adds app-level connectivity cubit bridging ConnectivityService. |
| lib/app/connectivity/connectivity_banner.dart | Adds offline banner UI. |
| lib/app/bootstrap/app_bootstrap.dart | Initializes connectivity + analytics/crash reporting + debug observer. |
| lib/app/app.dart | Injects analytics into router via NavigatorObserver. |
| lib/app/analytics/crash_reporter.dart | Adds global error capture forwarding to analytics. |
| lib/app/analytics/analytics_route_observer.dart | Adds screen-view tracking observer. |
| lib/app/analytics/analytics_bloc_observer.dart | Adds BLoC transition/error analytics observer. |
| e2e/playwright.config.ts | Adds Playwright configuration for E2E runs. |
| docs/REAL_API_INFO.md | Adds local “real API” endpoint documentation. |
| assets/mock/dashboard.json | Removes legacy dashboard mock payload. |
| assets/mock/POST_authenticate_verify_otp.json | Adds refresh_token to mocked auth OTP response. |
| assets/mock/POST_authenticate.json | Adds refresh_token to mocked auth response. |
| assets/mock/POST_api_token_refresh.json | Adds mock refresh endpoint response payload. |
| assets/mock/GET_dynamic_forms_pathParams.json | Adds mock dynamic form schema payload. |
| assets/mock/GET_app_config.json | Adds mock lifecycle app config payload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
|
||
| // API | ||
| static const String prodApiUrl = '__PROD_API_URL__'; | ||
| static const String prodApiUrl = 'http://localhost:8080/api'; |
Comment on lines
76
to
85
| dio.interceptors.addAll([ | ||
| ConnectivityInterceptor(), | ||
| AuthInterceptor(), | ||
| TokenRefreshInterceptor(dio: dio, onSessionExpired: onSessionExpired), | ||
| ResilienceInterceptor(), | ||
| if (!ProfileConstants.isProduction) MockInterceptor(), | ||
| CacheInterceptor(), | ||
| DevConsoleInterceptor(), | ||
| LoggingInterceptor(), | ||
| ]); |
Comment on lines
+23
to
+25
| /// 5. [MockInterceptor] — (dev/test only) short-circuits with mock data | ||
| /// 6. [DevConsoleInterceptor] — records requests in debug console | ||
| /// 7. [LoggingInterceptor] — structured request/response logging |
Comment on lines
+95
to
+118
| Future<void> onError(DioException err, ErrorInterceptorHandler handler) async { | ||
| // On network error for GET requests with networkFirst policy: try cache fallback | ||
| if (err.requestOptions.method.toUpperCase() == 'GET') { | ||
| final policy = _extractPolicy(err.requestOptions); | ||
| if (policy == CachePolicy.networkFirst || policy == CachePolicy.cacheFirst) { | ||
| final entry = await _storage.read(_cacheKey(err.requestOptions)); | ||
| if (entry != null) { | ||
| _log.info('Serving stale cache for offline request: {}', [err.requestOptions.path]); | ||
| handler.resolve( | ||
| Response( | ||
| requestOptions: err.requestOptions, | ||
| statusCode: 200, | ||
| data: entry.data, | ||
| headers: Headers.fromMap({ | ||
| 'x-cache': ['stale'], | ||
| }), | ||
| ), | ||
| ); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| handler.next(err); | ||
| } |
Comment on lines
+159
to
+165
| InterceptorInfo(name: 'AuthInterceptor', order: 1, detail: 'Attaches JWT token to requests'), | ||
| InterceptorInfo(name: 'TokenRefreshInterceptor', order: 2, detail: 'Refreshes expired access tokens'), | ||
| InterceptorInfo(name: 'ConnectivityInterceptor', order: 3, detail: 'Rejects requests when offline'), | ||
| InterceptorInfo(name: 'ResilienceInterceptor', order: 4, detail: 'Retry + circuit breaker'), | ||
| InterceptorInfo(name: 'CacheInterceptor', order: 5, detail: 'GET response caching with TTL'), | ||
| InterceptorInfo(name: 'DevConsoleInterceptor', order: 6, detail: 'Logs requests to dev console'), | ||
| InterceptorInfo(name: 'MockInterceptor', order: 7, active: false, detail: 'Serves mock data in dev/test'), |
Comment on lines
+22
to
+24
| @override | ||
| void onRequest(RequestOptions options, RequestInterceptorHandler handler) { | ||
| final status = ConnectivityService.instance.currentStatus; |
Comment on lines
+85
to
+88
| final exp = payloadMap["exp"]; | ||
| if (exp == null) return null; | ||
|
|
||
| return DateTime.fromMillisecondsSinceEpoch((exp as int) * 1000); |
Comment on lines
+90
to
+96
| FeatureFlagService.instance.addListener(() => notifyCount++); | ||
|
|
||
| FeatureFlagService.instance.updateFlags({'a': true}); | ||
| expect(notifyCount, 1); | ||
|
|
||
| // Clean up listener | ||
| FeatureFlagService.instance.removeListener(() => notifyCount++); |
Comment on lines
+41
to
+43
| if (key == StorageKeys.jwtToken.name && value.length > 20) { | ||
| return '${value.substring(0, 10)}...[masked]...${value.substring(value.length - 10)}'; | ||
| } |
- Added type checks for expiration payload in SecurityUtils to ensure valid numeric types. - Updated token expiration handling to convert expiration to integer. - Enhanced CacheInterceptor to only fallback to cache for connectivity errors on GET requests, improving error handling logic.
This was referenced Mar 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: enhance app functionality with connectivity monitoring and analytics integration
Added connectivity_plus and flutter_secure_storage dependencies to pubspec.yaml.
Implemented ConnectivityCubit for monitoring network status and displaying an offline banner.
Integrated analytics services for logging BLoC transitions and screen views.
Established crash reporting mechanisms to capture and log errors globally.
Introduced a developer console for debugging, featuring network and BLoC state inspection.
Added mock data for API responses and updated documentation for new features.