@@ -20,7 +20,7 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
20
20
late final ScheduledScreenshotRecorderCallback _callback;
21
21
var _status = _Status .running;
22
22
late final Duration _frameDuration;
23
- late final _idleFrameFiller = _IdleFrameFiller (_frameDuration, _onScreenshot);
23
+ // late final _idleFrameFiller = _IdleFrameFiller(_frameDuration, _onScreenshot);
24
24
25
25
@override
26
26
@protected
@@ -35,8 +35,7 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
35
35
_frameDuration = Duration (milliseconds: 1000 ~ / config.frameRate);
36
36
assert (_frameDuration.inMicroseconds > 0 );
37
37
38
- _scheduler = Scheduler (_frameDuration, _capture,
39
- options.bindingUtils.instance! .addPostFrameCallback);
38
+ _scheduler = Scheduler (_frameDuration, _capture, _addPostFrameCallback);
40
39
41
40
if (callback != null ) {
42
41
_callback = callback;
@@ -47,6 +46,12 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
47
46
_callback = callback;
48
47
}
49
48
49
+ void _addPostFrameCallback (FrameCallback callback) {
50
+ options.bindingUtils.instance!
51
+ ..ensureVisualUpdate ()
52
+ ..addPostFrameCallback (callback);
53
+ }
54
+
50
55
void start () {
51
56
assert (() {
52
57
// The following fails if callback hasn't been provided
@@ -74,14 +79,15 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
74
79
Future <void > stop () async {
75
80
options.logger (SentryLevel .debug, "$logName : stopping capture." );
76
81
_status = _Status .stopped;
77
- await Future .wait ([_scheduler.stop (), _idleFrameFiller.stop ()]);
82
+ await _scheduler.stop ();
83
+ // await Future.wait([_scheduler.stop(), _idleFrameFiller.stop()]);
78
84
options.logger (SentryLevel .debug, "$logName : capture stopped." );
79
85
}
80
86
81
87
Future <void > pause () async {
82
88
if (_status == _Status .running) {
83
89
_status = _Status .paused;
84
- _idleFrameFiller.pause ();
90
+ // _idleFrameFiller.pause();
85
91
await _scheduler.stop ();
86
92
}
87
93
}
@@ -90,7 +96,7 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
90
96
if (_status == _Status .paused) {
91
97
_status = _Status .running;
92
98
_startScheduler ();
93
- _idleFrameFiller.resume ();
99
+ // _idleFrameFiller.resume();
94
100
}
95
101
}
96
102
@@ -104,7 +110,7 @@ class ScheduledScreenshotRecorder extends ReplayScreenshotRecorder {
104
110
final screenshot = ScreenshotPng (
105
111
image.width, image.height, imageData, capturedScreenshot.timestamp);
106
112
await _onScreenshot (screenshot, true );
107
- _idleFrameFiller.actualFrameReceived (screenshot);
113
+ // _idleFrameFiller.actualFrameReceived(screenshot);
108
114
} else {
109
115
options.logger (
110
116
SentryLevel .debug,
@@ -140,69 +146,71 @@ class ScreenshotPng {
140
146
141
147
const ScreenshotPng (this .width, this .height, this .data, this .timestamp);
142
148
}
143
-
144
- // Workaround for https://github.com/getsentry/sentry-java/issues/3677
145
- // In short: when there are no postFrameCallbacks issued by Flutter (because
146
- // there are no animations or user interactions), the replay recorder will
147
- // need to get screenshots at a fixed frame rate. This class is responsible for
148
- // filling the gaps between actual frames with the most recent frame.
149
- class _IdleFrameFiller {
150
- final Duration _interval;
151
- final ScheduledScreenshotRecorderCallback _callback;
152
- var _status = _Status .running;
153
- Future <void >? _scheduled;
154
- ScreenshotPng ? _mostRecent;
155
-
156
- _IdleFrameFiller (this ._interval, this ._callback);
157
-
158
- void actualFrameReceived (ScreenshotPng screenshot) {
159
- // We store the most recent frame but only repost it when the most recent
160
- // one is the same instance (unchanged).
161
- _mostRecent = screenshot;
162
- // Also, the initial reposted frame will be delayed to allow actual frames
163
- // to cancel the reposting.
164
- repostLater (_interval * 1.5 , screenshot);
165
- }
166
-
167
- Future <void > stop () async {
168
- _status = _Status .stopped;
169
- final scheduled = _scheduled;
170
- _scheduled = null ;
171
- _mostRecent = null ;
172
- await scheduled;
173
- }
174
-
175
- void pause () {
176
- if (_status == _Status .running) {
177
- _status = _Status .paused;
178
- }
179
- }
180
-
181
- void resume () {
182
- if (_status == _Status .paused) {
183
- _status = _Status .running;
184
- }
185
- }
186
-
187
- void repostLater (Duration delay, ScreenshotPng screenshot) {
188
- _scheduled = Future .delayed (delay, () async {
189
- if (_status == _Status .stopped) {
190
- return ;
191
- }
192
-
193
- // Only repost if the screenshot haven't changed.
194
- if (screenshot == _mostRecent) {
195
- if (_status == _Status .running) {
196
- // We don't strictly need to await here but it helps to reduce load.
197
- // If the callback takes a long time, we still wait between calls,
198
- // based on the configured rate.
199
- await _callback (screenshot, false );
200
- }
201
- // On subsequent frames, we stick to the actual frame rate.
202
- repostLater (_interval, screenshot);
203
- }
204
- });
205
- }
206
- }
149
+ // TODO this is currently unused because we've decided to capture on every
150
+ // frame. Consider removing if we don't reverse the decision in the future.
151
+
152
+ // /// Workaround for https://github.com/getsentry/sentry-java/issues/3677
153
+ // /// In short: when there are no postFrameCallbacks issued by Flutter (because
154
+ // /// there are no animations or user interactions), the replay recorder will
155
+ // /// need to get screenshots at a fixed frame rate. This class is responsible for
156
+ // /// filling the gaps between actual frames with the most recent frame.
157
+ // class _IdleFrameFiller {
158
+ // final Duration _interval;
159
+ // final ScheduledScreenshotRecorderCallback _callback;
160
+ // var _status = _Status.running;
161
+ // Future<void>? _scheduled;
162
+ // ScreenshotPng? _mostRecent;
163
+
164
+ // _IdleFrameFiller(this._interval, this._callback);
165
+
166
+ // void actualFrameReceived(ScreenshotPng screenshot) {
167
+ // // We store the most recent frame but only repost it when the most recent
168
+ // // one is the same instance (unchanged).
169
+ // _mostRecent = screenshot;
170
+ // // Also, the initial reposted frame will be delayed to allow actual frames
171
+ // // to cancel the reposting.
172
+ // repostLater(_interval * 1.5, screenshot);
173
+ // }
174
+
175
+ // Future<void> stop() async {
176
+ // _status = _Status.stopped;
177
+ // final scheduled = _scheduled;
178
+ // _scheduled = null;
179
+ // _mostRecent = null;
180
+ // await scheduled;
181
+ // }
182
+
183
+ // void pause() {
184
+ // if (_status == _Status.running) {
185
+ // _status = _Status.paused;
186
+ // }
187
+ // }
188
+
189
+ // void resume() {
190
+ // if (_status == _Status.paused) {
191
+ // _status = _Status.running;
192
+ // }
193
+ // }
194
+
195
+ // void repostLater(Duration delay, ScreenshotPng screenshot) {
196
+ // _scheduled = Future.delayed(delay, () async {
197
+ // if (_status == _Status.stopped) {
198
+ // return;
199
+ // }
200
+
201
+ // // Only repost if the screenshot haven't changed.
202
+ // if (screenshot == _mostRecent) {
203
+ // if (_status == _Status.running) {
204
+ // // We don't strictly need to await here but it helps to reduce load.
205
+ // // If the callback takes a long time, we still wait between calls,
206
+ // // based on the configured rate.
207
+ // await _callback(screenshot, false);
208
+ // }
209
+ // // On subsequent frames, we stick to the actual frame rate.
210
+ // repostLater(_interval, screenshot);
211
+ // }
212
+ // });
213
+ // }
214
+ // }
207
215
208
216
enum _Status { stopped, running, paused }
0 commit comments