import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_application_1/app/app_session_view_model.dart'; import 'package:flutter_application_1/core/enums/activity_access_state_enum.dart'; import 'package:flutter_application_1/features/activity/activity_login_gate_page.dart'; import 'package:flutter_application_1/features/activity/activity_offline_blocked_page.dart'; import 'package:flutter_application_1/features/activity/activity_page.dart'; import 'package:flutter_application_1/features/auth/login_page.dart'; import 'package:flutter_application_1/features/device_connection/pages/connect_device_page.dart'; import 'package:flutter_application_1/features/home/home_page.dart'; import 'package:flutter_application_1/shared/dialogs/confirmation_dialog.dart'; import 'package:flutter_application_1/shared/dialogs/warning_dialog.dart'; class AppShell extends StatefulWidget { const AppShell({super.key}); @override State createState() => _AppShellState(); } class _AppShellState extends State { late final PageController _pageController; AppSessionViewModel? _session; bool _isShowingConnectionLostDialog = false; Future _confirmExitToLogin() async { final session = context.read(); await session.setBlockingDialogVisible(true); if (!mounted) { return false; } final shouldExit = await ConfirmationDialog.show( context, title: 'Keluar aplikasi?', message: 'Jika Anda keluar, koneksi ke skateboard akan diputus dan sesi saat ini akan berakhir.', confirmText: 'Keluar', cancelText: 'Batal', isDestructive: true, ); if (!mounted) { return false; } await session.setBlockingDialogVisible(false); if (!shouldExit || !mounted) { return false; } await session.disconnectAndEndSession(); if (!mounted) { return false; } Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const LoginPage()), (route) => false, ); return true; } @override void initState() { super.initState(); _pageController = PageController(initialPage: 0); WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) { return; } context.read().setControlSurfaceActive(true); }); } @override void didChangeDependencies() { super.didChangeDependencies(); final newSession = context.read(); if (_session == newSession) { return; } _session?.removeListener(_handleSessionStateChanged); _session = newSession; _session?.addListener(_handleSessionStateChanged); } Future _handleSessionStateChanged() async { final session = _session; if (!mounted || session == null || _isShowingConnectionLostDialog) { return; } if (!session.shouldShowConnectionLostDialog) { return; } _isShowingConnectionLostDialog = true; final message = session.connectionLostDialogMessage; session.consumeConnectionLostDialog(); await session.setBlockingDialogVisible(true); if (!mounted) { _isShowingConnectionLostDialog = false; return; } await WarningDialog.show( context, title: 'Koneksi terputus', message: message, buttonText: 'Ke Connect Device', ); if (!mounted) { _isShowingConnectionLostDialog = false; return; } await session.setBlockingDialogVisible(false); if (!mounted) { _isShowingConnectionLostDialog = false; return; } Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const ConnectDevicePage()), (route) => false, ); _isShowingConnectionLostDialog = false; } @override void dispose() { _session?.removeListener(_handleSessionStateChanged); _session?.setControlSurfaceActive(false); _pageController.dispose(); super.dispose(); } Widget _buildActivityArea(ActivityAccessState state) { switch (state) { case ActivityAccessState.unauthenticated: return const ActivityLoginGatePage(); case ActivityAccessState.offlineBlocked: return const ActivityOfflineBlockedPage(); case ActivityAccessState.ready: return const ActivityPage(); } } @override Widget build(BuildContext context) { final session = context.watch(); return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) async { if (didPop) return; final currentPage = _pageController.hasClients ? (_pageController.page ?? 0).round() : 0; if (currentPage != 0) { await _pageController.animateToPage( 0, duration: const Duration(milliseconds: 220), curve: Curves.easeOut, ); return; } await _confirmExitToLogin(); }, child: Scaffold( body: PageView( controller: _pageController, children: [ HomePage(onExitRequested: _confirmExitToLogin), _buildActivityArea(session.activityAccessState), ], ), ), ); } }