- Add phase3.1 requirement and implementation plan docs - Add Riverpod dependencies to both client_app and mitra_app - Wrap both app roots with ProviderScope - Migrate client_app AuthBloc → AuthNotifier (@riverpod annotation) - Migrate client_app ChatOpeningBloc → chatPricingProvider (FutureProvider) - Update router to use Riverpod-based auth state for redirects - Update all auth screens (display name, register, OTP, force register) - Update home screen and pricing bottom sheet - Add android:usesCleartextTraffic for dev HTTP access on both apps - mitra_app prepared with ProviderScope + ApiClient provider (blocs next) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.2 KiB
4.2 KiB
PRD: Phase 3 Stabilization & State Management Migration
Overview
Goal: Stabilize Phase 3 (Chat Engine) through end-to-end testing and migrate Flutter state management from BLoC to Riverpod + flutter_hooks
Success looks like: All Phase 3 features are verified working end-to-end across client_app, mitra_app, and control_center. Both Flutter apps use Riverpod as their sole state management solution.
Background
- Phase 3 (Chat Engine) is fully scaffolded but has not been end-to-end tested
- Current Flutter apps use BLoC pattern; Riverpod is preferred for maintainability and reduced boilerplate
- Migration should happen before Phase 4 to avoid compounding tech debt
FCM fallback for Chat Engine
Mitra Pairing
- Add configuration on Control center to configure Mitra's app require to ping or not.
- When Control Center allow non ping, application or backend will not force mitra to ping and allow them to keep online even when the app is closed or in backround
- Modify Mitra Pairing confirmation to send notification through FCM when websocket to Mitra is closed
Bi-Directional Chat (WebSocket + FCM)
Mitra App
- When there is new unread message, mitra app must shows badge on active session
- When there is new unread message, mitra app must shows badge on the chat active session inside active session page
- Unread badge on each active session will be cleared when the message has been read
- Unread badge on active session button on main page will be cleared when the message has been read
Customer App
- When there is new unread message, Customer app must shows badge on active session
- Unread badge will be cleared when unread message has been cleared
Chat Closure & Extension
- When chat closure called, backend will send closure signal to both Mitra and Customer
- Backend will use FCM if the websocket connection is down
Control Center
- Control center shows configuration for ping from mitra
Riverpod Migration
Scope
- Migrate all BLoC classes in
client_appandmitra_appto Riverpod annotation-based providers - Replace
flutter_blocwithflutter_riverpod,riverpod_annotation,flutter_hooks, andhooks_riverpod - Add
riverpod_generator+build_runneras dev dependencies for code generation - No backend or control_center changes
Migration Strategy
- Add Riverpod dependencies (
flutter_riverpod,hooks_riverpod,riverpod_annotation) and dev dependencies (riverpod_generator,build_runner,custom_lint,riverpod_lint) - Wrap app root with
ProviderScope - Migrate one Bloc at a time, starting with the simplest (e.g. AuthBloc)
- For each migrated Bloc:
- Replace
Bloc/Cubitclass with@riverpodannotatedNotifierorAsyncNotifier(extending_$ClassName) - Replace
BlocEvent+emit()pattern with notifier methods that updatestatedirectly - Run
dart run build_runner buildto generate.g.dartfiles - Replace
BlocProviderwith generated provider (e.g.authProvider) - Replace
BlocBuilderwidgets withConsumerWidget+ref.watch() - Replace
BlocListenerwithref.listen()inside widget or provider - Use
HookConsumerWidgetwhere flutter_hooks are needed (e.g.useTextEditingController,useEffect)
- Replace
- Run E2E verification after each migration to catch regressions
- Remove
flutter_blocdependency only after all Blocs are migrated
Affected Blocs
client_app— AuthBloc, PairingBloc, ChatBloc, ChatOpeningBloc, SessionClosureBlocmitra_app— AuthBloc, OnlineStatusBloc, MitraChatBloc, ExtensionBloc
Non-Functional Requirement
- WebSocket reconnects gracefully after network interruption (within 5s on stable network)
- Use FCM to send command or message when websocket is down
- No message loss during brief disconnects — undelivered messages sync on reconnect
- Chat screen maintains scroll position and input draft on app lifecycle events (background/foreground)
- Riverpod migration introduces zero new UI bugs — feature parity with BLoC implementation
Tech Stack
- State management: Riverpod + flutter_hooks (replacing flutter_bloc)
- No backend changes expected — migration is Flutter-only