1- import { connectChat } from './chat.js' ;
2- import { Socket } from 'phoenix' ;
1+ import { Socket , Presence } from 'phoenix' ;
32
43const pcConfig = { iceServers : [ { urls : 'stun:stun.l.google.com:19302' } ] } ;
54const localVideoPlayer = document . getElementById ( 'videoplayer-local' ) ;
65const videoPlayerWrapper = document . getElementById ( 'videoplayer-wrapper' ) ;
6+ const peerCount = document . getElementById ( 'viewercount' ) ;
77
88let localStream = undefined ;
99let channel = undefined ;
@@ -21,18 +21,15 @@ async function createPeerConnection() {
2121 const videoPlayer = document . createElement ( 'video' ) ;
2222 videoPlayer . srcObject = event . streams [ 0 ] ;
2323 videoPlayer . autoplay = true ;
24- videoPlayer . classList . add (
25- 'm-auto' ,
26- 'rounded-xl' ,
27- 'max-h-full' ,
28- 'max-w-full'
29- ) ;
24+ videoPlayer . className = 'rounded-xl w-full h-full object-cover' ;
3025
3126 videoPlayerWrapper . appendChild ( videoPlayer ) ;
27+ updateVideoGrid ( ) ;
3228
3329 event . track . onended = ( _ ) => {
3430 console . log ( 'Track ended: ' + trackId ) ;
3531 videoPlayerWrapper . removeChild ( videoPlayer ) ;
32+ updateVideoGrid ( ) ;
3633 } ;
3734 } else {
3835 // Audio tracks are associated with the stream (`event.streams[0]`) and require no separate actions
@@ -42,8 +39,13 @@ async function createPeerConnection() {
4239
4340 pc . onicegatheringstatechange = ( ) =>
4441 console . log ( 'Gathering state change: ' + pc . iceGatheringState ) ;
45- pc . onconnectionstatechange = ( ) =>
42+
43+ pc . onconnectionstatechange = ( ) => {
4644 console . log ( 'Connection state change: ' + pc . connectionState ) ;
45+ if ( pc . connectionState == 'failed' ) {
46+ pc . restartIce ( ) ;
47+ }
48+ } ;
4749 pc . onicecandidate = ( event ) => {
4850 if ( event . candidate == null ) {
4951 console . log ( 'Gathering candidates complete' ) ;
@@ -113,14 +115,54 @@ async function joinChannel() {
113115 pc . addIceCandidate ( candidate ) ;
114116 } ) ;
115117
116- channel . join ( ) ;
117- console . log ( 'Joined channel peer:signalling' ) ;
118+ const presence = new Presence ( channel ) ;
119+ presence . onSync ( ( ) => {
120+ peerCount . innerText = presence . list ( ) . length ;
121+ } ) ;
122+
123+ channel
124+ . join ( )
125+ . receive ( 'ok' , ( _ ) => console . log ( 'Joined channel peer:signalling' ) )
126+ . receive ( 'error' , ( resp ) => {
127+ console . error ( 'Unable to join the room:' , resp ) ;
128+ socket . disconnect ( ) ;
129+
130+ videoPlayerWrapper . removeChild ( localVideoPlayer ) ;
131+ console . log ( `Closing stream with id: ${ localStream . id } ` ) ;
132+ localStream . getTracks ( ) . forEach ( ( track ) => track . stop ( ) ) ;
133+ localStream = undefined ;
134+
135+ const errorNode = document . getElementById ( 'join-error-message' ) ;
136+ errorNode . innerText = 'Unable to join the room' ;
137+ if ( resp == 'peer_limit_reached' ) {
138+ errorNode . innerText +=
139+ ': Peer limit reached. Try again in a few minutes' ;
140+ }
141+ errorNode . classList . remove ( 'hidden' ) ;
142+ } ) ;
143+ }
144+
145+ function updateVideoGrid ( ) {
146+ const videoCount = videoPlayerWrapper . children . length ;
147+
148+ let columns ;
149+ if ( videoCount <= 1 ) {
150+ columns = 'grid-cols-1' ;
151+ } else if ( videoCount <= 4 ) {
152+ columns = 'grid-cols-2' ;
153+ } else if ( videoCount <= 9 ) {
154+ columns = 'grid-cols-3' ;
155+ } else if ( videoCount <= 16 ) {
156+ columns = 'grid-cols-4' ;
157+ } else {
158+ columns = 'grid-cols-5' ;
159+ }
160+
161+ videoPlayerWrapper . className = `w-full h-full grid gap-2 p-2 auto-rows-fr ${ columns } ` ;
118162}
119163
120164export const Home = {
121165 async mounted ( ) {
122- connectChat ( ) ;
123-
124166 await createPeerConnection ( ) ;
125167 await setupLocalMedia ( ) ;
126168 joinChannel ( ) ;
0 commit comments