- 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>
85 lines
4.2 KiB
Markdown
85 lines
4.2 KiB
Markdown
# 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_app` and `mitra_app` to Riverpod annotation-based providers
|
|
- Replace `flutter_bloc` with `flutter_riverpod`, `riverpod_annotation`, `flutter_hooks`, and `hooks_riverpod`
|
|
- Add `riverpod_generator` + `build_runner` as 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:
|
|
1. Replace `Bloc`/`Cubit` class with `@riverpod` annotated `Notifier` or `AsyncNotifier` (extending `_$ClassName`)
|
|
2. Replace `BlocEvent` + `emit()` pattern with notifier methods that update `state` directly
|
|
3. Run `dart run build_runner build` to generate `.g.dart` files
|
|
4. Replace `BlocProvider` with generated provider (e.g. `authProvider`)
|
|
5. Replace `BlocBuilder` widgets with `ConsumerWidget` + `ref.watch()`
|
|
6. Replace `BlocListener` with `ref.listen()` inside widget or provider
|
|
7. Use `HookConsumerWidget` where flutter_hooks are needed (e.g. `useTextEditingController`, `useEffect`)
|
|
- [ ] Run E2E verification after each migration to catch regressions
|
|
- [ ] Remove `flutter_bloc` dependency only after all Blocs are migrated
|
|
|
|
### Affected Blocs
|
|
- [ ] `client_app` — AuthBloc, PairingBloc, ChatBloc, ChatOpeningBloc, SessionClosureBloc
|
|
- [ ] `mitra_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
|