feat: type remote device models
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../app/error_message.dart';
|
||||
import '../app/load_state.dart';
|
||||
import '../models/ignis_device.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../widgets/load_error_view.dart';
|
||||
|
||||
@@ -129,8 +130,7 @@ class _GroupEditScreenState extends ConsumerState<GroupEditScreen> {
|
||||
_selectedMacs.clear();
|
||||
} else {
|
||||
for (final d in devices) {
|
||||
final mac = _extractMac(d);
|
||||
if (mac != null) _selectedMacs.add(mac);
|
||||
_selectedMacs.add(d.groupMemberId);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -182,8 +182,8 @@ class _GroupEditScreenState extends ConsumerState<GroupEditScreen> {
|
||||
}
|
||||
|
||||
Widget _buildDevices(
|
||||
LoadState<List<dynamic>> devicesState,
|
||||
List<dynamic> devices,
|
||||
LoadState<List<IgnisDevice>> devicesState,
|
||||
List<IgnisDevice> devices,
|
||||
) {
|
||||
if ((devicesState.isIdle || devicesState.isLoading) && devices.isEmpty) {
|
||||
return const Center(
|
||||
@@ -233,25 +233,24 @@ class _GroupEditScreenState extends ConsumerState<GroupEditScreen> {
|
||||
|
||||
final deviceIndex = index - statusHeaderCount;
|
||||
final d = devices[deviceIndex];
|
||||
final mac = _extractMac(d) ?? '';
|
||||
final name = _extractName(d);
|
||||
final ip = _extractIp(d);
|
||||
final selected = _selectedMacs.contains(mac);
|
||||
final selected = _selectedMacs.contains(d.groupMemberId);
|
||||
|
||||
return CheckboxListTile(
|
||||
value: selected,
|
||||
activeColor: Colors.deepOrange,
|
||||
title: Text(name),
|
||||
subtitle: Text(
|
||||
'$mac${ip != null ? ' - $ip' : ''}',
|
||||
style: const TextStyle(fontSize: 11, color: Colors.white38),
|
||||
),
|
||||
title: Text(d.name),
|
||||
subtitle: d.subtitle == null
|
||||
? null
|
||||
: Text(
|
||||
d.subtitle!,
|
||||
style: const TextStyle(fontSize: 11, color: Colors.white38),
|
||||
),
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
if (v == true) {
|
||||
_selectedMacs.add(mac);
|
||||
_selectedMacs.add(d.groupMemberId);
|
||||
} else {
|
||||
_selectedMacs.remove(mac);
|
||||
_selectedMacs.remove(d.groupMemberId);
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -260,32 +259,6 @@ class _GroupEditScreenState extends ConsumerState<GroupEditScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Извлечь MAC-адрес из объекта устройства
|
||||
String? _extractMac(dynamic device) {
|
||||
if (device is Map) {
|
||||
return (device['mac'] ?? device['id'] ?? device['mac_address'])
|
||||
?.toString();
|
||||
}
|
||||
return device?.toString();
|
||||
}
|
||||
|
||||
/// Извлечь имя устройства
|
||||
String _extractName(dynamic device) {
|
||||
if (device is Map) {
|
||||
return (device['name'] ?? device['model'] ?? device['mac'] ?? 'Лампа')
|
||||
.toString();
|
||||
}
|
||||
return device?.toString() ?? 'Лампа';
|
||||
}
|
||||
|
||||
/// Извлечь IP-адрес
|
||||
String? _extractIp(dynamic device) {
|
||||
if (device is Map) {
|
||||
return (device['ip'] ?? device['address'])?.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
final id = _idCtrl.text.trim();
|
||||
final name = _nameCtrl.text.trim();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../app/error_message.dart';
|
||||
import '../models/ignis_group.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../widgets/group_card.dart';
|
||||
import 'homes_screen.dart';
|
||||
@@ -175,9 +176,9 @@ class _RemoteScreenState extends ConsumerState<RemoteScreen> {
|
||||
padding: const EdgeInsets.only(top: 8, bottom: 80),
|
||||
itemCount: groups.length,
|
||||
itemBuilder: (context, index) {
|
||||
final g = Map<String, dynamic>.from(groups[index]);
|
||||
final g = groups[index];
|
||||
return Dismissible(
|
||||
key: Key(g['id'].toString()),
|
||||
key: Key(g.id),
|
||||
direction: DismissDirection.endToStart,
|
||||
background: Container(
|
||||
alignment: Alignment.centerRight,
|
||||
@@ -203,7 +204,7 @@ class _RemoteScreenState extends ConsumerState<RemoteScreen> {
|
||||
|
||||
Future<bool> _confirmAndDeleteGroup(
|
||||
BuildContext context,
|
||||
Map<String, dynamic> g,
|
||||
IgnisGroup g,
|
||||
) async {
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
final confirmed =
|
||||
@@ -211,7 +212,7 @@ class _RemoteScreenState extends ConsumerState<RemoteScreen> {
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: const Text('Удалить группу?'),
|
||||
content: Text('Удалить "${g['name']}"?'),
|
||||
content: Text('Удалить "${g.name}"?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(false),
|
||||
@@ -232,7 +233,7 @@ class _RemoteScreenState extends ConsumerState<RemoteScreen> {
|
||||
if (!confirmed) return false;
|
||||
|
||||
try {
|
||||
await ref.read(apiProvider).deleteGroup(g['id'].toString());
|
||||
await ref.read(apiProvider).deleteGroup(g.id);
|
||||
await ref.read(groupsProvider.notifier).refresh();
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
||||
@@ -296,8 +296,8 @@ class _AddScheduleSheetState extends ConsumerState<_AddScheduleSheet> {
|
||||
initialValue: _selectedGroupId,
|
||||
decoration: const InputDecoration(labelText: 'Группа'),
|
||||
items: groups.map((g) {
|
||||
final id = g['id'].toString();
|
||||
final name = g['name']?.toString() ?? id;
|
||||
final id = g.id;
|
||||
final name = g.name;
|
||||
return DropdownMenuItem(value: id, child: Text(name));
|
||||
}).toList(),
|
||||
onChanged: (v) => setState(() => _selectedGroupId = v),
|
||||
|
||||
Reference in New Issue
Block a user