fix conflicts
This commit is contained in:
commit
54703c77e4
10
.github/workflows/build-and-deploy.yml
vendored
10
.github/workflows/build-and-deploy.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.1
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: "Build and push front image"
|
- name: "Build and push front image"
|
||||||
uses: docker/build-push-action@v1
|
uses: docker/build-push-action@v1
|
||||||
@ -43,7 +43,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.1
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: "Build and push back image"
|
- name: "Build and push back image"
|
||||||
uses: docker/build-push-action@v1
|
uses: docker/build-push-action@v1
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.1
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: "Build and push back image"
|
- name: "Build and push back image"
|
||||||
uses: docker/build-push-action@v1
|
uses: docker/build-push-action@v1
|
||||||
@ -90,7 +90,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.1
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: "Build and push front image"
|
- name: "Build and push front image"
|
||||||
uses: docker/build-push-action@v1
|
uses: docker/build-push-action@v1
|
||||||
@ -114,7 +114,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.0
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
uses: thecodingmachine/deeployer@master
|
uses: thecodingmachine/deeployer@master
|
||||||
|
77
front/dist/resources/logos/boy.svg
vendored
Normal file
77
front/dist/resources/logos/boy.svg
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 188.149 188.149" style="enable-background:new 0 0 188.149 188.149;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<defs>
|
||||||
|
<circle id="SVGID_1_" cx="94.075" cy="94.075" r="94.074"/>
|
||||||
|
</defs>
|
||||||
|
<use xlink:href="#SVGID_1_" style="overflow:visible;fill:#4AC8EB;"/>
|
||||||
|
<clipPath id="SVGID_2_">
|
||||||
|
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
||||||
|
</clipPath>
|
||||||
|
<g style="clip-path:url(#SVGID_2_);">
|
||||||
|
<path style="fill:#A57561;" d="M148.572,197.629v0.01H39.507v-0.01c0-15.124,6.147-28.809,16.09-38.679
|
||||||
|
c0.463-0.463,0.926-0.905,1.408-1.347c1.43-1.326,2.931-2.57,4.493-3.732c1.028-0.771,2.098-1.491,3.177-2.189
|
||||||
|
c1.08-0.699,2.19-1.357,3.331-1.975c0.021-0.021,0.042-0.021,0.042-0.021c0.441-0.247,0.873-0.493,1.306-0.761
|
||||||
|
c1.295-0.761,2.519-1.624,3.69-2.56c4.966-3.948,8.812-9.254,11.001-15.34v-0.011c1.306-3.629,2.016-7.546,2.016-11.639
|
||||||
|
l16.121,0.072c0,4.04,0.688,7.927,1.964,11.525c2.169,6.117,5.994,11.433,10.96,15.401c0.339,0.277,0.688,0.545,1.038,0.802
|
||||||
|
c0.483,0.36,0.977,0.71,1.47,1.039c0.37,0.246,0.751,0.493,1.132,0.72c0.421,0.257,0.853,0.514,1.285,0.75
|
||||||
|
c0.041,0.011,0.071,0.021,0.103,0.041c0.03,0.02,0.062,0.041,0.093,0.061c1.265,0.699,2.498,1.439,3.69,2.221
|
||||||
|
c0.401,0.258,0.802,0.524,1.192,0.803c0.515,0.37,1.039,0.74,1.543,1.131h0.021C139.966,163.875,148.572,179.729,148.572,197.629
|
||||||
|
z"/>
|
||||||
|
<path style="fill:#EB6D4A;" d="M148.572,197.629H39.507c0-15.124,6.147-28.809,16.09-38.679c0.463-0.463,0.926-0.905,1.408-1.347
|
||||||
|
c1.43-1.326,2.931-2.581,4.493-3.742c1.028-0.762,2.098-1.491,3.177-2.18c1.08-0.699,2.19-1.357,3.331-1.975
|
||||||
|
c0.021-0.021,0.042-0.021,0.042-0.021c0.441-0.247,0.873-0.493,1.306-0.761c1.295-0.761,2.519-1.624,3.69-2.56
|
||||||
|
c5.347,5.469,12.79,8.852,21.046,8.852c8.226,0,15.669-3.393,21.016-8.842c0.339,0.277,0.688,0.545,1.038,0.802
|
||||||
|
c0.483,0.36,0.977,0.71,1.47,1.039c0.37,0.246,0.751,0.493,1.132,0.72c0.421,0.267,0.853,0.514,1.285,0.75
|
||||||
|
c0.041,0.011,0.071,0.021,0.103,0.041c0.03,0.011,0.062,0.031,0.093,0.052c1.265,0.699,2.498,1.439,3.69,2.23
|
||||||
|
c0.401,0.258,0.802,0.524,1.192,0.803c0.515,0.37,1.039,0.74,1.543,1.131h0.021C139.966,163.875,148.572,179.729,148.572,197.629
|
||||||
|
z"/>
|
||||||
|
<path style="fill:#A57561;" d="M52.183,46.81v34.117c0,28.977,25.437,52.466,41.857,52.466c16.421,0,41.858-23.489,41.858-52.466
|
||||||
|
V46.81H52.183z"/>
|
||||||
|
<path style="fill:#141720;" d="M52.183,76.823L52.183,76.823c2.063,0,3.734-1.671,3.734-3.733V49.356h-3.734V76.823z"/>
|
||||||
|
<path style="fill:#141720;" d="M135.899,76.823L135.899,76.823V49.356h-3.733V73.09
|
||||||
|
C132.165,75.152,133.836,76.823,135.899,76.823z"/>
|
||||||
|
<path style="fill:#141720;" d="M135.893,48.33c0,4.884-0.328,6.061-3.734,5.801c-0.137-2.367-17.141-4.296-38.111-4.296
|
||||||
|
c-20.985,0-37.989,1.929-38.126,4.296c-3.406,0.26-3.734-0.917-3.734-5.801c0-0.479,0.014-0.984,0.027-1.519
|
||||||
|
c0.52-12.052,7.318-34.582,41.833-34.582c34.5,0,41.299,22.53,41.818,34.582C135.879,47.346,135.893,47.852,135.893,48.33z"/>
|
||||||
|
</g>
|
||||||
|
<path style="clip-path:url(#SVGID_2_);fill:#FFFFFF;" d="M115.106,146.119c-3.517,10.826-10.601,21.539-21.036,30.299
|
||||||
|
c-10.436-8.76-17.509-19.473-21.025-30.299c0.052,0.02,0.113,0.041,0.165,0.061c5.531,4.955,12.852,7.979,20.86,7.979
|
||||||
|
c8.009,0,15.319-3.013,20.851-7.968C114.982,146.17,115.044,146.14,115.106,146.119z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
1
front/dist/resources/logos/discussion.svg
vendored
Normal file
1
front/dist/resources/logos/discussion.svg
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg height="682pt" viewBox="-21 -47 682.66669 682" width="682pt" xmlns="http://www.w3.org/2000/svg"><path d="m640 86.65625v283.972656c0 48.511719-39.472656 87.988282-87.988281 87.988282h-279.152344l-185.183594 128.863281v-128.863281c-48.375-.164063-87.675781-39.574219-87.675781-87.988282v-283.972656c0-48.515625 39.472656-87.988281 87.988281-87.988281h464.023438c48.515625 0 87.988281 39.472656 87.988281 87.988281zm0 0" fill="#ffdb2d"/><path d="m640 86.65625v283.972656c0 48.511719-39.472656 87.988282-87.988281 87.988282h-232.109375v-459.949219h232.109375c48.515625 0 87.988281 39.472656 87.988281 87.988281zm0 0" fill="#ffaa20"/><g fill="#fff"><path d="m171.296875 131.167969h297.40625v37.5h-297.40625zm0 0"/><path d="m171.296875 211.167969h297.40625v37.5h-297.40625zm0 0"/><path d="m171.296875 291.167969h297.40625v37.5h-297.40625zm0 0"/></g><path d="m319.902344 131.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/><path d="m319.902344 211.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/><path d="m319.902344 291.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
210
front/dist/resources/style/style.css
vendored
210
front/dist/resources/style/style.css
vendored
@ -1,6 +1,14 @@
|
|||||||
|
*{
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
}
|
||||||
body{
|
body{
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
body button:focus,
|
||||||
|
body img:focus,
|
||||||
|
body input:focus {
|
||||||
|
outline: -webkit-focus-ring-color auto 0;
|
||||||
|
}
|
||||||
body .message-info{
|
body .message-info{
|
||||||
width: 20%;
|
width: 20%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@ -72,14 +80,16 @@ body .message-info.warning{
|
|||||||
|
|
||||||
#div-myCamVideo {
|
#div-myCamVideo {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 15px;
|
||||||
bottom: 0;
|
bottom: 15px;
|
||||||
|
border-radius: 15px 15px 15px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
video#myCamVideo{
|
video#myCamVideo{
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
-webkit-transform: scaleX(-1);
|
-webkit-transform: scaleX(-1);
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
|
border-radius: 15px 15px 15px 15px;
|
||||||
/*width: 200px;*/
|
/*width: 200px;*/
|
||||||
/*height: 113px;*/
|
/*height: 113px;*/
|
||||||
}
|
}
|
||||||
@ -372,6 +382,7 @@ body {
|
|||||||
margin: 2%;
|
margin: 2%;
|
||||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, max-height 0.2s, max-width 0.2s;
|
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, max-height 0.2s, max-width 0.2s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border-radius: 15px 15px 15px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar > div:hover {
|
.sidebar > div:hover {
|
||||||
@ -384,6 +395,7 @@ body {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-mode {
|
.chat-mode {
|
||||||
@ -435,7 +447,7 @@ body {
|
|||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
top: -80%;
|
top: -80%;
|
||||||
left: 10%;
|
left: 10%;
|
||||||
background: #000000a6;
|
background: #333333;
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
transition: all 0.1s ease-out;
|
transition: all 0.1s ease-out;
|
||||||
}
|
}
|
||||||
@ -532,7 +544,7 @@ body {
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
background-color: #00000000;
|
background-color: #00000000;
|
||||||
color: #ffda01;
|
color: #ffda01;
|
||||||
border-radius: 10px;
|
border-radius: 15px;
|
||||||
padding: 10px 30px;
|
padding: 10px 30px;
|
||||||
transition: all .2s ease;
|
transition: all .2s ease;
|
||||||
}
|
}
|
||||||
@ -627,6 +639,7 @@ div.modal-report-user{
|
|||||||
left: calc(50% - 400px);
|
left: calc(50% - 400px);
|
||||||
top: 100px;
|
top: 100px;
|
||||||
background-color: #000000ad;
|
background-color: #000000ad;
|
||||||
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-report-user textarea{
|
.modal-report-user textarea{
|
||||||
@ -638,6 +651,7 @@ div.modal-report-user{
|
|||||||
color: white;
|
color: white;
|
||||||
width: calc(100% - 60px);
|
width: calc(100% - 60px);
|
||||||
margin: 30px;
|
margin: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-report-user img{
|
.modal-report-user img{
|
||||||
@ -669,7 +683,7 @@ div.modal-report-user{
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
background-color: #00000000;
|
background-color: #00000000;
|
||||||
color: #ffda01;
|
color: #ffda01;
|
||||||
border-radius: 10px;
|
border-radius: 15px;
|
||||||
padding: 10px 30px;
|
padding: 10px 30px;
|
||||||
transition: all .2s ease;
|
transition: all .2s ease;
|
||||||
}
|
}
|
||||||
@ -701,3 +715,189 @@ div.modal-report-user{
|
|||||||
max-width: calc(800px - 60px); /* size of modal - padding*/
|
max-width: calc(800px - 60px); /* size of modal - padding*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*MESSAGE*/
|
||||||
|
.discussion{
|
||||||
|
position: fixed;
|
||||||
|
left: -300px;
|
||||||
|
top: 0px;
|
||||||
|
width: 220px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #333333;
|
||||||
|
padding: 20px;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
.discussion.active{
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.discussion .active-btn{
|
||||||
|
display: none;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
background-color: #2d2d2dba;
|
||||||
|
position: absolute;
|
||||||
|
top: calc(50% - 25px);
|
||||||
|
margin-left: 315px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: none;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
.discussion .active-btn.active{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.discussion .active-btn:hover {
|
||||||
|
transform: scale(1.1) rotateY(3.142rad);
|
||||||
|
}
|
||||||
|
.discussion .active-btn img{
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
margin: 13px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .close-btn{
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 10px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.discussion .close-btn img{
|
||||||
|
height: 15px;
|
||||||
|
right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion p{
|
||||||
|
color: white;
|
||||||
|
font-size: 22px;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants{
|
||||||
|
height: 200px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant{
|
||||||
|
display: flex;
|
||||||
|
margin: 5px 10px;
|
||||||
|
background-color: #ffffff69;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant:hover{
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.discussion .participants .participant:hover p{
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant:before {
|
||||||
|
content: '';
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
background-color: #1e7e34;
|
||||||
|
position: absolute;
|
||||||
|
margin-left: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant img{
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant p{
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant button.report-btn{
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
background-color: #2d2d2dba;
|
||||||
|
right: 34px;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 6px 0px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
width: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all .5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .participants .participant:hover button.report-btn{
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages{
|
||||||
|
position: absolute;
|
||||||
|
height: calc(100% - 360px);
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-width: calc(100% - 40px);
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages h2{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages .message{
|
||||||
|
margin: 5px;
|
||||||
|
float: right;
|
||||||
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages .message.me{
|
||||||
|
float: left;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages .message p{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .messages .message p.body{
|
||||||
|
font-size: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .send-message{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 45px;
|
||||||
|
width: 220px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .send-message input{
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
height: 20px;
|
||||||
|
background-color: #171717;
|
||||||
|
color: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
border: none;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion .send-message img{
|
||||||
|
position: absolute;
|
||||||
|
margin-right: 10px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #ffffff69;
|
||||||
|
}
|
||||||
|
.discussion .send-message img:hover{
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -352,6 +352,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
//create input to move
|
//create input to move
|
||||||
this.userInputManager = new UserInputManager(this);
|
this.userInputManager = new UserInputManager(this);
|
||||||
|
mediaManager.setUserInputManager(this.userInputManager);
|
||||||
|
|
||||||
//notify game manager can to create currentUser in map
|
//notify game manager can to create currentUser in map
|
||||||
this.createCurrentPlayer();
|
this.createCurrentPlayer();
|
||||||
@ -431,35 +432,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
// From now, this game scene will be notified of reposition events
|
// From now, this game scene will be notified of reposition events
|
||||||
layoutManager.setListener(this);
|
layoutManager.setListener(this);
|
||||||
|
this.triggerOnMapLayerPropertyChange();
|
||||||
this.gameMap.onPropertyChange('openWebsite', (newValue, oldValue) => {
|
|
||||||
if (newValue === undefined) {
|
|
||||||
coWebsiteManager.closeCoWebsite();
|
|
||||||
} else {
|
|
||||||
coWebsiteManager.loadCoWebsite(newValue as string);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.gameMap.onPropertyChange('jitsiRoom', (newValue, oldValue, allProps) => {
|
|
||||||
if (newValue === undefined) {
|
|
||||||
this.stopJitsi();
|
|
||||||
} else {
|
|
||||||
if (JITSI_PRIVATE_MODE) {
|
|
||||||
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
|
|
||||||
|
|
||||||
this.connection.emitQueryJitsiJwtMessage(this.instance.replace('/', '-') + "-" + newValue, adminTag);
|
|
||||||
} else {
|
|
||||||
this.startJitsi(newValue as string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.gameMap.onPropertyChange('silent', (newValue, oldValue) => {
|
|
||||||
if (newValue === undefined || newValue === false || newValue === '') {
|
|
||||||
this.connection.setSilent(false);
|
|
||||||
} else {
|
|
||||||
this.connection.setSilent(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const camera = this.cameras.main;
|
const camera = this.cameras.main;
|
||||||
|
|
||||||
@ -567,7 +540,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// When connection is performed, let's connect SimplePeer
|
// When connection is performed, let's connect SimplePeer
|
||||||
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic);
|
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.GameManager.getPlayerName());
|
||||||
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
|
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
|
||||||
this.UserMessageManager = new UserMessageManager(this.connection);
|
this.UserMessageManager = new UserMessageManager(this.connection);
|
||||||
|
|
||||||
@ -592,15 +565,51 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
this.gameMap.setPosition(event.x, event.y);
|
this.gameMap.setPosition(event.x, event.y);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
this.scene.wake();
|
this.scene.wake();
|
||||||
this.scene.sleep(ReconnectingSceneName);
|
this.scene.sleep(ReconnectingSceneName);
|
||||||
|
|
||||||
|
//init user position and play trigger to check layers properties
|
||||||
|
this.gameMap.setPosition(this.CurrentPlayer.x, this.CurrentPlayer.y);
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private triggerOnMapLayerPropertyChange(){
|
||||||
|
this.gameMap.onPropertyChange('openWebsite', (newValue, oldValue) => {
|
||||||
|
if (newValue === undefined) {
|
||||||
|
coWebsiteManager.closeCoWebsite();
|
||||||
|
} else {
|
||||||
|
coWebsiteManager.loadCoWebsite(newValue as string);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.gameMap.onPropertyChange('jitsiRoom', (newValue, oldValue, allProps) => {
|
||||||
|
if (newValue === undefined) {
|
||||||
|
this.stopJitsi();
|
||||||
|
} else {
|
||||||
|
if (JITSI_PRIVATE_MODE) {
|
||||||
|
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
|
||||||
|
|
||||||
|
this.connection.emitQueryJitsiJwtMessage(this.instance.replace('/', '-') + "-" + newValue, adminTag);
|
||||||
|
} else {
|
||||||
|
this.startJitsi(newValue as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.gameMap.onPropertyChange('silent', (newValue, oldValue) => {
|
||||||
|
if (newValue === undefined || newValue === false || newValue === '') {
|
||||||
|
this.connection.setSilent(false);
|
||||||
|
} else {
|
||||||
|
this.connection.setSilent(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private switchLayoutMode(): void {
|
private switchLayoutMode(): void {
|
||||||
|
//if discussion is activated, this layout cannot be activated
|
||||||
|
if(mediaManager.activatedDiscussion){
|
||||||
|
return;
|
||||||
|
}
|
||||||
const mode = layoutManager.getLayoutMode();
|
const mode = layoutManager.getLayoutMode();
|
||||||
if (mode === LayoutMode.Presentation) {
|
if (mode === LayoutMode.Presentation) {
|
||||||
layoutManager.switchLayoutMode(LayoutMode.VideoChat);
|
layoutManager.switchLayoutMode(LayoutMode.VideoChat);
|
||||||
@ -704,6 +713,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
//todo: push that into the gameManager
|
//todo: push that into the gameManager
|
||||||
private loadNextGame(layer: ITiledMapLayer, mapWidth: number, roomId: string){
|
private loadNextGame(layer: ITiledMapLayer, mapWidth: number, roomId: string){
|
||||||
|
|
||||||
const room = new Room(roomId);
|
const room = new Room(roomId);
|
||||||
gameManager.loadMap(room, this.scene);
|
gameManager.loadMap(room, this.scene);
|
||||||
const exitSceneKey = roomId;
|
const exitSceneKey = roomId;
|
||||||
|
@ -7,6 +7,7 @@ import {mediaManager} from "../../WebRtc/MediaManager";
|
|||||||
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
||||||
import {SoundMeter} from "../Components/SoundMeter";
|
import {SoundMeter} from "../Components/SoundMeter";
|
||||||
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
||||||
|
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||||
|
|
||||||
export const EnableCameraSceneName = "EnableCameraScene";
|
export const EnableCameraSceneName = "EnableCameraScene";
|
||||||
enum LoginTextures {
|
enum LoginTextures {
|
||||||
@ -93,7 +94,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
this.login();
|
this.login();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').classList.add('active');
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').classList.add('active');
|
||||||
|
|
||||||
const mediaPromise = mediaManager.getCamera();
|
const mediaPromise = mediaManager.getCamera();
|
||||||
mediaPromise.then(this.getDevices.bind(this));
|
mediaPromise.then(this.getDevices.bind(this));
|
||||||
@ -150,10 +151,10 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
* Function called each time a camera is changed
|
* Function called each time a camera is changed
|
||||||
*/
|
*/
|
||||||
private setupStream(stream: MediaStream): void {
|
private setupStream(stream: MediaStream): void {
|
||||||
const img = this.getElementByIdOrFail<HTMLDivElement>('webRtcSetupNoVideo');
|
const img = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetupNoVideo');
|
||||||
img.style.display = 'none';
|
img.style.display = 'none';
|
||||||
|
|
||||||
const div = this.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
const div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
||||||
div.srcObject = stream;
|
div.srcObject = stream;
|
||||||
|
|
||||||
this.soundMeter.connectToSource(stream, new window.AudioContext());
|
this.soundMeter.connectToSource(stream, new window.AudioContext());
|
||||||
@ -164,7 +165,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
|
|
||||||
private updateWebCamName(): void {
|
private updateWebCamName(): void {
|
||||||
if (this.camerasList.length > 1) {
|
if (this.camerasList.length > 1) {
|
||||||
const div = this.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
const div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
||||||
|
|
||||||
let label = this.camerasList[this.cameraSelected].label;
|
let label = this.camerasList[this.cameraSelected].label;
|
||||||
// remove text in parenthesis
|
// remove text in parenthesis
|
||||||
@ -211,10 +212,10 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private reposition(): void {
|
private reposition(): void {
|
||||||
let div = this.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
let div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
||||||
let bounds = div.getBoundingClientRect();
|
let bounds = div.getBoundingClientRect();
|
||||||
if (!div.srcObject) {
|
if (!div.srcObject) {
|
||||||
div = this.getElementByIdOrFail<HTMLVideoElement>('webRtcSetup');
|
div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('webRtcSetup');
|
||||||
bounds = div.getBoundingClientRect();
|
bounds = div.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +256,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private login(): void {
|
private login(): void {
|
||||||
this.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||||
this.soundMeter.stop();
|
this.soundMeter.stop();
|
||||||
window.removeEventListener('resize', this.repositionCallback);
|
window.removeEventListener('resize', this.repositionCallback);
|
||||||
|
|
||||||
@ -276,13 +277,4 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
this.updateWebCamName();
|
this.updateWebCamName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getElementByIdOrFail<T extends HTMLElement>(id: string): T {
|
|
||||||
const elem = document.getElementById(id);
|
|
||||||
if (elem === null) {
|
|
||||||
throw new Error("Cannot find HTML element with id '"+id+"'");
|
|
||||||
}
|
|
||||||
// FIXME: does not check the type of the returned type
|
|
||||||
return elem as T;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
231
front/src/WebRtc/DiscussionManager.ts
Normal file
231
front/src/WebRtc/DiscussionManager.ts
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
import {HtmlUtils} from "./HtmlUtils";
|
||||||
|
import {MediaManager, ReportCallback, UpdatedLocalStreamCallback} from "./MediaManager";
|
||||||
|
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||||
|
export type SendMessageCallback = (message:string) => void;
|
||||||
|
|
||||||
|
export class DiscussionManager {
|
||||||
|
private mainContainer: HTMLDivElement;
|
||||||
|
|
||||||
|
private divDiscuss?: HTMLDivElement;
|
||||||
|
private divParticipants?: HTMLDivElement;
|
||||||
|
private nbpParticipants?: HTMLParagraphElement;
|
||||||
|
private divMessages?: HTMLParagraphElement;
|
||||||
|
private buttonActiveDiscussion?: HTMLButtonElement;
|
||||||
|
|
||||||
|
private participants: Map<number|string, HTMLDivElement> = new Map<number|string, HTMLDivElement>();
|
||||||
|
|
||||||
|
private activeDiscussion: boolean = false;
|
||||||
|
|
||||||
|
private sendMessageCallBack : Map<number|string, SendMessageCallback> = new Map<number|string, SendMessageCallback>();
|
||||||
|
|
||||||
|
private userInputManager?: UserInputManager;
|
||||||
|
|
||||||
|
constructor(private mediaManager: MediaManager, name: string) {
|
||||||
|
this.mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('main-container');
|
||||||
|
this.createDiscussPart(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createDiscussPart(name: string) {
|
||||||
|
this.divDiscuss = document.createElement('div');
|
||||||
|
this.divDiscuss.classList.add('discussion');
|
||||||
|
|
||||||
|
const buttonCloseDiscussion: HTMLButtonElement = document.createElement('button');
|
||||||
|
this.buttonActiveDiscussion = document.createElement('button');
|
||||||
|
buttonCloseDiscussion.classList.add('close-btn');
|
||||||
|
buttonCloseDiscussion.innerHTML = `<img src="resources/logos/close.svg"/>`;
|
||||||
|
buttonCloseDiscussion.addEventListener('click', () => {
|
||||||
|
this.hideDiscussion();
|
||||||
|
this.showButtonDiscussionBtn();
|
||||||
|
});
|
||||||
|
this.buttonActiveDiscussion.classList.add('active-btn');
|
||||||
|
this.buttonActiveDiscussion.innerHTML = `<img src="resources/logos/discussion.svg"/>`;
|
||||||
|
this.buttonActiveDiscussion.addEventListener('click', () => {
|
||||||
|
this.showDiscussionPart();
|
||||||
|
});
|
||||||
|
this.divDiscuss.appendChild(buttonCloseDiscussion);
|
||||||
|
this.divDiscuss.appendChild(this.buttonActiveDiscussion);
|
||||||
|
|
||||||
|
const myName: HTMLParagraphElement = document.createElement('p');
|
||||||
|
myName.innerText = name.toUpperCase();
|
||||||
|
this.nbpParticipants = document.createElement('p');
|
||||||
|
this.nbpParticipants.innerText = 'PARTICIPANTS (1)';
|
||||||
|
|
||||||
|
this.divParticipants = document.createElement('div');
|
||||||
|
this.divParticipants.classList.add('participants');
|
||||||
|
|
||||||
|
this.divMessages = document.createElement('div');
|
||||||
|
this.divMessages.classList.add('messages');
|
||||||
|
this.divMessages.innerHTML = "<h2>Local messages</h2>"
|
||||||
|
|
||||||
|
this.divDiscuss.appendChild(myName);
|
||||||
|
this.divDiscuss.appendChild(this.nbpParticipants);
|
||||||
|
this.divDiscuss.appendChild(this.divParticipants);
|
||||||
|
this.divDiscuss.appendChild(this.divMessages);
|
||||||
|
|
||||||
|
const sendDivMessage: HTMLDivElement = document.createElement('div');
|
||||||
|
sendDivMessage.classList.add('send-message');
|
||||||
|
const inputMessage: HTMLInputElement = document.createElement('input');
|
||||||
|
inputMessage.type = "text";
|
||||||
|
inputMessage.addEventListener('keyup', (event: KeyboardEvent) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
if(inputMessage.value === null
|
||||||
|
|| inputMessage.value === ''
|
||||||
|
|| inputMessage.value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.addMessage(name, inputMessage.value, true);
|
||||||
|
for(const callback of this.sendMessageCallBack.values()) {
|
||||||
|
callback(inputMessage.value);
|
||||||
|
}
|
||||||
|
inputMessage.value = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sendDivMessage.appendChild(inputMessage);
|
||||||
|
this.divDiscuss.appendChild(sendDivMessage);
|
||||||
|
|
||||||
|
//append in main container
|
||||||
|
this.mainContainer.appendChild(this.divDiscuss);
|
||||||
|
|
||||||
|
this.addParticipant('me', 'Moi', undefined, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public addParticipant(
|
||||||
|
userId: number|string,
|
||||||
|
name: string|undefined,
|
||||||
|
img?: string|undefined,
|
||||||
|
isMe: boolean = false,
|
||||||
|
reportCallback?: ReportCallback
|
||||||
|
) {
|
||||||
|
const divParticipant: HTMLDivElement = document.createElement('div');
|
||||||
|
divParticipant.classList.add('participant');
|
||||||
|
divParticipant.id = `participant-${userId}`;
|
||||||
|
|
||||||
|
const divImgParticipant: HTMLImageElement = document.createElement('img');
|
||||||
|
divImgParticipant.src = 'resources/logos/boy.svg';
|
||||||
|
if (img !== undefined) {
|
||||||
|
divImgParticipant.src = img;
|
||||||
|
}
|
||||||
|
const divPParticipant: HTMLParagraphElement = document.createElement('p');
|
||||||
|
if(!name){
|
||||||
|
name = 'Anonymous';
|
||||||
|
}
|
||||||
|
divPParticipant.innerText = name;
|
||||||
|
|
||||||
|
divParticipant.appendChild(divImgParticipant);
|
||||||
|
divParticipant.appendChild(divPParticipant);
|
||||||
|
|
||||||
|
if(!isMe) {
|
||||||
|
const reportBanUserAction: HTMLButtonElement = document.createElement('button');
|
||||||
|
reportBanUserAction.classList.add('report-btn')
|
||||||
|
reportBanUserAction.innerText = 'Report';
|
||||||
|
reportBanUserAction.addEventListener('click', () => {
|
||||||
|
if(reportCallback) {
|
||||||
|
this.mediaManager.showReportModal(`${userId}`, name ?? '', reportCallback);
|
||||||
|
}else{
|
||||||
|
console.info('report feature is not activated!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
divParticipant.appendChild(reportBanUserAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.divParticipants?.appendChild(divParticipant);
|
||||||
|
|
||||||
|
this.participants.set(userId, divParticipant);
|
||||||
|
this.showButtonDiscussionBtn();
|
||||||
|
|
||||||
|
this.updateParticipant(this.participants.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateParticipant(nb: number) {
|
||||||
|
if (!this.nbpParticipants) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.nbpParticipants.innerText = `PARTICIPANTS (${nb})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addMessage(name: string, message: string, isMe: boolean = false) {
|
||||||
|
const divMessage: HTMLDivElement = document.createElement('div');
|
||||||
|
divMessage.classList.add('message');
|
||||||
|
if(isMe){
|
||||||
|
divMessage.classList.add('me');
|
||||||
|
}
|
||||||
|
|
||||||
|
const pMessage: HTMLParagraphElement = document.createElement('p');
|
||||||
|
const date = new Date();
|
||||||
|
if(isMe){
|
||||||
|
name = 'Moi';
|
||||||
|
}
|
||||||
|
pMessage.innerHTML = `<span style="font-weight: bold">${name}</span>
|
||||||
|
<span style="color:#bac2cc;display:inline-block;font-size:12px;">
|
||||||
|
${date.getHours()}:${date.getMinutes()}
|
||||||
|
</span>`;
|
||||||
|
divMessage.appendChild(pMessage);
|
||||||
|
|
||||||
|
const userMessage: HTMLParagraphElement = document.createElement('p');
|
||||||
|
userMessage.innerText = message;
|
||||||
|
userMessage.classList.add('body');
|
||||||
|
divMessage.appendChild(userMessage);
|
||||||
|
|
||||||
|
this.divMessages?.appendChild(divMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeParticipant(userId: number|string){
|
||||||
|
const element = this.participants.get(userId);
|
||||||
|
if(element){
|
||||||
|
element.remove();
|
||||||
|
this.participants.delete(userId);
|
||||||
|
}
|
||||||
|
//if all participant leave, hide discussion button
|
||||||
|
if(this.participants.size === 1){
|
||||||
|
this.hideButtonDiscussionBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendMessageCallBack.delete(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onSendMessageCallback(userId: string|number, callback: SendMessageCallback): void {
|
||||||
|
this.sendMessageCallBack.set(userId, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
get activatedDiscussion(){
|
||||||
|
return this.activeDiscussion;
|
||||||
|
}
|
||||||
|
|
||||||
|
private showButtonDiscussionBtn(){
|
||||||
|
//if it's first participant, show discussion button
|
||||||
|
if(this.activatedDiscussion || this.participants.size === 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.buttonActiveDiscussion?.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
private showDiscussion(){
|
||||||
|
this.activeDiscussion = true;
|
||||||
|
if(this.userInputManager) {
|
||||||
|
this.userInputManager.clearAllInputKeyboard();
|
||||||
|
}
|
||||||
|
this.divDiscuss?.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideDiscussion(){
|
||||||
|
this.activeDiscussion = false;
|
||||||
|
if(this.userInputManager) {
|
||||||
|
this.userInputManager.initKeyBoardEvent();
|
||||||
|
}
|
||||||
|
this.divDiscuss?.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideButtonDiscussionBtn(){
|
||||||
|
this.buttonActiveDiscussion?.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public setUserInputManager(userInputManager : UserInputManager){
|
||||||
|
this.userInputManager = userInputManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public showDiscussionPart(){
|
||||||
|
this.showDiscussion();
|
||||||
|
this.hideButtonDiscussionBtn();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import {DivImportance, layoutManager} from "./LayoutManager";
|
import {DivImportance, layoutManager} from "./LayoutManager";
|
||||||
import {HtmlUtils} from "./HtmlUtils";
|
import {HtmlUtils} from "./HtmlUtils";
|
||||||
|
import {DiscussionManager, SendMessageCallback} from "./DiscussionManager";
|
||||||
|
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||||
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
const videoConstraint: boolean|MediaTrackConstraints = {
|
const videoConstraint: boolean|MediaTrackConstraints = {
|
||||||
@ -38,59 +40,65 @@ export class MediaManager {
|
|||||||
private cinemaBtn: HTMLDivElement;
|
private cinemaBtn: HTMLDivElement;
|
||||||
private monitorBtn: HTMLDivElement;
|
private monitorBtn: HTMLDivElement;
|
||||||
|
|
||||||
|
private discussionManager: DiscussionManager;
|
||||||
|
|
||||||
|
private userInputManager?: UserInputManager;
|
||||||
|
|
||||||
private hasCamera = true;
|
private hasCamera = true;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
this.myCamVideo = this.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
|
this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
|
||||||
this.webrtcInAudio = this.getElementByIdOrFail<HTMLAudioElement>('audio-webrtc-in');
|
this.webrtcInAudio = HtmlUtils.getElementByIdOrFail<HTMLAudioElement>('audio-webrtc-in');
|
||||||
this.webrtcInAudio.volume = 0.2;
|
this.webrtcInAudio.volume = 0.2;
|
||||||
|
|
||||||
this.microphoneBtn = this.getElementByIdOrFail<HTMLDivElement>('btn-micro');
|
this.microphoneBtn = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('btn-micro');
|
||||||
this.microphoneClose = this.getElementByIdOrFail<HTMLImageElement>('microphone-close');
|
this.microphoneClose = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('microphone-close');
|
||||||
this.microphoneClose.style.display = "none";
|
this.microphoneClose.style.display = "none";
|
||||||
this.microphoneClose.addEventListener('click', (e: MouseEvent) => {
|
this.microphoneClose.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.enableMicrophone();
|
this.enableMicrophone();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
this.microphone = this.getElementByIdOrFail<HTMLImageElement>('microphone');
|
this.microphone = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('microphone');
|
||||||
this.microphone.addEventListener('click', (e: MouseEvent) => {
|
this.microphone.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.disableMicrophone();
|
this.disableMicrophone();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cinemaBtn = this.getElementByIdOrFail<HTMLDivElement>('btn-video');
|
this.cinemaBtn = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('btn-video');
|
||||||
this.cinemaClose = this.getElementByIdOrFail<HTMLImageElement>('cinema-close');
|
this.cinemaClose = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('cinema-close');
|
||||||
this.cinemaClose.style.display = "none";
|
this.cinemaClose.style.display = "none";
|
||||||
this.cinemaClose.addEventListener('click', (e: MouseEvent) => {
|
this.cinemaClose.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.enableCamera();
|
this.enableCamera();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
this.cinema = this.getElementByIdOrFail<HTMLImageElement>('cinema');
|
this.cinema = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('cinema');
|
||||||
this.cinema.addEventListener('click', (e: MouseEvent) => {
|
this.cinema.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.disableCamera();
|
this.disableCamera();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
|
|
||||||
this.monitorBtn = this.getElementByIdOrFail<HTMLDivElement>('btn-monitor');
|
this.monitorBtn = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('btn-monitor');
|
||||||
this.monitorClose = this.getElementByIdOrFail<HTMLImageElement>('monitor-close');
|
this.monitorClose = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('monitor-close');
|
||||||
this.monitorClose.style.display = "block";
|
this.monitorClose.style.display = "block";
|
||||||
this.monitorClose.addEventListener('click', (e: MouseEvent) => {
|
this.monitorClose.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.enableScreenSharing();
|
this.enableScreenSharing();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
this.monitor = this.getElementByIdOrFail<HTMLImageElement>('monitor');
|
this.monitor = HtmlUtils.getElementByIdOrFail<HTMLImageElement>('monitor');
|
||||||
this.monitor.style.display = "none";
|
this.monitor.style.display = "none";
|
||||||
this.monitor.addEventListener('click', (e: MouseEvent) => {
|
this.monitor.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.disableScreenSharing();
|
this.disableScreenSharing();
|
||||||
//update tracking
|
//update tracking
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.discussionManager = new DiscussionManager(this,'');
|
||||||
}
|
}
|
||||||
|
|
||||||
public onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
|
public onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
|
||||||
@ -128,12 +136,12 @@ export class MediaManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public showGameOverlay(){
|
public showGameOverlay(){
|
||||||
const gameOverlay = this.getElementByIdOrFail('game-overlay');
|
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
|
||||||
gameOverlay.classList.add('active');
|
gameOverlay.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
public hideGameOverlay(){
|
public hideGameOverlay(){
|
||||||
const gameOverlay = this.getElementByIdOrFail('game-overlay');
|
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
|
||||||
gameOverlay.classList.remove('active');
|
gameOverlay.classList.remove('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,14 +380,17 @@ export class MediaManager {
|
|||||||
layoutManager.add(DivImportance.Normal, userId, html);
|
layoutManager.add(DivImportance.Normal, userId, html);
|
||||||
|
|
||||||
if (reportCallBack) {
|
if (reportCallBack) {
|
||||||
const reportBtn = this.getElementByIdOrFail<HTMLDivElement>(`report-${userId}`);
|
const reportBtn = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(`report-${userId}`);
|
||||||
reportBtn.addEventListener('click', (e: MouseEvent) => {
|
reportBtn.addEventListener('click', (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.showReportModal(userId, userName, reportCallBack);
|
this.showReportModal(userId, userName, reportCallBack);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.remoteVideo.set(userId, this.getElementByIdOrFail<HTMLVideoElement>(userId));
|
this.remoteVideo.set(userId, HtmlUtils.getElementByIdOrFail<HTMLVideoElement>(userId));
|
||||||
|
|
||||||
|
//permit to create participant in discussion part
|
||||||
|
this.addNewParticipant(userId, userName, undefined, reportCallBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
addScreenSharingActiveVideo(userId: string, divImportance: DivImportance = DivImportance.Important){
|
addScreenSharingActiveVideo(userId: string, divImportance: DivImportance = DivImportance.Important){
|
||||||
@ -393,7 +404,7 @@ export class MediaManager {
|
|||||||
|
|
||||||
layoutManager.add(divImportance, userId, html);
|
layoutManager.add(divImportance, userId, html);
|
||||||
|
|
||||||
this.remoteVideo.set(userId, this.getElementByIdOrFail<HTMLVideoElement>(userId));
|
this.remoteVideo.set(userId, HtmlUtils.getElementByIdOrFail<HTMLVideoElement>(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
disabledMicrophoneByUserId(userId: number){
|
disabledMicrophoneByUserId(userId: number){
|
||||||
@ -454,6 +465,9 @@ export class MediaManager {
|
|||||||
removeActiveVideo(userId: string){
|
removeActiveVideo(userId: string){
|
||||||
layoutManager.remove(userId);
|
layoutManager.remove(userId);
|
||||||
this.remoteVideo.delete(userId);
|
this.remoteVideo.delete(userId);
|
||||||
|
|
||||||
|
//permit to remove user in discussion part
|
||||||
|
this.removeParticipant(userId);
|
||||||
}
|
}
|
||||||
removeActiveScreenSharingVideo(userId: string) {
|
removeActiveScreenSharingVideo(userId: string) {
|
||||||
this.removeActiveVideo(`screen-sharing-${userId}`)
|
this.removeActiveVideo(`screen-sharing-${userId}`)
|
||||||
@ -516,18 +530,9 @@ export class MediaManager {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getElementByIdOrFail<T extends HTMLElement>(id: string): T {
|
public showReportModal(userId: string, userName: string, reportCallBack: ReportCallback){
|
||||||
const elem = document.getElementById(id);
|
|
||||||
if (elem === null) {
|
|
||||||
throw new Error("Cannot find HTML element with id '"+id+"'");
|
|
||||||
}
|
|
||||||
// FIXME: does not check the type of the returned type
|
|
||||||
return elem as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
private showReportModal(userId: string, userName: string, reportCallBack: ReportCallback){
|
|
||||||
//create report text area
|
//create report text area
|
||||||
const mainContainer = this.getElementByIdOrFail<HTMLDivElement>('main-container');
|
const mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('main-container');
|
||||||
|
|
||||||
const divReport = document.createElement('div');
|
const divReport = document.createElement('div');
|
||||||
divReport.classList.add('modal-report-user');
|
divReport.classList.add('modal-report-user');
|
||||||
@ -582,7 +587,34 @@ export class MediaManager {
|
|||||||
mainContainer.appendChild(divReport);
|
mainContainer.appendChild(divReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addNewParticipant(userId: number|string, name: string|undefined, img?: string, reportCallBack?: ReportCallback){
|
||||||
|
this.discussionManager.addParticipant(userId, name, img, false, reportCallBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeParticipant(userId: number|string){
|
||||||
|
this.discussionManager.removeParticipant(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public addNewMessage(name: string, message: string, isMe: boolean = false){
|
||||||
|
this.discussionManager.addMessage(name, message, isMe);
|
||||||
|
|
||||||
|
//when there are new message, show discussion
|
||||||
|
if(!this.discussionManager.activatedDiscussion) {
|
||||||
|
this.discussionManager.showDiscussionPart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public addSendMessageCallback(userId: string|number, callback: SendMessageCallback){
|
||||||
|
this.discussionManager.onSendMessageCallback(userId, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
get activatedDiscussion(){
|
||||||
|
return this.discussionManager.activatedDiscussion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setUserInputManager(userInputManager : UserInputManager){
|
||||||
|
this.discussionManager.setUserInputManager(userInputManager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mediaManager = new MediaManager();
|
export const mediaManager = new MediaManager();
|
||||||
|
@ -2,6 +2,7 @@ import * as SimplePeerNamespace from "simple-peer";
|
|||||||
import {mediaManager} from "./MediaManager";
|
import {mediaManager} from "./MediaManager";
|
||||||
import {TURN_SERVER, TURN_USER, TURN_PASSWORD} from "../Enum/EnvironmentVariable";
|
import {TURN_SERVER, TURN_USER, TURN_PASSWORD} from "../Enum/EnvironmentVariable";
|
||||||
import {RoomConnection} from "../Connexion/RoomConnection";
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
|
import {MESSAGE_TYPE_CONSTRAINT} from "./VideoPeer";
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
@ -148,6 +149,6 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
|
|
||||||
public stopPushingScreenSharingToRemoteUser(stream: MediaStream) {
|
public stopPushingScreenSharingToRemoteUser(stream: MediaStream) {
|
||||||
this.removeStream(stream);
|
this.removeStream(stream);
|
||||||
this.write(new Buffer(JSON.stringify({streamEnded: true})));
|
this.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, streamEnded: true})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
UpdatedLocalStreamCallback
|
UpdatedLocalStreamCallback
|
||||||
} from "./MediaManager";
|
} from "./MediaManager";
|
||||||
import {ScreenSharingPeer} from "./ScreenSharingPeer";
|
import {ScreenSharingPeer} from "./ScreenSharingPeer";
|
||||||
import {VideoPeer} from "./VideoPeer";
|
import {MESSAGE_TYPE_CONSTRAINT, MESSAGE_TYPE_MESSAGE, VideoPeer} from "./VideoPeer";
|
||||||
import {RoomConnection} from "../Connexion/RoomConnection";
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
|
|
||||||
export interface UserSimplePeerInterface{
|
export interface UserSimplePeerInterface{
|
||||||
@ -38,7 +38,7 @@ export class SimplePeer {
|
|||||||
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
||||||
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
|
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
|
||||||
|
|
||||||
constructor(private Connection: RoomConnection, private enableReporting: boolean) {
|
constructor(private Connection: RoomConnection, private enableReporting: boolean, private myName: string) {
|
||||||
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
|
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
|
||||||
this.sendLocalVideoStreamCallback = this.sendLocalVideoStream.bind(this);
|
this.sendLocalVideoStreamCallback = this.sendLocalVideoStream.bind(this);
|
||||||
this.sendLocalScreenSharingStreamCallback = this.sendLocalScreenSharingStream.bind(this);
|
this.sendLocalScreenSharingStreamCallback = this.sendLocalScreenSharingStream.bind(this);
|
||||||
@ -145,6 +145,12 @@ export class SimplePeer {
|
|||||||
mediaManager.addActiveVideo("" + user.userId, reportCallback, name);
|
mediaManager.addActiveVideo("" + user.userId, reportCallback, name);
|
||||||
|
|
||||||
const peer = new VideoPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
const peer = new VideoPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
||||||
|
|
||||||
|
//permit to send message
|
||||||
|
mediaManager.addSendMessageCallback(user.userId,(message: string) => {
|
||||||
|
peer.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_MESSAGE, name: this.myName.toUpperCase(), message: message})));
|
||||||
|
});
|
||||||
|
|
||||||
peer.toClose = false;
|
peer.toClose = false;
|
||||||
// When a connection is established to a video stream, and if a screen sharing is taking place,
|
// When a connection is established to a video stream, and if a screen sharing is taking place,
|
||||||
// the user sharing screen should also initiate a connection to the remote user!
|
// the user sharing screen should also initiate a connection to the remote user!
|
||||||
@ -318,7 +324,7 @@ export class SimplePeer {
|
|||||||
throw new Error('While adding media, cannot find user with ID ' + userId);
|
throw new Error('While adding media, cannot find user with ID ' + userId);
|
||||||
}
|
}
|
||||||
const localStream: MediaStream | null = mediaManager.localStream;
|
const localStream: MediaStream | null = mediaManager.localStream;
|
||||||
PeerConnection.write(new Buffer(JSON.stringify(mediaManager.constraintsMedia)));
|
PeerConnection.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, ...mediaManager.constraintsMedia})));
|
||||||
|
|
||||||
if(!localStream){
|
if(!localStream){
|
||||||
return;
|
return;
|
||||||
|
@ -5,6 +5,8 @@ import {RoomConnection} from "../Connexion/RoomConnection";
|
|||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
|
export const MESSAGE_TYPE_CONSTRAINT = 'constraint';
|
||||||
|
export const MESSAGE_TYPE_MESSAGE = 'message';
|
||||||
/**
|
/**
|
||||||
* A peer connection used to transmit video / audio signals between 2 peers.
|
* A peer connection used to transmit video / audio signals between 2 peers.
|
||||||
*/
|
*/
|
||||||
@ -78,19 +80,27 @@ export class VideoPeer extends Peer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.on('data', (chunk: Buffer) => {
|
this.on('data', (chunk: Buffer) => {
|
||||||
const constraint = JSON.parse(chunk.toString('utf8'));
|
const message = JSON.parse(chunk.toString('utf8'));
|
||||||
console.log("data", constraint);
|
console.log("data", message);
|
||||||
if (constraint.audio) {
|
|
||||||
mediaManager.enabledMicrophoneByUserId(this.userId);
|
if(message.type === MESSAGE_TYPE_CONSTRAINT) {
|
||||||
} else {
|
const constraint = message;
|
||||||
mediaManager.disabledMicrophoneByUserId(this.userId);
|
if (constraint.audio) {
|
||||||
|
mediaManager.enabledMicrophoneByUserId(this.userId);
|
||||||
|
} else {
|
||||||
|
mediaManager.disabledMicrophoneByUserId(this.userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraint.video || constraint.screen) {
|
||||||
|
mediaManager.enabledVideoByUserId(this.userId);
|
||||||
|
} else {
|
||||||
|
this.stream(undefined);
|
||||||
|
mediaManager.disabledVideoByUserId(this.userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constraint.video || constraint.screen) {
|
if(message.type === 'message') {
|
||||||
mediaManager.enabledVideoByUserId(this.userId);
|
mediaManager.addNewMessage(message.name, message.message);
|
||||||
} else {
|
|
||||||
this.stream(undefined);
|
|
||||||
mediaManager.disabledVideoByUserId(this.userId);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -163,7 +173,7 @@ export class VideoPeer extends Peer {
|
|||||||
private pushVideoToRemoteUser() {
|
private pushVideoToRemoteUser() {
|
||||||
try {
|
try {
|
||||||
const localStream: MediaStream | null = mediaManager.localStream;
|
const localStream: MediaStream | null = mediaManager.localStream;
|
||||||
this.write(new Buffer(JSON.stringify(mediaManager.constraintsMedia)));
|
this.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, ...mediaManager.constraintsMedia})));
|
||||||
|
|
||||||
if(!localStream){
|
if(!localStream){
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user