diff --git a/lib/screens/group_edit_screen.dart b/lib/screens/group_edit_screen.dart index d139c88..0c481cb 100644 --- a/lib/screens/group_edit_screen.dart +++ b/lib/screens/group_edit_screen.dart @@ -80,39 +80,19 @@ class _GroupEditScreenState extends ConsumerState { } Future _rescan() async { - final beforeIds = ref - .read(devicesProvider) - .data - .map((device) => device.groupMemberId) - .toSet(); - setState(() => _rescanning = true); try { - await ref.read(apiProvider).rescanNetwork(); - - var changed = false; - for (var attempt = 0; attempt < 6; attempt++) { - await Future.delayed(const Duration(seconds: 1)); - await ref.read(devicesProvider.notifier).load(); - final currentIds = ref - .read(devicesProvider) - .data - .map((device) => device.groupMemberId) - .toSet(); - if (!_sameSet(beforeIds, currentIds)) { - changed = true; - break; - } - } + final response = await ref.read(apiProvider).rescanNetwork(); + await ref.read(devicesProvider.notifier).load(); + final summary = response.data is Map + ? Map.from(response.data as Map) + : const {}; + final message = formatRescanSummary(summary); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - changed - ? 'Список устройств обновился' - : 'Сканирование завершилось, но новых устройств пока не видно', - ), + content: Text(message), duration: const Duration(seconds: 2), ), ); @@ -427,17 +407,31 @@ class _GroupEditScreenState extends ConsumerState { ); } - bool _sameSet(Set left, Set right) { - if (left.length != right.length) { - return false; - } - for (final item in left) { - if (!right.contains(item)) { - return false; - } - } - return true; +} + +int _summaryInt(Map summary, String key) { + final value = summary[key]; + if (value is int) { + return value; } + return int.tryParse(value?.toString() ?? '') ?? 0; +} + +String formatRescanSummary(Map summary) { + final found = _summaryInt(summary, 'found'); + final added = _summaryInt(summary, 'added'); + final updated = _summaryInt(summary, 'updated'); + final removed = _summaryInt(summary, 'removed_offline'); + + if (added == 0 && updated == 0 && removed == 0 && found == 0) { + return 'Сканирование завершено: устройства не найдены'; + } + + if (added == 0 && removed == 0) { + return 'Сканирование завершено: найдено $found, обновлено $updated'; + } + + return 'Сканирование завершено: найдено $found, новых $added, обновлено $updated, убрано $removed'; } class _ConflictBanner extends StatelessWidget { diff --git a/test/forms_widget_test.dart b/test/forms_widget_test.dart index d2b3b05..1840257 100644 --- a/test/forms_widget_test.dart +++ b/test/forms_widget_test.dart @@ -82,6 +82,39 @@ void main() { expect(api.createdGroupMacs, ['AA:BB']); }); + testWidgets('group edit screen shows backend rescan summary', ( + tester, + ) async { + final api = FakeIgnisApi( + devicesData: { + 'devices': [ + {'mac': 'AA:BB', 'name': 'Лампа 1'}, + ], + }, + groupsData: [], + )..rescanNetworkData = { + 'status': 'ok', + 'found': 3, + 'added': 1, + 'updated': 2, + 'removed_offline': 1, + 'pending_removal': 0, + 'online': 3, + }; + + await pumpTestApp(tester, child: const GroupEditScreen(), api: api); + await tester.pumpAndSettle(); + + await tester.tap(find.byTooltip('Пересканировать сеть')); + await tester.pumpAndSettle(); + + expect( + find.text('Сканирование завершено: найдено 3, новых 1, обновлено 2, убрано 1'), + findsOneWidget, + ); + expect(api.rescanCalls, 1); + }); + testWidgets('api keys screen validates and shows created key banner', ( tester, ) async { diff --git a/test/test_support.dart b/test/test_support.dart index daeffdf..a61f29d 100644 --- a/test/test_support.dart +++ b/test/test_support.dart @@ -36,6 +36,7 @@ class FakeIgnisApi extends IgnisApi { Object? eventLogData; Object? apiKeysData; Object? authData; + Object? rescanNetworkData; Object? devicesError; Object? scenesError; @@ -329,7 +330,17 @@ class FakeIgnisApi extends IgnisApi { if (error != null) throw error; return Response( requestOptions: RequestOptions(path: '/devices/rescan'), - data: {'ok': true}, + data: + rescanNetworkData ?? + { + 'status': 'ok', + 'found': 0, + 'added': 0, + 'updated': 0, + 'removed_offline': 0, + 'pending_removal': 0, + 'online': 0, + }, ); } }