From 730ab8fc76ac459d9510158aea1200b02f9ceb6a Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Mon, 23 Mar 2026 16:57:42 +0100 Subject: [PATCH 1/7] update useCamera type to RN --- packages/mobile-client/src/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index 470d7483..aef7b20a 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -13,8 +13,10 @@ import React from 'react'; import { FishjamProvider as ReactClientFishjamProvider, type FishjamProviderProps as ReactClientFishjamProviderProps, + useCamera as useCameraReactClient, useMicrophone as useMicrophoneReactClient, } from '@fishjam-cloud/react-client'; +import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc'; import { FishjamClient } from '@fishjam-cloud/ts-client'; export { RTCView, RTCPIPView, type RTCVideoViewProps, type RTCPIPViewProps } from './overrides/RTCView'; @@ -42,7 +44,6 @@ export { useForegroundService, type ForegroundServiceConfig } from './useForegro export { useCameraPermissions, useMicrophonePermissions, type PermissionStatus } from './hooks/usePermissions'; export { - useCamera, useInitializeDevices, InitializeDevicesSettings, useConnection, @@ -58,6 +59,10 @@ export { Variant, } from '@fishjam-cloud/react-client'; +export const useCamera = useCameraReactClient as () => Omit, 'cameraStream'> & { + cameraStream: RNMediaStream | null; +}; + export const useMicrophone = useMicrophoneReactClient as () => Omit< ReturnType, 'toggleMicrophoneMute' From b6188b93015c0050cc33b462901ec276be8a77a5 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Fri, 27 Mar 2026 11:48:21 +0100 Subject: [PATCH 2/7] fix other types --- examples/mobile-client/fishjam-chat/app.json | 4 +- .../fishjam-chat/utils/tracks.ts | 6 +- packages/mobile-client/src/index.ts | 38 ++++++------ .../mobile-client/src/overrides/RTCView.tsx | 6 +- packages/mobile-client/src/overrides/hooks.ts | 59 +++++++++++++++++++ packages/mobile-client/src/overrides/types.ts | 33 +++++++++++ 6 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 packages/mobile-client/src/overrides/hooks.ts create mode 100644 packages/mobile-client/src/overrides/types.ts diff --git a/examples/mobile-client/fishjam-chat/app.json b/examples/mobile-client/fishjam-chat/app.json index a336812d..b44374e1 100644 --- a/examples/mobile-client/fishjam-chat/app.json +++ b/examples/mobile-client/fishjam-chat/app.json @@ -71,9 +71,7 @@ } } ], - [ - "../common/plugins/build/withLocalWebrtcPaths.js" - ] + ["../common/plugins/build/withLocalWebrtcPaths.js"] ], "experiments": { "typedRoutes": true diff --git a/examples/mobile-client/fishjam-chat/utils/tracks.ts b/examples/mobile-client/fishjam-chat/utils/tracks.ts index 762da927..f9b7b68f 100644 --- a/examples/mobile-client/fishjam-chat/utils/tracks.ts +++ b/examples/mobile-client/fishjam-chat/utils/tracks.ts @@ -1,4 +1,8 @@ -import type { PeerId, PeerWithTracks, Track } from '@fishjam-cloud/react-native-client'; +import type { + PeerId, + PeerWithTracks, + Track, +} from '@fishjam-cloud/react-native-client'; export type GridTrack = { track: Track | null; diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index aef7b20a..f8265074 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -13,10 +13,7 @@ import React from 'react'; import { FishjamProvider as ReactClientFishjamProvider, type FishjamProviderProps as ReactClientFishjamProviderProps, - useCamera as useCameraReactClient, - useMicrophone as useMicrophoneReactClient, } from '@fishjam-cloud/react-client'; -import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc'; import { FishjamClient } from '@fishjam-cloud/ts-client'; export { RTCView, RTCPIPView, type RTCVideoViewProps, type RTCPIPViewProps } from './overrides/RTCView'; @@ -47,44 +44,44 @@ export { useInitializeDevices, InitializeDevicesSettings, useConnection, - useCustomSource, useDataChannel, - useLivestreamStreamer, - useLivestreamViewer, usePeers, useSandbox, - useScreenShare, useUpdatePeerMetadata, useVAD, Variant, } from '@fishjam-cloud/react-client'; -export const useCamera = useCameraReactClient as () => Omit, 'cameraStream'> & { - cameraStream: RNMediaStream | null; -}; +export { + useCamera, + useMicrophone, + useScreenShare, + useCustomSource, + useLivestreamStreamer, + useLivestreamViewer, +} from './overrides/hooks'; -export const useMicrophone = useMicrophoneReactClient as () => Omit< - ReturnType, - 'toggleMicrophoneMute' ->; +export type { + StreamerInputs, + ConnectStreamerConfig, + UseLivestreamStreamerResult, + UseLivestreamViewerResult, + Track, + CustomSource, + InitializeDevicesResult, +} from './overrides/types'; export type { UseInitializeDevicesParams, JoinRoomConfig, - ConnectStreamerConfig, - StreamerInputs, - UseLivestreamStreamerResult, ConnectViewerConfig, - UseLivestreamViewerResult, PeerWithTracks, RoomType, UseSandboxProps, BandwidthLimits, Brand, - CustomSource, DeviceError, DeviceItem, - InitializeDevicesResult, InitializeDevicesStatus, MiddlewareResult, PeerId, @@ -92,7 +89,6 @@ export type { PersistLastDeviceHandlers, SimulcastBandwidthLimits, StreamConfig, - Track, TrackId, TrackMiddleware, TracksMiddleware, diff --git a/packages/mobile-client/src/overrides/RTCView.tsx b/packages/mobile-client/src/overrides/RTCView.tsx index 01787e1a..24e631b8 100644 --- a/packages/mobile-client/src/overrides/RTCView.tsx +++ b/packages/mobile-client/src/overrides/RTCView.tsx @@ -4,14 +4,14 @@ import type React from 'react'; import { useMemo } from 'react'; export type RTCVideoViewProps = Omit, 'streamURL'> & { - mediaStream: MediaStream; + mediaStream: RNMediaStream; }; export type RTCPIPViewProps = Omit, 'streamURL'> & { - mediaStream: MediaStream; + mediaStream: RNMediaStream; }; -const convertMediaStreamToURL = (mediaStream: MediaStream | undefined): string | undefined => { +const convertMediaStreamToURL = (mediaStream: RNMediaStream | undefined): string | undefined => { const rnMediaStream = mediaStream as unknown as RNMediaStream; if (rnMediaStream && typeof rnMediaStream.toURL === 'function') { return rnMediaStream.toURL(); diff --git a/packages/mobile-client/src/overrides/hooks.ts b/packages/mobile-client/src/overrides/hooks.ts new file mode 100644 index 00000000..a82777e0 --- /dev/null +++ b/packages/mobile-client/src/overrides/hooks.ts @@ -0,0 +1,59 @@ +import { + useCamera as useCameraReactClient, + useCustomSource as useCustomSourceReactClient, + useLivestreamStreamer as useLivestreamStreamerReactClient, + useLivestreamViewer as useLivestreamViewerReactClient, + useMicrophone as useMicrophoneReactClient, + useScreenShare as useScreenShareReactClient, +} from '@fishjam-cloud/react-client'; +import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc'; +import { useCallback } from 'react'; + +import type { ConnectStreamerConfig, UseLivestreamStreamerResult, UseLivestreamViewerResult } from './types'; + +export const useCamera = useCameraReactClient as () => Omit, 'cameraStream'> & { + cameraStream: RNMediaStream | null; +}; + +export const useMicrophone = useMicrophoneReactClient as () => Omit< + ReturnType, + 'toggleMicrophoneMute' | 'microphoneStream' +> & { + microphoneStream: RNMediaStream | null; +}; + +export const useScreenShare = useScreenShareReactClient as () => Omit< + ReturnType, + 'stream' +> & { + stream: RNMediaStream | null; +}; + +export const useCustomSource = useCustomSourceReactClient as ( + sourceId: T, +) => Omit, 'stream' | 'setStream'> & { + stream: RNMediaStream | undefined; + setStream: (newStream: RNMediaStream | null) => void; +}; + +export function useLivestreamStreamer(): UseLivestreamStreamerResult { + const { connect: reactConnect, ...rest } = useLivestreamStreamerReactClient(); + + const connect = useCallback( + async (config: ConnectStreamerConfig, urlOverride?: string) => { + // @ts-expect-error RNMediaStream is MediaStream at runtime via webrtc polyfill + await reactConnect(config, urlOverride); + }, + [reactConnect], + ); + + return { ...rest, connect }; +} + +export function useLivestreamViewer(): UseLivestreamViewerResult { + const { stream, ...rest } = useLivestreamViewerReactClient(); + return { + ...rest, + stream: stream as unknown as RNMediaStream | null, + }; +} diff --git a/packages/mobile-client/src/overrides/types.ts b/packages/mobile-client/src/overrides/types.ts new file mode 100644 index 00000000..b3ae5617 --- /dev/null +++ b/packages/mobile-client/src/overrides/types.ts @@ -0,0 +1,33 @@ +import type { + CustomSource as ReactClientCustomSource, + InitializeDevicesResult as ReactClientInitializeDevicesResult, + Track as ReactClientTrack, + UseLivestreamStreamerResult as ReactClientUseLivestreamStreamerResult, + UseLivestreamViewerResult as ReactClientUseLivestreamViewerResult, +} from '@fishjam-cloud/react-client'; +import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc'; + +export type StreamerInputs = + | { video: RNMediaStream; audio?: RNMediaStream | null } + | { video?: null; audio: RNMediaStream }; + +export type ConnectStreamerConfig = { + inputs: StreamerInputs; + token: string; +}; + +export type UseLivestreamStreamerResult = Omit & { + connect: (config: ConnectStreamerConfig, urlOverride?: string) => Promise; +}; + +export type UseLivestreamViewerResult = Omit & { + stream: RNMediaStream | null; +}; + +export type Track = Omit & { stream: RNMediaStream | null }; + +export type CustomSource = Omit, 'stream'> & { stream?: RNMediaStream }; + +export type InitializeDevicesResult = Omit & { + stream: RNMediaStream | null; +}; From cfe90d3dd7b846bb6abbe722a705f946ab54c726 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Fri, 27 Mar 2026 11:52:23 +0100 Subject: [PATCH 3/7] fix fishjam-chat lint --- examples/mobile-client/fishjam-chat/.eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/mobile-client/fishjam-chat/.eslintrc.js b/examples/mobile-client/fishjam-chat/.eslintrc.js index 7f365ded..9d8402ae 100644 --- a/examples/mobile-client/fishjam-chat/.eslintrc.js +++ b/examples/mobile-client/fishjam-chat/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + root: true, extends: ['expo'], ignorePatterns: [ 'dist/*', From 6a5e2f7b3edba3e3fdafa472ac0a9fadacd0ae93 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Fri, 27 Mar 2026 12:00:26 +0100 Subject: [PATCH 4/7] fix usePeers --- packages/mobile-client/src/index.ts | 4 ++-- packages/mobile-client/src/overrides/hooks.ts | 16 ++++++++++++++- packages/mobile-client/src/overrides/types.ts | 20 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index f8265074..a7f6952c 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -45,7 +45,6 @@ export { InitializeDevicesSettings, useConnection, useDataChannel, - usePeers, useSandbox, useUpdatePeerMetadata, useVAD, @@ -59,6 +58,7 @@ export { useCustomSource, useLivestreamStreamer, useLivestreamViewer, + usePeers, } from './overrides/hooks'; export type { @@ -69,13 +69,13 @@ export type { Track, CustomSource, InitializeDevicesResult, + PeerWithTracks, } from './overrides/types'; export type { UseInitializeDevicesParams, JoinRoomConfig, ConnectViewerConfig, - PeerWithTracks, RoomType, UseSandboxProps, BandwidthLimits, diff --git a/packages/mobile-client/src/overrides/hooks.ts b/packages/mobile-client/src/overrides/hooks.ts index a82777e0..325accf2 100644 --- a/packages/mobile-client/src/overrides/hooks.ts +++ b/packages/mobile-client/src/overrides/hooks.ts @@ -4,12 +4,18 @@ import { useLivestreamStreamer as useLivestreamStreamerReactClient, useLivestreamViewer as useLivestreamViewerReactClient, useMicrophone as useMicrophoneReactClient, + usePeers as usePeersReactClient, useScreenShare as useScreenShareReactClient, } from '@fishjam-cloud/react-client'; import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc'; import { useCallback } from 'react'; -import type { ConnectStreamerConfig, UseLivestreamStreamerResult, UseLivestreamViewerResult } from './types'; +import type { + ConnectStreamerConfig, + PeerWithTracks, + UseLivestreamStreamerResult, + UseLivestreamViewerResult, +} from './types'; export const useCamera = useCameraReactClient as () => Omit, 'cameraStream'> & { cameraStream: RNMediaStream | null; @@ -57,3 +63,11 @@ export function useLivestreamViewer(): UseLivestreamViewerResult { stream: stream as unknown as RNMediaStream | null, }; } + +export function usePeers

, S = Record>() { + return usePeersReactClient() as unknown as { + localPeer: PeerWithTracks | null; + remotePeers: PeerWithTracks[]; + peers: PeerWithTracks[]; + }; +} diff --git a/packages/mobile-client/src/overrides/types.ts b/packages/mobile-client/src/overrides/types.ts index b3ae5617..93df6bd5 100644 --- a/packages/mobile-client/src/overrides/types.ts +++ b/packages/mobile-client/src/overrides/types.ts @@ -1,6 +1,7 @@ import type { CustomSource as ReactClientCustomSource, InitializeDevicesResult as ReactClientInitializeDevicesResult, + PeerWithTracks as ReactClientPeerWithTracks, Track as ReactClientTrack, UseLivestreamStreamerResult as ReactClientUseLivestreamStreamerResult, UseLivestreamViewerResult as ReactClientUseLivestreamViewerResult, @@ -31,3 +32,22 @@ export type CustomSource = Omit, 's export type InitializeDevicesResult = Omit & { stream: RNMediaStream | null; }; + +type TrackFields = + | 'tracks' + | 'cameraTrack' + | 'microphoneTrack' + | 'screenShareVideoTrack' + | 'screenShareAudioTrack' + | 'customVideoTracks' + | 'customAudioTracks'; + +export type PeerWithTracks = Omit, TrackFields> & { + tracks: Track[]; + cameraTrack?: Track; + microphoneTrack?: Track; + screenShareVideoTrack?: Track; + screenShareAudioTrack?: Track; + customVideoTracks: Track[]; + customAudioTracks: Track[]; +}; From 1d6384bf72a25c96475afb522524735526e0a6e5 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Fri, 27 Mar 2026 12:16:07 +0100 Subject: [PATCH 5/7] export initialize devices --- packages/mobile-client/src/index.ts | 2 +- packages/mobile-client/src/overrides/hooks.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index a7f6952c..235f54e5 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -41,7 +41,6 @@ export { useForegroundService, type ForegroundServiceConfig } from './useForegro export { useCameraPermissions, useMicrophonePermissions, type PermissionStatus } from './hooks/usePermissions'; export { - useInitializeDevices, InitializeDevicesSettings, useConnection, useDataChannel, @@ -53,6 +52,7 @@ export { export { useCamera, + useInitializeDevices, useMicrophone, useScreenShare, useCustomSource, diff --git a/packages/mobile-client/src/overrides/hooks.ts b/packages/mobile-client/src/overrides/hooks.ts index 325accf2..81df6fb8 100644 --- a/packages/mobile-client/src/overrides/hooks.ts +++ b/packages/mobile-client/src/overrides/hooks.ts @@ -1,6 +1,7 @@ import { useCamera as useCameraReactClient, useCustomSource as useCustomSourceReactClient, + useInitializeDevices as useInitializeDevicesReactClient, useLivestreamStreamer as useLivestreamStreamerReactClient, useLivestreamViewer as useLivestreamViewerReactClient, useMicrophone as useMicrophoneReactClient, @@ -12,6 +13,7 @@ import { useCallback } from 'react'; import type { ConnectStreamerConfig, + InitializeDevicesResult, PeerWithTracks, UseLivestreamStreamerResult, UseLivestreamViewerResult, @@ -64,6 +66,12 @@ export function useLivestreamViewer(): UseLivestreamViewerResult { }; } +export const useInitializeDevices = useInitializeDevicesReactClient as () => { + initializeDevices: ( + ...args: Parameters['initializeDevices']> + ) => Promise; +}; + export function usePeers

, S = Record>() { return usePeersReactClient() as unknown as { localPeer: PeerWithTracks | null; From 3162007a67d69e1c03ef5ea37e720a810ad90571 Mon Sep 17 00:00:00 2001 From: Milosz Filimowski Date: Fri, 27 Mar 2026 12:20:19 +0100 Subject: [PATCH 6/7] fix docs generation --- packages/mobile-client/src/index.ts | 1 + packages/mobile-client/src/overrides/types.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index 235f54e5..b63dbf52 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -70,6 +70,7 @@ export type { CustomSource, InitializeDevicesResult, PeerWithTracks, + TrackFields, } from './overrides/types'; export type { diff --git a/packages/mobile-client/src/overrides/types.ts b/packages/mobile-client/src/overrides/types.ts index 93df6bd5..9761f4ec 100644 --- a/packages/mobile-client/src/overrides/types.ts +++ b/packages/mobile-client/src/overrides/types.ts @@ -33,7 +33,7 @@ export type InitializeDevicesResult = Omit Date: Fri, 27 Mar 2026 12:45:09 +0100 Subject: [PATCH 7/7] add copilot change --- packages/mobile-client/src/overrides/RTCView.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/mobile-client/src/overrides/RTCView.tsx b/packages/mobile-client/src/overrides/RTCView.tsx index 24e631b8..9cbe15dc 100644 --- a/packages/mobile-client/src/overrides/RTCView.tsx +++ b/packages/mobile-client/src/overrides/RTCView.tsx @@ -12,13 +12,12 @@ export type RTCPIPViewProps = Omit { - const rnMediaStream = mediaStream as unknown as RNMediaStream; - if (rnMediaStream && typeof rnMediaStream.toURL === 'function') { - return rnMediaStream.toURL(); + if (mediaStream && typeof mediaStream.toURL === 'function') { + return mediaStream.toURL(); } else { console.error( 'mediaStream.toURL is not a function. Make sure to use the MediaStream type from @fishjam-cloud/react-native-webrtc', - rnMediaStream, + mediaStream, ); return undefined; }