1- import React , { useLayoutEffect , useMemo , useRef } from 'react' ;
1+ import React , { useLayoutEffect , useRef } from 'react' ;
22import { StyleSheet , type StyleProp , type ViewStyle } from 'react-native' ;
33import {
44 WebView ,
@@ -9,12 +9,9 @@ import {
99import type { BridgeTransport } from './bridge/client' ;
1010import { encodeEnvelope , type Envelope } from './bridge/envelope' ;
1111import { SeatLayerError } from './errors' ;
12- import { seatLayerWebDocument } from './generated/webDocument' ;
13- import type { ReadyInfo , SeatLayerConfiguration } from './types' ;
12+ import { seatLayerMobileOrigin , seatLayerMobilePageUrl , type ReadyInfo , type SeatLayerConfiguration } from './types' ;
1413import type { SeatLayerController } from './controller' ;
1514
16- const documentBaseUrl = 'https://seatlayer.local/' ;
17-
1815export interface SeatLayerViewProps {
1916 controller : SeatLayerController ;
2017 configuration : SeatLayerConfiguration ;
@@ -38,6 +35,17 @@ const NativeWebView = WebView as unknown as React.ForwardRefExoticComponent<
3835 WebViewProps & React . RefAttributes < WebViewHandle >
3936> ;
4037
38+ const configurationIds = new WeakMap < object , number > ( ) ;
39+ let nextConfigurationId = 0 ;
40+
41+ function configurationIdentity ( configuration : object ) : number {
42+ const existing = configurationIds . get ( configuration ) ;
43+ if ( existing !== undefined ) return existing ;
44+ nextConfigurationId += 1 ;
45+ configurationIds . set ( configuration , nextConfigurationId ) ;
46+ return nextConfigurationId ;
47+ }
48+
4149export function SeatLayerView ( {
4250 controller,
4351 configuration,
@@ -49,22 +57,27 @@ export function SeatLayerView({
4957 onLoadError,
5058} : SeatLayerViewProps ) : React . ReactElement {
5159 const webView = useRef < WebViewHandle | null > ( null ) ;
52- const configurationKey = useMemo (
53- ( ) => JSON . stringify ( configuration ) ,
54- [ configuration ] ,
55- ) ;
56- const viewKey = `${ configurationKey } :${ String ( reloadKey ?? '' ) } ` ;
60+ const onReadyRef = useRef ( onReady ) ;
61+ const onLoadErrorRef = useRef ( onLoadError ) ;
62+ onReadyRef . current = onReady ;
63+ onLoadErrorRef . current = onLoadError ;
64+ // Credentials and provider functions must never be serialized into a React
65+ // key. Depending on the configuration object reloads safely when either is
66+ // replaced, without putting the token in a string, log, or native view key.
67+ const viewKey = `${ configurationIdentity ( configuration ) } :${ String (
68+ reloadKey ?? 'seatlayer' ,
69+ ) } `;
5770
5871 useLayoutEffect ( ( ) => {
5972 const transport = new ReactNativeWebViewTransport ( ( ) => webView . current ) ;
6073 let active = true ;
6174 controller . beginHandshake ( transport , configuration ) . then (
6275 ( info ) => {
63- if ( active ) onReady ?.( info ) ;
76+ if ( active ) onReadyRef . current ?.( info ) ;
6477 } ,
6578 ( error : unknown ) => {
6679 if ( ! active ) return ;
67- onLoadError ?.(
80+ onLoadErrorRef . current ?.(
6881 error instanceof SeatLayerError
6982 ? error
7083 : SeatLayerError . transport ( 'SeatLayer handshake failed.' , error ) ,
@@ -78,10 +91,12 @@ export function SeatLayerView({
7891 false ,
7992 ) ;
8093 } ;
81- } , [ configurationKey , controller , onLoadError , onReady , reloadKey ] ) ;
94+ } , [ configuration , controller , reloadKey ] ) ;
8295
8396 const onMessage = ( event : WebViewMessageEvent ) : void => {
84- controller . ingestRaw ( event . nativeEvent . data ) ;
97+ if ( event . nativeEvent . url === seatLayerMobilePageUrl ) {
98+ controller . ingestRaw ( event . nativeEvent . data ) ;
99+ }
85100 } ;
86101
87102 const reportLoadFailure = ( message : string ) : void => {
@@ -95,8 +110,8 @@ export function SeatLayerView({
95110 testID = { testID }
96111 accessibilityLabel = { accessibilityLabel }
97112 style = { [ styles . webView , style ] }
98- source = { { html : seatLayerWebDocument , baseUrl : documentBaseUrl } }
99- originWhitelist = { [ '*' ] }
113+ source = { { uri : seatLayerMobilePageUrl } }
114+ originWhitelist = { [ seatLayerMobileOrigin ] }
100115 javaScriptEnabled
101116 domStorageEnabled
102117 mixedContentMode = "never"
@@ -118,9 +133,7 @@ export function SeatLayerView({
118133 )
119134 }
120135 onShouldStartLoadWithRequest = { ( request ) =>
121- request . url === 'about:blank' ||
122- request . url . startsWith ( documentBaseUrl ) ||
123- request . url . startsWith ( 'data:text/html' )
136+ request . url === seatLayerMobilePageUrl
124137 }
125138 />
126139 ) ;
0 commit comments