Extract settings and harden geofence automation
This commit is contained in:
@@ -4,9 +4,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../app/error_message.dart';
|
||||
import '../models/home_config.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../widgets/build_info_text.dart';
|
||||
import 'home_edit_screen.dart';
|
||||
import 'remote_screen.dart';
|
||||
import 'settings_screen.dart';
|
||||
|
||||
/// Экран "Дома" -- список серверов Ignis.
|
||||
/// Пользователь может добавить, удалить, переключить активный дом.
|
||||
@@ -61,108 +61,100 @@ class _HomesScreenState extends ConsumerState<HomesScreen>
|
||||
appBar: AppBar(
|
||||
title: const Text('ДОМА'),
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: homes.isEmpty
|
||||
? const _EmptyHomesView()
|
||||
: RefreshIndicator(
|
||||
color: Colors.deepOrange,
|
||||
onRefresh: _refreshEnvironmentState,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(12),
|
||||
children: [
|
||||
...homes.map((home) {
|
||||
final isActive = currentHome?.id == home.id;
|
||||
final isSwitching = _switchingHomeId == home.id;
|
||||
final isDeleting = _deletingHomeId == home.id;
|
||||
final isBusy = isSwitching || isDeleting;
|
||||
final distKm = location.distanceToKm(
|
||||
home.latitude,
|
||||
home.longitude,
|
||||
);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
child: ListTile(
|
||||
enabled: !isBusy,
|
||||
leading: Icon(
|
||||
Icons.home,
|
||||
color: isActive
|
||||
? Colors.deepOrange
|
||||
: Colors.white38,
|
||||
size: 28,
|
||||
),
|
||||
title: Text(
|
||||
home.name,
|
||||
style: TextStyle(
|
||||
fontWeight: isActive
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
color: isActive
|
||||
? Colors.deepOrange
|
||||
: Colors.white,
|
||||
),
|
||||
),
|
||||
subtitle: _HomeSubtitle(
|
||||
home: home,
|
||||
location: location,
|
||||
distKm: distKm,
|
||||
isActive: isActive,
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (isBusy)
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.edit,
|
||||
size: 20,
|
||||
color: Colors.white38,
|
||||
),
|
||||
onPressed: () => _editHome(context, home),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.delete_outline,
|
||||
size: 20,
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
onPressed: () =>
|
||||
_confirmDelete(context, home),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
onTap: isBusy
|
||||
? null
|
||||
: () => _selectHome(context, home),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SafeArea(
|
||||
top: false,
|
||||
minimum: EdgeInsets.only(bottom: 10),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: 6),
|
||||
child: BuildInfoText(),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
tooltip: 'Настройки',
|
||||
onPressed: () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) =>
|
||||
const SettingsScreen(entryPoint: SettingsEntryPoint.homes),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: homes.isEmpty
|
||||
? const _EmptyHomesView()
|
||||
: RefreshIndicator(
|
||||
color: Colors.deepOrange,
|
||||
onRefresh: _refreshEnvironmentState,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(12),
|
||||
children: [
|
||||
...homes.map((home) {
|
||||
final isActive = currentHome?.id == home.id;
|
||||
final isSwitching = _switchingHomeId == home.id;
|
||||
final isDeleting = _deletingHomeId == home.id;
|
||||
final isBusy = isSwitching || isDeleting;
|
||||
final distKm = location.distanceToKm(
|
||||
home.latitude,
|
||||
home.longitude,
|
||||
);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
child: ListTile(
|
||||
enabled: !isBusy,
|
||||
leading: Icon(
|
||||
Icons.home,
|
||||
color: isActive ? Colors.deepOrange : Colors.white38,
|
||||
size: 28,
|
||||
),
|
||||
title: Text(
|
||||
home.name,
|
||||
style: TextStyle(
|
||||
fontWeight: isActive
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
color: isActive ? Colors.deepOrange : Colors.white,
|
||||
),
|
||||
),
|
||||
subtitle: _HomeSubtitle(
|
||||
home: home,
|
||||
location: location,
|
||||
distKm: distKm,
|
||||
isActive: isActive,
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (isBusy)
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.edit,
|
||||
size: 20,
|
||||
color: Colors.white38,
|
||||
),
|
||||
onPressed: () => _editHome(context, home),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.delete_outline,
|
||||
size: 20,
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
onPressed: () => _confirmDelete(context, home),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
onTap: isBusy ? null : () => _selectHome(context, home),
|
||||
),
|
||||
);
|
||||
}),
|
||||
SizedBox(height: MediaQuery.of(context).padding.bottom + 80),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
backgroundColor: Colors.deepOrange,
|
||||
onPressed: () => _addHome(context),
|
||||
@@ -282,7 +274,9 @@ class _HomesScreenState extends ConsumerState<HomesScreen>
|
||||
}
|
||||
|
||||
Future<void> _syncLocationWatching() async {
|
||||
final shouldWatch = ref.read(homesProvider).any((home) => home.hasCoordinates);
|
||||
final shouldWatch = ref
|
||||
.read(homesProvider)
|
||||
.any((home) => home.hasCoordinates);
|
||||
if (shouldWatch == _isWatchingLocation) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user