11package io.sentry.android.replay
22
3+ import android.annotation.SuppressLint
34import android.annotation.TargetApi
45import android.content.Context
56import android.graphics.Bitmap
@@ -21,6 +22,7 @@ import io.sentry.SentryLevel.INFO
2122import io.sentry.SentryLevel.WARNING
2223import io.sentry.SentryOptions
2324import io.sentry.SentryReplayOptions
25+ import io.sentry.android.replay.util.DebugOverlayDrawable
2426import io.sentry.android.replay.util.MainLooperHandler
2527import io.sentry.android.replay.util.addOnDrawListenerSafe
2628import io.sentry.android.replay.util.getVisibleRects
@@ -37,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean
3739import kotlin.LazyThreadSafetyMode.NONE
3840import kotlin.math.roundToInt
3941
42+ @SuppressLint(" UseKtx" )
4043@TargetApi(26 )
4144internal class ScreenshotRecorder (
4245 val config : ScreenshotRecorderConfig ,
@@ -46,6 +49,10 @@ internal class ScreenshotRecorder(
4649 private val screenshotRecorderCallback : ScreenshotRecorderCallback ?
4750) : ViewTreeObserver.OnDrawListener {
4851
52+ private companion object {
53+ private const val DEBUG_MODE = false
54+ }
55+
4956 private var rootView: WeakReference <View >? = null
5057 private val maskingPaint by lazy(NONE ) { Paint () }
5158 private val singlePixelBitmap: Bitmap by lazy(NONE ) {
@@ -70,6 +77,8 @@ internal class ScreenshotRecorder(
7077 private val isCapturing = AtomicBoolean (true )
7178 private val lastCaptureSuccessful = AtomicBoolean (false )
7279
80+ private val debugOverlayDrawable = DebugOverlayDrawable ()
81+
7382 fun capture () {
7483 if (! isCapturing.get()) {
7584 if (options.sessionReplay.isDebug) {
@@ -121,6 +130,8 @@ internal class ScreenshotRecorder(
121130 root.traverse(viewHierarchy, options)
122131
123132 recorder.submitSafely(options, " screenshot_recorder.mask" ) {
133+ val debugMasks = mutableListOf<Rect >()
134+
124135 val canvas = Canvas (screenshot)
125136 canvas.setMatrix(prescaledMatrix)
126137 viewHierarchy.traverse { node ->
@@ -158,10 +169,16 @@ internal class ScreenshotRecorder(
158169 visibleRects.forEach { rect ->
159170 canvas.drawRoundRect(RectF (rect), 10f , 10f , maskingPaint)
160171 }
172+ if (DEBUG_MODE ) {
173+ debugMasks.addAll(visibleRects)
174+ }
161175 }
162176 return @traverse true
163177 }
164178
179+ if (DEBUG_MODE ) {
180+ mainLooperHandler.post { debugOverlayDrawable.update(debugMasks) }
181+ }
165182 screenshotRecorderCallback?.onScreenshotRecorded(screenshot)
166183 lastCaptureSuccessful.set(true )
167184 contentChanged.set(false )
@@ -194,11 +211,18 @@ internal class ScreenshotRecorder(
194211 // next bind the new root
195212 rootView = WeakReference (root)
196213 root.addOnDrawListenerSafe(this )
214+ if (DEBUG_MODE ) {
215+ root.overlay.add(debugOverlayDrawable)
216+ }
217+
197218 // invalidate the flag to capture the first frame after new window is attached
198219 contentChanged.set(true )
199220 }
200221
201222 fun unbind (root : View ? ) {
223+ if (DEBUG_MODE ) {
224+ root?.overlay?.remove(debugOverlayDrawable)
225+ }
202226 root?.removeOnDrawListenerSafe(this )
203227 }
204228
0 commit comments