import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../models/home_config.dart'; import '../providers/providers.dart'; /// Экран создания или редактирования "дома" (сервера Ignis). class HomeEditScreen extends ConsumerStatefulWidget { final HomeConfig? home; // null -- создание, иначе редактирование const HomeEditScreen({super.key, this.home}); @override ConsumerState createState() => _HomeEditScreenState(); } class _HomeEditScreenState extends ConsumerState { final _nameCtrl = TextEditingController(); final _urlCtrl = TextEditingController(); final _keyCtrl = TextEditingController(); final _latCtrl = TextEditingController(); final _lonCtrl = TextEditingController(); bool _geofenceEnabled = false; bool _saving = false; bool get _isEdit => widget.home != null; /// Координаты заполнены (оба поля непустые) bool get _hasCoordinates => _latCtrl.text.trim().isNotEmpty && _lonCtrl.text.trim().isNotEmpty; @override void initState() { super.initState(); if (_isEdit) { _nameCtrl.text = widget.home!.name; _urlCtrl.text = widget.home!.url; _keyCtrl.text = widget.home!.apiKey; if (widget.home!.latitude != null) { _latCtrl.text = widget.home!.latitude.toString(); } if (widget.home!.longitude != null) { _lonCtrl.text = widget.home!.longitude.toString(); } _geofenceEnabled = widget.home!.geofenceEnabled; } // Следим за полями координат чтобы обновлять доступность Switch _latCtrl.addListener(_onCoordsChanged); _lonCtrl.addListener(_onCoordsChanged); } void _onCoordsChanged() { // Если координаты очистили -- выключаем геофенс if (!_hasCoordinates && _geofenceEnabled) { setState(() => _geofenceEnabled = false); } else { setState(() {}); // перерисовать Switch enabled/disabled } } @override void dispose() { _latCtrl.removeListener(_onCoordsChanged); _lonCtrl.removeListener(_onCoordsChanged); _nameCtrl.dispose(); _urlCtrl.dispose(); _keyCtrl.dispose(); _latCtrl.dispose(); _lonCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_isEdit ? 'РЕДАКТИРОВАТЬ ДОМ' : 'НОВЫЙ ДОМ'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _nameCtrl, decoration: const InputDecoration( labelText: 'Название (например "Квартира")', prefixIcon: Icon(Icons.home), ), textCapitalization: TextCapitalization.sentences, ), const SizedBox(height: 12), TextField( controller: _urlCtrl, decoration: const InputDecoration( labelText: 'Адрес сервера (например ignis.akokos.ru)', prefixIcon: Icon(Icons.dns), ), keyboardType: TextInputType.url, ), const SizedBox(height: 12), TextField( controller: _keyCtrl, decoration: const InputDecoration( labelText: 'API Key', prefixIcon: Icon(Icons.key), ), obscureText: true, ), const SizedBox(height: 24), // ─── GPS-координаты (опционально) ─── const Text( 'Координаты дома (опционально)', style: TextStyle( color: Colors.white54, fontSize: 13, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), const Text( 'Для автоматизации по геолокации', style: TextStyle(color: Colors.white30, fontSize: 12), ), const SizedBox(height: 8), Row( children: [ Expanded( child: TextField( controller: _latCtrl, decoration: const InputDecoration( labelText: 'Широта', prefixIcon: Icon(Icons.location_on, size: 20), hintText: '51.128', ), keyboardType: const TextInputType.numberWithOptions( decimal: true, signed: true), ), ), const SizedBox(width: 12), Expanded( child: TextField( controller: _lonCtrl, decoration: const InputDecoration( labelText: 'Долгота', prefixIcon: Icon(Icons.location_on, size: 20), hintText: '71.430', ), keyboardType: const TextInputType.numberWithOptions( decimal: true, signed: true), ), ), ], ), const SizedBox(height: 16), // ─── Геофенс ─── SwitchListTile( title: const Text('Выключать свет при уходе'), subtitle: Text( _hasCoordinates ? 'Автовыключение при удалении на 500 м' : 'Задайте координаты для активации', style: TextStyle( fontSize: 12, color: _hasCoordinates ? Colors.white38 : Colors.white24, ), ), value: _geofenceEnabled, activeColor: Colors.deepOrange, onChanged: _hasCoordinates ? (v) => setState(() => _geofenceEnabled = v) : null, contentPadding: EdgeInsets.zero, secondary: Icon( Icons.directions_walk, color: _geofenceEnabled && _hasCoordinates ? Colors.deepOrange : Colors.white24, ), ), if (_geofenceEnabled && _hasCoordinates) const Padding( padding: EdgeInsets.only(left: 40, bottom: 4), child: Text( 'Проверка раз в ~15 мин (ограничение Android).\n' 'Работает в фоне, без постоянной нотификации.', style: TextStyle(fontSize: 11, color: Colors.white24), ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, height: 48, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.deepOrange, foregroundColor: Colors.white, ), onPressed: _saving ? null : _save, child: _saving ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : Text(_isEdit ? 'СОХРАНИТЬ' : 'ДОБАВИТЬ'), ), ), // Отступ внизу для системных кнопок SizedBox(height: MediaQuery.of(context).padding.bottom + 16), ], ), ), ); } Future _save() async { final name = _nameCtrl.text.trim(); final url = _urlCtrl.text.trim(); final key = _keyCtrl.text.trim(); final latText = _latCtrl.text.trim(); final lonText = _lonCtrl.text.trim(); if (name.isEmpty || url.isEmpty || key.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Заполните все обязательные поля')), ); return; } double? lat; double? lon; if (latText.isNotEmpty && lonText.isNotEmpty) { lat = double.tryParse(latText); lon = double.tryParse(lonText); if (lat == null || lon == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Некорректные координаты')), ); return; } } setState(() => _saving = true); final clearCoords = latText.isEmpty && lonText.isEmpty; final home = _isEdit ? widget.home!.copyWith( name: name, url: url, apiKey: key, latitude: lat, longitude: lon, geofenceEnabled: clearCoords ? false : _geofenceEnabled, clearCoordinates: clearCoords, ) : HomeConfig( id: DateTime.now().millisecondsSinceEpoch.toString(), name: name, url: url, apiKey: key, latitude: lat, longitude: lon, geofenceEnabled: _geofenceEnabled, ); if (_isEdit) { await ref.read(homesProvider.notifier).update(home); } else { await ref.read(homesProvider.notifier).add(home); } // Синхронизировать фоновый таск с новыми настройками final allHomes = ref.read(homesProvider); await syncGeofenceTask(allHomes); if (mounted) Navigator.of(context).pop(); } }