feat: surface device and scene load errors

This commit is contained in:
Artem Kokos
2026-04-23 20:24:08 +07:00
parent 90a86e932d
commit 1c40852ac6
4 changed files with 521 additions and 191 deletions

View File

@@ -503,7 +503,8 @@ class GroupsNotifier extends Notifier<List<dynamic>> {
await _api.controlGroup(id, {'state': on});
} catch (e) {
_lockUntil.remove(id);
refresh();
await refresh();
rethrow;
}
}
@@ -540,7 +541,8 @@ class GroupsNotifier extends Notifier<List<dynamic>> {
await _api.controlGroup(id, {'scene': scene});
} catch (e) {
_lockUntil.remove(id);
refresh();
await refresh();
rethrow;
}
}
@@ -558,64 +560,92 @@ class GroupsNotifier extends Notifier<List<dynamic>> {
// ─── Устройства (для создания групп) ─────────────────────────
final devicesProvider = NotifierProvider<DevicesNotifier, List<dynamic>>(
() => DevicesNotifier(),
);
final devicesProvider =
NotifierProvider<DevicesNotifier, LoadState<List<dynamic>>>(
() => DevicesNotifier(),
);
class DevicesNotifier extends Notifier<List<dynamic>> {
class DevicesNotifier extends Notifier<LoadState<List<dynamic>>> {
@override
List<dynamic> build() => [];
LoadState<List<dynamic>> build() => const LoadState.idle(<dynamic>[]);
/// Загрузить список устройств из текущего дома
Future<void> load() async {
state = LoadState.loading(state.data);
try {
final api = ref.read(apiProvider);
final res = await api.getDevices();
if (res.data is List) {
state = res.data;
} else if (res.data is Map) {
state =
res.data['data'] ?? res.data['devices'] ?? res.data.values.toList();
final data = res.data;
late final List<dynamic> devices;
if (data is List) {
devices = List<dynamic>.from(data);
} else if (data is Map) {
final value = data['data'] ?? data['devices'] ?? data.values.toList();
if (value is! List) {
throw FormatException('devices должен быть списком устройств');
}
devices = List<dynamic>.from(value);
} else {
throw FormatException('devices должен быть списком устройств');
}
state = devices.isEmpty
? LoadState.empty(devices)
: LoadState.data(devices);
} catch (e) {
debugPrint("Ошибка загрузки устройств: $e");
state = LoadState.error(state.data, describeLoadError(e));
}
}
}
// ─── Сцены ───────────────────────────────────────────────────
final scenesProvider = NotifierProvider<ScenesNotifier, List<dynamic>>(
() => ScenesNotifier(),
);
final scenesProvider =
NotifierProvider<ScenesNotifier, LoadState<List<dynamic>>>(
() => ScenesNotifier(),
);
class ScenesNotifier extends Notifier<List<dynamic>> {
class ScenesNotifier extends Notifier<LoadState<List<dynamic>>> {
@override
List<dynamic> build() => [];
LoadState<List<dynamic>> build() => const LoadState.idle(<dynamic>[]);
Future<void> load() async {
state = LoadState.loading(state.data);
try {
final api = ref.read(apiProvider);
final res = await api.getScenes();
final data = res.data;
late final List<dynamic> scenes;
if (data is List) {
state = data;
scenes = List<dynamic>.from(data);
} else if (data is Map) {
// Бэкенд может вернуть {scene_id: "Scene Name", ...}
// или {data: [...]} или {scenes: [...]}
if (data.containsKey('data') && data['data'] is List) {
state = data['data'];
} else if (data.containsKey('scenes') && data['scenes'] is List) {
state = data['scenes'];
if (data.containsKey('data')) {
final value = data['data'];
if (value is! List) {
throw FormatException('scenes.data должен быть списком сцен');
}
scenes = List<dynamic>.from(value);
} else if (data.containsKey('scenes')) {
final value = data['scenes'];
if (value is! List) {
throw FormatException('scenes должен быть списком сцен');
}
scenes = List<dynamic>.from(value);
} else {
// Map вида {id: name} -- преобразуем в список
state = data.entries
scenes = data.entries
.map((e) => {'id': e.key.toString(), 'name': e.value.toString()})
.toList();
}
} else {
throw FormatException('scenes должен быть списком сцен');
}
state = scenes.isEmpty ? LoadState.empty(scenes) : LoadState.data(scenes);
} catch (e) {
debugPrint("Ошибка загрузки сцен: $e");
state = LoadState.error(state.data, describeLoadError(e));
}
}
}