@quiltt/react-native 3.3.2 → 3.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @quiltt/react-native
2
2
 
3
+ ## 3.3.4
4
+
5
+ ### Patch Changes
6
+
7
+ - b659537: Fix MX OAuth and move some lib into peer dependencies
8
+ - Updated dependencies [b659537]
9
+ - @quiltt/core@3.3.4
10
+ - @quiltt/react@3.3.4
11
+
12
+ ## 3.3.3
13
+
14
+ ### Patch Changes
15
+
16
+ - 48a50d0: Fix handle plaid oauth link bug
17
+ - Updated dependencies [48a50d0]
18
+ - @quiltt/core@3.3.3
19
+ - @quiltt/react@3.3.3
20
+
3
21
  ## 3.3.2
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -7,12 +7,22 @@
7
7
 
8
8
  ## Installation
9
9
 
10
+ `@quiltt/react-native` expects `react`, `react-native`,`react-native-webview` and `core-js` as peer dependencies.
11
+
10
12
  ```shell
13
+ $ npm install react-native-webview
14
+ $ npm install core-js
11
15
  $ npm install @quiltt/react
16
+ $ npm install @quiltt/react-native
12
17
  # or
18
+ $ yarn add react-native-webview
19
+ $ yarn add core-js
13
20
  $ yarn add @quiltt/react
21
+ $ yarn add @quiltt/react-native
14
22
  # or
15
23
  # Please note that you will need to add `node-linker=hoisted` in `.npmrc` if you are using pnpm in expo app.`
24
+ $ pnpm add react-native-webview
25
+ $ pnpm add core-js
16
26
  $ pnpm add @quiltt/react
