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's alter browser history
let path = this.room.id; let path = this.room.id;
if (this.room.hash) { if (this.room.hash) {
path += '#'+this.room.hash; path += '#' + this.room.hash;
} }
window.history.pushState({}, 'WorkAdventure', path); 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. * @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 { update(time: number, delta: number) : void {
mediaManager.setLastUpdateScene();
this.currentTick = time; this.currentTick = time;
this.CurrentPlayer.moveUser(delta); this.CurrentPlayer.moveUser(delta);

View file

@ -40,6 +40,12 @@ export class MediaManager {
private cinemaBtn: HTMLDivElement; private cinemaBtn: HTMLDivElement;
private monitorBtn: HTMLDivElement; private monitorBtn: HTMLDivElement;
private previousConstraint : MediaStreamConstraints;
private focused : boolean = true;
private lastUpdateScene : Date = new Date();
private setTimeOutlastUpdateScene? : NodeJS.Timeout;
private discussionManager: DiscussionManager; private discussionManager: DiscussionManager;
private userInputManager?: UserInputManager; private userInputManager?: UserInputManager;
@ -100,9 +106,35 @@ export class MediaManager {
//update tracking //update tracking
}); });
this.previousConstraint = JSON.parse(JSON.stringify(this.constraintsMedia));
this.pingCameraStatus();
this.checkActiveUser();
this.discussionManager = new DiscussionManager(this,''); 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 { public onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
this.updatedLocalStreamCallBacks.add(callback); this.updatedLocalStreamCallBacks.add(callback);
} }
@ -160,12 +192,7 @@ export class MediaManager {
} }
public enableCamera() { public enableCamera() {
if(!this.hasCamera){ this.enableCameraStyle();
return;
}
this.cinemaClose.style.display = "none";
this.cinemaBtn.classList.remove("disabled");
this.cinema.style.display = "block";
this.constraintsMedia.video = videoConstraint; this.constraintsMedia.video = videoConstraint;
this.getCamera().then((stream: MediaStream) => { this.getCamera().then((stream: MediaStream) => {
this.triggerUpdatedLocalStreamCallbacks(stream); this.triggerUpdatedLocalStreamCallbacks(stream);
@ -173,7 +200,8 @@ export class MediaManager {
} }
public async disableCamera() { public async disableCamera() {
this.disabledCameraView(); this.disableCameraStyle();
if (this.constraintsMedia.audio !== false) { if (this.constraintsMedia.audio !== false) {
const stream = await this.getCamera(); const stream = await this.getCamera();
this.triggerUpdatedLocalStreamCallbacks(stream); 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() { public enableMicrophone() {
this.microphoneClose.style.display = "none"; this.enableMicrophoneStyle();
this.microphone.style.display = "block";
this.microphoneBtn.classList.remove("disabled");
this.constraintsMedia.audio = true; this.constraintsMedia.audio = true;
this.getCamera().then((stream) => { this.getCamera().then((stream) => {
@ -203,10 +220,7 @@ export class MediaManager {
} }
public async disableMicrophone() { public async disableMicrophone() {
this.microphoneClose.style.display = "block"; this.disableMicrophoneStyle();
this.microphone.style.display = "none";
this.microphoneBtn.classList.add("disabled");
this.constraintsMedia.audio = false;
this.stopMicrophone(); this.stopMicrophone();
if (this.constraintsMedia.video !== false) { 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() { private enableScreenSharing() {
this.monitorClose.style.display = "none"; this.monitorClose.style.display = "none";
this.monitor.style.display = "block"; this.monitor.style.display = "block";
@ -299,7 +359,7 @@ export class MediaManager {
return this.getLocalStream().catch(() => { return this.getLocalStream().catch(() => {
console.info('Error get camera, trying with video option at null'); console.info('Error get camera, trying with video option at null');
this.disabledCameraView(); this.disableCameraStyle();
return this.getLocalStream().then((stream : MediaStream) => { return this.getLocalStream().then((stream : MediaStream) => {
this.hasCamera = false; this.hasCamera = false;
return stream; return stream;
@ -621,6 +681,17 @@ export class MediaManager {
callback(); 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){ public addNewMessage(name: string, message: string, isMe: boolean = false){
this.discussionManager.addMessage(name, message, isMe); this.discussionManager.addMessage(name, message, isMe);
@ -642,6 +713,22 @@ export class MediaManager {
public setUserInputManager(userInputManager : UserInputManager){ public setUserInputManager(userInputManager : UserInputManager){
this.discussionManager.setUserInputManager(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(); 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('js', new Date());
gtag('config', 'UA-10196481-11'); gtag('config', 'UA-10196481-11');
if (window.location.host.endsWith("localhost")){
window['ga-disable-UA-10196481-11'] = true;
}
</script> </script>
<link rel="apple-touch-icon" sizes="57x57" href="static/images/favicons/apple-icon-57x57.png"> <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"> <link rel="apple-touch-icon" sizes="60x60" href="static/images/favicons/apple-icon-60x60.png">
@ -82,22 +85,32 @@
</div> </div>
<div class="col-2 col-md-6"> <div class="col-2 col-md-6">
<div class="social-links"> <div class="social-links">
<span class="share-title">Share your experience</span> <a href="https://www.facebook.com/workadventurebytcm">
<a onclick="shareFB()"> <img class="social-image" src="static/images/facebook_bw.png" />
<img class="social-image" src="static/images/facebook.png" />
</a> </a>
<a onclick="shareLI()"> <a href="https://www.linkedin.com/company/workadventure-by-tcm">
<img class="social-image" src="static/images/linkedin.png" /> <img class="social-image" src="static/images/linkedin_bw.png" />
</a> </a>
<a onclick="shareTW()"> <a href="https://twitter.com/Workadventure_">
<img class="social-image" src="static/images/twitter.png" /> <img class="social-image" src="static/images/twitter_bw.png" />
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div class="title title-main text-center"> <div class="title title-main text-center">
<h1>Your workplace<br/>but better</h1> <h1>Meet your teammates</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> <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>
<div class="row buttons-row justify-content-md-center pt-5"> <div class="row buttons-row justify-content-md-center pt-5">
<div class="col col-lg-3"> <div class="col col-lg-3">
@ -107,7 +120,7 @@
</div> </div>
<div class="col col-lg-3"> <div class="col col-lg-3">
<a class="custom-link play" target="_BLANK" onclick="startGame()" title="WORK ONLINE"> <a class="custom-link play" target="_BLANK" onclick="startGame()" title="WORK ONLINE">
WORK ONLINE TRY IT NOW!
</a> </a>
</div> </div>
</div> </div>
@ -158,7 +171,7 @@
<p>Click the button below to come and say hi!</p> <p>Click the button below to come and say hi!</p>
<p class="bubble-action"><span onclick="startGame()"> <p class="bubble-action"><span onclick="startGame()">
<img src="static/images/playicon.png" /> <img src="static/images/playicon.png" />
START IN PUBLIC MODE TRY IT NOW !
</span></p> </span></p>
</div> </div>
</div> </div>
@ -166,10 +179,11 @@
<div> <div>
<p>You can also create a private room with your friends or your team ! </p> <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-legend">To try, press button work in private</p>
<p class="bubble-action"><a href="/choose-map.html"> <p class="bubble-action">
<img src="static/images/playicon.png" /> <a href="/choose-map.html">
START WORKING IN PRIVATE <img src="static/images/playicon.png" />
</a></p> CHOOSE YOU OWN MAP
</a>
<p> <p>
Dont forget to activate your mic and camera, lets play Dont forget to activate your mic and camera, lets play
</p> </p>
@ -179,7 +193,6 @@
<img src="static/images/story/character-walk-right.gif" style="display:none;" /> <img src="static/images/story/character-walk-right.gif" style="display:none;" />
</section> </section>
<script> <script>
gsap.to(".title-main", { gsap.to(".title-main", {
//y:-1000, //y:-1000,
scale: 0, scale: 0,
@ -308,6 +321,57 @@
</div> </div>
</div> </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> </div>
<div class="section bg-white"> <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": { "dot-prop": {
"version": "4.2.0", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"is-obj": "^1.0.0" "is-obj": "^1.0.0"

View file

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