@@ -64,49 +64,55 @@ class ScreenshotStabilizer<R> {
6464 await prevScreenshot.hasSameImageAs (screenshot)) {
6565 // Sucessfully captured a stable screenshot (repeated at least twice).
6666 _tries = 0 ;
67- if (prevScreenshot.flow.id == screenshot.flow.id) {
68- // If it's from the same (retry) flow, use the first screenshot timestamp.
69- await _callback (prevScreenshot);
70- } else {
71- // Otherwise this was called from a scheduler (in a new flow) so use
72- // the new timestamp.
73- await _callback (screenshot);
74- }
75- } else if (maxTries != null && _tries >= maxTries! ) {
76- throw Exception ('Failed to capture a stable screenshot. '
77- 'Giving up after $_tries tries.' );
78- } else {
79- // Add a delay to give the UI a chance to stabilize.
80- // Only do this on every other frame so that there's a greater chance
81- // of two subsequent frames being the same.
82- final sleepMs = _tries % 2 == 1 ? min (100 , 10 * (_tries - 1 )) : 0 ;
83-
84- if (_tries > 1 ) {
85- _options.logger (
86- SentryLevel .debug,
87- '${_recorder .logName }: '
88- 'Retrying screenshot capture due to UI changes. '
89- 'Delay before next capture: $sleepMs ms.' );
90- }
9167
92- if (sleepMs > 0 ) {
93- await Future <void >.delayed (Duration (milliseconds: sleepMs));
94- }
68+ // If it's from the same (retry) flow, use the first screenshot
69+ // timestamp. Otherwise this was called from a scheduler (in a new flow)
70+ // so use the new timestamp.
71+ await _callback ((prevScreenshot.flow.id == screenshot.flow.id)
72+ ? prevScreenshot
73+ : screenshot);
9574
96- final completer = Completer <void >();
97- ensureFrameAndAddCallback ((Duration sinceSchedulerEpoch) async {
98- _tries++ ;
99- try {
100- await _recorder.capture (_onImageCaptured, screenshot.flow);
101- completer.complete ();
102- } catch (e, stackTrace) {
103- completer.completeError (e, stackTrace);
104- }
105- });
106- return completer.future;
75+ // Do not just return the Future resulting from callback().
76+ // We need to await here so that the dispose runs ASAP.
77+ return ;
10778 }
10879 } finally {
80+ // Note: we need to dispose (free the memory) before recursion.
10981 prevScreenshot? .dispose ();
11082 }
83+
84+ if (maxTries != null && _tries >= maxTries! ) {
85+ throw Exception ('Failed to capture a stable screenshot. '
86+ 'Giving up after $_tries tries.' );
87+ } else {
88+ // Add a delay to give the UI a chance to stabilize.
89+ // Only do this on every other frame so that there's a greater chance
90+ // of two subsequent frames being the same.
91+ final sleepMs = _tries % 2 == 1 ? min (100 , 10 * (_tries - 1 )) : 0 ;
92+
93+ if (_tries > 1 ) {
94+ _options.logger (
95+ SentryLevel .debug,
96+ '${_recorder .logName }: '
97+ 'Retrying screenshot capture due to UI changes. '
98+ 'Delay before next capture: $sleepMs ms.' );
99+ }
100+
101+ if (sleepMs > 0 ) {
102+ await Future <void >.delayed (Duration (milliseconds: sleepMs));
103+ }
104+
105+ final completer = Completer <void >();
106+ ensureFrameAndAddCallback ((Duration sinceSchedulerEpoch) async {
107+ _tries++ ;
108+ try {
109+ await _recorder.capture (_onImageCaptured, screenshot.flow);
110+ completer.complete ();
111+ } catch (e, stackTrace) {
112+ completer.completeError (e, stackTrace);
113+ }
114+ });
115+ return completer.future;
116+ }
111117 }
112118}
0 commit comments