TKK_E32221292/Aplikasi Android/lib/app/app_shell.dart

189 lines
5.2 KiB
Dart

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<AppShell> createState() => _AppShellState();
}
class _AppShellState extends State<AppShell> {
late final PageController _pageController;
AppSessionViewModel? _session;
bool _isShowingConnectionLostDialog = false;
Future<bool> _confirmExitToLogin() async {
final session = context.read<AppSessionViewModel>();
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<AppSessionViewModel>().setControlSurfaceActive(true);
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final newSession = context.read<AppSessionViewModel>();
if (_session == newSession) {
return;
}
_session?.removeListener(_handleSessionStateChanged);
_session = newSession;
_session?.addListener(_handleSessionStateChanged);
}
Future<void> _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<AppSessionViewModel>();
return PopScope<Object?>(
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),
],
),
),
);
}
}