Skip to content

Introduce Contentpass layer and OneTrust CMP adapters#48

Merged
0x7f merged 2 commits intomainfrom
contentpass-layer
Feb 13, 2026
Merged

Introduce Contentpass layer and OneTrust CMP adapters#48
0x7f merged 2 commits intomainfrom
contentpass-layer

Conversation

@0x7f
Copy link
Member

@0x7f 0x7f commented Feb 9, 2026

No description provided.

@0x7f 0x7f requested a review from slawomirzaba February 9, 2026 11:22
@0x7f 0x7f force-pushed the contentpass-layer branch 4 times, most recently from b1ed3dd to 6ac2466 Compare February 9, 2026 13:35
@0x7f 0x7f force-pushed the contentpass-layer branch from 6ac2466 to 9f3eddf Compare February 13, 2026 11:05
@0x7f 0x7f changed the title feat: introduce contentpass layer and cmp adapters Introduce Contentpass layer and OneTrust CMP adapters Feb 13, 2026
@0x7f 0x7f merged commit a9f242d into main Feb 13, 2026
3 checks passed
const [cmpFailed, setCmpFailed] = useState(false);
const [cmpAdapter, setCmpAdapter] = useState<CmpAdapter | null>(null);

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleaner:

useEffect(() => {
  const initCmp = async () => {
    try {
      await OTPublishersNativeSDK.startSDK(
        ONETRUST_CDN_LOCATION,
        ONETRUST_APP_ID,
        ONETRUST_LANGUAGE_CODE,
        {},
        false
      );

      const onetrustCmpAdapter: CmpAdapter =
        await createOnetrustCmpAdapter(OTPublishersNativeSDK);

      setCmpAdapter(onetrustCmpAdapter);
      setCmpReady(true);
    } catch (error: any) {
      console.error('Failed to initialize CMP', error);
      setCmpFailed(true);
    }
  };

  initCmp();
}, []);

export default function App() {
const [cmpReady, setCmpReady] = useState(false);
const [cmpFailed, setCmpFailed] = useState(false);
const [cmpAdapter, setCmpAdapter] = useState<CmpAdapter | null>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe cleaner to have just type CmpStatus = 'loading' | 'ready' | 'error';

and
const [status, setStatus] = useState('loading'); ad cmpFailed and cmpAdapter can be removed?

and then:

  if (status === 'loading') {
    return (
      <View style={styles.container}>
        <Text>Loading CMP...</Text>
      </View>
    );
  }

  if (status === 'error' || !cmpAdapter) {
    return (
      <View style={styles.container}>
        <Text>Failed to load CMP</Text>
      </View>
    );
  }

return (
<ContentpassSdkProvider contentpassConfig={contentpassConfig}>
<ContentpassConsentGate
cmpAdapter={cmpAdapter!}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for explanation mark with if above

hideAppWhenVisible={false}
>
<View style={styles.container}>
<Content cmpAdapter={cmpAdapter!} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same here

<ContentpassSdkProvider contentpassConfig={contentpassConfig}>
<ContentpassConsentGate
cmpAdapter={cmpAdapter!}
contentpassConfig={contentpassConfig}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ContentpassSdkProvider could expose contentpassConfig so no need to pass it to ContentpassConsentGate

const [isVisible, setIsVisible] = useState(false);
const [cpAuthState, setCpAuthState] = useState<ContentpassState | null>(null);
const [isShowingSecondLayer, setIsShowingSecondLayer] = useState(false);
const [isShowingContentpass, setIsShowingContentpass] = useState(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to have isShowingSecondLayer and isShowingContentpass as separated states? Is it possible for example to have them true in the same time? Maybe we could have one state with enum for it?


// Policy for setting the visibility of the consent layer
useEffect(() => {
const invalidStates = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalidStates doesn't have to be in effect

isShowingSecondLayer,
isVisible,
onVisibilityChange,
]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this whole useEffect is complex and not needed. We can remove:
const [isVisible, setIsVisible] = useState(false);

calculate isVisible in memo:

const isVisible = useMemo(() => {
  const invalidStates = [
    ContentpassStateType.INITIALISING,
    ContentpassStateType.ERROR,
  ];

  if (!cmpReady || !cpAuthState || invalidStates.includes(cpAuthState.state)) {
    return false;
  }

  if (isShowingSecondLayer || isShowingContentpass) {
    return false; 
  }

  const isFine =
    cpAuthState.state === ContentpassStateType.AUTHENTICATED || hasFullConsent;

  return !isFine;
}, [
  cmpReady,
  cpAuthState,
  hasFullConsent,
  isShowingSecondLayer,
  isShowingContentpass,
]);

have prev visibility on ref : const prevVisibleRef = React.useRef<boolean | null>(null);

and then simplify effect to:

useEffect(() => {
  if (prevVisibleRef.current === null) {
    prevVisibleRef.current = isVisible;
    return;
  }
  if (prevVisibleRef.current !== isVisible) {
    prevVisibleRef.current = isVisible;
    onVisibilityChange?.(isVisible);
  }
}, [isVisible, onVisibilityChange]);

}

cmpAdapter?.onConsentStatusChange?.((v: boolean) => setHasFullConsent(v));
cmpAdapter.getRequiredPurposes().then((v: string[]) => setPurposesList(v));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shoudn;t we recalculate it after consent changes?

return <>{children}</>;
}

function renderContentpassLayer() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderContentpassLayer() is a function declared on every render; Would be better to extract it to separated compnent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants