From 083bc9a7d67c84cdc34967b43ce0baae986a219c Mon Sep 17 00:00:00 2001 From: "venbatechnologies@gmail.com" Date: Mon, 21 Jun 2021 11:12:06 +0530 Subject: [PATCH] Fairoj : [UPGRADE] video conference layout with additional features are implemented --- angular.json | 26 ++ package.json | 4 +- .../chat-component.component.html | 36 +- .../chat-component.component.scss | 351 ++++++++++++++---- .../chat-component.component.ts | 2 +- src/app/pd/services/twilio/twilio.service.ts | 158 ++++++-- .../styles/scss/core/_main-sidebar.scss | 4 +- 7 files changed, 456 insertions(+), 125 deletions(-) diff --git a/angular.json b/angular.json index 379839a..94207eb 100644 --- a/angular.json +++ b/angular.json @@ -62,6 +62,29 @@ "maximumError": "10kb" } ] + }, + "staging": { + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] } } }, @@ -75,6 +98,9 @@ "configurations": { "production": { "browserTarget": "video-chat-user:build:production" + }, + "staging": { + "browserTarget": "video-chat-user:build:staging" } } }, diff --git a/package.json b/package.json index 03d6529..57e9ba9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "build": "ng build", "test": "ng test", "lint": "ng lint", - "e2e": "ng e2e" + "e2e": "ng e2e", + "staging":"ng build --configuration=staging", + "production":"ng build --prod" }, "private": true, "dependencies": { diff --git a/src/app/pd/chat-component/chat-component.component.html b/src/app/pd/chat-component/chat-component.component.html index e7d4000..2a3a952 100644 --- a/src/app/pd/chat-component/chat-component.component.html +++ b/src/app/pd/chat-component/chat-component.component.html @@ -8,20 +8,22 @@ -
+ -
+ -
-
-
+ +
+ + +

{{message}}


-
-
+
diff --git a/src/app/pd/chat-component/chat-component.component.scss b/src/app/pd/chat-component/chat-component.component.scss index 49a0039..6114d4c 100644 --- a/src/app/pd/chat-component/chat-component.component.scss +++ b/src/app/pd/chat-component/chat-component.component.scss @@ -6,98 +6,109 @@ body{ .copy_link { // position: absolute; // bottom: 40%; - margin-top: 21%; + // margin-top: 21%; text-align: center; border: 1px dashed #cececef5; - padding: 5px; + // padding: 5px; border-radius: 10px; + position: absolute; + top:10px; + right: 10px; + background-color: darkgray; + opacity: 0.7; p{ - color: #840000c9; + // color: #840000c9; + color: black; font-weight: 500; font-family: monospace; padding: 5px; } } -@media(max-width:500px) { +// @media(max-width:500px) { - div#myvideo { - max-width: 32%; - // min-width: 150px; - position: absolute; - // border: 2px solid #9E9E9E; - top:0; - left: 0; - // border-radius: 10px; - margin: 1% - // /* top: 20px; -} -.body-container { - padding: 0px !important; -} -div#peervideo { - /* height: 498px; */ - // position: relative; - // margin-top: 126px; - width: 100%; - // margin-top: 25%; - -} - -// .peer_message{ -// font-size: 20px; -// position: absolute; -// top: 11%; -// bottom: 10%; -// float: right; -// padding: 57px; -// /* border: 2px solid lavender; */ -// left: 8%; -// p{ -// text-align: center; -// } +// div#myvideo { +// max-width: 32%; +// // min-width: 150px; +// position: absolute; +// // border: 2px solid #9E9E9E; +// top:0; +// left: 0; +// // border-radius: 10px; +// margin: 1% +// // /* top: 20px; // } +// .body-container { +// padding: 0px !important; +// } +// div#peervideo { +// /* height: 498px; */ +// // position: relative; +// // margin-top: 126px; +// width: 100%; +// // margin-top: 25%; + +// } + +// // .peer_message{ +// // font-size: 20px; +// // position: absolute; +// // top: 11%; +// // bottom: 10%; +// // float: right; +// // padding: 57px; +// // /* border: 2px solid lavender; */ +// // left: 8%; +// // p{ +// // text-align: center; +// // } +// // } +// } + .peer_message > p { + padding: 3px; + border-radius: 5px; + background-color: darkgray; } @media(min-width:500px) { .peer_video{ max-height: 80vh; } - div#myvideo { - max-width: 22%; - // min-width: 150px; - position: absolute; - // border: 2px solid #9E9E9E; - top:0; - left: 0; - // border-radius: 10px; - margin: 1% - // max-width: 45%; - // text-align: center; - // margin-left:3%; - // margin-top:1%; - // min-width: 150px; - // position: absolute; - // border: 2px solid #9E9E9E; - // /* top: 20px; -} +// div#myvideo { +// max-width: 22%; +// // min-width: 150px; +// position: absolute; +// // border: 2px solid #9E9E9E; +// top:0; +// left: 0; +// // border-radius: 10px; +// margin: 1% +// // max-width: 45%; +// // text-align: center; +// // margin-left:3%; +// // margin-top:1%; +// // min-width: 150px; +// // position: absolute; +// // border: 2px solid #9E9E9E; +// // /* top: 20px; +// } -div#peervideo { - /* height: 498px; */ - max-width: 100%; - text-align: center; - margin-left:3%; - margin-top:1%; - // position: relative; - // margin-top: 126px; - // width: 100%; -} -} -.peer_video{ - max-height: 85vh !important; - text-align: center -} -body{ - margin:10px !important; +// div#peervideo { +// /* height: 498px; */ +// max-width: 100%; +// text-align: center; +// margin-left:3%; +// margin-top:1%; +// // position: relative; +// // margin-top: 126px; +// // width: 100%; +// } } +// .peer_video{ +// max-height: 85vh !important; +// text-align: center +// } +// body{ +// margin:10px !important; +// } .note-label{ justify-content: center; text-align: center; @@ -107,4 +118,194 @@ body{ span { margin-right: 0px !important; } -} \ No newline at end of file +} + + + + +.grid { + display: grid; + } + + :root { + --one-row: 87vh; + --two-rows: repeat(2, calc(87vh / 2)); + --three-rows: repeat(3, calc(87vh / 3)); + --four-rows: repeat(4, calc(87vh / 4)); + } + + $one-row:88vh; + // @media (orientation: portrait) { + // $one-row:88vh !important; + // } + $two-rows:repeat(2, calc(#{$one-row} / 2)); + $three-rows:repeat(3, calc(#{$one-row} / 3)); + $four-rows:repeat(4, calc(#{$one-row} / 4)); + + .grid--1 { + grid-template-rows: $one-row; + grid-template-areas: + "A"; + + @media (orientation: portrait) { + grid-template-areas: + "A"; + } + } + .grid--2 { + grid-template-rows: $one-row; + grid-template-areas: + "A B"; + + @media (orientation: portrait) { + grid-template-rows: $one-row; + grid-template-areas: + "A"; + ::ng-deep .my-video{ + position: absolute; + top: 0; + height:145px; + width: 140px; + } + } + + } + + .grid--3 { + grid-template-rows: $one-row; + // grid-template-areas: + // "A B" + // "C C"; + grid-template-areas: "A B C"; + @media (orientation: portrait) { + grid-template-rows: $one-row; + // grid-template-areas: + // "A B" + // "C C"; + grid-template-areas: + "A B"; + ::ng-deep .my-video{ + position: absolute; + top: 0; + height:145px; + width: 140px; + } + } + } + + .grid--4 { + grid-template-rows: $two-rows; + grid-template-areas: + "A B" + "C D"; + } + + .grid--5 { + grid-template-rows: $two-rows; + grid-template-areas: + "A A B B C C" + "D D D E E E"; + + @media (orientation: portrait) { + grid-template-rows: $three-rows; + grid-template-areas: + "A A B B" + "C C D D" + "E E E E"; + } + } + + .grid--6 { + grid-template-rows: $two-rows; + grid-template-areas: + "A B C" + "D E F"; + + @media (orientation: portrait) { + grid-template-rows: $three-rows; + grid-template-areas: + "A B" + "C D" + "E F"; + } + } + + .grid--7 { + grid-template-rows: $two-rows; + grid-template-areas: + "A A A B B B C C C D D D" + "E E E E F F F F G G G G"; + + @media (orientation: portrait) { + grid-template-rows: $three-rows; + grid-template-areas: + "A A A B B B" + "C C C D D D" + "E E F F G G"; + } + } + + .grid--8 { + grid-template-rows: $two-rows; + grid-template-areas: + "A B C D" + "E F G H"; + + @media (orientation: portrait) { + grid-template-rows: $four-rows; + grid-template-areas: + "A B" + "C D" + "E F" + "G H"; + } + } + + ::ng-deep .video-wrapper { + height: 100%; + overflow: hidden; + width: 100%; + padding: 2px; + .identity-name { + position: relative; + background-color: #b1b1b1; + text-align: center; + opacity: 0.8; + padding: 0; + bottom: 39px; + left: 0%; + .praticipant-name { + // width: 80%; + margin-left: 30px; + margin-right: 30px; + text-align: center; + align-items: center; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + } + .icons_participant { + display: none; + /* background: blue; */ + /* color: darkslategray; */ + position: absolute; + z-index: 3; + /* top: 0; */ + bottom: 6px; + right: 5px; + @media (orientation: portrait) { + bottom: 1px !important; + } + } + .audio { + left: 5px !important; + } + } + + ::ng-deep video { + height: 100%; + display: block; + object-fit: cover; + width: 100%; + } \ No newline at end of file diff --git a/src/app/pd/chat-component/chat-component.component.ts b/src/app/pd/chat-component/chat-component.component.ts index 4263bd3..4b35d08 100644 --- a/src/app/pd/chat-component/chat-component.component.ts +++ b/src/app/pd/chat-component/chat-component.component.ts @@ -67,7 +67,7 @@ export class ChatComponentComponent implements OnInit { return } this.type_name = this.type == '1' ? 'CUSTOMER' : this.type == '2' ? 'PDOFFICER' : this.type == '3' ? this.cm_name : 'UNKNOWN' - if(this.type == '2') { + if(this.type == '2' || this.type == '3') { if(window.location.origin.includes('localhost')){ this.cusUrl = window.location.origin+'/#/chat/'+this.randomStr+";id="+this.pd_id+";type=1;"; } diff --git a/src/app/pd/services/twilio/twilio.service.ts b/src/app/pd/services/twilio/twilio.service.ts index 5a53308..4c2f059 100644 --- a/src/app/pd/services/twilio/twilio.service.ts +++ b/src/app/pd/services/twilio/twilio.service.ts @@ -192,7 +192,7 @@ export class TwilioService { // When a Participant adds a Track, attach it to the DOM. room.on('trackPublished', (track, participant) => { console.log("Track Published",participant); - this.attachTracks([track]); + this.attachTracks([track],''); }); // When a Participant removes a Track, detach it from the DOM. @@ -225,7 +225,7 @@ export class TwilioService { while (element.firstChild) { element.removeChild(element.firstChild); } - let localElement = this.localVideo.nativeElement; + let localElement = this.remoteVideo.nativeElement; while (localElement.firstChild) { localElement.removeChild(localElement.firstChild); } @@ -291,50 +291,129 @@ console.log("Room participants", this.roomParticipants,this.roomObj) // },0) } attachParticipantTracks(participant): void { + console.log(participant) + // debugger; participant.tracks.forEach(part => { console.log("attachParticipantTracks",participant); - this.trackPublished(part); + this.trackPublished(part, participant); }); } - trackPublished(publication) { + trackPublished(publication, participantObj) { console.log("trackPublished publication",publication); if (publication.isSubscribed) - this.attachTracks(publication.track); + this.attachTracks(publication.track,participantObj); if (!publication.isSubscribed) publication.on('subscribed', track => { console.log(track); - this.attachTracks(track); + this.attachTracks(track, participantObj); + }); + participantObj.on('trackSubscribed', track => { + console.log("Track Sbu",track) + track.on('disabled', (tt) => { + let participantEle = document.getElementsByName(tt.sid) + console.log("disabled",tt,tt.sid,participantEle) + // do something with the UI here + this.participantMuteUI(tt,'0') + // debugger; + }); + track.on('enabled', (tt) => { + console.log("enabled",tt) + this.participantMuteUI(tt,'1') + // do something with the UI here + // debugger; + }); + }); } - - attachTracks(tracks) { - console.log("attachTracks",tracks); + participantMuteUI(track,status) { + // for (let track of participant.tracks) { + Array.from(this.remoteVideo.nativeElement.children).forEach((child:any) => { + // console.log('children.length=' + this.remoteVideo.nativeElement.children.length,child.getAttribute('sid'),track[0],track); + if(child.getAttribute('sid') == track.sid) { + console.log(child,child.getAttribute('participant-sid')) + let id = child.getAttribute('participant-sid')+'-'+track.kind + let currentVideoEle = document.getElementById(id) + console.log(currentVideoEle,id) + if(currentVideoEle && currentVideoEle != null) { + this.renderer.setStyle(currentVideoEle, 'display', status == '0' ? 'block' : 'none'); + } + } + }); + // } +} +createMatIcon(iconName,kind,participant_sid) { + const matIcon = this.renderer.createElement('mat-icon'); + this.renderer.addClass(matIcon, 'mat-icon'); + this.renderer.addClass(matIcon, 'material-icons'); + this.renderer.addClass(matIcon,'icons_participant') + this.renderer.setAttribute(matIcon,'id',participant_sid+'-'+kind,) + this.renderer.addClass(matIcon,kind) + matIcon.innerHTML = iconName + return matIcon +} + attachTracks(tracks,participantObj) { + console.log("attachTracks",tracks,participantObj.videoTracks['Entries']); const element = tracks.attach(); this.renderer.data.id = tracks.sid; console.log("Renderer",this.renderer,tracks.sid) - if(tracks.kind == 'video') { - this.renderer.setAttribute(element,'class','inner') + const divEle = this.renderer.createElement('div') + + if(!tracks.isEnabled) { + this.renderer.setStyle(element,'background-color','black'); } - this.renderer.setAttribute(element,'sid',tracks.sid) - this.renderer.setStyle(element, 'min-height', '80vh'); - this.renderer.setStyle(element, 'height', '100%'); - console.log("Width",window.screen.width); - if(window.screen.width >= 500) { - this.renderer.setStyle(element, 'width', '100%'); - } - // this.renderer.setStyle(element, 'min-width', '100%'); - this.renderer.setStyle(element, 'max-width', '100%'); - this.renderer.setStyle(element,'object-fit','fill'); - this.renderer.appendChild(this.remoteVideo.nativeElement, element); + + this.renderer.appendChild(divEle,element) - setTimeout(()=>{ - console.log("Remote video size",this.remoteVideo.nativeElement.offsetHeight,this.remoteVideo) - if(this.remoteVideo.nativeElement.offsetHeight < 350) { - // this.remoteVideo.nativeElement.style.marginTop = '0px' - // this.renderer.setStyle(element,'object-fit','fill'); + if(tracks.kind == 'video') { + this.renderer.setAttribute(divEle,'class','video-wrapper') + if(participantObj && participantObj.hasOwnProperty('identity') && participantObj.identity) { + const pEle = this.renderer.createElement('div') + this.renderer.setAttribute(pEle,'class','identity-name') + + const spanEle = this.renderer.createElement('p'); + this.renderer.setAttribute(spanEle,'class','praticipant-name') + spanEle.innerHTML = participantObj.identity + this.renderer.appendChild(pEle,spanEle) + + this.renderer.appendChild(pEle,this.createMatIcon('videocam_off','video',participantObj.sid)) + this.renderer.appendChild(pEle,this.createMatIcon('mic_off','audio',participantObj.sid)) + + this.renderer.appendChild(divEle,pEle) + } } -},5000) + else{ + this.renderer.setStyle(divEle, 'display', 'none'); +} +// FOR PARTICIPANT SID + // this.renderer.setAttribute(divEle,participantObj.sid,'') + this.renderer.setAttribute(divEle,'participant-sid',participantObj.sid) + // this.renderer.setAttribute(divEle,'id',participantObj.sid) + + // FOR TRACK SID + this.renderer.setAttribute(divEle,'sid',tracks.sid) + // this.renderer.setStyle(element, 'min-height', '80vh'); + // this.renderer.setStyle(element, 'height', '100%'); + // console.log("Width",window.screen.width); + // if(window.screen.width >= 500) { + // // this.renderer.setStyle(element, 'width', '100%'); + // } + // this.renderer.setStyle(element, 'min-width', '100%'); + // this.renderer.setStyle(element, 'max-width', '100%'); + // this.renderer.setStyle(element,'object-fit','fill'); + + + this.renderer.appendChild(this.remoteVideo.nativeElement, divEle); +setTimeout(() => { + this.participantMuteUI(tracks,tracks.isEnabled ? '1' : '0') +},0) +// setTimeout(()=>{ +// console.log("Remote video size",this.remoteVideo.nativeElement.offsetHeight,this.remoteVideo) +// if(this.remoteVideo.nativeElement.offsetHeight < 350) { +// // this.remoteVideo.nativeElement.style.marginTop = '0px' +// // this.renderer.setStyle(element,'object-fit','fill'); +// } +// },5000) this.btnSubject.next({name:"peerVideoEnable",id:'1',value:true}) } @@ -342,12 +421,33 @@ console.log("Room participants", this.roomParticipants,this.roomObj) console.log("Local Video",this.roomObj.localParticipant) this.roomObj.localParticipant.videoTracks.forEach(publication => { const element = publication.track.attach(); + const divEle = this.renderer.createElement('div') + + this.renderer.setAttribute(divEle,'class','video-wrapper my-video') this.renderer.data.id = publication.track.sid; this.renderer.setStyle(element, 'width', '100%'); if(publication.track.kind == 'video') { this.renderer.setAttribute(element,'class','inner') } - this.renderer.appendChild(this.localVideo.nativeElement, element); + this.renderer.appendChild(divEle,element) + + const pEle = this.renderer.createElement('div') + this.renderer.setAttribute(pEle,'class','identity-name') + + const spanEle = this.renderer.createElement('p'); + this.renderer.setAttribute(spanEle,'class','praticipant-name') + spanEle.innerHTML = "You" + this.renderer.appendChild(pEle,spanEle) + + this.renderer.appendChild(divEle,pEle) + + // const pEle = this.renderer.createElement('p') + // this.renderer.setAttribute(pEle,'class','praticipant-name') + // pEle.innerHTML = "You" + // this.renderer.setAttribute(pEle,'class','identity-name') + + + this.renderer.appendChild(this.remoteVideo.nativeElement, divEle); this.btnSubject.next({name:"is_video_enable",id:'1',value:true}) this.msgSubject.next("Waiting for participant...") }) diff --git a/src/assets/styles/scss/core/_main-sidebar.scss b/src/assets/styles/scss/core/_main-sidebar.scss index 6edfbaf..802a290 100755 --- a/src/assets/styles/scss/core/_main-sidebar.scss +++ b/src/assets/styles/scss/core/_main-sidebar.scss @@ -189,14 +189,14 @@ overflow-x: hidden; overflow-y: auto; position: relative; - padding: 1.5rem; + padding: 0; background: #eeeeee; // margin-bottom: 2rem; } @media(max-width:991px) { .body-container { - padding: 0.5rem; + padding: 0; } html { font-size: 14px;