sentry-react-native icon indicating copy to clipboard operation
sentry-react-native copied to clipboard

[Feature Request] View masking previews

Open amrfarid140 opened this issue 1 year ago • 4 comments

Problem Statement

I am integrating Session Replay in a React native based app with some custom masking rules. Each time I need to check how the view is masked, I have to run the app, wait for the session to appear on sentry, scroll the video to find my target screen and finally check the masking. Repeat until I've got it right.

This is very tedious to do and is error-prone.

Solution Brainstorm

Add a SentryMaskPreview component that can be used to render a masked child component. We can then rely on hot-reload to get a quick feedback loop when implementing custom masking logic.


The iOS native feature request: https://github.com/getsentry/sentry-cocoa/issues/4633

amrfarid140 avatar Dec 13 '24 07:12 amrfarid140

Hi @amrfarid140, thank you for the suggestion, this sounds good and helpful.

I think we could even add global option to show the custom masking previews.

Sentry.init({
  integrations: [
    mobileReplayIntegration({
      previewCustomMasks: true,
    }),
  ]
})

As you mentioned the process of the custom masking took some time, could you share a bit more about your experience?

Were you using the React Sentry.Mask and Sentry.Unmask components?

Have you encountered any unexpected behaviour with these classes?

krystofwoldrich avatar Dec 13 '24 11:12 krystofwoldrich

Thanks for considering @krystofwoldrich !

Were you using the React Sentry.Mask and Sentry.Unmask components? Have you encountered any unexpected behaviour with these classes?

Yes actually I have this one component that I am unable to Mask and wrapping it with Mask disables rendering it.

I will try to pull together a small reproducer project but for now. It goes like

/** A Text component that applies our own stylings **/

type TextProps = RnTextProps &
  PropsWithChildren & {
    children: string | ReactNode;
    color?: keyof ThemeColor;
    flex?: number;
    fontSize?: number;
    lineHeight?: number;
    letterSpacing?: number;
    preset?: TextPresetType;
    textAlign?: 'left' | 'center' | 'right';
    weight?: TextWeightType;
  };

export const Text = forwardRef<RNText, TextProps>(
  (
    {
      children,
      color = 'charcoal',
      flex,
      fontSize,
      lineHeight,
      preset = 'bodySmall',
      textAlign,
      style,
      weight,
      letterSpacing,
      ...rest
    },
    ref,
  ) => {
    const { theme } = useTheme();
    const textPreset = useMemo(() => textPresets(theme)[preset], [preset, theme]);

    return (
      <RNText
        ref={ref}
        style={[
          {
            ...textPreset,
            ...(weight ? textWeight(theme)[weight] : {}),
            color: theme.colors[color],
            fontSize: fontSize ? fontSize : textPreset.fontSize,
            lineHeight: lineHeight ? lineHeight : textPreset.lineHeight,
            textAlign: textAlign ? textAlign : textPreset.textAlign,
            letterSpacing: letterSpacing,
            flex: flex ? flex : undefined,
          },
          style ? style : {},
        ]}
        {...rest}
      >
        {children}
      </RNText>
    );
  },
);



/** When being used inside an RNText +  createElement**/
<RNText>
{React.createElement(Text, { children: "This text should be masked" })}
</RNText>

Then masking fails. It's completely unmasked by default for some reason even though Sentry SDK promises that all texts are masked by default.

What I tried is:

  1. Wrap the whole thing in Sentry.Mask -> still the text is unmasked
<Sentry.Mak>
<RNText>
{React.createElement(Text, { children: "This text should be masked" })}
</RNText>
</Sentry.Mask>
  1. Wrap the createElement in Sentry.Mask -> the text doesn't render
<RNText>
<Sentry.Mak>
{React.createElement(Text, { children: "This text should be masked" })}
</Sentry.Mask>
</RNText>
  1. Wrap our internal Text in Sentry.Mask -> the text doesn't render

I think the main problem though is that we are effectively rendering a Text inside a Text like this

<Text>
<Text>
This text should be masked
</Text>
</Text>

Which breaks the default Text masking. Other than that both the Mask component and the default masking rules work good for us in all other places.

amrfarid140 avatar Dec 13 '24 12:12 amrfarid140

Is there any update or news on implementing this option?

rodolfoBee avatar Sep 17 '25 11:09 rodolfoBee

Thank you for iterating on this @rodolfoBee 🙇 This is in our backlog. Please feel free to upvote the issue 👍

antonis avatar Sep 17 '25 12:09 antonis