MIF_E31222656/lib/widgets/session_guard_wrapper.dart

145 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:tugas_akhir_supabase/services/session_manager.dart';
import 'package:tugas_akhir_supabase/widgets/session_expired_dialog.dart';
/// A widget that enforces session validation for authenticated routes.
///
/// This widget should wrap any screen that requires authentication.
/// It will automatically check if the session is valid and redirect to login
/// if the session has expired.
class SessionGuardWrapper extends StatefulWidget {
final Widget child;
final bool enforceAuthentication;
const SessionGuardWrapper({
super.key,
required this.child,
this.enforceAuthentication = true,
});
@override
State<SessionGuardWrapper> createState() => _SessionGuardWrapperState();
}
class _SessionGuardWrapperState extends State<SessionGuardWrapper> {
bool _isCheckingSession = false;
bool _sessionExpired = false;
bool _showingDialog = false;
bool _hasInitialized = false;
@override
void initState() {
super.initState();
// Initialize with a delay to prevent race conditions
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && !_hasInitialized) {
_hasInitialized = true;
// Check session on widget initialization
if (widget.enforceAuthentication) {
_checkSession();
}
}
});
// Tambahkan listener untuk dismiss dialog jika user login/logout
Supabase.instance.client.auth.onAuthStateChange.listen((event) {
final currentUser = Supabase.instance.client.auth.currentUser;
if (currentUser != null) {
setState(() {
_sessionExpired = false;
_showingDialog = false;
});
// Pop dialog jika masih terbuka
if (Navigator.canPop(context)) {
Navigator.of(
context,
rootNavigator: true,
).popUntil((route) => route.isFirst);
}
}
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Check session when dependencies change (e.g., after navigation)
// But only if we haven't initialized yet or if there's a significant change
if (widget.enforceAuthentication &&
!_isCheckingSession &&
_hasInitialized) {
// Add a small delay to prevent race conditions during navigation
Future.delayed(const Duration(milliseconds: 100), () {
if (mounted) {
_checkSession();
}
});
}
}
Future<void> _checkSession() async {
// Session checking DISABLED for permissive mode
debugPrint('SessionGuard: Session checking DISABLED for permissive mode');
return;
}
void _showExpiredDialog() {
if (_showingDialog) return;
// Double check if user is actually logged in before showing dialog
final currentUser = Supabase.instance.client.auth.currentUser;
final currentSession = Supabase.instance.client.auth.currentSession;
if (currentUser == null || currentSession == null) {
debugPrint(
'SessionGuard: No user or session, not showing expired dialog',
);
_showingDialog = false;
return;
}
debugPrint(
'SessionGuard: Showing expired dialog for user: ${currentUser.id}',
);
_showingDialog = true;
// Show dialog on next frame to avoid build phase issues
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) {
_showingDialog = false;
return;
}
// Final check before showing dialog
final finalUser = Supabase.instance.client.auth.currentUser;
if (finalUser == null) {
debugPrint('SessionGuard: User logged out before showing dialog');
_showingDialog = false;
return;
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const SessionExpiredDialog(),
).then((_) {
_showingDialog = false;
});
});
}
@override
Widget build(BuildContext context) {
debugPrint('SessionGuard: build called - PERMISSIVE MODE');
// PERMISSIVE MODE - Always show the child without any restrictions
debugPrint(
'SessionGuard: Showing child widget without session restrictions',
);
return widget.child;
}
}