refactor: stabilize app bootstrap and polling

This commit is contained in:
Artem Kokos
2026-04-22 23:37:15 +07:00
parent 7c0a2675c6
commit 762d16dc78
5 changed files with 353 additions and 59 deletions

View File

@@ -3,7 +3,7 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:workmanager/workmanager.dart';
import 'providers/providers.dart';
import 'app/app_bootstrap.dart';
import 'screens/homes_screen.dart';
import 'screens/remote_screen.dart';
import 'services/geofence_worker.dart';
@@ -78,53 +78,83 @@ class _MainGateState extends ConsumerState<MainGate> {
@override
void initState() {
super.initState();
_bootstrap();
Future.microtask(_bootstrap);
}
Future<void> _bootstrap() async {
try {
// Загружаем список домов
await ref.read(homesProvider.notifier).load();
await ref.read(currentHomeProvider.notifier).load();
await ref.read(appBootstrapProvider.notifier).bootstrap();
if (!mounted) return;
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) {
final bootstrap = ref.read(appBootstrapProvider);
switch (bootstrap.status) {
case AppBootstrapStatus.ready:
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const RemoteScreen()),
);
break;
case AppBootstrapStatus.noHomes:
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const HomesScreen()),
);
}
break;
case AppBootstrapStatus.bootstrapping:
case AppBootstrapStatus.authFailed:
case AppBootstrapStatus.networkFailed:
case AppBootstrapStatus.invalidConfig:
case AppBootstrapStatus.failed:
break;
}
}
@override
Widget build(BuildContext context) {
final bootstrap = ref.watch(appBootstrapProvider);
final message = bootstrap.message;
if (!bootstrap.isBootstrapping && message != null) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.warning_amber_rounded,
color: Colors.deepOrange,
size: 56,
),
const SizedBox(height: 16),
const Text(
'Не удалось запустить приложение',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text(
message,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.white54),
),
const SizedBox(height: 20),
FilledButton.icon(
onPressed: _bootstrap,
icon: const Icon(Icons.refresh),
label: const Text('Повторить'),
),
TextButton(
onPressed: () => Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const HomesScreen()),
),
child: const Text('Открыть список домов'),
),
],
),
),
),
);
}
return const Scaffold(
body: Center(
child: Column(