Harden geofence automation and home editing
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../app/error_message.dart';
|
||||
import '../features/homes/services/home_connection_change.dart';
|
||||
import '../models/home_config.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../services/api_client.dart';
|
||||
@@ -23,6 +24,8 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
final _latCtrl = TextEditingController();
|
||||
final _lonCtrl = TextEditingController();
|
||||
bool _saving = false;
|
||||
bool _loadingApiKey = false;
|
||||
String _originalApiKey = '';
|
||||
|
||||
bool get _isEdit => widget.home != null;
|
||||
|
||||
@@ -42,6 +45,7 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
if (widget.home!.longitude != null) {
|
||||
_lonCtrl.text = widget.home!.longitude.toString();
|
||||
}
|
||||
_loadingApiKey = true;
|
||||
_loadApiKey();
|
||||
}
|
||||
|
||||
@@ -51,11 +55,19 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
}
|
||||
|
||||
Future<void> _loadApiKey() async {
|
||||
final apiKey = await ref
|
||||
.read(settingsServiceProvider)
|
||||
.getHomeApiKey(widget.home!.id);
|
||||
if (mounted && apiKey != null) {
|
||||
_keyCtrl.text = apiKey;
|
||||
try {
|
||||
final apiKey = await ref
|
||||
.read(settingsServiceProvider)
|
||||
.getHomeApiKey(widget.home!.id);
|
||||
_originalApiKey = apiKey ?? '';
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_keyCtrl.text = _originalApiKey;
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _loadingApiKey = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +142,12 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
const SizedBox(height: 12),
|
||||
TextFormField(
|
||||
controller: _keyCtrl,
|
||||
decoration: const InputDecoration(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'API Key',
|
||||
helperText: 'Ключ проверяется перед сохранением дома',
|
||||
prefixIcon: Icon(Icons.key),
|
||||
helperText: _loadingApiKey
|
||||
? 'Загружаем сохранённый ключ...'
|
||||
: 'Ключ проверяется только при изменении подключения',
|
||||
prefixIcon: const Icon(Icons.key),
|
||||
),
|
||||
obscureText: true,
|
||||
validator: (value) =>
|
||||
@@ -236,7 +250,7 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
backgroundColor: Colors.deepOrange,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
onPressed: _saving ? null : _save,
|
||||
onPressed: (_saving || _loadingApiKey) ? null : _save,
|
||||
child: _saving
|
||||
? const SizedBox(
|
||||
width: 20,
|
||||
@@ -259,6 +273,12 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
|
||||
Future<void> _save() async {
|
||||
FocusScope.of(context).unfocus();
|
||||
if (_loadingApiKey) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Подождите, API key ещё загружается')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
@@ -319,6 +339,12 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
setState(() => _saving = true);
|
||||
|
||||
final clearCoords = latText.isEmpty && lonText.isEmpty;
|
||||
final credentialsChanged = hasHomeConnectionChanges(
|
||||
originalHome: widget.home,
|
||||
normalizedUrl: url,
|
||||
apiKey: key,
|
||||
originalApiKey: _originalApiKey,
|
||||
);
|
||||
|
||||
final home = _isEdit
|
||||
? widget.home!.copyWith(
|
||||
@@ -337,17 +363,25 @@ class _HomeEditScreenState extends ConsumerState<HomeEditScreen> {
|
||||
);
|
||||
|
||||
try {
|
||||
await ref.read(apiProvider).validateCredentials(url, key);
|
||||
if (credentialsChanged) {
|
||||
await ref.read(apiProvider).validateCredentials(url, key);
|
||||
}
|
||||
|
||||
if (_isEdit) {
|
||||
await ref.read(homesProvider.notifier).update(home, apiKey: key);
|
||||
await ref
|
||||
.read(homesProvider.notifier)
|
||||
.update(home, apiKey: credentialsChanged ? key : null);
|
||||
} else {
|
||||
await ref.read(homesProvider.notifier).add(home, apiKey: key);
|
||||
}
|
||||
|
||||
final currentHome = ref.read(currentHomeProvider);
|
||||
if (currentHome?.id == home.id) {
|
||||
await ref.read(currentHomeProvider.notifier).select(home);
|
||||
if (credentialsChanged) {
|
||||
await ref.read(currentHomeProvider.notifier).select(home);
|
||||
} else {
|
||||
await ref.read(currentHomeProvider.notifier).switchTo(home);
|
||||
}
|
||||
}
|
||||
|
||||
if (mounted) Navigator.of(context).pop();
|
||||
|
||||
@@ -277,6 +277,11 @@ class _HomesScreenState extends ConsumerState<HomesScreen>
|
||||
final shouldWatch = ref
|
||||
.read(homesProvider)
|
||||
.any((home) => home.hasCoordinates);
|
||||
if (shouldWatch && _isWatchingLocation) {
|
||||
await _userLocationNotifier.ensureWatchingStarted();
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldWatch == _isWatchingLocation) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user