11import * as React from 'react' ;
22
3- import { Image , StyleSheet , ViewStyle } from 'react-native' ;
3+ import { Image , StyleSheet , type ViewStyle } from 'react-native' ;
44import {
55 isTrackReference ,
6- TrackReferenceOrPlaceholder ,
6+ type TrackReferenceOrPlaceholder ,
77 useEnsureTrackRef ,
88 useIsMuted ,
99 useIsSpeaking ,
@@ -14,63 +14,71 @@ import { View } from 'react-native';
1414import { Text } from 'react-native' ;
1515import { useTheme } from '@react-navigation/native' ;
1616import { Track } from 'livekit-client' ;
17+ import { Component , forwardRef } from 'react' ;
1718export type Props = {
1819 trackRef : TrackReferenceOrPlaceholder ;
1920 style ?: ViewStyle ;
2021 zOrder ?: number ;
2122 mirror ?: boolean ;
23+ useIOSPIP ?: boolean ;
2224} ;
23- export const ParticipantView = ( {
24- style = { } ,
25- trackRef,
26- zOrder,
27- mirror,
28- } : Props ) => {
29- const trackReference = useEnsureTrackRef ( trackRef ) ;
30- const { identity, name } = useParticipantInfo ( {
31- participant : trackReference . participant ,
32- } ) ;
33- const isSpeaking = useIsSpeaking ( trackRef . participant ) ;
34- const isVideoMuted = useIsMuted ( trackRef ) ;
35- const { colors } = useTheme ( ) ;
36- let videoView ;
37- if ( isTrackReference ( trackRef ) && ! isVideoMuted ) {
38- videoView = (
39- < VideoTrack
40- style = { styles . videoView }
41- trackRef = { trackRef }
42- zOrder = { zOrder }
43- mirror = { mirror }
44- />
45- ) ;
46- } else {
47- videoView = (
48- < View style = { styles . videoView } >
49- < View style = { styles . spacer } />
50- < Image
51- style = { styles . icon }
52- source = { require ( './icons/baseline_videocam_off_white_24dp.png' ) }
25+ export const ParticipantView = forwardRef < Component , Props > (
26+ ( { style = { } , trackRef, zOrder, mirror, useIOSPIP = false } : Props , ref ) => {
27+ const trackReference = useEnsureTrackRef ( trackRef ) ;
28+ const { identity, name } = useParticipantInfo ( {
29+ participant : trackReference . participant ,
30+ } ) ;
31+ const isSpeaking = useIsSpeaking ( trackRef . participant ) ;
32+ const isVideoMuted = useIsMuted ( trackRef ) ;
33+ const { colors } = useTheme ( ) ;
34+ let videoView ;
35+ if ( isTrackReference ( trackRef ) && ! isVideoMuted ) {
36+ videoView = (
37+ < VideoTrack
38+ style = { styles . videoView }
39+ trackRef = { trackRef }
40+ zOrder = { zOrder }
41+ mirror = { mirror }
42+ ref = { ref }
43+ iosPIP = { {
44+ enabled : useIOSPIP ,
45+ startAutomatically : true ,
46+ preferredSize : {
47+ width : 800 ,
48+ height : 800 ,
49+ } ,
50+ } }
5351 />
54- < View style = { styles . spacer } />
55- </ View >
56- ) ;
57- }
52+ ) ;
53+ } else {
54+ videoView = (
55+ < View style = { styles . videoView } >
56+ < View style = { styles . spacer } />
57+ < Image
58+ style = { styles . icon }
59+ source = { require ( './icons/baseline_videocam_off_white_24dp.png' ) }
60+ />
61+ < View style = { styles . spacer } />
62+ </ View >
63+ ) ;
64+ }
5865
59- let displayName = name ? name : identity ;
60- if ( trackRef . source === Track . Source . ScreenShare ) {
61- displayName = displayName + "'s screen" ;
62- }
66+ let displayName = name ? name : identity ;
67+ if ( trackRef . source === Track . Source . ScreenShare ) {
68+ displayName = displayName + "'s screen" ;
69+ }
6370
64- return (
65- < View style = { [ styles . container , style ] } >
66- { videoView }
67- < View style = { styles . identityBar } >
68- < Text style = { { color : colors . text } } > { displayName } </ Text >
71+ return (
72+ < View style = { [ styles . container , style ] } >
73+ { videoView }
74+ < View style = { styles . identityBar } >
75+ < Text style = { { color : colors . text } } > { displayName } </ Text >
76+ </ View >
77+ { isSpeaking && < View style = { styles . speakingIndicator } /> }
6978 </ View >
70- { isSpeaking && < View style = { styles . speakingIndicator } /> }
71- </ View >
72- ) ;
73- } ;
79+ ) ;
80+ }
81+ ) ;
7482
7583const styles = StyleSheet . create ( {
7684 container : {
0 commit comments