160 lines
5.7 KiB
Dart
160 lines
5.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:on_field_work/helpers/services/app_logger.dart';
|
|
import 'package:on_field_work/helpers/extensions/app_localization_delegate.dart';
|
|
import 'package:on_field_work/helpers/services/localizations/language.dart';
|
|
import 'package:on_field_work/helpers/services/navigation_services.dart';
|
|
import 'package:on_field_work/helpers/services/storage/local_storage.dart';
|
|
import 'package:on_field_work/helpers/theme/app_theme.dart';
|
|
import 'package:on_field_work/helpers/theme/theme_customizer.dart';
|
|
import 'package:on_field_work/helpers/theme/app_notifier.dart';
|
|
import 'package:on_field_work/routes.dart';
|
|
|
|
class MyApp extends StatelessWidget {
|
|
final bool isOffline;
|
|
|
|
const MyApp({super.key, required this.isOffline});
|
|
|
|
Future<String> _getInitialRoute() async {
|
|
try {
|
|
final token = LocalStorage.getJwtToken();
|
|
if (token == null || token.isEmpty) {
|
|
logSafe("User not logged in. Routing to /auth/login-option");
|
|
return "/auth/login-option";
|
|
}
|
|
|
|
final bool hasMpin = LocalStorage.getIsMpin();
|
|
if (hasMpin) {
|
|
await LocalStorage.setBool("mpin_verified", false);
|
|
logSafe("Routing to /auth/mpin-auth");
|
|
return "/auth/mpin-auth";
|
|
}
|
|
|
|
logSafe("No MPIN. Routing to /dashboard");
|
|
return "/dashboard";
|
|
} catch (e, stacktrace) {
|
|
logSafe("Error determining initial route",
|
|
level: LogLevel.error, error: e, stackTrace: stacktrace);
|
|
return "/auth/login-option";
|
|
}
|
|
}
|
|
|
|
// ✨ REVISED: Helper Widget to show a full-screen, well-designed offline status
|
|
Widget _buildConnectivityOverlay(BuildContext context) {
|
|
// If not offline, return an empty widget.
|
|
if (!isOffline) return const SizedBox.shrink();
|
|
|
|
// Otherwise, return a full-screen overlay.
|
|
return Directionality(
|
|
textDirection: AppTheme.textDirection,
|
|
child: Scaffold(
|
|
backgroundColor:
|
|
Colors.grey.shade100, // Light background for the offline state
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.cloud_off,
|
|
color: Colors.red.shade700, // Prominent color
|
|
size: 100,
|
|
),
|
|
const SizedBox(height: 24),
|
|
const Text(
|
|
"You Are Offline",
|
|
style: TextStyle(
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 40.0),
|
|
child: Text(
|
|
"Please check your internet connection and try again.",
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
color: Colors.black54,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 32),
|
|
// Optional: Add a button for the user to potentially refresh/retry
|
|
// ElevatedButton(
|
|
// onPressed: () {
|
|
// // Add logic to re-check connectivity or navigate (if possible)
|
|
// },
|
|
// child: const Text("RETRY"),
|
|
// ),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Consumer<AppNotifier>(
|
|
builder: (_, notifier, __) {
|
|
return FutureBuilder<String>(
|
|
future: _getInitialRoute(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
logSafe("FutureBuilder snapshot error",
|
|
level: LogLevel.error, error: snapshot.error);
|
|
return const MaterialApp(
|
|
home: Center(child: Text("Error determining route")),
|
|
);
|
|
}
|
|
|
|
if (!snapshot.hasData) {
|
|
return const MaterialApp(
|
|
home: Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
return GetMaterialApp(
|
|
debugShowCheckedModeBanner: false,
|
|
theme: AppTheme.lightTheme,
|
|
darkTheme: AppTheme.darkTheme,
|
|
themeMode: ThemeCustomizer.instance.theme,
|
|
navigatorKey: NavigationService.navigatorKey,
|
|
initialRoute: snapshot.data!,
|
|
getPages: getPageRoute(),
|
|
builder: (context, child) {
|
|
NavigationService.registerContext(context);
|
|
|
|
// 💡 REVISED: Use a Stack to place the offline overlay ON TOP of the app content.
|
|
// This allows the full-screen view to cover everything, including the main app content.
|
|
return Stack(
|
|
children: [
|
|
Directionality(
|
|
textDirection: AppTheme.textDirection,
|
|
child: child ?? const SizedBox(),
|
|
),
|
|
// 2. The full-screen connectivity overlay, only visible when offline
|
|
_buildConnectivityOverlay(context),
|
|
],
|
|
);
|
|
},
|
|
localizationsDelegates: [
|
|
AppLocalizationsDelegate(context),
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
],
|
|
supportedLocales: Language.getLocales(),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|