diff --git a/examples/mobile-client/fishjam-chat/app/(tabs)/room.tsx b/examples/mobile-client/fishjam-chat/app/(tabs)/room.tsx index 1acd314f..854338c9 100644 --- a/examples/mobile-client/fishjam-chat/app/(tabs)/room.tsx +++ b/examples/mobile-client/fishjam-chat/app/(tabs)/room.tsx @@ -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 = diff --git a/examples/mobile-client/fishjam-chat/app/livestream/streamer.tsx b/examples/mobile-client/fishjam-chat/app/livestream/streamer.tsx index f207816a..83c62992 100644 --- a/examples/mobile-client/fishjam-chat/app/livestream/streamer.tsx +++ b/examples/mobile-client/fishjam-chat/app/livestream/streamer.tsx @@ -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; @@ -120,7 +115,7 @@ export default function LivestreamStreamerScreen() { {cameraStream ? ( diff --git a/examples/mobile-client/fishjam-chat/app/livestream/viewer.tsx b/examples/mobile-client/fishjam-chat/app/livestream/viewer.tsx index 5092fabf..8b841bcd 100644 --- a/examples/mobile-client/fishjam-chat/app/livestream/viewer.tsx +++ b/examples/mobile-client/fishjam-chat/app/livestream/viewer.tsx @@ -53,6 +53,7 @@ export default function LivestreamViewerScreen() { style={styles.rtcView} streamURL={stream.toURL()} objectFit="contain" + mirror={true} /> ) : ( diff --git a/examples/mobile-client/fishjam-chat/app/room/preview.tsx b/examples/mobile-client/fishjam-chat/app/room/preview.tsx index b43e1119..b6d8646d 100644 --- a/examples/mobile-client/fishjam-chat/app/room/preview.tsx +++ b/examples/mobile-client/fishjam-chat/app/room/preview.tsx @@ -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(); @@ -103,10 +97,6 @@ export default function PreviewScreen() { } }, [getSandboxPeerToken, roomName, joinRoom, userName]); - const streamURL = cameraStream - ? (cameraStream as MediaStreamWithURL).toURL() - : null; - return ( {error && {error}} @@ -119,9 +109,9 @@ export default function PreviewScreen() { Initializing camera... - ) : streamURL ? ( + ) : cameraStream ? ( 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"; @@ -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, diff --git a/examples/mobile-client/minimal-react-native/components/VideosGridItem.tsx b/examples/mobile-client/minimal-react-native/components/VideosGridItem.tsx index 50e0b71d..d83f0c2c 100644 --- a/examples/mobile-client/minimal-react-native/components/VideosGridItem.tsx +++ b/examples/mobile-client/minimal-react-native/components/VideosGridItem.tsx @@ -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 ( @@ -24,6 +18,7 @@ export const VideosGridItem = ({ peer }: { peer: GridTrack }) => { streamURL={streamURL} objectFit="cover" style={styles.videoContent} + mirror={true} /> ) : ( diff --git a/examples/mobile-client/video-player/app.json b/examples/mobile-client/video-player/app.json index cfdf29b3..ab709c83 100644 --- a/examples/mobile-client/video-player/app.json +++ b/examples/mobile-client/video-player/app.json @@ -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", diff --git a/examples/mobile-client/video-player/components/FishjamPlayerStreamer.tsx b/examples/mobile-client/video-player/components/FishjamPlayerStreamer.tsx index 2fd1fff1..ecc9418c 100644 --- a/examples/mobile-client/video-player/components/FishjamPlayerStreamer.tsx +++ b/examples/mobile-client/video-player/components/FishjamPlayerStreamer.tsx @@ -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(); @@ -68,7 +63,7 @@ export const FishjamPlayerStreamer = ({ roomName }: { roomName: string }) => { diff --git a/examples/mobile-client/video-player/components/FishjamPlayerViewer.tsx b/examples/mobile-client/video-player/components/FishjamPlayerViewer.tsx index a8e9bff2..72c397c2 100644 --- a/examples/mobile-client/video-player/components/FishjamPlayerViewer.tsx +++ b/examples/mobile-client/video-player/components/FishjamPlayerViewer.tsx @@ -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(); @@ -31,7 +27,7 @@ export const FishjamPlayerViewer = ({ roomName }: { roomName: string }) => { <> diff --git a/examples/mobile-client/video-player/index.js b/examples/mobile-client/video-player/index.js new file mode 100644 index 00000000..4eede251 --- /dev/null +++ b/examples/mobile-client/video-player/index.js @@ -0,0 +1,6 @@ +import { registerRootComponent } from 'expo'; + +import App from './App'; + +registerRootComponent(App); + diff --git a/examples/mobile-client/video-player/package.json b/examples/mobile-client/video-player/package.json index ed78e715..dac5cdf6 100644 --- a/examples/mobile-client/video-player/package.json +++ b/examples/mobile-client/video-player/package.json @@ -1,5 +1,6 @@ { "name": "video-player", + "main": "index.js", "version": "1.0.0", "scripts": { "start": "expo start", diff --git a/packages/mobile-client/src/index.ts b/packages/mobile-client/src/index.ts index 380858ea..b17cb72a 100644 --- a/packages/mobile-client/src/index.ts +++ b/packages/mobile-client/src/index.ts @@ -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, @@ -26,15 +30,10 @@ 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, @@ -42,15 +41,50 @@ export { 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, ServerMetadata = Record>(): { + localPeer: PeerWithTracks | null; + remotePeers: PeerWithTracks[]; + peers: PeerWithTracks[]; +} { + const result = usePeersReactClient(); + return { + localPeer: result.localPeer as PeerWithTracks | null, + remotePeers: result.remotePeers as PeerWithTracks[], + peers: result.peers as PeerWithTracks[], + }; +} + +export const useCamera = useCameraReactClient as () => Omit< ReturnType, 'cameraStream' > & { cameraStream: RNMediaStream | null; }; + +export const useMicrophone = useMicrophoneReactClient as () => Omit< ReturnType, 'microphoneStream' > & { + microphoneStream: RNMediaStream | null; +}; + +export const useLivestreamViewer = useLivestreamViewerReactClient as () => Omit< ReturnType, 'stream' > & { + stream: RNMediaStream | null; +}; + +export const useLivestreamStreamer = + useLivestreamStreamerReactClient as () => Omit< + ReturnType, + 'connect' + > & { + connect: (config: ConnectStreamerConfig, urlOverride?: string) => Promise; + }; + export type { UseInitializeDevicesParams, JoinRoomConfig, - ConnectStreamerConfig, - StreamerInputs, UseLivestreamStreamerResult, ConnectViewerConfig, - UseLivestreamViewerResult, - PeerWithTracks, RoomType, UseSandboxProps, BandwidthLimits, @@ -66,7 +100,6 @@ export type { PersistLastDeviceHandlers, SimulcastBandwidthLimits, StreamConfig, - Track, TrackId, TrackMiddleware, TracksMiddleware, @@ -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 & { + stream: RNMediaStream | null; +}; + +export type StreamerInputs = Omit & { + audio?: RNMediaStream; +} | Omit & { + video: RNMediaStream; + audio?: RNMediaStream | null; +}; + +export type ConnectStreamerConfig = Omit & { + inputs: StreamerInputs; +}; + // persistLastDevice is not supported on mobile export type FishjamProviderProps = Omit; export function FishjamProvider(props: FishjamProviderProps) { @@ -89,3 +143,18 @@ export function FishjamProvider(props: FishjamProviderProps) { persistLastDevice: false, }); } + +export type Track = Omit & { stream: RNMediaStream | null }; + +export type PeerWithTracks = Omit< + ReactClientPeerWithTracks, + 'tracks' | 'cameraTrack' | 'microphoneTrack' | 'screenShareVideoTrack' | 'screenShareAudioTrack' | 'customVideoTracks' | 'customAudioTracks' +> & { + tracks: Track[]; + cameraTrack?: Track; + microphoneTrack?: Track; + screenShareVideoTrack?: Track; + screenShareAudioTrack?: Track; + customVideoTracks: Track[]; + customAudioTracks: Track[]; +};