135 lines
4.0 KiB
Dart
135 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:workmanager/workmanager.dart';
|
||
import 'providers/providers.dart';
|
||
import 'screens/homes_screen.dart';
|
||
import 'screens/remote_screen.dart';
|
||
import 'services/geofence_worker.dart';
|
||
|
||
/// Top-level callback для workmanager (выполняется в отдельном изоляте).
|
||
@pragma('vm:entry-point')
|
||
void callbackDispatcher() {
|
||
Workmanager().executeTask((taskName, inputData) async {
|
||
if (taskName == geofenceTaskName) {
|
||
return await executeGeofenceCheck();
|
||
}
|
||
return true;
|
||
});
|
||
}
|
||
|
||
void main() {
|
||
WidgetsFlutterBinding.ensureInitialized();
|
||
|
||
// Инициализация workmanager
|
||
Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
||
|
||
runApp(const ProviderScope(child: IgnisApp()));
|
||
}
|
||
|
||
class IgnisApp extends StatelessWidget {
|
||
const IgnisApp({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
title: 'Ignis',
|
||
debugShowCheckedModeBanner: false,
|
||
theme: ThemeData.dark(useMaterial3: true).copyWith(
|
||
scaffoldBackgroundColor: const Color(0xFF0E0E0E),
|
||
colorScheme: ColorScheme.fromSeed(
|
||
seedColor: Colors.deepOrange,
|
||
brightness: Brightness.dark,
|
||
),
|
||
appBarTheme: const AppBarTheme(
|
||
backgroundColor: Color(0xFF1A1A1A),
|
||
elevation: 0,
|
||
centerTitle: true,
|
||
),
|
||
cardTheme: CardThemeData(
|
||
color: const Color(0xFF1E1E1E),
|
||
elevation: 2,
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||
),
|
||
sliderTheme: const SliderThemeData(
|
||
trackHeight: 4,
|
||
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 8),
|
||
),
|
||
),
|
||
home: const MainGate(),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// Стартовый экран -- проверяет наличие домов и перенаправляет
|
||
class MainGate extends ConsumerStatefulWidget {
|
||
const MainGate({super.key});
|
||
|
||
@override
|
||
ConsumerState<MainGate> createState() => _MainGateState();
|
||
}
|
||
|
||
class _MainGateState extends ConsumerState<MainGate> {
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_bootstrap();
|
||
}
|
||
|
||
Future<void> _bootstrap() async {
|
||
try {
|
||
// Загружаем список домов
|
||
await ref.read(homesProvider.notifier).load();
|
||
await ref.read(currentHomeProvider.notifier).load();
|
||
|
||
if (!mounted) return;
|
||
|
||
final home = ref.read(currentHomeProvider);
|
||
|
||
if (home != null) {
|
||
// Есть дом -- идём на пульт управления
|
||
await ref.read(groupsProvider.notifier).initAndRefresh();
|
||
// Загружаем info об авторизации (admin / не admin)
|
||
await ref.read(authInfoProvider.notifier).load();
|
||
|
||
// Запускаем / обновляем геофенс-таск если нужно
|
||
await syncGeofenceTask(ref.read(homesProvider));
|
||
|
||
if (mounted) {
|
||
Navigator.of(context).pushReplacement(
|
||
MaterialPageRoute(builder: (_) => const RemoteScreen()),
|
||
);
|
||
}
|
||
} else {
|
||
// Нет домов -- на экран управления домами
|
||
if (mounted) {
|
||
Navigator.of(context).pushReplacement(
|
||
MaterialPageRoute(builder: (_) => const HomesScreen()),
|
||
);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
debugPrint("Ошибка бутстрапа: $e");
|
||
if (mounted) {
|
||
Navigator.of(context).pushReplacement(
|
||
MaterialPageRoute(builder: (_) => const HomesScreen()),
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return const Scaffold(
|
||
body: Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
CircularProgressIndicator(color: Colors.deepOrange),
|
||
SizedBox(height: 20),
|
||
Text("Загрузка...", style: TextStyle(color: Colors.white54)),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
} |