From 2c1dcf93315c5b2be5738dcd7ef723408194c056 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Fri, 14 Feb 2025 20:08:08 +0530 Subject: [PATCH 01/17] Class... OOPS --- src/LiveboardEmbedClass.ts | 18 ++++++ src/componentFactory.tsx | 70 +++++++++++++++++++++++ src/event-bridge.ts | 6 ++ src/index.ts | 5 +- src/tsEmbed.tsx | 110 +++++++++++++++++++++++++++++++++++++ src/util.ts | 6 ++ 6 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 src/LiveboardEmbedClass.ts create mode 100644 src/componentFactory.tsx create mode 100644 src/tsEmbed.tsx create mode 100644 src/util.ts diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts new file mode 100644 index 0000000..8adddd2 --- /dev/null +++ b/src/LiveboardEmbedClass.ts @@ -0,0 +1,18 @@ +import { TSEmbed } from './tsEmbed'; +import { componentFactory } from './componentFactory'; +import { ViewConfig, LiveboardViewConfig } from './types'; +import WebView from 'react-native-webview'; +import { EmbedProps } from './util'; + +class LiveboardEmbedClass extends TSEmbed { + constructor(webViewRef: React.RefObject, config?: T) { + super(webViewRef, config); + } +} + +export interface LiveboardEmbedProps extends LiveboardViewConfig, EmbedProps {} +export const LiveboardEmbedClassX = componentFactory< + typeof LiveboardEmbedClass, + LiveboardViewConfig, + LiveboardEmbedProps +>(LiveboardEmbedClass); \ No newline at end of file diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx new file mode 100644 index 0000000..376a786 --- /dev/null +++ b/src/componentFactory.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { WebView } from 'react-native-webview'; +import { TSEmbed } from './tsEmbed'; +import { + EmbedEvent, + ViewConfig, + MessageCallback, +} from './types'; +import { EmbedProps } from './util'; + +export type EmbedEventHandlers = { [key in keyof typeof EmbedEvent as `on${Capitalize}`]?: MessageCallback }; + + +export interface ViewConfigAndListeners { + viewConfig: T; + listeners: { [key in EmbedEvent]?: MessageCallback }; +} + +const getViewPropsAndListeners = ( + props: T +): ViewConfigAndListeners => { + return Object.keys(props).reduce( + (accu, key) => { + if (key.startsWith('on')) { + const eventName = key.slice(2) as keyof typeof EmbedEvent; + (accu.listeners as Record)[EmbedEvent[eventName]] = props[key as keyof T] as MessageCallback; + } else { + (accu.viewConfig as Record)[key] = props[key as keyof T]; + } + return accu as ViewConfigAndListeners; + }, + { + viewConfig: {} as U, + listeners: {}, + }, + ); +}; + +export const componentFactory = ( + EmbedConstructor: T, +) => React.forwardRef, U>( + (props, forwardedRef) => { + const embedInstance = React.useRef | null>(null); + const webViewRef = React.useRef(null); + + React.useEffect(() => { + const { viewConfig, listeners } = getViewPropsAndListeners(props as U); + + embedInstance.current = new EmbedConstructor(webViewRef, viewConfig) as InstanceType; + + Object.entries(listeners).forEach(([eventName, callback]) => { + embedInstance.current?.on(eventName as EmbedEvent, callback as MessageCallback); + }); + + if (forwardedRef && typeof forwardedRef === 'object') { + forwardedRef.current = embedInstance.current; + } + + return () => { + embedInstance.current?.destroy(); + }; + }, [props]); + + if (!embedInstance.current) { + return null; + } + + return embedInstance.current.getComponent(); + } +); \ No newline at end of file diff --git a/src/event-bridge.ts b/src/event-bridge.ts index cb37c70..3c9e17d 100644 --- a/src/event-bridge.ts +++ b/src/event-bridge.ts @@ -85,4 +85,10 @@ export class EmbedBridge { private generateEventId(): string { return `evt_${Date.now()}_${Math.floor(Math.random() * 100000)}`; } + + public destroy() { + this.events = {}; + this.pendingReplies = {}; + this.webViewRef = { current: null }; + } } diff --git a/src/index.ts b/src/index.ts index 71f707b..4b90f9c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,10 @@ import { useLiveboardRef } from "./hooks/useLiveboardRef"; import { init } from "./init"; import { LiveboardEmbed, LiveboardEmbedRef } from "./LiveboardEmbed"; +import { LiveboardEmbedClassX } from "./LiveboardEmbedClass"; +import { AuthType, ViewConfig } from "./types"; - -export { init, LiveboardEmbed, useLiveboardRef }; +export { init, LiveboardEmbed, useLiveboardRef, LiveboardEmbedClassX, AuthType, ViewConfig }; export type { LiveboardEmbedRef }; const EmbedReactNativeSDK = { diff --git a/src/tsEmbed.tsx b/src/tsEmbed.tsx new file mode 100644 index 0000000..26c063e --- /dev/null +++ b/src/tsEmbed.tsx @@ -0,0 +1,110 @@ +import WebView, { WebViewMessageEvent } from "react-native-webview"; +import { EmbedBridge } from "./event-bridge"; +import React from "react"; +import { ViewConfig } from "./types"; + + +export class TSEmbed { + protected webViewRef: React.RefObject; + protected embedBridge: EmbedBridge; + protected viewConfig: T; + protected vercelShellLoaded: boolean = false; + + constructor(webViewRef: React.RefObject, config?: T) { + this.webViewRef = webViewRef; + this.embedBridge = new EmbedBridge(webViewRef); + this.viewConfig = config || {} as T; + } + + protected getEmbedType() { + return this.constructor.name.replace('EmbedClass', ''); + } + + protected updateConfig(config: Partial) { + this.viewConfig = { ...this.viewConfig, ...config }; + if(this.vercelShellLoaded) { + this.render(); + } + } + + public render() { + if(!this.webViewRef.current || !this.vercelShellLoaded) { + console.log("[TSEmbed] Waiting for Vercel shell to load..."); + return; + } + + const initMsg = { + type: "init", + payload: this.viewConfig, + }; + + this.embedBridge.sendMessage(initMsg); + + const message = { + type: "EMBED", + embedType: this.getEmbedType(), + payload: this.viewConfig, + }; + + this.embedBridge.sendMessage(message); + + } + + public on(eventName: string, callback: Function) { + this.embedBridge.registerEmbedEvent(eventName, callback); + } + + public trigger(hostEventName: string, payload?: any) { + return this.embedBridge.trigger(hostEventName, payload); + } + + public handleMessage(event: WebViewMessageEvent) { + try { + const msg = JSON.parse(event.nativeEvent.data); + if (msg.type === "INIT_VERCEL_SHELL") { + this.vercelShellLoaded = true; + this.render(); + } + this.embedBridge.handleMessage(msg); + } catch (err) { + console.error("[TsEmbed] handleMessage parse error:", err); + } + } + + public destroy() { + this.embedBridge.destroy(); + + } + + public getComponent() { + return ( + { + const { nativeEvent } = syntheticEvent; + console.warn("error in the webview", nativeEvent); + }} + keyboardDisplayRequiresUserAction={false} + automaticallyAdjustContentInsets={false} + scrollEnabled={false} + onHttpError= {(syntheticEvent) => { + const { nativeEvent } = syntheticEvent; + console.warn("HTTP error in the webview", nativeEvent); + }} + style={{ flex: 1, + height: '100%', + width: '100%' + }} + /> + ); + } + +} \ No newline at end of file diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..a427806 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,6 @@ +import { EmbedEventHandlers } from "./componentFactory"; +import { ViewConfig } from "./types"; + +export interface EmbedProps extends ViewConfig, EmbedEventHandlers { + +} \ No newline at end of file From b09400cbb9eec515f9132ff1d62b1e2d237d6f99 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Mon, 17 Feb 2025 07:14:52 +0530 Subject: [PATCH 02/17] Webview import issue --- src/tsEmbed.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsEmbed.tsx b/src/tsEmbed.tsx index 26c063e..2c37f61 100644 --- a/src/tsEmbed.tsx +++ b/src/tsEmbed.tsx @@ -1,4 +1,4 @@ -import WebView, { WebViewMessageEvent } from "react-native-webview"; +import { WebView, WebViewMessageEvent } from "react-native-webview"; import { EmbedBridge } from "./event-bridge"; import React from "react"; import { ViewConfig } from "./types"; From 35a27283a769d76530a26104bab73f7dd25b121a Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 13:03:59 +0530 Subject: [PATCH 03/17] first mount fix --- src/BaseEmbed.tsx | 109 ----------------------------------- src/LiveboardEmbed.tsx | 21 ------- src/LiveboardEmbedClass.ts | 2 +- src/componentFactory.tsx | 38 +++++++----- src/hooks/useLiveboardRef.ts | 7 --- src/index.ts | 14 +---- src/tsEmbed.tsx | 61 ++++++++++++-------- 7 files changed, 63 insertions(+), 189 deletions(-) delete mode 100644 src/BaseEmbed.tsx delete mode 100644 src/LiveboardEmbed.tsx delete mode 100644 src/hooks/useLiveboardRef.ts diff --git a/src/BaseEmbed.tsx b/src/BaseEmbed.tsx deleted file mode 100644 index bc946e7..0000000 --- a/src/BaseEmbed.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React, { - useRef, - useEffect, - useImperativeHandle, - forwardRef, - useMemo, - useState, -} from "react"; -import { WebView, WebViewMessageEvent } from "react-native-webview"; -import { EmbedBridge, EmbedMessage } from "./event-bridge"; -import { embedConfigCache } from "./init"; - -interface BaseEmbedProps { - typeofEmbed: string; - [key: string]: any; -} - -export interface TSEmbedRef { - trigger: (hostEventName: string, payload?: any) => Promise; -} - -export const BaseEmbed = forwardRef( - (props, ref) => { - const webViewRef = useRef(null); - const embedBridge = useMemo(() => new EmbedBridge(webViewRef), []); - const [vercelShellLoaded, setVercelShellLoaded] = useState(false); - const [viewConfig, setViewConfig] = useState>({}); - - useEffect(() => { - const newViewConfig: Record = {}; - Object.keys(props).forEach((key) => { - if (key.startsWith("on")) { - const eventName = key.substring(2); - embedBridge.registerEmbedEvent(eventName, props[key]); - } else if (key !== 'embedType') { - newViewConfig[key] = props[key]; - } - }); - setViewConfig(newViewConfig); - }, [props, embedBridge]); - - useEffect(() => { - if (!webViewRef.current || !vercelShellLoaded) { - console.log("[BaseEmbed] Waiting for Vercel shell to load..."); - return; - } - - const initMsg = { - type: "INIT", - payload: embedConfigCache, - }; - embedBridge.sendMessage(initMsg); - - const message = { - type: "EMBED", - embedType: props.embedType, - viewConfig: viewConfig, - }; - embedBridge.sendMessage(message); - }, [viewConfig, embedBridge, props.embedType, vercelShellLoaded]); - - useImperativeHandle(ref, () => ({ - trigger: (hostEventName: string, payload?: any) => { - return embedBridge.trigger(hostEventName, payload); - }, - })); - - const handleMessage = (event: WebViewMessageEvent) => { - try { - const msg = JSON.parse(event.nativeEvent.data); - if (msg.type === "INIT_VERCEL_SHELL") { - setVercelShellLoaded(true); - } - embedBridge.handleMessage(msg); - } catch (err) { - console.error("Unable to parse the message from the webview", err); - } - }; - - return ( - { - const { nativeEvent } = syntheticEvent; - console.warn("error in the webview", nativeEvent); - }} - keyboardDisplayRequiresUserAction={false} // Add this for iOS - automaticallyAdjustContentInsets={false} // Add this - scrollEnabled={false} - onHttpError= {(syntheticEvent) => { - const { nativeEvent } = syntheticEvent; - console.warn("HTTP error in the webview", nativeEvent); - }} - style={{ flex: 1, - height: '100%', // Explicit height - width: '100%' - }} - /> - ); - } -); diff --git a/src/LiveboardEmbed.tsx b/src/LiveboardEmbed.tsx deleted file mode 100644 index af99729..0000000 --- a/src/LiveboardEmbed.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React, { forwardRef } from "react"; -import { BaseEmbed, TSEmbedRef } from "./BaseEmbed"; -import { LiveboardViewConfig, EmbedEvent } from "./types"; - -type EventHandlers = { - [K in EmbedEvent as `on${Capitalize}`]?: (event: any) => void; -} - -export type LiveboardEmbedRef = TSEmbedRef; - -export const LiveboardEmbed = forwardRef( - (props, ref) => { - return ( - - ); - } -); diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index 8adddd2..998d6a8 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -11,7 +11,7 @@ class LiveboardEmbedClass e } export interface LiveboardEmbedProps extends LiveboardViewConfig, EmbedProps {} -export const LiveboardEmbedClassX = componentFactory< +export const LiveboardEmbed = componentFactory< typeof LiveboardEmbedClass, LiveboardViewConfig, LiveboardEmbedProps diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 376a786..c2d2f48 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { WebView } from 'react-native-webview'; import { TSEmbed } from './tsEmbed'; import { @@ -43,28 +43,34 @@ export const componentFactory = | null>(null); const webViewRef = React.useRef(null); + if(!embedInstance.current) { + embedInstance.current = new EmbedConstructor(webViewRef) as InstanceType; + } + + const renderedWebView = React.useMemo(() => { + return embedInstance.current?.render(); + }, []); + React.useEffect(() => { - const { viewConfig, listeners } = getViewPropsAndListeners(props as U); - embedInstance.current = new EmbedConstructor(webViewRef, viewConfig) as InstanceType; + return () => { + embedInstance.current?.destroy(); + embedInstance.current = null; + } + }, []) + + React.useEffect(() => { + const { viewConfig, listeners } = getViewPropsAndListeners(props as U); + if(forwardedRef && typeof forwardedRef == 'object') { + forwardedRef.current = embedInstance?.current; + } + embedInstance?.current?.updateConfig(viewConfig); Object.entries(listeners).forEach(([eventName, callback]) => { embedInstance.current?.on(eventName as EmbedEvent, callback as MessageCallback); }); - - if (forwardedRef && typeof forwardedRef === 'object') { - forwardedRef.current = embedInstance.current; - } - - return () => { - embedInstance.current?.destroy(); - }; }, [props]); - if (!embedInstance.current) { - return null; - } - - return embedInstance.current.getComponent(); + return renderedWebView; } ); \ No newline at end of file diff --git a/src/hooks/useLiveboardRef.ts b/src/hooks/useLiveboardRef.ts deleted file mode 100644 index 5bdaaeb..0000000 --- a/src/hooks/useLiveboardRef.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useRef } from "react"; -import { TSEmbedRef } from "src/BaseEmbed"; - -export const useLiveboardRef = () => { - const liveboardRef = useRef(null); - return liveboardRef; -}; diff --git a/src/index.ts b/src/index.ts index 4b90f9c..be79ee6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,5 @@ -import { useLiveboardRef } from "./hooks/useLiveboardRef"; import { init } from "./init"; -import { LiveboardEmbed, LiveboardEmbedRef } from "./LiveboardEmbed"; -import { LiveboardEmbedClassX } from "./LiveboardEmbedClass"; +import { LiveboardEmbed } from "./LiveboardEmbedClass"; import { AuthType, ViewConfig } from "./types"; -export { init, LiveboardEmbed, useLiveboardRef, LiveboardEmbedClassX, AuthType, ViewConfig }; -export type { LiveboardEmbedRef }; - -const EmbedReactNativeSDK = { - init, - LiveboardEmbed, - useLiveboardRef, -}; -export default EmbedReactNativeSDK; \ No newline at end of file +export { init, LiveboardEmbed, AuthType, ViewConfig }; diff --git a/src/tsEmbed.tsx b/src/tsEmbed.tsx index 2c37f61..8d046b3 100644 --- a/src/tsEmbed.tsx +++ b/src/tsEmbed.tsx @@ -2,81 +2,96 @@ import { WebView, WebViewMessageEvent } from "react-native-webview"; import { EmbedBridge } from "./event-bridge"; import React from "react"; import { ViewConfig } from "./types"; +import { embedConfigCache } from "./init"; export class TSEmbed { protected webViewRef: React.RefObject; - protected embedBridge: EmbedBridge; + protected embedBridge: EmbedBridge | null = null; protected viewConfig: T; protected vercelShellLoaded: boolean = false; + private pendingHandlers: Array<[string, Function]> = []; constructor(webViewRef: React.RefObject, config?: T) { this.webViewRef = webViewRef; - this.embedBridge = new EmbedBridge(webViewRef); this.viewConfig = config || {} as T; + this.handleMessage = this.handleMessage.bind(this); } protected getEmbedType() { return this.constructor.name.replace('EmbedClass', ''); } - protected updateConfig(config: Partial) { + public updateConfig(config: Partial) { this.viewConfig = { ...this.viewConfig, ...config }; if(this.vercelShellLoaded) { - this.render(); + this.sendConfigToShell(); } } - public render() { + public sendConfigToShell() { if(!this.webViewRef.current || !this.vercelShellLoaded) { console.log("[TSEmbed] Waiting for Vercel shell to load..."); return; } const initMsg = { - type: "init", - payload: this.viewConfig, + type: "INIT", + payload: embedConfigCache, }; - this.embedBridge.sendMessage(initMsg); + this.embedBridge?.sendMessage(initMsg); const message = { type: "EMBED", embedType: this.getEmbedType(), - payload: this.viewConfig, + viewConfig: this.viewConfig, }; - this.embedBridge.sendMessage(message); + this.embedBridge?.sendMessage(message); } public on(eventName: string, callback: Function) { - this.embedBridge.registerEmbedEvent(eventName, callback); - } + if (this.embedBridge) { + this.embedBridge.registerEmbedEvent(eventName, callback); + } else { + console.log("[TSEmbed] Queuing event handler:", eventName); + this.pendingHandlers.push([eventName, callback]); + } + } public trigger(hostEventName: string, payload?: any) { - return this.embedBridge.trigger(hostEventName, payload); + return this.embedBridge?.trigger(hostEventName, payload); } public handleMessage(event: WebViewMessageEvent) { try { - const msg = JSON.parse(event.nativeEvent.data); - if (msg.type === "INIT_VERCEL_SHELL") { - this.vercelShellLoaded = true; - this.render(); - } - this.embedBridge.handleMessage(msg); + const msg = JSON.parse(event.nativeEvent.data); + if (msg.type === "INIT_VERCEL_SHELL") { + this.vercelShellLoaded = true; + this.embedBridge = new EmbedBridge(this.webViewRef); + + // Process pending handlers + this.pendingHandlers.forEach(([eventName, callback]) => { + this.embedBridge?.registerEmbedEvent(eventName, callback); + }); + this.pendingHandlers = []; + + this.sendConfigToShell(); + } + this.embedBridge?.handleMessage(msg); } catch (err) { - console.error("[TsEmbed] handleMessage parse error:", err); + console.error("[TsEmbed] handleMessage parse error:", err); } - } + } public destroy() { - this.embedBridge.destroy(); + this.embedBridge?.destroy(); } - public getComponent() { + public render() { return ( Date: Sat, 22 Feb 2025 13:08:37 +0530 Subject: [PATCH 04/17] new-v for npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f974feb..5cda18c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "1.0.0", + "version": "3.0.0", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", From 68e88a96aa43d3d99751d7cd8bd4cdda631ed111 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 13:29:44 +0530 Subject: [PATCH 05/17] expo type error --- package.json | 5 ----- src/componentFactory.tsx | 2 +- src/tsEmbed.tsx | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 5cda18c..b4a5dd0 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,6 @@ "@rollup/plugin-commonjs": "^28.0.2", "@rollup/plugin-node-resolve": "^16.0.0", "@rollup/plugin-typescript": "^12.1.2", - "@types/react": "^18.3.18", - "@types/react-native": "^0.72.8", - "react": "^18.3.1", - "react-native": "^0.77.0", - "react-native-webview": "^13.13.2", "rollup": "^4.32.0", "rollup-plugin-dts": "^6.1.1", "typescript": "^5.7.3" diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index c2d2f48..00cfc0b 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -71,6 +71,6 @@ export const componentFactory = ; } ); \ No newline at end of file diff --git a/src/tsEmbed.tsx b/src/tsEmbed.tsx index 8d046b3..ad776d8 100644 --- a/src/tsEmbed.tsx +++ b/src/tsEmbed.tsx @@ -91,7 +91,7 @@ export class TSEmbed { } - public render() { + public render(): JSX.Element { return ( Date: Sat, 22 Feb 2025 13:32:31 +0530 Subject: [PATCH 06/17] v publish npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4a5dd0..d3d33a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.0", + "version": "3.0.1", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", From 8a16534779e9d3bcb2d7b461a57805393efc8648 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 13:34:45 +0530 Subject: [PATCH 07/17] v jsx --- src/componentFactory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 00cfc0b..1581fa9 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -71,6 +71,6 @@ export const componentFactory = ; + return renderedWebView || <>; } ); \ No newline at end of file From 58c96b971d8dd83d4d3aad9582a4d81b1a6f21dc Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 14:18:41 +0530 Subject: [PATCH 08/17] v jsx --- src/componentFactory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 1581fa9..859974e 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -71,6 +71,6 @@ export const componentFactory = ; + return renderedWebView || <> as JSX.Element; } ); \ No newline at end of file From fb37c03f7064057dfd08951ab641fbe9bccc2b7a Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 14:19:17 +0530 Subject: [PATCH 09/17] v jsx --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3d33a9..3e4c9b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.1", + "version": "3.0.2", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", From f0f95b0da0ab59c1123e5019dabf6e6f24361410 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sat, 22 Feb 2025 14:45:49 +0530 Subject: [PATCH 10/17] all return paths --- package.json | 2 +- src/componentFactory.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3e4c9b6..75280bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.2", + "version": "3.0.3", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 859974e..8a45f46 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -69,7 +69,11 @@ export const componentFactory = { embedInstance.current?.on(eventName as EmbedEvent, callback as MessageCallback); }); - }, [props]); + }, [props]); + + if(!embedInstance.current) { + return null; + } return renderedWebView || <> as JSX.Element; } From d770311f0eb18ef0b79580f95db63c25fbd6472c Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sun, 23 Feb 2025 09:39:23 +0530 Subject: [PATCH 11/17] remove undefined type return --- package.json | 2 +- src/componentFactory.tsx | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 75280bf..f04c865 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.3", + "version": "3.0.4", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 8a45f46..f1c4046 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -47,12 +47,11 @@ export const componentFactory = ; } - const renderedWebView = React.useMemo(() => { - return embedInstance.current?.render(); + const renderedWebView = React.useMemo((): JSX.Element | null => { + return embedInstance.current?.render() ?? null; }, []); React.useEffect(() => { - return () => { embedInstance.current?.destroy(); embedInstance.current = null; @@ -75,6 +74,6 @@ export const componentFactory = as JSX.Element; + return renderedWebView ?? null; } ); \ No newline at end of file From b8a526cc686480fa56831be86a418ceb46356486 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sun, 23 Feb 2025 09:49:48 +0530 Subject: [PATCH 12/17] ReactNode infer removal --- package.json | 2 +- src/LiveboardEmbedClass.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f04c865..585a43d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.4", + "version": "3.0.5", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index 998d6a8..d0d36b6 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -11,7 +11,9 @@ class LiveboardEmbedClass e } export interface LiveboardEmbedProps extends LiveboardViewConfig, EmbedProps {} -export const LiveboardEmbed = componentFactory< +export const LiveboardEmbed: React.ForwardRefExoticComponent< + LiveboardEmbedProps & React.RefAttributes> +> = componentFactory< typeof LiveboardEmbedClass, LiveboardViewConfig, LiveboardEmbedProps From 715980d24cdb0ad4553f4983159eed92366a3799 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sun, 23 Feb 2025 17:39:42 +0530 Subject: [PATCH 13/17] exporting as react.FC --- package.json | 2 +- src/LiveboardEmbedClass.ts | 14 +++++--- src/componentFactory.tsx | 66 ++++++++++++++++++-------------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 585a43d..80f06df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.5", + "version": "3.0.6", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index d0d36b6..abaaf4d 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -1,8 +1,9 @@ import { TSEmbed } from './tsEmbed'; import { componentFactory } from './componentFactory'; -import { ViewConfig, LiveboardViewConfig } from './types'; +import { LiveboardViewConfig } from './types'; import WebView from 'react-native-webview'; import { EmbedProps } from './util'; +import React from 'react'; class LiveboardEmbedClass extends TSEmbed { constructor(webViewRef: React.RefObject, config?: T) { @@ -11,10 +12,13 @@ class LiveboardEmbedClass e } export interface LiveboardEmbedProps extends LiveboardViewConfig, EmbedProps {} -export const LiveboardEmbed: React.ForwardRefExoticComponent< - LiveboardEmbedProps & React.RefAttributes> -> = componentFactory< + +const LiveboardEmbedComponent = componentFactory< typeof LiveboardEmbedClass, LiveboardViewConfig, LiveboardEmbedProps ->(LiveboardEmbedClass); \ No newline at end of file +>(LiveboardEmbedClass); + +export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as React.FC< + LiveboardEmbedProps & React.RefAttributes> +>; \ No newline at end of file diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index f1c4046..b89614c 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -38,42 +38,40 @@ const getViewPropsAndListeners = ( export const componentFactory = ( EmbedConstructor: T, -) => React.forwardRef, U>( - (props, forwardedRef) => { - const embedInstance = React.useRef | null>(null); - const webViewRef = React.useRef(null); - - if(!embedInstance.current) { - embedInstance.current = new EmbedConstructor(webViewRef) as InstanceType; - } - - const renderedWebView = React.useMemo((): JSX.Element | null => { - return embedInstance.current?.render() ?? null; - }, []); - - React.useEffect(() => { - return () => { - embedInstance.current?.destroy(); - embedInstance.current = null; - } - }, []) - - React.useEffect(() => { - const { viewConfig, listeners } = getViewPropsAndListeners(props as U); - if(forwardedRef && typeof forwardedRef == 'object') { - forwardedRef.current = embedInstance?.current; - } - embedInstance?.current?.updateConfig(viewConfig); +) => React.forwardRef, U>((props, forwardedRef): JSX.Element | null => { + const embedInstance = React.useRef | null>(null); + const webViewRef = React.useRef(null); + + if(!embedInstance.current) { + embedInstance.current = new EmbedConstructor(webViewRef) as InstanceType; + } - Object.entries(listeners).forEach(([eventName, callback]) => { - embedInstance.current?.on(eventName as EmbedEvent, callback as MessageCallback); - }); - }, [props]); + const renderedWebView = React.useMemo((): JSX.Element | null => { + return embedInstance.current?.render() ?? null; + }, []); - if(!embedInstance.current) { - return null; + React.useEffect(() => { + return () => { + embedInstance.current?.destroy(); + embedInstance.current = null; + } + }, []) + + React.useEffect(() => { + const { viewConfig, listeners } = getViewPropsAndListeners(props as U); + if(forwardedRef && typeof forwardedRef == 'object') { + forwardedRef.current = embedInstance?.current; } + embedInstance?.current?.updateConfig(viewConfig); - return renderedWebView ?? null; + Object.entries(listeners).forEach(([eventName, callback]) => { + embedInstance.current?.on(eventName as EmbedEvent, callback as MessageCallback); + }); + }, [props]); + + if(!embedInstance.current) { + return null; } -); \ No newline at end of file + + return renderedWebView ?? null; +}); \ No newline at end of file From 0ba9b0fc5320f3045795f1275d1941f01e38948a Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sun, 23 Feb 2025 17:50:03 +0530 Subject: [PATCH 14/17] simple typeof X fix check --- package.json | 2 +- src/LiveboardEmbedClass.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 80f06df..dc2c7aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.6", + "version": "3.0.7", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index abaaf4d..07c8cd8 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -19,6 +19,4 @@ const LiveboardEmbedComponent = componentFactory< LiveboardEmbedProps >(LiveboardEmbedClass); -export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as React.FC< - LiveboardEmbedProps & React.RefAttributes> ->; \ No newline at end of file +export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as typeof LiveboardEmbedComponent; \ No newline at end of file From 4872741447cf97ed0b891a76055249611e989174 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Sun, 23 Feb 2025 21:05:27 +0530 Subject: [PATCH 15/17] undefined returned --- package.json | 2 +- src/componentFactory.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index dc2c7aa..b10e358 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.7", + "version": "3.0.8", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index b89614c..3156bd8 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -48,7 +48,7 @@ export const componentFactory = { return embedInstance.current?.render() ?? null; - }, []); + }, [props]); React.useEffect(() => { return () => { From 995be3b3c1b004b1ff0011949406fb1085cf95e1 Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Mon, 24 Feb 2025 07:15:36 +0530 Subject: [PATCH 16/17] check x --- package.json | 2 +- src/LiveboardEmbedClass.ts | 2 +- src/componentFactory.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b10e358..3fbb07a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.8", + "version": "3.0.9", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index 07c8cd8..945d504 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -19,4 +19,4 @@ const LiveboardEmbedComponent = componentFactory< LiveboardEmbedProps >(LiveboardEmbedClass); -export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as typeof LiveboardEmbedComponent; \ No newline at end of file +export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as React.NamedExoticComponent>>; \ No newline at end of file diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 3156bd8..00a3e34 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -60,7 +60,7 @@ export const componentFactory = { const { viewConfig, listeners } = getViewPropsAndListeners(props as U); if(forwardedRef && typeof forwardedRef == 'object') { - forwardedRef.current = embedInstance?.current; + (forwardedRef as React.MutableRefObject | null>).current = embedInstance?.current; } embedInstance?.current?.updateConfig(viewConfig); From e027b62d70eb6a499123bd4163706c51b3a88b4a Mon Sep 17 00:00:00 2001 From: "Prashant.patil" Date: Mon, 24 Feb 2025 08:13:30 +0530 Subject: [PATCH 17/17] null either --- package.json | 2 +- src/LiveboardEmbedClass.ts | 8 +------- src/componentFactory.tsx | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 3fbb07a..888f9bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embed-react-native-sdk", - "version": "3.0.9", + "version": "3.0.10", "description": "React Native SDK for Embedding TS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", diff --git a/src/LiveboardEmbedClass.ts b/src/LiveboardEmbedClass.ts index 945d504..7e108a8 100644 --- a/src/LiveboardEmbedClass.ts +++ b/src/LiveboardEmbedClass.ts @@ -13,10 +13,4 @@ class LiveboardEmbedClass e export interface LiveboardEmbedProps extends LiveboardViewConfig, EmbedProps {} -const LiveboardEmbedComponent = componentFactory< - typeof LiveboardEmbedClass, - LiveboardViewConfig, - LiveboardEmbedProps ->(LiveboardEmbedClass); - -export const LiveboardEmbed = React.memo(LiveboardEmbedComponent) as React.NamedExoticComponent>>; \ No newline at end of file +export const LiveboardEmbed = componentFactory(LiveboardEmbedClass) || null; \ No newline at end of file diff --git a/src/componentFactory.tsx b/src/componentFactory.tsx index 00a3e34..bfc9e9a 100644 --- a/src/componentFactory.tsx +++ b/src/componentFactory.tsx @@ -47,7 +47,7 @@ export const componentFactory = { - return embedInstance.current?.render() ?? null; + return embedInstance.current?.render() as React.JSX.Element ?? null; }, [props]); React.useEffect(() => {