Skip to content
Closed
2 changes: 1 addition & 1 deletion examples/mobile-client/fishjam-chat/app/(tabs)/room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function RoomScreen() {
Keyboard.dismiss();
router.push({
pathname: "/room/preview",
params: { roomName, userName: displayName, videoRoomEnv },
params: { roomName, userName: displayName},
});
} catch (e) {
const message =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ import { changeFishjamId } from "../../utils/fishjamIdStore";
import { Button } from "../../components";
import { BrandColors } from "../../utils/Colors";

// Helper type for MediaStream with toURL method from react-native-webrtc
interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

export default function LivestreamStreamerScreen() {
const { roomName } = useLocalSearchParams<{
roomName: string;
Expand Down Expand Up @@ -120,7 +115,7 @@ export default function LivestreamStreamerScreen() {
{cameraStream ? (
<RTCView
style={styles.rtcView}
streamURL={(cameraStream as MediaStreamWithURL).toURL()}
streamURL={cameraStream.toURL()}
objectFit="cover"
mirror={true}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export default function LivestreamViewerScreen() {
style={styles.rtcView}
streamURL={stream.toURL()}
objectFit="contain"
mirror={true}
/>
) : (
<View style={styles.placeholder}>
Expand Down
16 changes: 3 additions & 13 deletions examples/mobile-client/fishjam-chat/app/room/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ import {
import { Button, InCallButton, NoCameraView } from "../../components";
import { BrandColors } from "../../utils/Colors";

// Helper type for MediaStream with toURL method from react-native-webrtc
interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

export default function PreviewScreen() {
const { roomName, userName, videoRoomEnv } = useLocalSearchParams<{
const { roomName, userName } = useLocalSearchParams<{
roomName: string;
userName: string;
videoRoomEnv: string;
}>();

const { getSandboxPeerToken } = useSandbox();
Expand Down Expand Up @@ -103,10 +97,6 @@ export default function PreviewScreen() {
}
}, [getSandboxPeerToken, roomName, joinRoom, userName]);

const streamURL = cameraStream
? (cameraStream as MediaStreamWithURL).toURL()
: null;

return (
<SafeAreaView style={styles.container} edges={["bottom"]}>
{error && <Text style={styles.errorText}>{error}</Text>}
Expand All @@ -119,9 +109,9 @@ export default function PreviewScreen() {
<ActivityIndicator size="large" color={BrandColors.darkBlue100} />
<Text style={styles.loadingText}>Initializing camera...</Text>
</View>
) : streamURL ? (
) : cameraStream ? (
<RTCView
streamURL={streamURL}
streamURL={cameraStream.toURL()}
style={styles.cameraPreviewView}
objectFit="cover"
mirror={true}
Expand Down
14 changes: 5 additions & 9 deletions examples/mobile-client/fishjam-chat/components/VideosGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,11 @@ export const parsePeersToTracks = (
...remotePeers.flatMap((peer) => createGridTracksFromPeer(peer, false)),
];

//TODO: FCE-2487 remove it when MediaStream will be updated
interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

const GridTrackItem = ({ peer, index }: { peer: GridTrack; index: number }) => {
//TODO: FCE-2487 overwrite Track to include MediaStream from react-native-webrtc
const streamURL = peer.track?.stream && !peer.track?.metadata?.paused
? (peer.track.stream as MediaStreamWithURL).toURL()
: null;
const streamURL =
peer.track?.stream && !peer.track?.metadata?.paused
? peer.track.stream.toURL()
: null;

const isSelfVideo = peer.isLocal && peer.track?.metadata?.type === "camera";

Expand All @@ -101,6 +96,7 @@ const GridTrackItem = ({ peer, index }: { peer: GridTrack; index: number }) => {
streamURL={streamURL}
objectFit="cover"
style={styles.video}
mirror={true}
pip={{
enabled: isSelfVideo,
startAutomatically: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@ import { View, StyleSheet, Text } from 'react-native';
import { GridTrack } from '../types';
import React from 'react';

//TODO: FCE-2487 remove it when MediaStream will be updated
interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

export const VideosGridItem = ({ peer }: { peer: GridTrack }) => {
//TODO: FCE-2487 overwrite Track to include MediaStream from react-native-webrtc
const streamURL = peer.track?.stream ? (peer.track.stream as MediaStreamWithURL).toURL() : null;
const streamURL = peer.track?.stream ? peer.track.stream.toURL() : null;

return (
<View style={styles.container}>
Expand All @@ -24,6 +18,7 @@ export const VideosGridItem = ({ peer }: { peer: GridTrack }) => {
streamURL={streamURL}
objectFit="cover"
style={styles.videoContent}
mirror={true}
/>
) : (
<View style={styles.videoContent}>
Expand Down
1 change: 1 addition & 0 deletions examples/mobile-client/video-player/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"name": "video-player",
"slug": "video-player",
"version": "1.0.0",
"main": "index.js",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "videoplayer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import { useInitializeDevices, useCamera, useLivestreamStreamer, useMicrophone, useSandbox, RTCView } from "@fishjam-cloud/mobile-client"
import { useEffect } from "react";

// Helper type for MediaStream with toURL method from react-native-webrtc
interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

export const FishjamPlayerStreamer = ({ roomName }: { roomName: string }) => {
const { getSandboxLivestream } = useSandbox();

Expand Down Expand Up @@ -68,7 +63,7 @@ export const FishjamPlayerStreamer = ({ roomName }: { roomName: string }) => {
<View style={styles.videoContainer}>
<RTCView
style={styles.video}
streamURL={cameraStream ? (cameraStream as MediaStreamWithURL).toURL() : undefined}
streamURL={cameraStream?.toURL()}
mirror={true}
objectFit="cover"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { View, StyleSheet, Text, ActivityIndicator } from "react-native";
import { useSandbox, useLivestreamViewer, RTCView } from '@fishjam-cloud/mobile-client';
import { useEffect } from "react";

interface MediaStreamWithURL extends MediaStream {
toURL(): string;
}

export const FishjamPlayerViewer = ({ roomName }: { roomName: string }) => {
const { getSandboxViewerToken } = useSandbox();
const { connect, disconnect, stream } = useLivestreamViewer();
Expand All @@ -31,7 +27,7 @@ export const FishjamPlayerViewer = ({ roomName }: { roomName: string }) => {
<>
<RTCView
style={styles.video}
streamURL={(stream as MediaStreamWithURL).toURL()}
streamURL={stream?.toURL()}
mirror={true}
objectFit="cover"
/>
Expand Down
6 changes: 6 additions & 0 deletions examples/mobile-client/video-player/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { registerRootComponent } from 'expo';

import App from './App';

registerRootComponent(App);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Why was this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but this example wasn't working without it.


1 change: 1 addition & 0 deletions examples/mobile-client/video-player/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "video-player",
"main": "index.js",
"version": "1.0.0",
"scripts": {
"start": "expo start",
Expand Down
89 changes: 79 additions & 10 deletions packages/mobile-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import React from 'react';
import {
FishjamProvider as ReactClientFishjamProvider,
type FishjamProviderProps as ReactClientFishjamProviderProps,
type Track as ReactClientTrack,
type PeerWithTracks as ReactClientPeerWithTracks,
} from '@fishjam-cloud/react-client';

import type { MediaStream as RNMediaStream } from '@fishjam-cloud/react-native-webrtc';

export {
RTCView,
ScreenCapturePickerView,
Expand All @@ -26,31 +30,61 @@ export {
export type { CallKitAction, CallKitConfig, ForegroundServiceConfig } from '@fishjam-cloud/react-native-webrtc';

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

import {
usePeers as usePeersReactClient,
useCamera as useCameraReactClient,
useMicrophone as useMicrophoneReactClient,
useLivestreamViewer as useLivestreamViewerReactClient,
useLivestreamStreamer as useLivestreamStreamerReactClient,
} from '@fishjam-cloud/react-client';

export function usePeers<PeerMetadata = Record<string, unknown>, ServerMetadata = Record<string, unknown>>(): {
localPeer: PeerWithTracks<PeerMetadata, ServerMetadata> | null;
remotePeers: PeerWithTracks<PeerMetadata, ServerMetadata>[];
peers: PeerWithTracks<PeerMetadata, ServerMetadata>[];
} {
const result = usePeersReactClient<PeerMetadata, ServerMetadata>();
return {
localPeer: result.localPeer as PeerWithTracks<PeerMetadata, ServerMetadata> | null,
remotePeers: result.remotePeers as PeerWithTracks<PeerMetadata, ServerMetadata>[],
peers: result.peers as PeerWithTracks<PeerMetadata, ServerMetadata>[],
};
}

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

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

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

export const useLivestreamStreamer =
useLivestreamStreamerReactClient as () => Omit<
ReturnType<typeof useLivestreamStreamerReactClient>,
'connect'
> & {
connect: (config: ConnectStreamerConfig, urlOverride?: string) => Promise<void>;
};

export type {
UseInitializeDevicesParams,
JoinRoomConfig,
ConnectStreamerConfig,
StreamerInputs,
UseLivestreamStreamerResult,
ConnectViewerConfig,
UseLivestreamViewerResult,
PeerWithTracks,
RoomType,
UseSandboxProps,
BandwidthLimits,
Expand All @@ -66,7 +100,6 @@ export type {
PersistLastDeviceHandlers,
SimulcastBandwidthLimits,
StreamConfig,
Track,
TrackId,
TrackMiddleware,
TracksMiddleware,
Expand All @@ -81,6 +114,27 @@ export type {
TrackBandwidthLimit,
} from '@fishjam-cloud/react-client';

import type {
UseLivestreamViewerResult as ReactClientUseLivestreamViewerResult,
StreamerInputs as ReactClientStreamerInputs,
ConnectStreamerConfig as ReactClientConnectStreamerConfig,
} from '@fishjam-cloud/react-client';

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

export type StreamerInputs = Omit<ReactClientStreamerInputs, 'audio'> & {
audio?: RNMediaStream;
} | Omit<ReactClientStreamerInputs, 'video' | 'audio'> & {
video: RNMediaStream;
audio?: RNMediaStream | null;
};

export type ConnectStreamerConfig = Omit<ReactClientConnectStreamerConfig, 'inputs'> & {
inputs: StreamerInputs;
};

// persistLastDevice is not supported on mobile
export type FishjamProviderProps = Omit<ReactClientFishjamProviderProps, 'persistLastDevice'>;
export function FishjamProvider(props: FishjamProviderProps) {
Expand All @@ -89,3 +143,18 @@ export function FishjamProvider(props: FishjamProviderProps) {
persistLastDevice: false,
});
}

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

export type PeerWithTracks<PeerMetadata, ServerMetadata> = Omit<
ReactClientPeerWithTracks<PeerMetadata, ServerMetadata>,
'tracks' | 'cameraTrack' | 'microphoneTrack' | 'screenShareVideoTrack' | 'screenShareAudioTrack' | 'customVideoTracks' | 'customAudioTracks'
> & {
tracks: Track[];
cameraTrack?: Track;
microphoneTrack?: Track;
screenShareVideoTrack?: Track;
screenShareAudioTrack?: Track;
customVideoTracks: Track[];
customAudioTracks: Track[];
};