Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Formatting
  • Loading branch information
romtsn committed Sep 30, 2024
commit 9a470c9e0bca844fddca021a1cd5ce7e1832d88b
40 changes: 37 additions & 3 deletions sentry-android-replay/api/sentry-android-replay.api
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public final class io/sentry/android/replay/GeneratedVideo {
public fun toString ()Ljava/lang/String;
}

public final class io/sentry/android/replay/ModifierExtensionsKt {
public static final fun sentryReplayIgnore (Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
public static final fun sentryReplayRedact (Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
}

public abstract interface class io/sentry/android/replay/Recorder : java/io/Closeable {
public abstract fun pause ()V
public abstract fun resume ()V
Expand Down Expand Up @@ -103,6 +108,11 @@ public final class io/sentry/android/replay/ScreenshotRecorderConfig$Companion {
public final fun from (Landroid/content/Context;Lio/sentry/SentryReplayOptions;)Lio/sentry/android/replay/ScreenshotRecorderConfig;
}

public final class io/sentry/android/replay/SentryReplayModifiers {
public static final field INSTANCE Lio/sentry/android/replay/SentryReplayModifiers;
public final fun getSentryPrivacy ()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
}

public final class io/sentry/android/replay/SessionReplayOptionsKt {
public static final fun getRedactAllImages (Lio/sentry/SentryReplayOptions;)Z
public static final fun getRedactAllText (Lio/sentry/SentryReplayOptions;)Z
Expand Down Expand Up @@ -130,6 +140,18 @@ public abstract interface class io/sentry/android/replay/gestures/TouchRecorderC
public abstract fun onTouchEvent (Landroid/view/MotionEvent;)V
}

public final class io/sentry/android/replay/util/AndroidTextLayout : io/sentry/android/replay/util/TextLayout {
public fun <init> (Landroid/text/Layout;)V
public fun getDominantTextColor ()Ljava/lang/Integer;
public fun getEllipsisCount (I)I
public fun getLineBottom (I)I
public fun getLineCount ()I
public fun getLineStart (I)I
public fun getLineTop (I)I
public fun getLineVisibleEnd (I)I
public fun getPrimaryHorizontal (II)F
}

public class io/sentry/android/replay/util/FixedWindowCallback : android/view/Window$Callback {
public final field delegate Landroid/view/Window$Callback;
public fun <init> (Landroid/view/Window$Callback;)V
Expand Down Expand Up @@ -160,6 +182,17 @@ public class io/sentry/android/replay/util/FixedWindowCallback : android/view/Wi
public fun onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
}

public abstract interface class io/sentry/android/replay/util/TextLayout {
public abstract fun getDominantTextColor ()Ljava/lang/Integer;
public abstract fun getEllipsisCount (I)I
public abstract fun getLineBottom (I)I
public abstract fun getLineCount ()I
public abstract fun getLineStart (I)I
public abstract fun getLineTop (I)I
public abstract fun getLineVisibleEnd (I)I
public abstract fun getPrimaryHorizontal (II)F
}

public abstract interface class io/sentry/android/replay/video/SimpleFrameMuxer {
public abstract fun getVideoTime ()J
public abstract fun isStarted ()Z
Expand Down Expand Up @@ -195,6 +228,7 @@ public abstract class io/sentry/android/replay/viewhierarchy/ViewHierarchyNode {
public final fun isObscured (Lio/sentry/android/replay/viewhierarchy/ViewHierarchyNode;)Z
public final fun isVisible ()Z
public final fun setChildren (Ljava/util/List;)V
public final fun setImportantForCaptureToAncestors (Z)V
public final fun setImportantForContentCapture (Z)V
public final fun traverse (Lkotlin/jvm/functions/Function1;)V
}
Expand All @@ -214,10 +248,10 @@ public final class io/sentry/android/replay/viewhierarchy/ViewHierarchyNode$Imag
}

public final class io/sentry/android/replay/viewhierarchy/ViewHierarchyNode$TextViewHierarchyNode : io/sentry/android/replay/viewhierarchy/ViewHierarchyNode {
public fun <init> (Landroid/text/Layout;Ljava/lang/Integer;IIFFIIFILio/sentry/android/replay/viewhierarchy/ViewHierarchyNode;ZZZLandroid/graphics/Rect;)V
public synthetic fun <init> (Landroid/text/Layout;Ljava/lang/Integer;IIFFIIFILio/sentry/android/replay/viewhierarchy/ViewHierarchyNode;ZZZLandroid/graphics/Rect;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lio/sentry/android/replay/util/TextLayout;Ljava/lang/Integer;IIFFIIFILio/sentry/android/replay/viewhierarchy/ViewHierarchyNode;ZZZLandroid/graphics/Rect;)V
public synthetic fun <init> (Lio/sentry/android/replay/util/TextLayout;Ljava/lang/Integer;IIFFIIFILio/sentry/android/replay/viewhierarchy/ViewHierarchyNode;ZZZLandroid/graphics/Rect;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getDominantColor ()Ljava/lang/Integer;
public final fun getLayout ()Landroid/text/Layout;
public final fun getLayout ()Lio/sentry/android/replay/util/TextLayout;
public final fun getPaddingLeft ()I
public final fun getPaddingTop ()I
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.graphics.Rect
import android.graphics.RectF
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.util.Log
import android.view.PixelCopy
import android.view.View
import android.view.ViewGroup
Expand All @@ -39,7 +38,6 @@ import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
import kotlin.math.roundToInt
import kotlin.system.measureNanoTime

@TargetApi(26)
internal class ScreenshotRecorder(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // to access internal vals and classes

package io.sentry.android.replay.util

import android.graphics.Rect
Expand Down Expand Up @@ -109,9 +110,11 @@ internal fun LayoutNode.findTextAttributes(): TextAttributes {
val modifierClassName = modifier::class.java.name
if (modifierClassName.contains("Text")) {
color = try {
(modifier::class.java.getDeclaredField("color")
.apply { isAccessible = true }
.get(modifier) as? ColorProducer)
(
modifier::class.java.getDeclaredField("color")
.apply { isAccessible = true }
.get(modifier) as? ColorProducer
)
?.invoke()
} catch (e: Throwable) {
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package io.sentry.android.replay.util
*/
interface TextLayout {
val lineCount: Int

/**
* Returns the dominant text color of the layout by looking at the [ForegroundColorSpan] spans if
* this text is a [Spanned] text. If the text is not a [Spanned] text or there are no spans, it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") // to access internal vals

package io.sentry.android.replay.viewhierarchy

import android.annotation.TargetApi
Expand Down Expand Up @@ -168,12 +169,16 @@ internal object ComposeViewHierarchyNode {
val rootNode = (view as? Owner)?.root ?: return false
rootNode.traverse(parent, options)
} catch (e: Throwable) {
options.logger.log(SentryLevel.ERROR, e, """
options.logger.log(
SentryLevel.ERROR,
e,
"""
Error traversing Compose tree. Most likely you're using an unsupported version of
androidx.compose.ui:ui. The minimum supported version is 1.5.0. If it's a newer
version, please open a github issue with the version you're using, so we can add
support for it.
""".trimIndent())
""".trimIndent()
)
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.sentry.android.replay.viewhierarchy

import android.annotation.TargetApi
import android.graphics.Rect
import android.text.Layout
import android.view.View
import android.widget.ImageView
import android.widget.TextView
Expand Down Expand Up @@ -273,26 +272,26 @@ sealed class ViewHierarchyNode(
val (isVisible, visibleRect) = view.isVisibleToUser()
val shouldRedact = isVisible && view.shouldRedact(options)
when (view) {
is TextView -> {
parent?.setImportantForCaptureToAncestors(true)
return TextViewHierarchyNode(
layout = view.layout?.let { AndroidTextLayout(it) },
dominantColor = view.currentTextColor.toOpaque(),
paddingLeft = view.totalPaddingLeft,
paddingTop = view.totalPaddingTopSafe,
x = view.x,
y = view.y,
width = view.width,
height = view.height,
elevation = (parent?.elevation ?: 0f) + view.elevation,
shouldRedact = shouldRedact,
distance = distance,
parent = parent,
isImportantForContentCapture = true,
isVisible = isVisible,
visibleRect = visibleRect
)
}
is TextView -> {
parent?.setImportantForCaptureToAncestors(true)
return TextViewHierarchyNode(
layout = view.layout?.let { AndroidTextLayout(it) },
dominantColor = view.currentTextColor.toOpaque(),
paddingLeft = view.totalPaddingLeft,
paddingTop = view.totalPaddingTopSafe,
x = view.x,
y = view.y,
width = view.width,
height = view.height,
elevation = (parent?.elevation ?: 0f) + view.elevation,
shouldRedact = shouldRedact,
distance = distance,
parent = parent,
isImportantForContentCapture = true,
isVisible = isVisible,
visibleRect = visibleRect
)
}

is ImageView -> {
parent?.setImportantForCaptureToAncestors(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
Expand All @@ -26,7 +24,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Color.Companion
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
Expand Down
9 changes: 9 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,14 @@ public final class io/sentry/PropagationContext {
public fun traceContext ()Lio/sentry/TraceContext;
}

public final class io/sentry/ReplayApi {
public fun <init> (Lio/sentry/ReplayController;)V
public fun getReplayId ()Lio/sentry/protocol/SentryId;
public fun isRecording ()Z
public fun pause ()V
public fun resume ()V
}

public abstract interface class io/sentry/ReplayBreadcrumbConverter {
public abstract fun convert (Lio/sentry/Breadcrumb;)Lio/sentry/rrweb/RRWebEvent;
}
Expand Down Expand Up @@ -1893,6 +1901,7 @@ public final class io/sentry/Sentry {
public static fun pushScope ()V
public static fun removeExtra (Ljava/lang/String;)V
public static fun removeTag (Ljava/lang/String;)V
public static fun replay ()Lio/sentry/ReplayApi;
public static fun reportFullDisplayed ()V
public static fun reportFullyDisplayed ()V
public static fun setCurrentHub (Lio/sentry/IHub;)V
Expand Down
16 changes: 4 additions & 12 deletions sentry/src/main/java/io/sentry/ReplayApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,22 @@ public ReplayApi(final @NotNull ReplayController replayController) {
this.replayController = replayController;
}

/**
* Resumes screen recording if it was paused.
*/
/** Resumes screen recording if it was paused. */
public void resume() {
replayController.resume();
}

/**
* Pauses screen recording entirely, but does not stop the current replay.
*/
/** Pauses screen recording entirely, but does not stop the current replay. */
public void pause() {
replayController.pause();
}

/**
* Returns whether the replay is currently running
*/
/** Returns whether the replay is currently running */
public boolean isRecording() {
return replayController.isRecording();
}

/**
* The id of the currently running replay or {@link SentryId#EMPTY_ID} if no replay is running
*/
/** The id of the currently running replay or {@link SentryId#EMPTY_ID} if no replay is running */
@NotNull
public SentryId getReplayId() {
return replayController.getReplayId();
Expand Down