Skip to content

Commit 77cce7c

Browse files
committed
Add debounce to ScreenshotWidget
1 parent 136c365 commit 77cce7c

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

flutter/lib/src/event_processor/screenshot_event_processor.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class ScreenshotEventProcessor implements EventProcessor {
1919
bool get _hasSentryScreenshotWidget =>
2020
sentryScreenshotWidgetGlobalKey.currentContext != null;
2121

22+
final _debounceDuration = Duration(milliseconds: 100);
23+
24+
/// Only apply this event processor every [debounceDuration] duration.
25+
DateTime? _lastApplyCall;
26+
27+
/// The debounce duration for applying this event processor.
28+
Duration get debounceDuration => _debounceDuration;
29+
2230
@override
2331
Future<SentryEvent?> apply(SentryEvent event, Hint hint) async {
2432
if (event is SentryTransaction) {
@@ -30,6 +38,19 @@ class ScreenshotEventProcessor implements EventProcessor {
3038
_hasSentryScreenshotWidget) {
3139
return event;
3240
}
41+
42+
final now = DateTime.now();
43+
final difference = _lastApplyCall?.difference(DateTime.now()).abs();
44+
_lastApplyCall = now;
45+
46+
if (difference != null && difference < debounceDuration) {
47+
_options.logger(
48+
SentryLevel.warning,
49+
'Skipping screenshot due to too many calls within a short time frame.',
50+
);
51+
return event; // Debounce
52+
}
53+
3354
final beforeScreenshot = _options.beforeScreenshot;
3455
if (beforeScreenshot != null) {
3556
try {

flutter/lib/src/integrations/screenshot_integration.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:sentry/sentry.dart';
22
import '../event_processor/screenshot_event_processor.dart';
33
import '../sentry_flutter_options.dart';
4+
import '../utils/debouncer.dart';
45

56
/// Adds [ScreenshotEventProcessor] to options event processors if
67
/// [SentryFlutterOptions.attachScreenshot] is true

flutter/test/event_processor/screenshot_event_processor_test.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,60 @@ void main() {
178178
expect(beforeScreenshotHint, hint);
179179
});
180180
});
181+
182+
group("debounce", () {
183+
testWidgets("limits added screenshots within debounce timeframe",
184+
(tester) async {
185+
// Run with real async https://stackoverflow.com/a/54021863
186+
await tester.runAsync(() async {
187+
final sut = fixture.getSut(FlutterRenderer.canvasKit, false);
188+
189+
await tester.pumpWidget(SentryScreenshotWidget(
190+
child: Text('Catching Pokémon is a snap!',
191+
textDirection: TextDirection.ltr)));
192+
193+
final throwable = Exception();
194+
195+
final firstEvent = SentryEvent(throwable: throwable);
196+
final firstHint = Hint();
197+
198+
final secondEvent = SentryEvent(throwable: throwable);
199+
final secondHint = Hint();
200+
201+
await sut.apply(firstEvent, firstHint);
202+
await sut.apply(secondEvent, secondHint);
203+
204+
expect(firstHint.screenshot, isNotNull);
205+
expect(secondHint.screenshot, isNull);
206+
});
207+
});
208+
209+
testWidgets("adds screenshots after debounce timeframe", (tester) async {
210+
// Run with real async https://stackoverflow.com/a/54021863
211+
await tester.runAsync(() async {
212+
final sut = fixture.getSut(FlutterRenderer.canvasKit, false);
213+
214+
await tester.pumpWidget(SentryScreenshotWidget(
215+
child: Text('Catching Pokémon is a snap!',
216+
textDirection: TextDirection.ltr)));
217+
218+
final throwable = Exception();
219+
220+
final firstEvent = SentryEvent(throwable: throwable);
221+
final firstHint = Hint();
222+
223+
final secondEvent = SentryEvent(throwable: throwable);
224+
final secondHint = Hint();
225+
226+
await sut.apply(firstEvent, firstHint);
227+
await Future<void>.delayed(sut.debounceDuration);
228+
await sut.apply(secondEvent, secondHint);
229+
230+
expect(firstHint.screenshot, isNotNull);
231+
expect(secondHint.screenshot, isNotNull);
232+
});
233+
});
234+
});
181235
}
182236

183237
class Fixture {

0 commit comments

Comments
 (0)