Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/mobile-client/fishjam-chat/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
root: true,
extends: ['expo'],
ignorePatterns: [
'dist/*',
Expand Down
4 changes: 1 addition & 3 deletions examples/mobile-client/fishjam-chat/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@
}
}
],
[
"../common/plugins/build/withLocalWebrtcPaths.js"
]
["../common/plugins/build/withLocalWebrtcPaths.js"]
],
"experiments": {
"typedRoutes": true
Expand Down
6 changes: 5 additions & 1 deletion examples/mobile-client/fishjam-chat/utils/tracks.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
40 changes: 21 additions & 19 deletions packages/mobile-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import React from 'react';
import {
FishjamProvider as ReactClientFishjamProvider,
type FishjamProviderProps as ReactClientFishjamProviderProps,
useMicrophone as useMicrophoneReactClient,
} from '@fishjam-cloud/react-client';
import { FishjamClient } from '@fishjam-cloud/ts-client';

Expand Down Expand Up @@ -42,52 +41,55 @@ export { useForegroundService, type ForegroundServiceConfig } from './useForegro
export { useCameraPermissions, useMicrophonePermissions, type PermissionStatus } from './hooks/usePermissions';

export {
useCamera,
useInitializeDevices,
InitializeDevicesSettings,
useConnection,
useCustomSource,
useDataChannel,
useLivestreamStreamer,
useLivestreamViewer,
usePeers,
useSandbox,
useScreenShare,
useUpdatePeerMetadata,
useVAD,
Variant,
} from '@fishjam-cloud/react-client';

export const useMicrophone = useMicrophoneReactClient as () => Omit<
ReturnType<typeof useMicrophoneReactClient>,
'toggleMicrophoneMute'
>;
export {
useCamera,
useInitializeDevices,
useMicrophone,
useScreenShare,
useCustomSource,
useLivestreamStreamer,
useLivestreamViewer,
usePeers,
} from './overrides/hooks';

export type {
UseInitializeDevicesParams,
JoinRoomConfig,
ConnectStreamerConfig,
StreamerInputs,
ConnectStreamerConfig,
UseLivestreamStreamerResult,
ConnectViewerConfig,
UseLivestreamViewerResult,
Track,
CustomSource,
InitializeDevicesResult,
PeerWithTracks,
TrackFields,
} from './overrides/types';

export type {
UseInitializeDevicesParams,
JoinRoomConfig,
ConnectViewerConfig,
RoomType,
UseSandboxProps,
BandwidthLimits,
Brand,
CustomSource,
DeviceError,
DeviceItem,
InitializeDevicesResult,
InitializeDevicesStatus,
MiddlewareResult,
PeerId,
PeerStatus,
PersistLastDeviceHandlers,
SimulcastBandwidthLimits,
StreamConfig,
Track,
TrackId,
TrackMiddleware,
TracksMiddleware,
Expand Down
13 changes: 6 additions & 7 deletions packages/mobile-client/src/overrides/RTCView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@ import type React from 'react';
import { useMemo } from 'react';

export type RTCVideoViewProps = Omit<React.ComponentPropsWithRef<typeof OriginalRTCView>, 'streamURL'> & {
mediaStream: MediaStream;
mediaStream: RNMediaStream;
};

export type RTCPIPViewProps = Omit<React.ComponentPropsWithRef<typeof OriginalRTCPIPView>, 'streamURL'> & {
mediaStream: MediaStream;
mediaStream: RNMediaStream;
};

const convertMediaStreamToURL = (mediaStream: MediaStream | undefined): string | undefined => {
const rnMediaStream = mediaStream as unknown as RNMediaStream;
if (rnMediaStream && typeof rnMediaStream.toURL === 'function') {
return rnMediaStream.toURL();
const convertMediaStreamToURL = (mediaStream: RNMediaStream | undefined): string | undefined => {
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;
}
Expand Down
81 changes: 81 additions & 0 deletions packages/mobile-client/src/overrides/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {
useCamera as useCameraReactClient,
useCustomSource as useCustomSourceReactClient,
useInitializeDevices as useInitializeDevicesReactClient,
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,
InitializeDevicesResult,
PeerWithTracks,
UseLivestreamStreamerResult,
UseLivestreamViewerResult,
} from './types';

export const useCamera = useCameraReactClient as () => Omit<ReturnType<typeof useCameraReactClient>, 'cameraStream'> & {
cameraStream: RNMediaStream | null;
};

export const useMicrophone = useMicrophoneReactClient as () => Omit<
ReturnType<typeof useMicrophoneReactClient>,
'toggleMicrophoneMute' | 'microphoneStream'
> & {
microphoneStream: RNMediaStream | null;
};

export const useScreenShare = useScreenShareReactClient as () => Omit<
ReturnType<typeof useScreenShareReactClient>,
'stream'
> & {
stream: RNMediaStream | null;
};

export const useCustomSource = useCustomSourceReactClient as <T extends string>(
sourceId: T,
) => Omit<ReturnType<typeof useCustomSourceReactClient>, '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,
};
}

export const useInitializeDevices = useInitializeDevicesReactClient as () => {
initializeDevices: (
...args: Parameters<ReturnType<typeof useInitializeDevicesReactClient>['initializeDevices']>
) => Promise<InitializeDevicesResult>;
};

export function usePeers<P = Record<string, unknown>, S = Record<string, unknown>>() {
return usePeersReactClient<P, S>() as unknown as {
localPeer: PeerWithTracks<P, S> | null;
remotePeers: PeerWithTracks<P, S>[];
peers: PeerWithTracks<P, S>[];
};
}
53 changes: 53 additions & 0 deletions packages/mobile-client/src/overrides/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type {
CustomSource as ReactClientCustomSource,
InitializeDevicesResult as ReactClientInitializeDevicesResult,
PeerWithTracks as ReactClientPeerWithTracks,
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<ReactClientUseLivestreamStreamerResult, 'connect'> & {
connect: (config: ConnectStreamerConfig, urlOverride?: string) => Promise<void>;
};

export type UseLivestreamViewerResult = Omit<ReactClientUseLivestreamViewerResult, 'stream'> & {
stream: RNMediaStream | null;
};

export type Track = Omit<ReactClientTrack, 'stream'> & { stream: RNMediaStream | null };

export type CustomSource<T extends string> = Omit<ReactClientCustomSource<T>, 'stream'> & { stream?: RNMediaStream };

export type InitializeDevicesResult = Omit<ReactClientInitializeDevicesResult, 'stream'> & {
stream: RNMediaStream | null;
};

export type TrackFields =
| 'tracks'
| 'cameraTrack'
| 'microphoneTrack'
| 'screenShareVideoTrack'
| 'screenShareAudioTrack'
| 'customVideoTracks'
| 'customAudioTracks';

export type PeerWithTracks<P, S> = Omit<ReactClientPeerWithTracks<P, S>, TrackFields> & {
tracks: Track[];
cameraTrack?: Track;
microphoneTrack?: Track;
screenShareVideoTrack?: Track;
screenShareAudioTrack?: Track;
customVideoTracks: Track[];
customAudioTracks: Track[];
};
Loading