import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mirror_protocol/mirror_protocol.dart'; import 'package:mirror_ui/mirror_ui.dart'; import '../providers/connection_provider.dart'; import 'ha_entity_picker_screen.dart'; import 'weather_picker_screen.dart'; class DashboardEditorScreen extends ConsumerStatefulWidget { const DashboardEditorScreen({super.key}); @override ConsumerState createState() => _DashboardEditorScreenState(); } class _DashboardEditorScreenState extends ConsumerState { List _widgets = []; bool _loading = true; static const _widgetMeta = { 'clock': (icon: Icons.access_time, label: 'Clock'), 'weather': (icon: Icons.cloud, label: 'Weather'), 'calendar': (icon: Icons.calendar_month, label: 'Calendar'), 'ha_entities': (icon: Icons.home, label: 'HA Entities'), }; @override void initState() { super.initState(); _requestConfig(); } void _requestConfig() { final existing = ref.read(dashboardConfigProvider); if (existing != null) { setState(() { _widgets = List.from(existing.widgets); _loading = false; }); } else { // Request from display ref.read(connectionProvider.notifier).send(DashboardConfigRequest()); // Wait briefly then fall back to default Future.delayed(const Duration(seconds: 2), () { if (_loading && mounted) { setState(() { _widgets = List.from(DashboardLayoutConfig.defaultLayout().widgets); _loading = false; }); } }); } } @override void didChangeDependencies() { super.didChangeDependencies(); // Listen for config response ref.listen(dashboardConfigProvider, (prev, next) { if (next != null && _loading) { setState(() { _widgets = List.from(next.widgets); _loading = false; }); } }); } void _onReorder(int oldIndex, int newIndex) { setState(() { if (newIndex > oldIndex) newIndex--; final item = _widgets.removeAt(oldIndex); _widgets.insert(newIndex, item); // Update positions for (var i = 0; i < _widgets.length; i++) { _widgets[i] = _widgets[i].copyWith(position: i); } }); } void _toggleVisibility(int index) { setState(() { _widgets[index] = _widgets[index].copyWith(visible: !_widgets[index].visible); }); } Future _openConfig(int index) async { final widget = _widgets[index]; switch (widget.type) { case 'ha_entities': final currentIds = (widget.config['entity_ids'] as List?)?.cast() ?? []; final result = await Navigator.of(context).push>( MaterialPageRoute( builder: (_) => HaEntityPickerScreen(selectedIds: currentIds), ), ); if (result != null && mounted) { setState(() { _widgets[index] = widget.copyWith( config: {...widget.config, 'entity_ids': result}, ); }); } case 'weather': final currentEntity = widget.config['entity_id'] as String?; final result = await Navigator.of(context).push( MaterialPageRoute( builder: (_) => WeatherPickerScreen(selectedEntityId: currentEntity), ), ); if (result != null && mounted) { setState(() { _widgets[index] = widget.copyWith( config: {...widget.config, 'entity_id': result}, ); }); } default: ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('No settings for ${widget.type}')), ); } } void _saveLayout() { final layout = DashboardLayoutConfig(widgets: _widgets); ref.read(connectionProvider.notifier).send(DashboardConfigUpdate(layout: layout)); ref.read(dashboardConfigProvider.notifier).state = layout; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Dashboard layout saved')), ); Navigator.of(context).pop(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Dashboard Layout'), backgroundColor: MirrorTheme.background, ), backgroundColor: MirrorTheme.background, body: _loading ? const Center(child: CircularProgressIndicator()) : Column( children: [ Expanded( child: ReorderableListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), itemCount: _widgets.length, onReorderItem: (oldIndex, newIndex) => _onReorder(oldIndex, newIndex), itemBuilder: (context, index) { final widget = _widgets[index]; final meta = _widgetMeta[widget.type]; final icon = meta?.icon ?? Icons.widgets; final label = meta?.label ?? widget.type; final hasConfig = widget.type == 'ha_entities' || widget.type == 'weather'; return Card( key: ValueKey(widget.id), color: MirrorTheme.surface, margin: const EdgeInsets.symmetric(vertical: 4), child: ListTile( leading: Icon(icon, color: MirrorTheme.accent), title: Text(label), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ if (hasConfig) IconButton( icon: const Icon(Icons.settings, size: 20), onPressed: () => _openConfig(index), ), Switch( value: widget.visible, onChanged: (_) => _toggleVisibility(index), activeThumbColor: MirrorTheme.accent, ), const Icon(Icons.drag_handle), ], ), ), ); }, ), ), Padding( padding: const EdgeInsets.all(16), child: SizedBox( width: double.infinity, child: FilledButton.icon( onPressed: _saveLayout, icon: const Icon(Icons.save), label: const Text('Save Layout'), ), ), ), ], ), ); } }