17
27
  ```
18
28
 
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var b=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var Q=Object.prototype.hasOwnProperty;var T=(r,o)=>{for(var i in o)b(r,i,{get:o[i],enumerable:!0})},U=(r,o,i,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let c of L(o))!Q.call(r,c)&&c!==i&&b(r,c,{get:()=>o[c],enumerable:!(t=D(o,c))||t.enumerable});return r};var K=r=>U(b({},"__esModule",{value:!0}),r);var I={};T(I,{QuilttConnector:()=>k,default:()=>M});module.exports=K(I);var G=require("core-js/stable/atob"),X=require("core-js/stable/url");var p=require("@quiltt/core"),n=require("react"),A=require("react-native"),q=require("react-native-webview");var l=require("react-native"),y=require("react/jsx-runtime"),C=({children:r})=>(0,y.jsx)(l.SafeAreaView,{style:$.AndroidSafeArea,children:r}),$=l.StyleSheet.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:l.Platform.OS==="android"?l.StatusBar.currentHeight:0}});var P=require("@quiltt/react"),w=require("react/jsx-runtime"),j=({connectorId:r,connectionId:o,oauthRedirectUrl:i,onEvent:t,onLoad:c,onExit:s,onExitSuccess:u,onExitAbort:f,onExitError:m})=>{let h=(0,n.useRef)(null),{session:d}=(0,P.useQuilttSession)();i=encodeURIComponent(i);let R=`https://${r}.quiltt.app/?mode=webview&oauth_redirect_url=${i}&sdk=react-native`,V=(0,n.useCallback)(()=>{var e;let a=` const options = { source: 'quiltt', type: 'Options', token: '${d==null?void 0:d.token}', connectorId: '${r}', connectionId: '${o}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=h.current)==null||e.injectJavaScript(a)},[o,r,d==null?void 0:d.token]),O=a=>{let e=new URL(a.url);return e.host.includes("quiltt")?!0:e.protocol==="quilttconnector:"?(W(e),!1):(g(e.href),!1)},S=()=>{var e;let a="localStorage.clear();";(e=h.current)==null||e.injectJavaScript(a)},W=a=>{a.searchParams.delete("source"),a.searchParams.append("connectorId",r);let e=Object.fromEntries(a.searchParams);switch(a.host){case"Load":V(),t==null||t(p.ConnectorSDKEventType.Load,e),c==null||c(e);break;case"ExitAbort":S(),t==null||t(p.ConnectorSDKEventType.ExitAbort,e),s==null||s(p.ConnectorSDKEventType.ExitAbort,e),f==null||f(e);break;case"ExitError":S(),t==null||t(p.ConnectorSDKEventType.ExitError,e),s==null||s(p.ConnectorSDKEventType.ExitError,e),m==null||m(e);break;case"ExitSuccess":S(),t==null||t(p.ConnectorSDKEventType.ExitSuccess,e),s==null||s(p.ConnectorSDKEventType.ExitSuccess,e),u==null||u(e);break;case"OauthRequested":g(a.searchParams.get("oauthUrl"));break;default:console.log("unhandled event",a);break}},g=a=>A.Linking.openURL(a);return(0,w.jsx)(C,{children:(0,w.jsx)(q.WebView,{ref:h,originWhitelist:["https://*","quilttconnector://*"],source:{uri:R},onShouldStartLoadWithRequest:O,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},k=j;var M=k;0&&(module.exports={QuilttConnector});
1
+ "use strict";var b=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var j=(a,o)=>{for(var c in o)b(a,c,{get:o[c],enumerable:!0})},M=(a,o,c,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of $(o))!K.call(a,s)&&s!==c&&b(a,s,{get:()=>o[s],enumerable:!(r=T(o,s))||r.enumerable});return a};var I=a=>M(b({},"__esModule",{value:!0}),a);var A=(a,o,c)=>new Promise((r,s)=>{var i=l=>{try{d(c.next(l))}catch(u){s(u)}},m=l=>{try{d(c.throw(l))}catch(u){s(u)}},d=l=>l.done?r(l.value):Promise.resolve(l.value).then(i,m);d((c=c.apply(a,o)).next())});var B={};j(B,{QuilttConnector:()=>g,default:()=>_});module.exports=I(B);var x=require("core-js/stable/atob"),E=require("core-js/stable/url");var p=require("@quiltt/core"),h=require("react"),k=require("react-native"),q=require("react-native-webview");var n=require("react-native"),L=require("react/jsx-runtime"),R=({children:a})=>(0,L.jsx)(n.SafeAreaView,{style:J.AndroidSafeArea,children:a}),J=n.StyleSheet.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:n.Platform.OS==="android"?n.StatusBar.currentHeight:0}});var O=require("@quiltt/react");var w=require("react/jsx-runtime"),H=({connectorId:a,connectionId:o,oauthRedirectUrl:c,onEvent:r,onLoad:s,onExit:i,onExitSuccess:m,onExitAbort:d,onExitError:l})=>{let u=(0,h.useRef)(null),{session:f}=(0,O.useQuilttSession)();c=encodeURIComponent(c);let U=`https://${a}.quiltt.app/?mode=webview&oauth_redirect_url=${c}&sdk=react-native`,P=(0,h.useCallback)(()=>{var e;let t=` const options = { source: 'quiltt', type: 'Options', token: '${f==null?void 0:f.token}', connectorId: '${a}', connectionId: '${o}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=u.current)==null||e.injectJavaScript(t)},[o,a,f==null?void 0:f.token]),V=["quiltt.app","quiltt.dev","moneydesktop.com","cdn.plaid.com/link/v2/stable/link.html"],Q=t=>y(t)?!1:V.some(e=>t.href.includes(e)),W=t=>{let e=new URL(t.url);return y(e)?(D(e),!1):Q(e)?!0:(C(e),!1)},S=()=>{var e;let t="localStorage.clear();";(e=u.current)==null||e.injectJavaScript(t)},y=t=>t.protocol==="quilttconnector:",D=t=>{t.searchParams.delete("source"),t.searchParams.append("connectorId",a);let e=Object.fromEntries(t.searchParams);switch(t.host){case"Load":P(),r==null||r(p.ConnectorSDKEventType.Load,e),s==null||s(e);break;case"ExitAbort":S(),r==null||r(p.ConnectorSDKEventType.ExitAbort,e),i==null||i(p.ConnectorSDKEventType.ExitAbort,e),d==null||d(e);break;case"ExitError":S(),r==null||r(p.ConnectorSDKEventType.ExitError,e),i==null||i(p.ConnectorSDKEventType.ExitError,e),l==null||l(e);break;case"ExitSuccess":S(),r==null||r(p.ConnectorSDKEventType.ExitSuccess,e),i==null||i(p.ConnectorSDKEventType.ExitSuccess,e),m==null||m(e);break;case"Authenticate":break;case"OauthRequested":C(new URL(t.searchParams.get("oauthUrl")));break;default:console.log("unhandled event",t);break}},C=t=>A(void 0,null,function*(){if(t.protocol!=="https:"){console.log(`handleOAuthUrl - Skipping non https url - ${t.href}`);return}(yield k.Linking.canOpenURL(t.href))&&k.Linking.openURL(t.href)});return(0,w.jsx)(R,{children:(0,w.jsx)(q.WebView,{ref:u,originWhitelist:["https://*","quilttconnector://*"],source:{uri:U},onShouldStartLoadWithRequest:W,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},g=H;var _=g;0&&(module.exports={QuilttConnector});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n const eventHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (url.host.includes('quiltt')) return true\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url.href)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'OauthRequested':\n handleOAuthUrl(url.searchParams.get('oauthUrl') as string)\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = (oauthUrl: string) => Linking.openURL(oauthUrl)\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={eventHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["src_exports","__export","QuilttConnector_default","src_default","__toCommonJS","import_atob","import_url","import_core","import_react","import_react_native","import_react_native_webview","import_react_native","import_jsx_runtime","AndroidSafeAreaView","children","styles","import_react","import_jsx_runtime","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","session","connectorUrl","initInjectedJavaScript","_a","script","eventHandler","request","url","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","oauthUrl","AndroidSafeAreaView","QuilttConnector_default","src_default","QuilttConnector_default"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview\n // For other urls, we assume those are bank urls, which needs to be handle in external browser.\n // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.\n const allowedListUrl = [\n 'quiltt.app',\n 'quiltt.dev',\n 'moneydesktop.com',\n 'cdn.plaid.com/link/v2/stable/link.html',\n ]\n const shouldRender = (url: URL) => {\n if (isQuilttEvent(url)) return false\n return allowedListUrl.some((href) => url.href.includes(href))\n }\n\n const requestHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (isQuilttEvent(url)) {\n handleQuilttEvent(url)\n return false\n }\n if (shouldRender(url)) return true\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const isQuilttEvent = (url: URL) => url.protocol === 'quilttconnector:'\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'Authenticate':\n // @todo handle Authenticate\n break\n case 'OauthRequested':\n handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = async (oauthUrl: URL) => {\n if (oauthUrl.protocol !== 'https:') {\n console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)\n return\n }\n if (await Linking.canOpenURL(oauthUrl.href)) {\n Linking.openURL(oauthUrl.href)\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={requestHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["src_exports","__export","QuilttConnector_default","src_default","__toCommonJS","import_atob","import_url","import_core","import_react","import_react_native","import_react_native_webview","import_react_native","import_jsx_runtime","AndroidSafeAreaView","children","styles","import_react","import_jsx_runtime","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","session","connectorUrl","initInjectedJavaScript","_a","script","allowedListUrl","shouldRender","url","isQuilttEvent","href","requestHandler","request","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","oauthUrl","__async","AndroidSafeAreaView","QuilttConnector_default","src_default","QuilttConnector_default"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import"core-js/stable/atob";import"core-js/stable/url";import{ConnectorSDKEventType as o}from"@quiltt/core";import{useCallback as W,useRef as D}from"react";import{Linking as L}from"react-native";import{WebView as Q}from"react-native-webview";import{SafeAreaView as A,StyleSheet as q,Platform as P,StatusBar as R}from"react-native";import{jsx as O}from"react/jsx-runtime";var S=({children:c})=>O(A,{style:V.AndroidSafeArea,children:c}),V=q.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:P.OS==="android"?R.currentHeight:0}});import{useQuilttSession as T}from"@quiltt/react";import{jsx as b}from"react/jsx-runtime";var U=({connectorId:c,connectionId:m,oauthRedirectUrl:i,onEvent:r,onLoad:l,onExit:a,onExitSuccess:p,onExitAbort:d,onExitError:n})=>{let u=D(null),{session:s}=T();i=encodeURIComponent(i);let k=`https://${c}.quiltt.app/?mode=webview&oauth_redirect_url=${i}&sdk=react-native`,g=W(()=>{var e;let t=` const options = { source: 'quiltt', type: 'Options', token: '${s==null?void 0:s.token}', connectorId: '${c}', connectionId: '${m}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=u.current)==null||e.injectJavaScript(t)},[m,c,s==null?void 0:s.token]),C=t=>{let e=new URL(t.url);return e.host.includes("quiltt")?!0:e.protocol==="quilttconnector:"?(y(e),!1):(h(e.href),!1)},f=()=>{var e;let t="localStorage.clear();";(e=u.current)==null||e.injectJavaScript(t)},y=t=>{t.searchParams.delete("source"),t.searchParams.append("connectorId",c);let e=Object.fromEntries(t.searchParams);switch(t.host){case"Load":g(),r==null||r(o.Load,e),l==null||l(e);break;case"ExitAbort":f(),r==null||r(o.ExitAbort,e),a==null||a(o.ExitAbort,e),d==null||d(e);break;case"ExitError":f(),r==null||r(o.ExitError,e),a==null||a(o.ExitError,e),n==null||n(e);break;case"ExitSuccess":f(),r==null||r(o.ExitSuccess,e),a==null||a(o.ExitSuccess,e),p==null||p(e);break;case"OauthRequested":h(t.searchParams.get("oauthUrl"));break;default:console.log("unhandled event",t);break}},h=t=>L.openURL(t);return b(S,{children:b(Q,{ref:u,originWhitelist:["https://*","quilttconnector://*"],source:{uri:k},onShouldStartLoadWithRequest:C,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},w=U;var x=w;export{w as QuilttConnector,x as default};
1
+ var b=(c,f,s)=>new Promise((r,p)=>{var a=o=>{try{i(s.next(o))}catch(l){p(l)}},u=o=>{try{i(s.throw(o))}catch(l){p(l)}},i=o=>o.done?r(o.value):Promise.resolve(o.value).then(a,u);i((s=s.apply(c,f)).next())});import"core-js/stable/atob";import"core-js/stable/url";import{ConnectorSDKEventType as n}from"@quiltt/core";import{useCallback as T,useRef as $}from"react";import{Linking as w}from"react-native";import{WebView as K}from"react-native-webview";import{SafeAreaView as U,StyleSheet as P,Platform as V,StatusBar as Q}from"react-native";import{jsx as D}from"react/jsx-runtime";var k=({children:c})=>D(U,{style:W.AndroidSafeArea,children:c}),W=P.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:V.OS==="android"?Q.currentHeight:0}});import{useQuilttSession as j}from"@quiltt/react";import{jsx as g}from"react/jsx-runtime";var M=({connectorId:c,connectionId:f,oauthRedirectUrl:s,onEvent:r,onLoad:p,onExit:a,onExitSuccess:u,onExitAbort:i,onExitError:o})=>{let l=$(null),{session:d}=j();s=encodeURIComponent(s);let C=`https://${c}.quiltt.app/?mode=webview&oauth_redirect_url=${s}&sdk=react-native`,A=T(()=>{var e;let t=` const options = { source: 'quiltt', type: 'Options', token: '${d==null?void 0:d.token}', connectorId: '${c}', connectionId: '${f}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=l.current)==null||e.injectJavaScript(t)},[f,c,d==null?void 0:d.token]),R=["quiltt.app","quiltt.dev","moneydesktop.com","cdn.plaid.com/link/v2/stable/link.html"],L=t=>h(t)?!1:R.some(e=>t.href.includes(e)),q=t=>{let e=new URL(t.url);return h(e)?(O(e),!1):L(e)?!0:(S(e),!1)},m=()=>{var e;let t="localStorage.clear();";(e=l.current)==null||e.injectJavaScript(t)},h=t=>t.protocol==="quilttconnector:",O=t=>{t.searchParams.delete("source"),t.searchParams.append("connectorId",c);let e=Object.fromEntries(t.searchParams);switch(t.host){case"Load":A(),r==null||r(n.Load,e),p==null||p(e);break;case"ExitAbort":m(),r==null||r(n.ExitAbort,e),a==null||a(n.ExitAbort,e),i==null||i(e);break;case"ExitError":m(),r==null||r(n.ExitError,e),a==null||a(n.ExitError,e),o==null||o(e);break;case"ExitSuccess":m(),r==null||r(n.ExitSuccess,e),a==null||a(n.ExitSuccess,e),u==null||u(e);break;case"Authenticate":break;case"OauthRequested":S(new URL(t.searchParams.get("oauthUrl")));break;default:console.log("unhandled event",t);break}},S=t=>b(void 0,null,function*(){if(t.protocol!=="https:"){console.log(`handleOAuthUrl - Skipping non https url - ${t.href}`);return}(yield w.canOpenURL(t.href))&&w.openURL(t.href)});return g(k,{children:g(K,{ref:l,originWhitelist:["https://*","quilttconnector://*"],source:{uri:C},onShouldStartLoadWithRequest:q,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},y=M;var oe=y;export{y as QuilttConnector,oe as default};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n const eventHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (url.host.includes('quiltt')) return true\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url.href)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'OauthRequested':\n handleOAuthUrl(url.searchParams.get('oauthUrl') as string)\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = (oauthUrl: string) => Linking.openURL(oauthUrl)\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={eventHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["ConnectorSDKEventType","useCallback","useRef","Linking","WebView","SafeAreaView","StyleSheet","Platform","StatusBar","jsx","AndroidSafeAreaView","children","styles","useQuilttSession","jsx","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","useRef","session","connectorUrl","initInjectedJavaScript","useCallback","_a","script","eventHandler","request","url","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","ConnectorSDKEventType","oauthUrl","Linking","AndroidSafeAreaView","WebView","QuilttConnector_default","src_default","QuilttConnector_default"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview\n // For other urls, we assume those are bank urls, which needs to be handle in external browser.\n // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.\n const allowedListUrl = [\n 'quiltt.app',\n 'quiltt.dev',\n 'moneydesktop.com',\n 'cdn.plaid.com/link/v2/stable/link.html',\n ]\n const shouldRender = (url: URL) => {\n if (isQuilttEvent(url)) return false\n return allowedListUrl.some((href) => url.href.includes(href))\n }\n\n const requestHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (isQuilttEvent(url)) {\n handleQuilttEvent(url)\n return false\n }\n if (shouldRender(url)) return true\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const isQuilttEvent = (url: URL) => url.protocol === 'quilttconnector:'\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'Authenticate':\n // @todo handle Authenticate\n break\n case 'OauthRequested':\n handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = async (oauthUrl: URL) => {\n if (oauthUrl.protocol !== 'https:') {\n console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)\n return\n }\n if (await Linking.canOpenURL(oauthUrl.href)) {\n Linking.openURL(oauthUrl.href)\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={requestHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["ConnectorSDKEventType","useCallback","useRef","Linking","WebView","SafeAreaView","StyleSheet","Platform","StatusBar","jsx","AndroidSafeAreaView","children","styles","useQuilttSession","jsx","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","useRef","session","useQuilttSession","connectorUrl","initInjectedJavaScript","useCallback","_a","script","allowedListUrl","shouldRender","url","isQuilttEvent","href","requestHandler","request","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","ConnectorSDKEventType","oauthUrl","__async","Linking","AndroidSafeAreaView","WebView","QuilttConnector_default","src_default","QuilttConnector_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltt/react-native",
3
- "version": "3.3.2",
3
+ "version": "3.3.4",
4
4
  "description": "React Native components for Quiltt Connector",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -18,13 +18,13 @@
18
18
  "homepage": "https://github.com/quiltt/quiltt-public/tree/main/ECMAScript/react-native#readme",
19
19
  "peerDependencies": {
20
20
  "react": "^18.2.0",
21
- "react-native": "^0.72.5"
21
+ "react-native": "^0.72.5",
22
+ "core-js": "^3.26.0",
23
+ "react-native-webview": "^13.0.0"
22
24
  },
23
25
  "dependencies": {
24
- "core-js": "3.33.2",
25
- "react-native-webview": "13.6.2",
26
- "@quiltt/core": "3.3.2",
27
- "@quiltt/react": "3.3.2"
26
+ "@quiltt/core": "3.3.4",
27
+ "@quiltt/react": "3.3.4"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@apollo/client": "3.7.16",
@@ -52,16 +52,30 @@ export const QuilttConnector = ({
52
52
  webViewRef.current?.injectJavaScript(script)
53
53
  }, [connectionId, connectorId, session?.token])
54
54
 
55
- const eventHandler = (request: ShouldStartLoadRequest) => {
55
+ // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview
56
+ // For other urls, we assume those are bank urls, which needs to be handle in external browser.
57
+ // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.
58
+ const allowedListUrl = [
59
+ 'quiltt.app',
60
+ 'quiltt.dev',
61
+ 'moneydesktop.com',
62
+ 'cdn.plaid.com/link/v2/stable/link.html',
63
+ ]
64
+ const shouldRender = (url: URL) => {
65
+ if (isQuilttEvent(url)) return false
66
+ return allowedListUrl.some((href) => url.href.includes(href))
67
+ }
68
+
69
+ const requestHandler = (request: ShouldStartLoadRequest) => {
56
70
  const url = new URL(request.url)
57
- if (url.host.includes('quiltt')) return true
58
- if (url.protocol === 'quilttconnector:') {
71
+ if (isQuilttEvent(url)) {
59
72
  handleQuilttEvent(url)
60
73
  return false
61
74
  }
75
+ if (shouldRender(url)) return true
62
76
  // Plaid set oauth url by doing window.location.href = url
63
77
  // This is the only way I know to handle this.
64
- handleOAuthUrl(url.href)
78
+ handleOAuthUrl(url)
65
79
  return false
66
80
  }
67
81
 
@@ -70,6 +84,8 @@ export const QuilttConnector = ({
70
84
  webViewRef.current?.injectJavaScript(script)
71
85
  }
72
86
 
87
+ const isQuilttEvent = (url: URL) => url.protocol === 'quilttconnector:'
88
+
73
89
  const handleQuilttEvent = (url: URL) => {
74
90
  url.searchParams.delete('source')
75
91
  url.searchParams.append('connectorId', connectorId)
@@ -100,8 +116,11 @@ export const QuilttConnector = ({
100
116
  onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)
101
117
  onExitSuccess?.(metadata)
102
118
  break
119
+ case 'Authenticate':
120
+ // @todo handle Authenticate
121
+ break
103
122
  case 'OauthRequested':
104
- handleOAuthUrl(url.searchParams.get('oauthUrl') as string)
123
+ handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))
105
124
  break
106
125
  default:
107
126
  console.log('unhandled event', url)
@@ -109,7 +128,15 @@ export const QuilttConnector = ({
109
128
  }
110
129
  }
111
130
 
112
- const handleOAuthUrl = (oauthUrl: string) => Linking.openURL(oauthUrl)
131
+ const handleOAuthUrl = async (oauthUrl: URL) => {
132
+ if (oauthUrl.protocol !== 'https:') {
133
+ console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)
134
+ return
135
+ }
136
+ if (await Linking.canOpenURL(oauthUrl.href)) {
137
+ Linking.openURL(oauthUrl.href)
138
+ }
139
+ }
113
140
 
114
141
  return (
115
142
  <AndroidSafeAreaView>
@@ -117,7 +144,7 @@ export const QuilttConnector = ({
117
144
  ref={webViewRef}
118
145
  originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?
119
146
  source={{ uri: connectorUrl }}
120
- onShouldStartLoadWithRequest={eventHandler}
147
+ onShouldStartLoadWithRequest={requestHandler}
121
148
  javaScriptEnabled
122
149
  domStorageEnabled // To enable localStorage in Android webview
123
150
  webviewDebuggingEnabled // Not sure if this works