@cloudflare/realtimekit-react-native 1.2.0-staging.0 → 1.2.0-staging.1

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.
Files changed (30) hide show
  1. package/android/src/main/AndroidManifest.xml +6 -1
  2. package/android/src/main/java/com/cloudflare/realtimekit/KeepAliveService.java +176 -0
  3. package/android/src/main/java/com/cloudflare/realtimekit/RTKHelperModule.java +27 -60
  4. package/lib/commonjs/LocalMediaHandler.js +114 -82
  5. package/lib/commonjs/LocalMediaHandler.js.map +1 -1
  6. package/lib/commonjs/LocalMediaUtils.js +3 -5
  7. package/lib/commonjs/LocalMediaUtils.js.map +1 -1
  8. package/lib/commonjs/ReactHooks.js +27 -9
  9. package/lib/commonjs/ReactHooks.js.map +1 -1
  10. package/lib/commonjs/index.js.map +1 -1
  11. package/lib/commonjs/utils/version.js +1 -1
  12. package/lib/commonjs/utils/version.js.map +1 -1
  13. package/lib/module/LocalMediaHandler.js +114 -82
  14. package/lib/module/LocalMediaHandler.js.map +1 -1
  15. package/lib/module/LocalMediaUtils.js +3 -5
  16. package/lib/module/LocalMediaUtils.js.map +1 -1
  17. package/lib/module/ReactHooks.js +27 -8
  18. package/lib/module/ReactHooks.js.map +1 -1
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/utils/version.js +1 -1
  21. package/lib/module/utils/version.js.map +1 -1
  22. package/lib/typescript/LocalMediaHandler.d.ts +18 -4
  23. package/lib/typescript/ReactHooks.d.ts +18 -0
  24. package/lib/typescript/index.d.ts +1 -0
  25. package/lib/typescript/utils/version.d.ts +1 -1
  26. package/package.json +1 -1
  27. package/plugin/build/withRTK.js +50 -22
  28. package/plugin/src/withRTK.ts +58 -23
  29. package/android/src/main/java/com/cloudflare/realtimekit/ForegroundService.java +0 -46
  30. package/android/src/main/java/com/cloudflare/realtimekit/NotificationHelper.java +0 -126
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNative","_realtimekit","_interopRequireDefault","_ReactContext","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_BackgroundHandler","_AudioSampleHandler","_LocalMediaUtils","_LocalMediaHandler","e","__esModule","default","useRealtimeKitClient","clientParams","isRunning","useRef","client","setClient","useState","resetOnLeave","initClient","useCallback","options","current","undefined","cleanUpEvents","RealtimeKitClient","init","then","meeting","finally","useEffect","onLeave","state","self","on","removeListener","connectedMeetings","onMeetingChanged","newClient","setTimeout","shouldUpdate","slice","newSlice","Array","isArray","length","useRTKSelector","selector","useRealtimeKitSelector","updates","useContext","RealtimeKitContext","Error","forceUpdate","useReducer","c","currentState","listener","newStateSlice","addListener","RTKHelper","NativeModules","webRTCModuleEmitter","removeAllListeners","deviceChangeListener","BackgroundTimer","stop","Platform","OS","isForegroundServiceRunning","val","stopService","broadcastEmitter","_err"],"sources":["ReactHooks.tsx"],"sourcesContent":["import {\n useState,\n useEffect,\n useRef,\n useReducer,\n useContext,\n useCallback,\n} from 'react';\nimport { NativeModules, Platform } from 'react-native';\nimport RealtimeKitClient, {\n RTKClientOptions,\n LeaveRoomState,\n} from '@cloudflare/realtimekit';\nimport { RealtimeKitContext } from './ReactContext';\nimport BackgroundTimer from './BackgroundHandler';\nimport { webRTCModuleEmitter } from './AudioSampleHandler';\nimport { deviceChangeListener } from './LocalMediaUtils';\nimport { broadcastEmitter } from './LocalMediaHandler';\n\ninterface RealtimeKitClientParams {\n resetOnLeave?: boolean;\n}\n\n/**\n * Hook which manages a RealtimeKitClient instance\n */\nexport const useRealtimeKitClient = (\n clientParams?: RealtimeKitClientParams\n): [\n RealtimeKitClient | undefined,\n (options: RTKClientOptions) => Promise<RealtimeKitClient | undefined>\n] => {\n const isRunning = useRef(false);\n const [client, setClient] = useState<RealtimeKitClient>();\n const resetOnLeave = clientParams?.resetOnLeave;\n\n const initClient = useCallback(\n async (\n options: RTKClientOptions\n ): Promise<RealtimeKitClient | undefined> => {\n if (isRunning.current) return undefined;\n isRunning.current = true;\n cleanUpEvents();\n return RealtimeKitClient.init(options)\n .then((meeting: RealtimeKitClient) => {\n setClient(meeting);\n return meeting;\n })\n .finally(() => {\n isRunning.current = false;\n });\n },\n []\n );\n\n useEffect(() => {\n if (!client || !resetOnLeave) return () => {};\n const onLeave = ({ state }: { state: LeaveRoomState }) => {\n if (state !== 'connected-meeting' && state !== 'disconnected') {\n setClient(undefined);\n }\n };\n\n client.self.on('roomLeft', onLeave);\n return () => {\n client.self.removeListener('roomLeft', onLeave);\n };\n }, [client, resetOnLeave]);\n\n useEffect(() => {\n if (!client || !client.connectedMeetings) return () => {};\n const onMeetingChanged = (newClient: RealtimeKitClient) => {\n // NOTE: do NOT clear this timeout in the effect cleanup. `setClient(\n // undefined)` re-runs this effect (client is a dependency) and its\n // cleanup fires *before* the timeout — clearing it would drop the new\n // client and leave the UI stuck on the loading screen.\n setClient(undefined);\n setTimeout(() => {\n setClient(newClient);\n }, 100);\n };\n client.connectedMeetings.on('meetingChanged', onMeetingChanged);\n return () => {\n client.connectedMeetings.removeListener(\n 'meetingChanged',\n onMeetingChanged\n );\n };\n }, [client]);\n\n return [client, initClient] as [\n RealtimeKitClient | undefined,\n (options: RTKClientOptions) => Promise<RealtimeKitClient | undefined>\n ];\n};\n\n/**\n * Utility function which determines whether to trigger update or not\n */\nconst shouldUpdate = <StateSlice,>(\n slice: StateSlice,\n newSlice: StateSlice\n): boolean => {\n if (slice !== newSlice) {\n return true;\n }\n if (Array.isArray(slice) && Array.isArray(newSlice)) {\n if (slice.length !== newSlice.length) {\n return true;\n }\n }\n\n return false;\n};\n\ntype StateSelector<T extends object, U> = (state: T) => U;\n\n/**\n * @deprecated Use `useRealtimeKitSelector` instead.\n * Hook which extracts data from the RealtimeKitClient object\n */\nexport const useRTKSelector = <StateSlice,>(\n selector: StateSelector<RealtimeKitClient, StateSlice>\n) => {\n return useRealtimeKitSelector(selector);\n};\n\n/**\n * Hook which extracts data from the RealtimeKitClient object\n */\nexport const useRealtimeKitSelector = <StateSlice,>(\n selector: StateSelector<RealtimeKitClient, StateSlice>\n) => {\n const { meeting, updates } = useContext(RealtimeKitContext);\n if (!meeting)\n throw new Error(\n 'useRealtimeKitSelector must be used within the RealtimeKitProvider'\n );\n const state = useRef(selector(meeting));\n const [, forceUpdate] = useReducer((c) => c + 1, 0) as [never, () => void];\n\n useEffect(() => {\n const currentState = meeting && selector(meeting);\n const listener = () => {\n const newStateSlice = meeting && selector(meeting);\n if (shouldUpdate(state.current, newStateSlice)) {\n state.current = newStateSlice;\n forceUpdate();\n }\n };\n if (\n currentState &&\n typeof currentState === 'object' &&\n 'addListener' in currentState\n ) {\n (currentState as any).addListener('*', forceUpdate);\n return () => {\n (currentState as any).removeListener('*', forceUpdate);\n };\n }\n updates?.addListener(listener);\n return () => {\n updates?.removeListener(listener);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [meeting, updates]);\n return state.current;\n};\n\nfunction cleanUpEvents() {\n const { RTKHelper } = NativeModules;\n\n webRTCModuleEmitter.removeAllListeners('audioSamples');\n deviceChangeListener.removeAllListeners('onAudioDeviceChanged');\n BackgroundTimer.stop();\n\n try {\n if (Platform.OS === 'android') {\n RTKHelper.isForegroundServiceRunning().then((val) => {\n if (val) {\n RTKHelper.stopService();\n }\n });\n } else {\n broadcastEmitter.removeAllListeners('iOS_BroadcastStarted');\n broadcastEmitter.removeAllListeners('iOS_BroadcastStopped');\n }\n } catch (_err) {}\n}\nexport * from './ReactContext';\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNative","_realtimekit","_interopRequireDefault","_ReactContext","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_BackgroundHandler","_AudioSampleHandler","_LocalMediaUtils","_LocalMediaHandler","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","set","getOwnPropertyDescriptor","useRealtimeKitClient","clientParams","isRunning","useRef","client","setClient","useState","resetOnLeave","keepAliveService","undefined","LocalMediaHandler","configure","initClient","useCallback","options","current","cleanUpEvents","RealtimeKitClient","init","then","meeting","finally","useEffect","onLeave","state","Platform","OS","_NativeModules$RTKHel","_NativeModules$RTKHel2","NativeModules","RTKHelper","stopMeetingService","self","on","removeListener","connectedMeetings","onMeetingChanged","newClient","setTimeout","shouldUpdate","slice","newSlice","Array","isArray","length","useRTKSelector","selector","useRealtimeKitSelector","updates","useContext","RealtimeKitContext","Error","forceUpdate","useReducer","c","currentState","listener","newStateSlice","addListener","webRTCModuleEmitter","removeAllListeners","deviceChangeListener","BackgroundTimer","stop","_NativeModules$RTKHel3","_NativeModules$RTKHel4","broadcastEmitter","_err"],"sources":["ReactHooks.tsx"],"sourcesContent":["import {\n useState,\n useEffect,\n useRef,\n useReducer,\n useContext,\n useCallback,\n} from 'react';\nimport { NativeModules, Platform } from 'react-native';\nimport RealtimeKitClient, {\n RTKClientOptions,\n LeaveRoomState,\n} from '@cloudflare/realtimekit';\nimport { RealtimeKitContext } from './ReactContext';\nimport BackgroundTimer from './BackgroundHandler';\nimport { webRTCModuleEmitter } from './AudioSampleHandler';\nimport { deviceChangeListener } from './LocalMediaUtils';\nimport { broadcastEmitter } from './LocalMediaHandler';\nimport LocalMediaHandler, { MeetingServiceConfig } from './LocalMediaHandler';\n\n/**\n * Public configuration for the Android meeting foreground service.\n * Structurally identical to the relevant fields of MeetingServiceConfig so\n * no cast is required when passing it to LocalMediaHandler.configure().\n */\nexport type KeepAliveServiceConfig = Pick<\n MeetingServiceConfig,\n 'enabled' | 'title' | 'text'\n>;\n\ninterface RealtimeKitClientParams {\n resetOnLeave?: boolean;\n /**\n * Android only. Configures (or disables) the meeting foreground service.\n *\n * @example\n * // Disable:\n * useRealtimeKitClient({ keepAliveService: { enabled: false } })\n *\n * // Custom notification text:\n * useRealtimeKitClient({ keepAliveService: { enabled: true, title: 'Team call', text: 'Tap to return' } })\n */\n keepAliveService?: KeepAliveServiceConfig;\n}\n\n/**\n * Hook which manages a RealtimeKitClient instance\n */\nexport const useRealtimeKitClient = (\n clientParams?: RealtimeKitClientParams\n): [\n RealtimeKitClient | undefined,\n (options: RTKClientOptions) => Promise<RealtimeKitClient | undefined>\n] => {\n const isRunning = useRef(false);\n const [client, setClient] = useState<RealtimeKitClient>();\n const resetOnLeave = clientParams?.resetOnLeave;\n const keepAliveService = clientParams?.keepAliveService;\n\n // Configure synchronously during render — not in useEffect — so the\n // module-level config is guaranteed to be in place before initClient()\n // is called. useEffect is asynchronous w.r.t. render and would create a\n // race where initClient() fires before the config is applied.\n // LocalMediaHandler.configure() is idempotent for the same values.\n if (keepAliveService !== undefined) {\n LocalMediaHandler.configure(keepAliveService);\n }\n\n const initClient = useCallback(\n async (\n options: RTKClientOptions\n ): Promise<RealtimeKitClient | undefined> => {\n if (isRunning.current) return undefined;\n isRunning.current = true;\n cleanUpEvents();\n return RealtimeKitClient.init(options)\n .then((meeting: RealtimeKitClient) => {\n setClient(meeting);\n return meeting;\n })\n .finally(() => {\n isRunning.current = false;\n });\n },\n []\n );\n\n useEffect(() => {\n if (!client || !resetOnLeave) return () => {};\n const onLeave = ({ state }: { state: LeaveRoomState }) => {\n if (state !== 'connected-meeting' && state !== 'disconnected') {\n setClient(undefined);\n }\n if (\n state === 'ended' ||\n state === 'kicked' ||\n state === 'rejected' ||\n state === 'failed'\n ) {\n // Stop the KeepAlive foreground service when the meeting ends.\n if (Platform.OS === 'android') {\n NativeModules.RTKHelper?.stopMeetingService?.();\n }\n }\n };\n\n client.self.on('roomLeft', onLeave);\n return () => {\n client.self.removeListener('roomLeft', onLeave);\n };\n }, [client, resetOnLeave]);\n\n useEffect(() => {\n if (!client || !client.connectedMeetings) return () => {};\n const onMeetingChanged = (newClient: RealtimeKitClient) => {\n // NOTE: do NOT clear this timeout in the effect cleanup. `setClient(\n // undefined)` re-runs this effect (client is a dependency) and its\n // cleanup fires *before* the timeout — clearing it would drop the new\n // client and leave the UI stuck on the loading screen.\n setClient(undefined);\n setTimeout(() => {\n setClient(newClient);\n }, 100);\n };\n client.connectedMeetings.on('meetingChanged', onMeetingChanged);\n return () => {\n client.connectedMeetings.removeListener(\n 'meetingChanged',\n onMeetingChanged\n );\n };\n }, [client]);\n\n return [client, initClient] as [\n RealtimeKitClient | undefined,\n (options: RTKClientOptions) => Promise<RealtimeKitClient | undefined>\n ];\n};\n\n/**\n * Utility function which determines whether to trigger update or not\n */\nconst shouldUpdate = <StateSlice,>(\n slice: StateSlice,\n newSlice: StateSlice\n): boolean => {\n if (slice !== newSlice) {\n return true;\n }\n if (Array.isArray(slice) && Array.isArray(newSlice)) {\n if (slice.length !== newSlice.length) {\n return true;\n }\n }\n\n return false;\n};\n\ntype StateSelector<T extends object, U> = (state: T) => U;\n\n/**\n * @deprecated Use `useRealtimeKitSelector` instead.\n * Hook which extracts data from the RealtimeKitClient object\n */\nexport const useRTKSelector = <StateSlice,>(\n selector: StateSelector<RealtimeKitClient, StateSlice>\n) => {\n return useRealtimeKitSelector(selector);\n};\n\n/**\n * Hook which extracts data from the RealtimeKitClient object\n */\nexport const useRealtimeKitSelector = <StateSlice,>(\n selector: StateSelector<RealtimeKitClient, StateSlice>\n) => {\n const { meeting, updates } = useContext(RealtimeKitContext);\n if (!meeting)\n throw new Error(\n 'useRealtimeKitSelector must be used within the RealtimeKitProvider'\n );\n const state = useRef(selector(meeting));\n const [, forceUpdate] = useReducer((c) => c + 1, 0) as [never, () => void];\n\n useEffect(() => {\n const currentState = meeting && selector(meeting);\n const listener = () => {\n const newStateSlice = meeting && selector(meeting);\n if (shouldUpdate(state.current, newStateSlice)) {\n state.current = newStateSlice;\n forceUpdate();\n }\n };\n if (\n currentState &&\n typeof currentState === 'object' &&\n 'addListener' in currentState\n ) {\n (currentState as any).addListener('*', forceUpdate);\n return () => {\n (currentState as any).removeListener('*', forceUpdate);\n };\n }\n updates?.addListener(listener);\n return () => {\n updates?.removeListener(listener);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [meeting, updates]);\n return state.current;\n};\n\nfunction cleanUpEvents() {\n webRTCModuleEmitter.removeAllListeners('audioSamples');\n deviceChangeListener.removeAllListeners('onAudioDeviceChanged');\n BackgroundTimer.stop();\n\n try {\n if (Platform.OS === 'android') {\n NativeModules.RTKHelper?.stopMeetingService?.();\n } else {\n broadcastEmitter.removeAllListeners('iOS_BroadcastStarted');\n broadcastEmitter.removeAllListeners('iOS_BroadcastStopped');\n }\n } catch (_err) {}\n}\nexport * from './ReactContext';\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_realtimekit","_interopRequireDefault","_LocalMediaHandler","_AudioSampleHandler","_BackgroundHandler","_reactNativeWebrtc","_DeviceInfo","_base","_ReactHooks","e","__esModule","default","global","atob","decode","btoa","encode","registerGlobals","LINKING_ERROR","Platform","select","ios","Core","NativeModules","Proxy","get","Error","Object","defineProperty","navigator","configurable","LocalMediaHandler","AudioSampleHandler","BackgroundTimer","DeviceInfo","_default","exports","RealtimeKitMeeting"],"sources":["index.tsx"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nimport RealtimeKitMeeting from '@cloudflare/realtimekit';\nimport LocalMediaHandler from './LocalMediaHandler';\nimport AudioSampleHandler from './AudioSampleHandler';\nimport BackgroundTimer from './BackgroundHandler';\nimport { registerGlobals } from '@cloudflare/react-native-webrtc';\nimport './utils/crypto';\nimport 'text-encoding-polyfill';\nimport 'react-native-url-polyfill/auto';\nimport DeviceInfo from './DeviceInfo';\nimport { encode, decode } from 'base-64';\nglobal.atob = decode;\nglobal.btoa = encode;\n\nexport {\n RealtimeKitProvider,\n useRealtimeKitClient,\n useRTKSelector,\n useRealtimeKitSelector,\n useRealtimeKitMeeting,\n} from './ReactHooks';\n\nregisterGlobals();\n\nconst LINKING_ERROR =\n `The package '@cloudflare/realtimekit-react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Core = NativeModules.Core\n ? NativeModules.Core\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\ndeclare global {\n // @ts-ignore\n var navigator: any;\n}\n\nObject.defineProperty(navigator as any, 'isReactNative', {\n get: function () {\n return true;\n },\n configurable: true,\n});\n\nObject.defineProperty(navigator as any, 'userAgent', {\n get: function () {\n return 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4753.0 Safari/537.36'; // customized user agent\n },\n configurable: true,\n});\n\nObject.defineProperty(navigator as any, 'RNLocalMediaHandlerImpl', {\n get: function () {\n return LocalMediaHandler;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNAudioSampleHandlerImpl', {\n get: function () {\n return AudioSampleHandler;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNBackgroundTimerImpl', {\n get: function () {\n return BackgroundTimer;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNDeviceInfoImpl', {\n get: function () {\n return DeviceInfo;\n },\n});\n\nexport default RealtimeKitMeeting;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,kBAAA,GAAAD,sBAAA,CAAAF,OAAA;AACA,IAAAI,mBAAA,GAAAF,sBAAA,CAAAF,OAAA;AACA,IAAAK,kBAAA,GAAAH,sBAAA,CAAAF,OAAA;AACA,IAAAM,kBAAA,GAAAN,OAAA;AACAA,OAAA;AACAA,OAAA;AACAA,OAAA;AACA,IAAAO,WAAA,GAAAL,sBAAA,CAAAF,OAAA;AACA,IAAAQ,KAAA,GAAAR,OAAA;AAIA,IAAAS,WAAA,GAAAT,OAAA;AAMsB,SAAAE,uBAAAQ,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AATtBG,MAAM,CAACC,IAAI,GAAGC,YAAM;AACpBF,MAAM,CAACG,IAAI,GAAGC,YAAM;AAUpB,IAAAC,kCAAe,EAAC,CAAC;AAEjB,MAAMC,aAAa,GACjB,+FAA+F,GAC/FC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEV,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,6CAA6C;;AAE/C;AACA,MAAMW,IAAI,GAAGC,0BAAa,CAACD,IAAI,GAC3BC,0BAAa,CAACD,IAAI,GAClB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAOLS,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,eAAe,EAAE;EACvDJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAO,IAAI;EACb,CAAC;EACDK,YAAY,EAAE;AAChB,CAAC,CAAC;AAEFH,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,WAAW,EAAE;EACnDJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAO,yHAAyH,CAAC,CAAC;EACpI,CAAC;EACDK,YAAY,EAAE;AAChB,CAAC,CAAC;AAEFH,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,yBAAyB,EAAE;EACjEJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOM,0BAAiB;EAC1B;AACF,CAAC,CAAC;AAEFJ,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,0BAA0B,EAAE;EAClEJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOO,2BAAkB;EAC3B;AACF,CAAC,CAAC;AAEFL,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,uBAAuB,EAAE;EAC/DJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOQ,0BAAe;EACxB;AACF,CAAC,CAAC;AAEFN,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,kBAAkB,EAAE;EAC1DJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOS,mBAAU;EACnB;AACF,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAzB,OAAA,GAEY0B,oBAAkB","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_realtimekit","_interopRequireDefault","_LocalMediaHandler","_AudioSampleHandler","_BackgroundHandler","_reactNativeWebrtc","_DeviceInfo","_base","_ReactHooks","e","__esModule","default","global","atob","decode","btoa","encode","registerGlobals","LINKING_ERROR","Platform","select","ios","Core","NativeModules","Proxy","get","Error","Object","defineProperty","navigator","configurable","LocalMediaHandler","AudioSampleHandler","BackgroundTimer","DeviceInfo","_default","exports","RealtimeKitMeeting"],"sources":["index.tsx"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nimport RealtimeKitMeeting from '@cloudflare/realtimekit';\nimport LocalMediaHandler from './LocalMediaHandler';\nimport AudioSampleHandler from './AudioSampleHandler';\nimport BackgroundTimer from './BackgroundHandler';\nimport { registerGlobals } from '@cloudflare/react-native-webrtc';\nimport './utils/crypto';\nimport 'text-encoding-polyfill';\nimport 'react-native-url-polyfill/auto';\nimport DeviceInfo from './DeviceInfo';\nimport { encode, decode } from 'base-64';\nexport type { KeepAliveServiceConfig } from './ReactHooks';\nglobal.atob = decode;\nglobal.btoa = encode;\n\nexport {\n RealtimeKitProvider,\n useRealtimeKitClient,\n useRTKSelector,\n useRealtimeKitSelector,\n useRealtimeKitMeeting,\n} from './ReactHooks';\n\nregisterGlobals();\n\nconst LINKING_ERROR =\n `The package '@cloudflare/realtimekit-react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Core = NativeModules.Core\n ? NativeModules.Core\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\ndeclare global {\n // @ts-ignore\n var navigator: any;\n}\n\nObject.defineProperty(navigator as any, 'isReactNative', {\n get: function () {\n return true;\n },\n configurable: true,\n});\n\nObject.defineProperty(navigator as any, 'userAgent', {\n get: function () {\n return 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4753.0 Safari/537.36'; // customized user agent\n },\n configurable: true,\n});\n\nObject.defineProperty(navigator as any, 'RNLocalMediaHandlerImpl', {\n get: function () {\n return LocalMediaHandler;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNAudioSampleHandlerImpl', {\n get: function () {\n return AudioSampleHandler;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNBackgroundTimerImpl', {\n get: function () {\n return BackgroundTimer;\n },\n});\n\nObject.defineProperty(navigator as any, 'RNDeviceInfoImpl', {\n get: function () {\n return DeviceInfo;\n },\n});\n\nexport default RealtimeKitMeeting;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,kBAAA,GAAAD,sBAAA,CAAAF,OAAA;AACA,IAAAI,mBAAA,GAAAF,sBAAA,CAAAF,OAAA;AACA,IAAAK,kBAAA,GAAAH,sBAAA,CAAAF,OAAA;AACA,IAAAM,kBAAA,GAAAN,OAAA;AACAA,OAAA;AACAA,OAAA;AACAA,OAAA;AACA,IAAAO,WAAA,GAAAL,sBAAA,CAAAF,OAAA;AACA,IAAAQ,KAAA,GAAAR,OAAA;AAKA,IAAAS,WAAA,GAAAT,OAAA;AAMsB,SAAAE,uBAAAQ,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AATtBG,MAAM,CAACC,IAAI,GAAGC,YAAM;AACpBF,MAAM,CAACG,IAAI,GAAGC,YAAM;AAUpB,IAAAC,kCAAe,EAAC,CAAC;AAEjB,MAAMC,aAAa,GACjB,+FAA+F,GAC/FC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEV,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,6CAA6C;;AAE/C;AACA,MAAMW,IAAI,GAAGC,0BAAa,CAACD,IAAI,GAC3BC,0BAAa,CAACD,IAAI,GAClB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAOLS,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,eAAe,EAAE;EACvDJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAO,IAAI;EACb,CAAC;EACDK,YAAY,EAAE;AAChB,CAAC,CAAC;AAEFH,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,WAAW,EAAE;EACnDJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAO,yHAAyH,CAAC,CAAC;EACpI,CAAC;EACDK,YAAY,EAAE;AAChB,CAAC,CAAC;AAEFH,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,yBAAyB,EAAE;EACjEJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOM,0BAAiB;EAC1B;AACF,CAAC,CAAC;AAEFJ,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,0BAA0B,EAAE;EAClEJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOO,2BAAkB;EAC3B;AACF,CAAC,CAAC;AAEFL,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,uBAAuB,EAAE;EAC/DJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOQ,0BAAe;EACxB;AACF,CAAC,CAAC;AAEFN,MAAM,CAACC,cAAc,CAACC,SAAS,EAAS,kBAAkB,EAAE;EAC1DJ,GAAG,EAAE,SAAAA,CAAA,EAAY;IACf,OAAOS,mBAAU;EACnB;AACF,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAzB,OAAA,GAEY0B,oBAAkB","ignoreList":[]}
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.SDK_VERSION = void 0;
7
- const SDK_VERSION = exports.SDK_VERSION = '1.2.0';
7
+ const SDK_VERSION = exports.SDK_VERSION = '1.2.0-staging.1';
8
8
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["SDK_VERSION","exports"],"sources":["version.ts"],"sourcesContent":["export const SDK_VERSION = '1.2.0';\n"],"mappings":";;;;;;AAAO,MAAMA,WAAW,GAAAC,OAAA,CAAAD,WAAA,GAAG,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["SDK_VERSION","exports"],"sources":["version.ts"],"sourcesContent":["export const SDK_VERSION = '1.2.0-staging.1';\n"],"mappings":";;;;;;AAAO,MAAMA,WAAW,GAAAC,OAAA,CAAAD,WAAA,GAAG,iBAAiB","ignoreList":[]}
@@ -19,6 +19,19 @@ const {
19
19
  } = NativeModules;
20
20
  export const broadcastEmitter = new NativeEventEmitter(BroadcastEventEmitter);
21
21
 
22
+ // ---------------------------------------------------------------------------
23
+ // Meeting foreground service config
24
+ // Set by LocalMediaHandler.configure() before the first init() call.
25
+ // ---------------------------------------------------------------------------
26
+
27
+ let _meetingServiceConfig = {
28
+ enabled: true,
29
+ title: 'In a call',
30
+ text: 'Tap to return to your meeting',
31
+ channelId: 'rtk_meeting',
32
+ channelName: 'Ongoing Meeting'
33
+ };
34
+
22
35
  // eslint-disable-next-line no-shadow
23
36
  export let MediaEvents = /*#__PURE__*/function (MediaEvents) {
24
37
  MediaEvents[MediaEvents["AUDIO_TRACK_CHANGE"] = 0] = "AUDIO_TRACK_CHANGE";
@@ -45,26 +58,6 @@ var _broadcastEmitter = /*#__PURE__*/new WeakMap();
45
58
  var _broadcastStartedSubscription = /*#__PURE__*/new WeakMap();
46
59
  var _broadcastStoppedSubscription = /*#__PURE__*/new WeakMap();
47
60
  export default class LocalMediaHandler extends EventEmitter {
48
- async configureForeground() {
49
- if (Platform.OS !== 'android') return;
50
- const val = await RTKHelper.isForegroundServiceRunning();
51
- if (!val) {
52
- if (Platform.Version >= 33) {
53
- const res = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
54
- if (res !== PermissionsAndroid.RESULTS.GRANTED) {
55
- console.warn('Permission required for screenshare notification');
56
- }
57
- }
58
- if (Platform.Version >= 26) {
59
- await RTKHelper.createNotificationChannel();
60
- }
61
- try {
62
- await RTKHelper.startService();
63
- } catch (e) {
64
- console.warn('Failed to start foreground service', e);
65
- }
66
- }
67
- }
68
61
  constructor(localMediaUtils) {
69
62
  super();
70
63
  _classPrivateFieldInitSpec(this, _localMediaUtils, void 0);
@@ -88,9 +81,15 @@ export default class LocalMediaHandler extends EventEmitter {
88
81
  _classPrivateFieldInitSpec(this, _broadcastStartedSubscription, void 0);
89
82
  _classPrivateFieldInitSpec(this, _broadcastStoppedSubscription, void 0);
90
83
  _defineProperty(this, "_handleAppStateChange", nextAppState => {
91
- if (_classPrivateFieldGet(_appState, this).match(/inactive|background/) && nextAppState === 'active') {
92
- BackgroundTimer.clearInterval(_classPrivateFieldGet(_interval, this));
93
- _classPrivateFieldSet(_interval, this, null);
84
+ const prevAppState = _classPrivateFieldGet(_appState, this);
85
+ _classPrivateFieldSet(_appState, this, nextAppState);
86
+ if (prevAppState.match(/inactive|background/) && nextAppState === 'active') {
87
+ // App returned to foreground — stop the background keep-alive timer
88
+ // and kick the video track to recover the camera feed.
89
+ if (_classPrivateFieldGet(_interval, this) !== null) {
90
+ BackgroundTimer.clearInterval(_classPrivateFieldGet(_interval, this));
91
+ _classPrivateFieldSet(_interval, this, null);
92
+ }
94
93
  if (this.videoTrack) {
95
94
  this.videoTrack.enabled = false;
96
95
  setTimeout(() => {
@@ -99,16 +98,23 @@ export default class LocalMediaHandler extends EventEmitter {
99
98
  }
100
99
  }, 100);
101
100
  }
102
- } else {
103
- if (_classPrivateFieldGet(_interval, this) === null) {
104
- if (this.screenShareEnabled || this._pendingScreenShare) {
105
- this.configureForeground();
106
- }
101
+ } else if (nextAppState.match(/inactive|background/)) {
102
+ // App moved to background — start a recurring no-op timer to keep the
103
+ // JS thread alive so WebRTC/native events continue to be processed.
104
+ // Clear any existing interval first to avoid accumulation.
105
+ if (_classPrivateFieldGet(_interval, this) !== null) {
106
+ BackgroundTimer.clearInterval(_classPrivateFieldGet(_interval, this));
107
107
  }
108
108
  _classPrivateFieldSet(_interval, this, BackgroundTimer.setInterval(() => {}, 1000));
109
- _classPrivateFieldSet(_appState, this, nextAppState);
110
109
  }
111
110
  });
111
+ // Arrow function so `this` is stable — the same reference is used in both
112
+ // addEventListener (setScreenShareTracks) and removeEventListener
113
+ // (removeScreenShareTracks). A regular method + .bind(this) creates a new
114
+ // function object on every call, making removeEventListener a no-op.
115
+ _defineProperty(this, "onScreenShareEnded", () => {
116
+ this.emit('SCREENSHARE_ENDED');
117
+ });
112
118
  _classPrivateFieldSet(_localMediaUtils, this, localMediaUtils);
113
119
  _classPrivateFieldSet(_broadcastEmitter, this, broadcastEmitter);
114
120
  _classPrivateFieldSet(_appState, this, '');
@@ -486,6 +492,11 @@ export default class LocalMediaHandler extends EventEmitter {
486
492
  if (Platform.OS === 'android') {
487
493
  _classPrivateFieldSet(_appStateSubscription, this, AppState.addEventListener('change', this._handleAppStateChange));
488
494
  }
495
+
496
+ // Start the meeting foreground service so Android keeps the app alive
497
+ // in the background during a call. The app is guaranteed to be in the
498
+ // foreground at this point (user just tapped join / setup screen).
499
+ await this.startMeetingService();
489
500
  }
490
501
  stopScreenShareTracks(tracks = {}) {
491
502
  const {
@@ -493,20 +504,22 @@ export default class LocalMediaHandler extends EventEmitter {
493
504
  video = true
494
505
  } = tracks;
495
506
  if (audio) {
496
- var _this$screenShareTrac;
507
+ var _this$screenShareTrac, _this$screenShareTrac2;
497
508
  (_this$screenShareTrac = this.screenShareTracks) === null || _this$screenShareTrac === void 0 || (_this$screenShareTrac = _this$screenShareTrac.audio) === null || _this$screenShareTrac === void 0 || _this$screenShareTrac.stop();
509
+ (_this$screenShareTrac2 = this.screenShareTracks) === null || _this$screenShareTrac2 === void 0 || (_this$screenShareTrac2 = _this$screenShareTrac2.audio) === null || _this$screenShareTrac2 === void 0 || _this$screenShareTrac2.release();
498
510
  }
499
511
  if (video) {
500
- var _this$screenShareTrac2;
501
- (_this$screenShareTrac2 = this.screenShareTracks) === null || _this$screenShareTrac2 === void 0 || (_this$screenShareTrac2 = _this$screenShareTrac2.video) === null || _this$screenShareTrac2 === void 0 || _this$screenShareTrac2.stop();
512
+ var _this$screenShareTrac3, _this$screenShareTrac4;
513
+ (_this$screenShareTrac3 = this.screenShareTracks) === null || _this$screenShareTrac3 === void 0 || (_this$screenShareTrac3 = _this$screenShareTrac3.video) === null || _this$screenShareTrac3 === void 0 || _this$screenShareTrac3.stop();
514
+ (_this$screenShareTrac4 = this.screenShareTracks) === null || _this$screenShareTrac4 === void 0 || (_this$screenShareTrac4 = _this$screenShareTrac4.video) === null || _this$screenShareTrac4 === void 0 || _this$screenShareTrac4.release();
502
515
  }
503
516
  if (audio && video) {
504
517
  this.screenShareEnabled = false;
505
518
  }
506
519
  }
507
520
  removeScreenShareTracks(tracks) {
508
- var _this$screenShareTrac3;
509
- (_this$screenShareTrac3 = this.screenShareTracks.video) === null || _this$screenShareTrac3 === void 0 || _this$screenShareTrac3.removeEventListener('ended', this.onScreenShareEnded);
521
+ var _this$screenShareTrac5;
522
+ (_this$screenShareTrac5 = this.screenShareTracks.video) === null || _this$screenShareTrac5 === void 0 || _this$screenShareTrac5.removeEventListener('ended', this.onScreenShareEnded);
510
523
  this.stopScreenShareTracks(tracks);
511
524
  this.screenShareTracks = {
512
525
  audio: undefined,
@@ -538,7 +551,7 @@ export default class LocalMediaHandler extends EventEmitter {
538
551
  this.videoTrack = videoTrack;
539
552
  }
540
553
  setScreenShareTracks(tracks) {
541
- var _this$screenShareTrac4;
554
+ var _this$screenShareTrac6;
542
555
  const {
543
556
  audio,
544
557
  video
@@ -550,10 +563,7 @@ export default class LocalMediaHandler extends EventEmitter {
550
563
  });
551
564
  }
552
565
  this.screenShareTracks = tracks;
553
- (_this$screenShareTrac4 = this.screenShareTracks.video) === null || _this$screenShareTrac4 === void 0 || _this$screenShareTrac4.addEventListener('ended', this.onScreenShareEnded.bind(this));
554
- }
555
- onScreenShareEnded() {
556
- this.emit('SCREENSHARE_ENDED');
566
+ (_this$screenShareTrac6 = this.screenShareTracks.video) === null || _this$screenShareTrac6 === void 0 || _this$screenShareTrac6.addEventListener('ended', this.onScreenShareEnded);
557
567
  }
558
568
  async disableAudio() {
559
569
  await this.toggleAudio();
@@ -679,53 +689,19 @@ export default class LocalMediaHandler extends EventEmitter {
679
689
  return;
680
690
  }
681
691
  }
682
- async toggleScreenShare() {
683
- if (this.screenShareEnabled && Platform.OS !== 'ios') {
684
- this.removeScreenShareTracks();
685
- try {
686
- const val = await RTKHelper.isForegroundServiceRunning();
687
- if (val) {
688
- await RTKHelper.stopService();
689
- }
690
- } catch (e) {
691
- console.warn('Failed to stop foreground service', e);
692
- }
693
- return;
694
- }
695
- if (Platform.OS === 'ios' && this.screenShareEnabled) {
696
- NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
697
- _classPrivateFieldSet(_screenShareState, this, 'PENDING');
698
- await new Promise((resolve, reject) => {
699
- let timeoutId;
700
- let time = 0;
701
- timeoutId = setInterval(() => {
702
- if (_classPrivateFieldGet(_screenShareState, this) === 'STOPPED') {
703
- clearInterval(timeoutId);
704
- resolve();
705
- }
706
- time = time + 100;
707
- if (time > 20000) {
708
- clearInterval(timeoutId);
709
- reject('Timeout exceeded for disableScreenShare()');
710
- }
711
- }, 100);
712
- });
713
- return;
714
- }
692
+ async enableScreenShare() {
693
+ // Guard: do nothing if already sharing or a consent dialog is in flight.
694
+ if (this.screenShareEnabled || this._pendingScreenShare) return;
715
695
  if (Platform.OS === 'android') {
716
696
  this._pendingScreenShare = true;
717
- await this.configureForeground();
718
697
  try {
698
+ // getScreenShareTracks() manages the full flow:
699
+ // consent dialog → start MediaProjectionService → create MediaStream
719
700
  this.setScreenShareTracks(await LocalMediaUtils.getScreenShareTracks());
720
701
  this.screenShareEnabled = true;
721
702
  } catch (e) {
722
703
  console.warn('Failed to start screenshare', e);
723
704
  this.screenShareEnabled = false;
724
- const val = await RTKHelper.isForegroundServiceRunning();
725
- if (val) {
726
- await RTKHelper.stopService();
727
- }
728
- this._pendingScreenShare = false;
729
705
  } finally {
730
706
  this._pendingScreenShare = false;
731
707
  }
@@ -750,11 +726,32 @@ export default class LocalMediaHandler extends EventEmitter {
750
726
  });
751
727
  }
752
728
  }
753
- async enableScreenShare() {
754
- await this.toggleScreenShare();
755
- }
756
729
  async disableScreenShare() {
757
- await this.toggleScreenShare();
730
+ // Guard: nothing to stop if not sharing and no consent dialog is pending.
731
+ if (!this.screenShareEnabled && !this._pendingScreenShare) return;
732
+ if (Platform.OS !== 'ios') {
733
+ this.removeScreenShareTracks();
734
+ return;
735
+ }
736
+
737
+ // iOS: trigger the broadcast picker to stop the extension.
738
+ NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
739
+ _classPrivateFieldSet(_screenShareState, this, 'PENDING');
740
+ await new Promise((resolve, reject) => {
741
+ let timeoutId;
742
+ let time = 0;
743
+ timeoutId = setInterval(() => {
744
+ if (_classPrivateFieldGet(_screenShareState, this) === 'STOPPED') {
745
+ clearInterval(timeoutId);
746
+ resolve();
747
+ }
748
+ time = time + 100;
749
+ if (time > 20000) {
750
+ clearInterval(timeoutId);
751
+ reject('Timeout exceeded for disableScreenShare()');
752
+ }
753
+ }, 100);
754
+ });
758
755
  }
759
756
  getAllDevices() {
760
757
  return _classPrivateFieldGet(_localMediaUtils, this).availableDevices;
@@ -881,10 +878,45 @@ export default class LocalMediaHandler extends EventEmitter {
881
878
  this.emit('DEVICE_LIST_UPDATED', changedDevices);
882
879
  }
883
880
  }
881
+
882
+ /**
883
+ * Override the meeting foreground service config before the first meeting
884
+ * session. Called by useRealtimeKitClient when keepAliveService is set.
885
+ */
886
+ static configure(config) {
887
+ _meetingServiceConfig = {
888
+ ..._meetingServiceConfig,
889
+ ...config
890
+ };
891
+ }
884
892
  static async init(_) {
885
893
  const localMediaUtils = await LocalMediaUtils.init();
886
894
  return new LocalMediaHandler(localMediaUtils);
887
895
  }
896
+ async startMeetingService() {
897
+ if (Platform.OS !== 'android') return;
898
+ if (!_meetingServiceConfig.enabled) return;
899
+
900
+ // Android 13+ (API 33): request POST_NOTIFICATIONS so the foreground-service
901
+ // notification appears in the shade.
902
+ if (Number(Platform.Version) >= 33) {
903
+ try {
904
+ await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
905
+ } catch (e) {
906
+ console.warn('Failed to request POST_NOTIFICATIONS permission', e);
907
+ }
908
+ }
909
+ try {
910
+ await RTKHelper.startMeetingService({
911
+ title: _meetingServiceConfig.title,
912
+ text: _meetingServiceConfig.text,
913
+ channelId: _meetingServiceConfig.channelId,
914
+ channelName: _meetingServiceConfig.channelName
915
+ });
916
+ } catch (e) {
917
+ console.warn('Failed to start KeepAliveService', e);
918
+ }
919
+ }
888
920
  emit(event, ...args) {
889
921
  return super.emit(event, ...args);
890
922
  }