517 lines
28 KiB
Dart
517 lines
28 KiB
Dart
// lib/main.dart
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'dart:async'; // Import Timer
|
|
|
|
import 'package:provider/single_child_widget.dart';
|
|
import 'package:environment_monitoring_app/services/api_service.dart';
|
|
import 'package:environment_monitoring_app/services/database_helper.dart';
|
|
|
|
import 'package:environment_monitoring_app/services/local_storage_service.dart';
|
|
import 'package:environment_monitoring_app/services/river_in_situ_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/river_manual_triennial_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/river_investigative_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/air_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/telegram_service.dart';
|
|
import 'package:environment_monitoring_app/services/server_config_service.dart';
|
|
import 'package:environment_monitoring_app/services/retry_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_in_situ_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_investigative_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_npe_report_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_tarball_sampling_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_manual_pre_departure_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_manual_sonde_calibration_service.dart';
|
|
import 'package:environment_monitoring_app/services/marine_manual_equipment_maintenance_service.dart';
|
|
|
|
import 'package:environment_monitoring_app/theme.dart';
|
|
import 'package:environment_monitoring_app/auth_provider.dart';
|
|
|
|
// Core Screens
|
|
import 'package:environment_monitoring_app/screens/login.dart';
|
|
import 'package:environment_monitoring_app/screens/register.dart';
|
|
import 'package:environment_monitoring_app/screens/forgot_password.dart';
|
|
import 'package:environment_monitoring_app/screens/logout.dart';
|
|
import 'package:environment_monitoring_app/home_page.dart';
|
|
import 'package:environment_monitoring_app/screens/profile.dart';
|
|
import 'package:environment_monitoring_app/screens/settings.dart';
|
|
|
|
// Settings Screen Imports
|
|
import 'package:environment_monitoring_app/screens/settings/submission_preferences_settings.dart';
|
|
import 'package:environment_monitoring_app/screens/settings/telegram_alert_settings.dart';
|
|
import 'package:environment_monitoring_app/screens/settings/api_ftp_configurations_settings.dart';
|
|
import 'package:environment_monitoring_app/screens/settings/parameter_limits_settings.dart';
|
|
import 'package:environment_monitoring_app/screens/settings/air_clients_settings.dart';
|
|
import 'package:environment_monitoring_app/screens/settings/station_info_settings.dart';
|
|
|
|
// Department Home Pages
|
|
import 'package:environment_monitoring_app/screens/air/air_home_page.dart';
|
|
import 'package:environment_monitoring_app/screens/river/river_home_page.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/marine_home_page.dart';
|
|
|
|
// Air Screens
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_installation_screen.dart';
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_collection_screen.dart';
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_report.dart' as airManualReport;
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_data_status_log.dart' as airManualDataStatusLog;
|
|
import 'package:environment_monitoring_app/screens/air/manual/air_manual_image_request.dart' as airManualImageRequest;
|
|
import 'package:environment_monitoring_app/screens/air/continuous/air_continuous_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/air/continuous/overview.dart' as airContinuousOverview;
|
|
import 'package:environment_monitoring_app/screens/air/continuous/entry.dart' as airContinuousEntry;
|
|
import 'package:environment_monitoring_app/screens/air/continuous/report.dart' as airContinuousReport;
|
|
import 'package:environment_monitoring_app/screens/air/investigative/air_investigative_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/air/investigative/overview.dart' as airInvestigativeOverview;
|
|
import 'package:environment_monitoring_app/screens/air/investigative/entry.dart' as airInvestigativeEntry;
|
|
import 'package:environment_monitoring_app/screens/air/investigative/report.dart' as airInvestigativeReport;
|
|
|
|
// River Screens
|
|
import 'package:environment_monitoring_app/screens/river/manual/river_manual_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/river/manual/in_situ_sampling.dart' as riverManualInSituSampling;
|
|
import 'package:environment_monitoring_app/screens/river/manual/river_manual_data_status_log.dart' as riverManualDataStatusLog;
|
|
import 'package:environment_monitoring_app/screens/river/manual/river_manual_report.dart' as riverManualReport;
|
|
import 'package:environment_monitoring_app/screens/river/manual/triennial/river_manual_triennial_sampling.dart' as riverManualTriennialSampling;
|
|
import 'package:environment_monitoring_app/screens/river/manual/river_manual_image_request.dart' as riverManualImageRequest;
|
|
import 'package:environment_monitoring_app/screens/river/continuous/river_continuous_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/river/continuous/overview.dart' as riverContinuousOverview;
|
|
import 'package:environment_monitoring_app/screens/river/continuous/entry.dart' as riverContinuousEntry;
|
|
import 'package:environment_monitoring_app/screens/river/continuous/report.dart' as riverContinuousReport;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/river_investigative_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/river/investigative/river_investigative_manual_sampling.dart' as riverInvestigativeManualSampling;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/river_investigative_data_status_log.dart' as riverInvestigativeDataStatusLog;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/river_investigative_image_request.dart' as riverInvestigativeImageRequest;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/overview.dart' as riverInvestigativeOverview;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/entry.dart' as riverInvestigativeEntry;
|
|
import 'package:environment_monitoring_app/screens/river/investigative/report.dart' as riverInvestigativeReport;
|
|
|
|
// Marine Screens
|
|
import 'package:environment_monitoring_app/screens/marine/manual/info_centre_document.dart' as marineManualInfoCentreDocument;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_pre_sampling.dart' as marineManualPreSampling;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/in_situ_sampling.dart' as marineManualInSituSampling;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_report.dart' as marineManualReport;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_npe_report_hub.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_pre_departure_checklist_screen.dart' as marineManualPreDepartureChecklist;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_sonde_calibration_screen.dart' as marineManualSondeCalibration;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/reports/marine_manual_equipment_maintenance_screen.dart' as marineManualEquipmentMaintenance;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_data_status_log.dart' as marineManualDataStatusLog;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/marine_manual_report_status_log.dart' as marineManualReportStatusLog;
|
|
import 'package:environment_monitoring_app/screens/marine/manual/marine_image_request.dart' as marineManualImageRequest;
|
|
import 'package:environment_monitoring_app/screens/marine/continuous/marine_continuous_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/continuous/overview.dart' as marineContinuousOverview;
|
|
import 'package:environment_monitoring_app/screens/marine/continuous/entry.dart' as marineContinuousEntry;
|
|
import 'package:environment_monitoring_app/screens/marine/continuous/report.dart' as marineContinuousReport;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/marine_investigative_info_centre_document.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/marine_investigative_manual_sampling.dart' as marineInvestigativeManualSampling;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/marine_investigative_data_status_log.dart' as marineInvestigativeDataStatusLog;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/marine_investigative_image_request.dart' as marineInvestigativeImageRequest;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/overview.dart' as marineInvestigativeOverview;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/entry.dart' as marineInvestigativeEntry;
|
|
import 'package:environment_monitoring_app/screens/marine/investigative/report.dart' as marineInvestigativeReport;
|
|
|
|
import 'package:environment_monitoring_app/models/tarball_data.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step1.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step2.dart';
|
|
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step3_summary.dart';
|
|
|
|
void main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Create singleton instances of core services before running the app
|
|
final DatabaseHelper databaseHelper = DatabaseHelper();
|
|
final TelegramService telegramService = TelegramService();
|
|
final ApiService apiService = ApiService(telegramService: telegramService);
|
|
final RetryService retryService = RetryService();
|
|
|
|
// Sampling Services
|
|
final MarineInSituSamplingService marineInSituService = MarineInSituSamplingService(telegramService);
|
|
final RiverInSituSamplingService riverInSituService = RiverInSituSamplingService(telegramService);
|
|
final MarineInvestigativeSamplingService marineInvestigativeService = MarineInvestigativeSamplingService(telegramService);
|
|
final RiverInvestigativeSamplingService riverInvestigativeService = RiverInvestigativeSamplingService(telegramService);
|
|
final MarineTarballSamplingService marineTarballService = MarineTarballSamplingService(telegramService);
|
|
|
|
// --- START: Instantiate Marine Report Services ---
|
|
final MarineNpeReportService marineNpeService = MarineNpeReportService(telegramService);
|
|
// FIX: Added telegramService to constructors below
|
|
final MarineManualPreDepartureService marinePreDepartureService = MarineManualPreDepartureService(apiService, telegramService);
|
|
final MarineManualSondeCalibrationService marineSondeCalibrationService = MarineManualSondeCalibrationService(apiService, telegramService);
|
|
final MarineManualEquipmentMaintenanceService marineEquipmentMaintenanceService = MarineManualEquipmentMaintenanceService(apiService, telegramService);
|
|
// --- END: Instantiate Marine Report Services ---
|
|
|
|
telegramService.setApiService(apiService);
|
|
|
|
// The AuthProvider needs to be created here so it can be passed to the retry service.
|
|
final authProvider = AuthProvider(
|
|
apiService: apiService,
|
|
dbHelper: databaseHelper,
|
|
serverConfigService: ServerConfigService(),
|
|
retryService: retryService,
|
|
);
|
|
|
|
// Initialize the retry service with all its dependencies.
|
|
retryService.initialize(
|
|
marineInSituService: marineInSituService,
|
|
riverInSituService: riverInSituService,
|
|
marineInvestigativeService: marineInvestigativeService,
|
|
riverInvestigativeService: riverInvestigativeService,
|
|
marineTarballService: marineTarballService,
|
|
|
|
// --- START: Pass the new services to initialize ---
|
|
marineNpeService: marineNpeService,
|
|
marinePreDepartureService: marinePreDepartureService,
|
|
marineSondeCalibrationService: marineSondeCalibrationService,
|
|
marineEquipmentMaintenanceService: marineEquipmentMaintenanceService,
|
|
// --- END: Pass the new services ---
|
|
|
|
authProvider: authProvider,
|
|
);
|
|
|
|
setupPeriodicServices(telegramService, retryService);
|
|
|
|
runApp(
|
|
MultiProvider(
|
|
providers: <SingleChildWidget>[
|
|
ChangeNotifierProvider.value(value: authProvider),
|
|
Provider<ApiService>(create: (_) => apiService),
|
|
Provider<DatabaseHelper>(create: (_) => databaseHelper),
|
|
Provider<TelegramService>(create: (_) => telegramService),
|
|
Provider(create: (_) => LocalStorageService()),
|
|
Provider.value(value: retryService),
|
|
|
|
// Sampling Services
|
|
Provider.value(value: marineInSituService),
|
|
Provider.value(value: marineInvestigativeService),
|
|
Provider.value(value: riverInSituService),
|
|
Provider.value(value: riverInvestigativeService),
|
|
Provider.value(value: marineTarballService),
|
|
|
|
// Report Services (Use Provider.value since they are already instantiated)
|
|
Provider.value(value: marineNpeService),
|
|
Provider.value(value: marinePreDepartureService),
|
|
Provider.value(value: marineSondeCalibrationService),
|
|
Provider.value(value: marineEquipmentMaintenanceService),
|
|
|
|
// Other Independent Services
|
|
Provider(create: (context) => RiverManualTriennialSamplingService(telegramService)),
|
|
Provider(create: (context) => AirSamplingService(databaseHelper, telegramService)),
|
|
],
|
|
child: const RootApp(),
|
|
),
|
|
);
|
|
}
|
|
|
|
void setupPeriodicServices(TelegramService telegramService, RetryService retryService) {
|
|
// Initial processing on startup (delayed)
|
|
Future.delayed(const Duration(seconds: 5), () {
|
|
debugPrint("[Main] Performing initial alert queue processing on app start.");
|
|
telegramService.processAlertQueue();
|
|
debugPrint("[Main] Performing initial retry queue processing on app start.");
|
|
retryService.processRetryQueue();
|
|
});
|
|
|
|
// Start recurring timers to process both queues every 5 minutes.
|
|
Timer.periodic(const Duration(minutes: 5), (timer) {
|
|
debugPrint("[Main] Periodic check: Processing Telegram alert queue...");
|
|
telegramService.processAlertQueue();
|
|
debugPrint("[Main] Periodic check: Processing main retry queue...");
|
|
retryService.processRetryQueue();
|
|
});
|
|
}
|
|
|
|
class RootApp extends StatefulWidget {
|
|
const RootApp({super.key});
|
|
|
|
@override
|
|
State<RootApp> createState() => _RootAppState();
|
|
}
|
|
|
|
class _RootAppState extends State<RootApp> {
|
|
Timer? _configSyncTimer;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_initializeConnectivityListener();
|
|
_performInitialSessionCheck();
|
|
_initializePeriodicSync();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_configSyncTimer?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
void _performInitialSessionCheck() async {
|
|
await Future.delayed(const Duration(milliseconds: 100));
|
|
if (mounted) {
|
|
final authProvider = Provider.of<AuthProvider>(context, listen: false);
|
|
await authProvider.proactiveTokenRefresh();
|
|
final didTransition = await authProvider.checkAndTransitionToOnlineSession();
|
|
if (!didTransition) {
|
|
authProvider.validateAndRefreshSession();
|
|
}
|
|
}
|
|
}
|
|
|
|
void _initializeConnectivityListener() {
|
|
Connectivity().onConnectivityChanged.listen((List<ConnectivityResult> results) {
|
|
if (!results.contains(ConnectivityResult.none)) {
|
|
debugPrint("[Main] Internet connection detected.");
|
|
if (mounted) {
|
|
final authProvider = Provider.of<AuthProvider>(context, listen: false);
|
|
final telegramService = Provider.of<TelegramService>(context, listen: false);
|
|
final retryService = Provider.of<RetryService>(context, listen: false);
|
|
|
|
authProvider.checkAndTransitionToOnlineSession().then((didTransition) {
|
|
if (!didTransition) {
|
|
authProvider.validateAndRefreshSession();
|
|
}
|
|
});
|
|
|
|
telegramService.processAlertQueue();
|
|
retryService.processRetryQueue();
|
|
}
|
|
} else {
|
|
debugPrint("[Main] Internet connection lost.");
|
|
}
|
|
});
|
|
}
|
|
|
|
void _initializePeriodicSync() {
|
|
_configSyncTimer = Timer.periodic(const Duration(hours: 1), (timer) {
|
|
debugPrint("[Main] Periodic 1-hour sync triggered.");
|
|
if (mounted) {
|
|
final authProvider = context.read<AuthProvider>();
|
|
if (authProvider.isLoggedIn && !authProvider.isSessionExpired) {
|
|
debugPrint("[Main] User is logged in. Starting periodic data sync...");
|
|
authProvider.syncAllData().catchError((e) {
|
|
debugPrint("[Main] Error during periodic 1-hour sync: $e");
|
|
});
|
|
} else {
|
|
debugPrint("[Main] Skipping periodic sync: User not logged in or session expired.");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Consumer<AuthProvider>(
|
|
builder: (context, auth, child) {
|
|
Widget homeWidget;
|
|
if (auth.isLoading) {
|
|
homeWidget = const SplashScreen();
|
|
} else if (auth.isLoggedIn) {
|
|
homeWidget = const SessionAwareWrapper(child: HomePage());
|
|
} else {
|
|
homeWidget = const LoginScreen();
|
|
}
|
|
|
|
return MaterialApp(
|
|
title: 'Environment Monitoring App',
|
|
theme: AppTheme.darkBlueTheme,
|
|
debugShowCheckedModeBanner: false,
|
|
home: homeWidget,
|
|
onGenerateRoute: (settings) {
|
|
if (settings.name == '/marine/manual/tarball/step2') {
|
|
final args = settings.arguments as TarballSamplingData;
|
|
return MaterialPageRoute(builder: (context) {
|
|
return TarballSamplingStep2(data: args);
|
|
});
|
|
}
|
|
if (settings.name == '/marine/manual/tarball/step3') {
|
|
final args = settings.arguments as TarballSamplingData;
|
|
return MaterialPageRoute(builder: (context) {
|
|
return TarballSamplingStep3Summary(data: args);
|
|
});
|
|
}
|
|
if (settings.name == '/marine/manual/data-log') {
|
|
return MaterialPageRoute(builder: (context) {
|
|
return const marineManualDataStatusLog.MarineManualDataStatusLog();
|
|
});
|
|
}
|
|
return null;
|
|
},
|
|
routes: {
|
|
'/register': (context) => const RegisterScreen(),
|
|
'/forgot-password': (context) => ForgotPasswordScreen(),
|
|
'/logout': (context) => const LogoutScreen(),
|
|
'/home': (context) => const HomePage(),
|
|
'/profile': (context) => const ProfileScreen(),
|
|
'/settings': (context) => const SettingsScreen(),
|
|
'/settings/submission-prefs': (context) => SubmissionPreferencesSettingsScreen(),
|
|
'/settings/telegram-alerts': (context) => TelegramAlertSettingsScreen(),
|
|
'/settings/api-ftp-configs': (context) => ApiFtpConfigurationsSettingsScreen(),
|
|
'/settings/parameter-limits': (context) => ParameterLimitsSettingsScreen(),
|
|
'/settings/air-clients': (context) => AirClientsSettingsScreen(),
|
|
'/settings/station-info': (context) => StationInfoSettingsScreen(),
|
|
'/air/home': (context) => const AirHomePage(),
|
|
'/river/home': (context) => const RiverHomePage(),
|
|
'/marine/home': (context) => const MarineHomePage(),
|
|
'/air/manual/info': (context) => const AirManualInfoCentreDocument(),
|
|
'/air/manual/installation': (context) => const AirManualInstallationScreen(),
|
|
'/air/manual/collection': (context) => const AirManualCollectionScreen(),
|
|
'/air/manual/report': (context) => airManualReport.AirManualReport(),
|
|
'/air/manual/data-log': (context) => airManualDataStatusLog.AirManualDataStatusLog(),
|
|
'/air/manual/image-request': (context) => airManualImageRequest.AirManualImageRequest(),
|
|
'/air/continuous/info': (context) => const AirContinuousInfoCentreDocument(),
|
|
'/air/continuous/overview': (context) => airContinuousOverview.OverviewScreen(),
|
|
'/air/continuous/entry': (context) => airContinuousEntry.EntryScreen(),
|
|
'/air/continuous/report': (context) => airContinuousReport.ReportScreen(),
|
|
'/air/investigative/info': (context) => const AirInvestigativeInfoCentreDocument(),
|
|
'/air/investigative/overview': (context) => airInvestigativeOverview.OverviewScreen(),
|
|
'/air/investigative/entry': (context) => airInvestigativeEntry.EntryScreen(),
|
|
'/air/investigative/report': (context) => airInvestigativeReport.ReportScreen(),
|
|
'/river/manual/info': (context) => const RiverManualInfoCentreDocument(),
|
|
'/river/manual/in-situ': (context) => riverManualInSituSampling.RiverInSituSamplingScreen(),
|
|
'/river/manual/report': (context) => riverManualReport.RiverManualReport(),
|
|
'/river/manual/triennial': (context) => riverManualTriennialSampling.RiverManualTriennialSamplingScreen(),
|
|
'/river/manual/data-log': (context) => riverManualDataStatusLog.RiverManualDataStatusLog(),
|
|
'/river/manual/image-request': (context) => riverManualImageRequest.RiverManualImageRequest(),
|
|
'/river/continuous/info': (context) => const RiverContinuousInfoCentreDocument(),
|
|
'/river/continuous/overview': (context) => riverContinuousOverview.OverviewScreen(),
|
|
'/river/continuous/entry': (context) => riverContinuousEntry.EntryScreen(),
|
|
'/river/continuous/report': (context) => riverContinuousReport.ReportScreen(),
|
|
'/river/investigative/info': (context) => const RiverInvestigativeInfoCentreDocument(),
|
|
'/river/investigative/manual-sampling': (context) => riverInvestigativeManualSampling.RiverInvestigativeManualSamplingScreen(),
|
|
'/river/investigative/data-log': (context) => const riverInvestigativeDataStatusLog.RiverInvestigativeDataStatusLog(),
|
|
'/river/investigative/image-request': (context) => const riverInvestigativeImageRequest.RiverInvestigativeImageRequest(),
|
|
'/river/investigative/overview': (context) => riverInvestigativeOverview.OverviewScreen(),
|
|
'/river/investigative/entry': (context) => riverInvestigativeEntry.EntryScreen(),
|
|
'/river/investigative/report': (context) => riverInvestigativeReport.ReportScreen(),
|
|
'/marine/manual/info': (context) => marineManualInfoCentreDocument.MarineInfoCentreDocument(),
|
|
'/marine/manual/pre-sampling': (context) => marineManualPreSampling.MarineManualPreSampling(),
|
|
'/marine/manual/in-situ': (context) => marineManualInSituSampling.MarineInSituSampling(),
|
|
'/marine/manual/tarball': (context) => const TarballSamplingStep1(),
|
|
'/marine/manual/report': (context) => const marineManualReport.MarineManualReportHomePage(),
|
|
'/marine/manual/report/npe': (context) => const MarineManualNPEReportHub(),
|
|
'/marine/manual/report/pre-departure': (context) => const marineManualPreDepartureChecklist.MarineManualPreDepartureChecklistScreen(),
|
|
'/marine/manual/report/calibration': (context) => const marineManualSondeCalibration.MarineManualSondeCalibrationScreen(),
|
|
'/marine/manual/report/maintenance': (context) => const marineManualEquipmentMaintenance.MarineManualEquipmentMaintenanceScreen(),
|
|
'/marine/manual/image-request': (context) => const marineManualImageRequest.MarineImageRequestScreen(),
|
|
'/marine/manual/report-log': (context) => const marineManualReportStatusLog.MarineManualReportStatusLog(),
|
|
'/marine/continuous/info': (context) => const MarineContinuousInfoCentreDocument(),
|
|
'/marine/continuous/overview': (context) => marineContinuousOverview.OverviewScreen(),
|
|
'/marine/continuous/entry': (context) => marineContinuousEntry.EntryScreen(),
|
|
'/marine/continuous/report': (context) => marineContinuousReport.ReportScreen(),
|
|
'/marine/investigative/info': (context) => const MarineInvestigativeInfoCentreDocument(),
|
|
'/marine/investigative/manual-sampling': (context) => marineInvestigativeManualSampling.MarineInvestigativeManualSampling(),
|
|
'/marine/investigative/data-log': (context) => const marineInvestigativeDataStatusLog.MarineInvestigativeDataStatusLog(),
|
|
'/marine/investigative/image-request': (context) => const marineInvestigativeImageRequest.MarineInvestigativeImageRequestScreen(),
|
|
'/marine/investigative/overview': (context) => marineInvestigativeOverview.OverviewScreen(),
|
|
'/marine/investigative/entry': (context) => marineInvestigativeEntry.EntryScreen(),
|
|
'/marine/investigative/report': (context) => marineInvestigativeReport.ReportScreen(),
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class SessionAwareWrapper extends StatefulWidget {
|
|
final Widget child;
|
|
const SessionAwareWrapper({super.key, required this.child});
|
|
|
|
@override
|
|
State<SessionAwareWrapper> createState() => _SessionAwareWrapperState();
|
|
}
|
|
|
|
class _SessionAwareWrapperState extends State<SessionAwareWrapper> {
|
|
bool _isDialogShowing = false;
|
|
late AuthProvider _authProvider;
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
_authProvider = Provider.of<AuthProvider>(context);
|
|
_authProvider.addListener(_handleSessionExpired);
|
|
_checkAndShowDialogIfNeeded(_authProvider.isSessionExpired);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_authProvider.removeListener(_handleSessionExpired);
|
|
super.dispose();
|
|
}
|
|
|
|
void _handleSessionExpired() {
|
|
_checkAndShowDialogIfNeeded(_authProvider.isSessionExpired);
|
|
}
|
|
|
|
void _checkAndShowDialogIfNeeded(bool isExpired) {
|
|
if (isExpired && !_isDialogShowing && mounted) {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted && !_isDialogShowing) {
|
|
_showSessionExpiredDialog();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> _showSessionExpiredDialog() async {
|
|
if (!mounted) return;
|
|
|
|
setState(() => _isDialogShowing = true);
|
|
await showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (BuildContext dialogContext) {
|
|
return AlertDialog(
|
|
title: const Text("Session Expired"),
|
|
content: const Text(
|
|
"Your online session has expired. You can continue working offline, but you will not be able to sync data until you log in again."),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
child: const Text("Continue Offline"),
|
|
onPressed: () {
|
|
Navigator.of(dialogContext).pop();
|
|
},
|
|
),
|
|
ElevatedButton(
|
|
child: const Text("Login Now"),
|
|
onPressed: () {
|
|
_authProvider.logout();
|
|
Navigator.of(dialogContext).pop();
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
if (mounted) {
|
|
setState(() => _isDialogShowing = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return widget.child;
|
|
}
|
|
}
|
|
|
|
class SplashScreen extends StatelessWidget {
|
|
const SplashScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Image.asset(
|
|
'assets/icon4.png',
|
|
height: 360,
|
|
width: 360,
|
|
),
|
|
const SizedBox(height: 24),
|
|
const CircularProgressIndicator(),
|
|
const SizedBox(height: 20),
|
|
const Text('Loading MMS data...', style: TextStyle(fontSize: 16)),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |