Skip to content

Commit 4bc7c72

Browse files
Fix persistent and disappearing error badges for Inspector (#9805)
* Fix persistent and disappearing error badges for Inspector * Add release note for error badge fix * Increase timeout for asyncEval tests on Windows CI * Revert "Increase timeout for asyncEval tests on Windows CI" This reverts commit 9b461c3. * Update packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * update error badge unread count incrementally * remove bad merge --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 0868729 commit 4bc7c72

4 files changed

Lines changed: 49 additions & 42 deletions

File tree

packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ class InspectorController extends DisposableController
157157
// TODO(kenz): When this method is called outside createState(), this post
158158
// frame callback can be removed.
159159
WidgetsBinding.instance.addPostFrameCallback((_) {
160-
serviceConnection.errorBadgeManager.clearErrorCount(InspectorScreen.id);
160+
serviceConnection.errorBadgeManager.clearErrors(InspectorScreen.id);
161161
});
162-
filterErrors();
163162
}
164163

165164
void _handleConnectionStop() {
@@ -381,8 +380,6 @@ class InspectorController extends DisposableController
381380
return;
382381
}
383382

384-
filterErrors();
385-
386383
return _waitForPendingUpdateDone();
387384
}
388385

@@ -404,13 +401,6 @@ class InspectorController extends DisposableController
404401
await onForceRefresh();
405402
}
406403

407-
void filterErrors() {
408-
serviceConnection.errorBadgeManager.filterErrors(
409-
InspectorScreen.id,
410-
(id) => hasDiagnosticsValue(InspectorInstanceRef(id)),
411-
);
412-
}
413-
414404
void setActivate(bool enabled) {
415405
if (!enabled) {
416406
onIsolateStopped();
@@ -977,17 +967,12 @@ class InspectorController extends DisposableController
977967
_selectedErrorIndex.value = errorIndex;
978968

979969
if (errorIndex != null) {
980-
// Mark the error as "seen" as this will render slightly differently
981-
// so the user can track which errored nodes they've viewed.
970+
// Marking an error as read will automatically update the badge count to
971+
// reflect the remaining unread errors.
982972
serviceConnection.errorBadgeManager.markErrorAsRead(
983973
InspectorScreen.id,
984974
errors[inspectorRef!]!,
985975
);
986-
// Also clear the error badge since new errors may have arrived while
987-
// the inspector was visible (normally they're cleared when visiting
988-
// the screen) and visiting an errored node seems an appropriate
989-
// acknowledgement of the errors.
990-
serviceConnection.errorBadgeManager.clearErrorCount(InspectorScreen.id);
991976
}
992977
}
993978

packages/devtools_app/lib/src/shared/managers/error_badge_manager.dart

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class ErrorBadgeManager extends DisposableController
6666

6767
final inspectableError = _extractInspectableError(e);
6868
if (inspectableError != null) {
69-
incrementBadgeCount(InspectorScreen.id);
7069
appendError(InspectorScreen.id, inspectableError);
7170
}
7271
}
@@ -113,6 +112,10 @@ class ErrorBadgeManager extends DisposableController
113112
}
114113

115114
void incrementBadgeCount(String screenId) {
115+
if (_activeErrors.containsKey(screenId)) {
116+
return;
117+
}
118+
116119
final notifier = _errorCountNotifier(screenId);
117120
if (notifier == null) return;
118121

@@ -124,12 +127,40 @@ class ErrorBadgeManager extends DisposableController
124127
final errors = _activeErrors[screenId];
125128
if (errors == null) return;
126129

130+
final previousError = errors.value[error.id];
131+
127132
// Build a new map with the new error. Adding to the existing map
128133
// won't cause the ValueNotifier to fire (and it's not permitted to call
129134
// notifyListeners() directly).
130135
final newValue = LinkedHashMap<String, DevToolsError>.of(errors.value);
131136
newValue[error.id] = error;
132137
errors.value = newValue;
138+
139+
if (previousError == null) {
140+
if (!error.read) {
141+
_incrementUnreadCount(screenId);
142+
}
143+
return;
144+
}
145+
146+
if (previousError.read && !error.read) {
147+
_incrementUnreadCount(screenId);
148+
} else if (!previousError.read && error.read) {
149+
_decrementUnreadCount(screenId);
150+
}
151+
}
152+
153+
void _incrementUnreadCount(String screenId) {
154+
final notifier = _errorCountNotifier(screenId);
155+
if (notifier == null) return;
156+
notifier.value = notifier.value + 1;
157+
}
158+
159+
void _decrementUnreadCount(String screenId) {
160+
final notifier = _errorCountNotifier(screenId);
161+
if (notifier == null) return;
162+
if (notifier.value == 0) return;
163+
notifier.value = notifier.value - 1;
133164
}
134165

135166
ValueListenable<int> errorCountNotifier(String screenId) {
@@ -150,25 +181,20 @@ class ErrorBadgeManager extends DisposableController
150181
}
151182

152183
void clearErrorCount(String screenId) {
184+
if (_activeErrors.containsKey(screenId)) {
185+
return;
186+
}
153187
_activeErrorCounts[screenId]?.value = 0;
154188
}
155189

156190
void clearErrors(String screenId) {
157-
clearErrorCount(screenId);
158-
_activeErrors[screenId]?.value = LinkedHashMap<String, DevToolsError>();
159-
}
160-
161-
void filterErrors(String screenId, bool Function(String id) isValid) {
162-
final errors = _activeErrors[screenId];
163-
if (errors == null) return;
164-
165-
final oldCount = errors.value.length;
166-
final newValue = Map.fromEntries(
167-
errors.value.entries.where((e) => isValid(e.key)),
168-
);
169-
if (newValue.length != oldCount) {
170-
errors.value = newValue as LinkedHashMap<String, DevToolsError>;
191+
if (!_activeErrors.containsKey(screenId)) {
192+
clearErrorCount(screenId);
193+
return;
171194
}
195+
196+
_activeErrors[screenId]?.value = LinkedHashMap<String, DevToolsError>();
197+
_activeErrorCounts[screenId]?.value = 0;
172198
}
173199

174200
void markErrorAsRead(String screenId, DevToolsError error) {
@@ -188,6 +214,7 @@ class ErrorBadgeManager extends DisposableController
188214
return MapEntry(e.key, e.value.asRead());
189215
}),
190216
);
217+
_decrementUnreadCount(screenId);
191218
}
192219
}
193220

packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ To learn more about DevTools, check out the
2121

2222
## Inspector updates
2323

24-
TODO: Remove this section if there are not any updates.
24+
- Fixed an issue where the Inspector error badge count would improperly increase or disappear during navigation. [#9524](https://github.com/flutter/devtools/issues/9524)
2525

2626
## Performance updates
2727

packages/devtools_app/test/shared/managers/error_badge_manager_test.dart

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ import 'package:devtools_app/src/screens/profiler/profiler_screen.dart';
1313
import 'package:devtools_app/src/shared/managers/error_badge_manager.dart';
1414
import 'package:flutter_test/flutter_test.dart';
1515

16-
final supportedScreenIds = [
17-
InspectorScreen.id,
18-
PerformanceScreen.id,
19-
NetworkScreen.id,
20-
];
16+
final screensWithCountOnly = [PerformanceScreen.id, NetworkScreen.id];
2117

2218
final allScreenIds = [
2319
InspectorScreen.id,
@@ -55,7 +51,7 @@ void main() {
5551
allScreenIds.forEach(errorBadgeManager.incrementBadgeCount);
5652

5753
for (final id in allScreenIds) {
58-
if (supportedScreenIds.contains(id)) {
54+
if (screensWithCountOnly.contains(id)) {
5955
expect(errorBadgeManager.errorCountNotifier(id).value, equals(1));
6056
} else {
6157
expect(errorBadgeManager.errorCountNotifier(id).value, equals(0));
@@ -67,7 +63,7 @@ void main() {
6763
allScreenIds.forEach(errorBadgeManager.incrementBadgeCount);
6864

6965
for (final id in allScreenIds) {
70-
if (supportedScreenIds.contains(id)) {
66+
if (screensWithCountOnly.contains(id)) {
7167
expect(errorBadgeManager.errorCountNotifier(id).value, equals(1));
7268
} else {
7369
expect(errorBadgeManager.errorCountNotifier(id).value, equals(0));
@@ -108,7 +104,6 @@ void main() {
108104
InspectorScreen.id,
109105
DevToolsError('An error', InspectorScreen.id),
110106
);
111-
errorBadgeManager.incrementBadgeCount(InspectorScreen.id);
112107

113108
expect(getActiveErrorCount(InspectorScreen.id), equals(1));
114109
expect(

0 commit comments

Comments
 (0)