Phase 3.1: Complete mitra_app Riverpod migration (all blocs, fix auth bug)
- Migrate AuthBloc → MitraAuthNotifier (fixes stuck-loading bug: now returns MitraAuthInitialData when currentUser is null) - Migrate StatusBloc → OnlineStatusNotifier (heartbeat timer + lifecycle) - Migrate ExtensionBloc → MitraExtensionNotifier (accept/reject + goodbye) - Migrate ChatRequestBloc → ChatRequestNotifier (WebSocket incoming requests) - Migrate MitraChatBloc → MitraChatNotifier (WebSocket chat + messages) - Update router to use Riverpod auth state for redirects - Remove all flutter_bloc usage from mitra_app screens and main.dart - MultiBlocProvider fully removed from mitra_app Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'core/auth/auth_bloc.dart';
|
||||
import 'core/auth/auth_notifier.dart';
|
||||
import 'features/splash/splash_screen.dart';
|
||||
import 'features/auth/screens/login_screen.dart';
|
||||
import 'features/auth/screens/otp_screen.dart';
|
||||
@@ -11,34 +11,40 @@ import 'features/chat/screens/mitra_chat_screen.dart';
|
||||
import 'features/chat/screens/chat_history_screen.dart';
|
||||
import 'features/chat/screens/chat_transcript_screen.dart';
|
||||
|
||||
class _BlocRefreshNotifier extends ChangeNotifier {
|
||||
late final StreamSubscription _subscription;
|
||||
class RouterNotifier extends ChangeNotifier {
|
||||
final Ref _ref;
|
||||
|
||||
_BlocRefreshNotifier(AuthBloc bloc) {
|
||||
_subscription = bloc.stream.listen((_) => notifyListeners());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
RouterNotifier(this._ref) {
|
||||
_ref.listen(mitraAuthProvider, (_, __) => notifyListeners());
|
||||
}
|
||||
}
|
||||
|
||||
GoRouter buildRouter(AuthBloc authBloc) {
|
||||
final routerProvider = Provider<GoRouter>((ref) => buildRouter(ref));
|
||||
|
||||
GoRouter buildRouter(Ref ref) {
|
||||
final notifier = RouterNotifier(ref);
|
||||
|
||||
return GoRouter(
|
||||
initialLocation: '/splash',
|
||||
refreshListenable: _BlocRefreshNotifier(authBloc),
|
||||
refreshListenable: notifier,
|
||||
redirect: (context, state) {
|
||||
final authState = authBloc.state;
|
||||
final authState = ref.read(mitraAuthProvider);
|
||||
final isSplash = state.matchedLocation == '/splash';
|
||||
final isAuthRoute = state.matchedLocation.startsWith('/login') ||
|
||||
state.matchedLocation.startsWith('/otp');
|
||||
|
||||
// Show splash while loading
|
||||
if (authState is AuthLoading) return isSplash ? null : '/splash';
|
||||
if (authState is AsyncLoading) return isSplash ? null : '/splash';
|
||||
|
||||
if (authState is AuthAuthenticated) {
|
||||
final data = authState.valueOrNull;
|
||||
if (data == null) {
|
||||
// Error state — show login
|
||||
if (!isAuthRoute && !isSplash) return '/login';
|
||||
if (isSplash) return '/login';
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data is MitraAuthAuthenticatedData) {
|
||||
return (isSplash || isAuthRoute) ? '/home' : null;
|
||||
}
|
||||
if (!isAuthRoute && !isSplash) return '/login';
|
||||
|
||||
Reference in New Issue
Block a user