Merge branch 'develop' into firefox-error-jitsi

# Conflicts:
#	front/src/WebRtc/MediaManager.ts
This commit is contained in:
Gregoire Parant 2020-11-23 15:46:19 +01:00
commit 26cfae7136
10 changed files with 216 additions and 69 deletions

View file

@ -317,7 +317,7 @@ export class GameScene extends ResizableScene implements CenterListener {
// Let's alter browser history
let path = this.room.id;
if (this.room.hash) {
path += '#'+this.room.hash;
path += '#' + this.room.hash;
}
window.history.pushState({}, 'WorkAdventure', path);
@ -906,6 +906,7 @@ export class GameScene extends ResizableScene implements CenterListener {
* @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update(time: number, delta: number) : void {
mediaManager.setLastUpdateScene();
this.currentTick = time;
this.CurrentPlayer.moveUser(delta);

View file

@ -40,6 +40,12 @@ export class MediaManager {
private cinemaBtn: HTMLDivElement;
private monitorBtn: HTMLDivElement;
private previousConstraint : MediaStreamConstraints;
private focused : boolean = true;
private lastUpdateScene : Date = new Date();
private setTimeOutlastUpdateScene? : NodeJS.Timeout;
private discussionManager: DiscussionManager;
private userInputManager?: UserInputManager;
@ -100,9 +106,35 @@ export class MediaManager {
//update tracking
});
this.previousConstraint = JSON.parse(JSON.stringify(this.constraintsMedia));
this.pingCameraStatus();
this.checkActiveUser();
this.discussionManager = new DiscussionManager(this,'');
}
public setLastUpdateScene(){
this.lastUpdateScene = new Date();
}
public blurCamera() {
if(!this.focused){
return;
}
this.focused = false;
this.previousConstraint = JSON.parse(JSON.stringify(this.constraintsMedia));
this.disableCamera();
}
public focusCamera() {
if(this.focused){
return;
}
this.focused = true;
this.applyPreviousConfig();
}
public onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
this.updatedLocalStreamCallBacks.add(callback);
}
@ -160,12 +192,7 @@ export class MediaManager {
}
public enableCamera() {
if(!this.hasCamera){
return;
}
this.cinemaClose.style.display = "none";
this.cinemaBtn.classList.remove("disabled");
this.cinema.style.display = "block";
this.enableCameraStyle();
this.constraintsMedia.video = videoConstraint;
this.getCamera().then((stream: MediaStream) => {
this.triggerUpdatedLocalStreamCallbacks(stream);
@ -173,7 +200,8 @@ export class MediaManager {
}
public async disableCamera() {
this.disabledCameraView();
this.disableCameraStyle();
if (this.constraintsMedia.audio !== false) {
const stream = await this.getCamera();
this.triggerUpdatedLocalStreamCallbacks(stream);
@ -182,19 +210,8 @@ export class MediaManager {
}
}
private disabledCameraView(){
this.cinemaClose.style.display = "block";
this.cinema.style.display = "none";
this.cinemaBtn.classList.add("disabled");
this.constraintsMedia.video = false;
this.myCamVideo.srcObject = null;
this.stopCamera();
}
public enableMicrophone() {
this.microphoneClose.style.display = "none";
this.microphone.style.display = "block";
this.microphoneBtn.classList.remove("disabled");
this.enableMicrophoneStyle();
this.constraintsMedia.audio = true;
this.getCamera().then((stream) => {
@ -203,10 +220,7 @@ export class MediaManager {
}
public async disableMicrophone() {
this.microphoneClose.style.display = "block";
this.microphone.style.display = "none";
this.microphoneBtn.classList.add("disabled");
this.constraintsMedia.audio = false;
this.disableMicrophoneStyle();
this.stopMicrophone();
if (this.constraintsMedia.video !== false) {
@ -217,6 +231,52 @@ export class MediaManager {
}
}
private applyPreviousConfig() {
this.constraintsMedia = this.previousConstraint;
if(!this.constraintsMedia.video){
this.disableCameraStyle();
}else{
this.enableCameraStyle();
}
if(!this.constraintsMedia.audio){
this.disableMicrophoneStyle()
}else{
this.enableMicrophoneStyle()
}
this.getCamera().then((stream: MediaStream) => {
this.triggerUpdatedLocalStreamCallbacks(stream);
});
}
private enableCameraStyle(){
this.cinemaClose.style.display = "none";
this.cinemaBtn.classList.remove("disabled");
this.cinema.style.display = "block";
}
private disableCameraStyle(){
this.cinemaClose.style.display = "block";
this.cinema.style.display = "none";
this.cinemaBtn.classList.add("disabled");
this.constraintsMedia.video = false;
this.myCamVideo.srcObject = null;
this.stopCamera();
}
private enableMicrophoneStyle(){
this.microphoneClose.style.display = "none";
this.microphone.style.display = "block";
this.microphoneBtn.classList.remove("disabled");
}
private disableMicrophoneStyle(){
this.microphoneClose.style.display = "block";
this.microphone.style.display = "none";
this.microphoneBtn.classList.add("disabled");
this.constraintsMedia.audio = false;
}
private enableScreenSharing() {
this.monitorClose.style.display = "none";
this.monitor.style.display = "block";
@ -299,7 +359,7 @@ export class MediaManager {
return this.getLocalStream().catch(() => {
console.info('Error get camera, trying with video option at null');
this.disabledCameraView();
this.disableCameraStyle();
return this.getLocalStream().then((stream : MediaStream) => {
this.hasCamera = false;
return stream;
@ -621,6 +681,17 @@ export class MediaManager {
callback();
}
}
/**
* For some reasons, the microphone muted icon or the stream is not always up to date.
* Here, every 30 seconds, we are "reseting" the streams and sending again the constraints to the other peers via the data channel again (see SimplePeer::pushVideoToRemoteUser)
**/
private pingCameraStatus(){
setTimeout(() => {
console.log('ping camera status');
this.triggerUpdatedLocalStreamCallbacks(this.localStream);
this.pingCameraStatus();
}, 30000);
}
public addNewMessage(name: string, message: string, isMe: boolean = false){
this.discussionManager.addMessage(name, message, isMe);
@ -642,6 +713,22 @@ export class MediaManager {
public setUserInputManager(userInputManager : UserInputManager){
this.discussionManager.setUserInputManager(userInputManager);
}
//check if user is active
private checkActiveUser(){
if(this.setTimeOutlastUpdateScene){
clearTimeout(this.setTimeOutlastUpdateScene);
}
this.setTimeOutlastUpdateScene = setTimeout(() => {
const now = new Date();
//if last update is more of 10 sec
if( (now.getTime() - this.lastUpdateScene.getTime()) > 10000) {
this.blurCamera();
}else{
this.focusCamera();
}
this.checkActiveUser();
}, this.focused ? 10000 : 1000);
}
}
export const mediaManager = new MediaManager();

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -10,6 +10,9 @@
gtag('js', new Date());
gtag('config', 'UA-10196481-11');
if (window.location.host.endsWith("localhost")){
window['ga-disable-UA-10196481-11'] = true;
}
</script>
<link rel="apple-touch-icon" sizes="57x57" href="static/images/favicons/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="static/images/favicons/apple-icon-60x60.png">
@ -82,22 +85,32 @@
</div>
<div class="col-2 col-md-6">
<div class="social-links">
<span class="share-title">Share your experience</span>
<a onclick="shareFB()">
<img class="social-image" src="static/images/facebook.png" />
<a href="https://www.facebook.com/workadventurebytcm">
<img class="social-image" src="static/images/facebook_bw.png" />
</a>
<a onclick="shareLI()">
<img class="social-image" src="static/images/linkedin.png" />
<a href="https://www.linkedin.com/company/workadventure-by-tcm">
<img class="social-image" src="static/images/linkedin_bw.png" />
</a>
<a onclick="shareTW()">
<img class="social-image" src="static/images/twitter.png" />
<a href="https://twitter.com/Workadventure_">
<img class="social-image" src="static/images/twitter_bw.png" />
</a>
</div>
</div>
</div>
<div class="title title-main text-center">
<h1>Your workplace<br/>but better</h1>
<h3>You are impatient to discover this new world? Click on "Work online" and meet new people or share this adventure with your colleagues and friends by clicking on "Work in private"</h3>
<h1>Meet your teammates</h1>
<h3>
WorkAdventure preserves your social interaction while COVID is still out there.
</h3>
<h3>
Stay connected with your teamworkers, by creating your own online workspace to work remotely.
</h3>
<h3>
Stay connected with your clients by providing a dedicated digital place to organize meetings, workshops.
</h3>
<h3>
Stay connected with your future collaborators by organizing online event.
</h3>
</div>
<div class="row buttons-row justify-content-md-center pt-5">
<div class="col col-lg-3">
@ -107,7 +120,7 @@
</div>
<div class="col col-lg-3">
<a class="custom-link play" target="_BLANK" onclick="startGame()" title="WORK ONLINE">
WORK ONLINE
TRY IT NOW!
</a>
</div>
</div>
@ -158,7 +171,7 @@
<p>Click the button below to come and say hi!</p>
<p class="bubble-action"><span onclick="startGame()">
<img src="static/images/playicon.png" />
START IN PUBLIC MODE
TRY IT NOW !
</span></p>
</div>
</div>
@ -166,10 +179,11 @@
<div>
<p>You can also create a private room with your friends or your team ! </p>
<p class="bubble-legend">To try, press button work in private</p>
<p class="bubble-action"><a href="/choose-map.html">
<img src="static/images/playicon.png" />
START WORKING IN PRIVATE
</a></p>
<p class="bubble-action">
<a href="/choose-map.html">
<img src="static/images/playicon.png" />
CHOOSE YOU OWN MAP
</a>
<p>
Dont forget to activate your mic and camera, lets play
</p>
@ -179,7 +193,6 @@
<img src="static/images/story/character-walk-right.gif" style="display:none;" />
</section>
<script>
gsap.to(".title-main", {
//y:-1000,
scale: 0,
@ -308,6 +321,57 @@
</div>
</div>
</div>
<div class="row mt-5">
<div class="col-lg-9 text-right">
<p class="py-3 font-weight-bold" style="font-size: 1.25rem">
Want to try Woradventure with your team mates or friends?
</p>
</div>
<div class="col-lg-3">
<a class="custom-link relative" href="/choose-map.html" title="WORK IN PRIVATE">
GET STARTED!
</a>
</div>
</div>
<div class="social-links text-center pt-2 pb-4">
<span class="share-title">... and if you liked woradventure, share your experience!</span>
<a onclick="shareFB()">
<img class="social-image" src="static/images/facebook.png" />
</a>
<a onclick="shareLI()">
<img class="social-image" src="static/images/linkedin.png" />
</a>
<a onclick="shareTW()">
<img class="social-image" src="static/images/twitter.png" />
</a>
</div>
</div>
</div>
<div class="section bg-white text-center pt-5">
<div class="container-fluid container-lg">
<div class="row justify-content-md-center">
<div class="col-12 col-md-12 text-center">
<h3>WORKADVENTURE'S USE CASES</h3>
</div>
<p>
Workadventure is an intuitive and fun solution to professional issues:
</p>
<ul class="text-left">
<li>
Work in a remote way within a team,
</li>
<li>
Create an event (even a big one),
</li>
<li>
Stay connected and increase social interactions...
</li>
</ul>
<p>
Feel free to contact us if you need a specific map, need a dedicated admin console or any
support (for instance a large number of connexions) : <a href="mailto:workadventure@thecodingmachine.com" target="_blank">workadventure@thecodingmachine.com</a>
</p>
</div>
</div>
</div>
<div class="section bg-white">

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -2251,9 +2251,9 @@
}
},
"dot-prop": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
"integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
"dev": true,
"requires": {
"is-obj": "^1.0.0"

View file

@ -80,11 +80,17 @@ header {
h1 {
font-family: 'Karmatic Arcade';
font-size: 2.75rem;
margin-bottom: 1.25rem;
margin-bottom: 2rem;
}
h3 {
min-height: 200px;
padding: 1rem;
text-align: left;
padding: 1rem 0 0 1rem;
&:before{
content: ">";
position: absolute;
left: -10px;
}
}
@include media-breakpoint-down(xs) {
h3 {
@ -152,7 +158,6 @@ header {
text-align: center;
z-index: 2;
transition: all .1s cubic-bezier(0.000, -0.600, 1.000, 1.650); /* custom */
//transition-timing-function: cubic-bezier(0.000, -0.600, 1.000, 1.650); /* custom */
@include media-breakpoint-down(sm) {
display: none;
}
@ -171,33 +176,23 @@ header {
background-image: url('../images/btn-bg-3.png');
cursor: pointer;
}
&.start {
/*padding-left: 55px;*/
&:before {
/*content: "";
position: absolute;
background: url('../images/playicon.png') no-repeat;
height: 20px;
width: 21px;
left: 36px;
top: 23px;*/
}
}
&.light{
background-image: url('../images/btn-bg-light.png');
}
/*&::after{
content: "";
position: absolute;
background-size: 60%;
width: 100%;
height: 100%;
}*/
&.relative{
position: relative;
left: auto;
right: auto;
bottom: auto;
}
}
.social-links a {
cursor: pointer;
&:hover{
text-decoration: none;
}
}
img{
@ -388,7 +383,7 @@ img{
}
}
&.how-to{
padding: 6.25rem 0;
padding: 6.25rem 0 0;
background: url('../images/bg-briques.jpg') repeat-x bottom;
.desktop-only {
padding: 0 1.25rem 4rem;