diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html
index 062622b8..c4763b6e 100644
--- a/front/dist/index.tmpl.html
+++ b/front/dist/index.tmpl.html
@@ -48,20 +48,27 @@
-
-
-
+
+
+
-
diff --git a/front/dist/resources/html/EnableCameraScene.html b/front/dist/resources/html/EnableCameraScene.html
index 0763d7dd..2dda6cc1 100644
--- a/front/dist/resources/html/EnableCameraScene.html
+++ b/front/dist/resources/html/EnableCameraScene.html
@@ -48,7 +48,7 @@
text-align: center;
margin: 0;
position: absolute;
- top: 44vh;
+ top: 40vh;
width: 100%;
}
#enableCameraScene button {
diff --git a/front/dist/resources/html/helpCameraSettings.html b/front/dist/resources/html/helpCameraSettings.html
index a04668fe..ee8e16e2 100644
--- a/front/dist/resources/html/helpCameraSettings.html
+++ b/front/dist/resources/html/helpCameraSettings.html
@@ -60,6 +60,9 @@
font-size: 8px;
margin: 0px 20px;
}
+ #helpCameraSettings section p a{
+ font-size: 8px;
+ }
#helpCameraSettings section p.err{
color: #ff0000;
}
@@ -95,6 +98,10 @@
If you prefer to continue without allowing camera and microphone access, click on Continue
+
+
Refresh
diff --git a/front/dist/resources/style/mobile-style.scss b/front/dist/resources/style/mobile-style.scss
index d9ed4b2e..21753ebd 100644
--- a/front/dist/resources/style/mobile-style.scss
+++ b/front/dist/resources/style/mobile-style.scss
@@ -23,27 +23,17 @@
}
.btn-cam-action {
+ min-width: 150px;
+
&:hover{
transform: translateY(20px);
}
div {
+ margin: 0 1%;
&:hover {
background-color: #666;
}
-
- bottom: 30px;
-
- &.btn-micro {
- right: 0;
- }
-
- &.btn-monitor {
- right: 130px;
- }
-
- &.btn-video {
- right: 65px;
- }
+ margin-bottom: 30px;
}
}
diff --git a/front/dist/resources/style/style.css b/front/dist/resources/style/style.css
index 97e363f9..213b00f2 100644
--- a/front/dist/resources/style/style.css
+++ b/front/dist/resources/style/style.css
@@ -98,7 +98,7 @@ body .message-info.warning{
}
.video-container button.report:hover {
- width: 150px;
+ width: 160px;
}
.video-container button.report img{
@@ -126,6 +126,7 @@ body .message-info.warning{
.video-container video{
height: 100%;
+ cursor: url('/resources/logos/cursor_pointer.png'), pointer;
}
.video-container video:focus{
@@ -141,7 +142,7 @@ body .message-info.warning{
right: 15px;
bottom: 30px;
border-radius: 15px 15px 15px 15px;
- max-height: 200px;
+ max-height: 20%;
}
video#myCamVideo{
@@ -153,19 +154,60 @@ video#myCamVideo{
/*height: 113px;*/
}
+.sound-progress{
+ display: none;
+ position: absolute;
+ right: 14px;
+ top: calc(50% - 5px);
+}
+.sound-progress.active{
+ display: table-column;
+}
+.sound-progress span{
+ position: absolute;
+ color: black;
+ background-color: #00000020;
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+}
+.sound-progress span.active{
+ background-color: #00c3ff66
+}
+.sound-progress span:nth-child(1){
+ top: calc(50% + 20px);
+}
+.sound-progress span:nth-child(2){
+ top: calc(50% + 10px);
+}
+.sound-progress span:nth-child(3){
+ top: calc(50% - 0px);
+}
+.sound-progress span:nth-child(4){
+ top: calc(50% - 10px);
+}
+.sound-progress span:nth-child(5){
+ top: calc(50% - 20px);
+}
.btn-cam-action {
pointer-events: all;
position: absolute;
- bottom: 0px;
- right: 0px;
- width: 450px;
- height: 150px;
+ display: inline-flex;
+ bottom: 10px;
+ right: 15px;
+ width: 15vw;
+ height: 40px;
+ text-align: center;
+ align-content: center;
+ align-items: center;
+ justify-content: center;
+ justify-items: center;
}
/*btn animation*/
.btn-cam-action div{
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
- position: absolute;
+ /*position: absolute;*/
border: solid 0px black;
width: 44px;
height: 44px;
@@ -174,7 +216,8 @@ video#myCamVideo{
border-radius: 48px;
transform: translateY(20px);
transition-timing-function: ease-in-out;
- bottom: 20px;
+ margin-bottom: 20px;
+ margin: 0 4%;
}
.btn-cam-action div.disabled {
background: #d75555;
@@ -193,17 +236,17 @@ video#myCamVideo{
.btn-micro{
pointer-events: auto;
transition: all .3s;
- right: 44px;
+ /*right: 44px;*/
}
.btn-video{
pointer-events: auto;
transition: all .25s;
- right: 134px;
+ /*right: 134px;*/
}
.btn-monitor{
pointer-events: auto;
transition: all .2s;
- right: 224px;
+ /*right: 224px;*/
}
.btn-copy{
pointer-events: auto;
@@ -497,7 +540,7 @@ input[type=range]:focus::-ms-fill-upper {
position: absolute;
width: 100%;
height: 100%;
- pointer-events: none;
+ pointer-events: all;
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
}
@@ -533,7 +576,7 @@ input[type=range]:focus::-ms-fill-upper {
.sidebar {
flex: 0 0 25%;
display: flex;
- pointer-events: none;
+ pointer-events: all;
}
.sidebar > div {
@@ -547,6 +590,10 @@ input[type=range]:focus::-ms-fill-upper {
margin: 0%;
}
+.sidebar > div video {
+ cursor: url('/resources/logos/cursor_pointer.png'), pointer;
+}
+
/* Let's make sure videos are vertically centered if they need to be cropped */
.media-container {
display: flex;
@@ -1111,17 +1158,34 @@ div.action{
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
+div.action.info,
+div.action.warning,
+div.action.danger{
+ transition: all 1s ease;
+ animation: mymove 1s;
+ animation-iteration-count: infinite;
+ animation-timing-function: ease-in-out;
+}
div.action p.action-body{
+ cursor: url('/resources/logos/cursor_pointer.png'), pointer;
padding: 10px;
background-color: #2d2d2dba;
color: #fff;
font-size: 14px;
font-weight: 500;
text-align: center;
- max-width: 250px;
- margin-left: calc(50% - 125px);
+ max-width: 350px;
+ margin-left: calc(50% - 175px);
border-radius: 15px;
}
+div.action.warning p.action-body{
+ background-color: #ff9800eb;
+ color: #000;
+}
+div.action.danger p.action-body{
+ background-color: #da0000e3;
+ color: #000;
+}
.popUpElement{
font-family: 'Press Start 2P';
text-align: left;
diff --git a/front/dist/static/images/favicons/manifest.json b/front/dist/static/images/favicons/manifest.json
index 013d4a6a..47ad9377 100644
--- a/front/dist/static/images/favicons/manifest.json
+++ b/front/dist/static/images/favicons/manifest.json
@@ -1,41 +1,149 @@
{
- "name": "App",
- "icons": [
- {
- "src": "\/android-icon-36x36.png",
- "sizes": "36x36",
- "type": "image\/png",
- "density": "0.75"
- },
- {
- "src": "\/android-icon-48x48.png",
- "sizes": "48x48",
- "type": "image\/png",
- "density": "1.0"
- },
- {
- "src": "\/android-icon-72x72.png",
- "sizes": "72x72",
- "type": "image\/png",
- "density": "1.5"
- },
- {
- "src": "\/android-icon-96x96.png",
- "sizes": "96x96",
- "type": "image\/png",
- "density": "2.0"
- },
- {
- "src": "\/android-icon-144x144.png",
- "sizes": "144x144",
- "type": "image\/png",
- "density": "3.0"
- },
- {
- "src": "\/android-icon-192x192.png",
- "sizes": "192x192",
- "type": "image\/png",
- "density": "4.0"
- }
- ]
+ "short_name": "WA",
+ "name": "WorkAdventure",
+ "icons": [
+ {
+ "src": "/static/images/favicons/apple-icon-57x57.png",
+ "sizes": "57x57",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-60x60.png",
+ "sizes": "60x60",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-76x76.png",
+ "sizes": "76x76",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-114x114.png",
+ "sizes": "114x114",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-120x120.png",
+ "sizes": "120x120",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-152x152.png",
+ "sizes": "152x152",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/apple-icon-180x180.png",
+ "sizes": "180x180",
+ "type": "image\/png"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-36x36.png",
+ "sizes": "36x36",
+ "type": "image\/png",
+ "density": "0.75"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-48x48.png",
+ "sizes": "48x48",
+ "type": "image\/png",
+ "density": "1.0"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+
+ {
+ "src": "/static/images/favicons/favicon-16x16.png",
+ "sizes": "16x16",
+ "type": "image\/png",
+ "density": "1"
+ },
+ {
+ "src": "/static/images/favicons/favicon-32x32.png",
+ "sizes": "32x32",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+ {
+ "src": "/static/images/favicons/favicon-96x96.png",
+ "sizes": "96x96",
+ "type": "image\/png",
+ "density": "2.0"
+ },
+
+ {
+ "src": "/static/images/favicons/android-icon-36x36.png",
+ "sizes": "36x36",
+ "type": "image\/png",
+ "density": "1"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-48x48.png",
+ "sizes": "48x48",
+ "type": "image\/png",
+ "density": "1"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-96x96.png",
+ "sizes": "96x96",
+ "type": "image\/png",
+ "density": "2.0"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image\/png",
+ "density": "3.0"
+ },
+ {
+ "src": "/static/images/favicons/android-icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image\/png",
+ "density": "4.0"
+ }
+ ],
+ "start_url": "/",
+ "background_color": "#000000",
+ "display_override": ["window-control-overlay", "minimal-ui"],
+ "display": "standalone",
+ "scope": "/",
+ "theme_color": "#000000",
+ "shortcuts": [
+ {
+ "name": "WorkAdventures",
+ "short_name": "WA",
+ "description": "WorkAdventure application",
+ "url": "/",
+ "icons": [{ "src": "/static/images/favicons/android-icon-192x192.png", "sizes": "192x192" }]
+ }
+ ],
+ "description": "WorkAdventure application",
+ "screenshots": [],
+ "related_applications": [{
+ "platform": "web",
+ "url": "https://workadventu.re"
+ }, {
+ "platform": "play",
+ "url": "https://play.workadventu.re"
+ }]
}
\ No newline at end of file
diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts
index da10a8ca..6047d430 100644
--- a/front/src/Phaser/Game/GameManager.ts
+++ b/front/src/Phaser/Game/GameManager.ts
@@ -89,10 +89,7 @@ export class GameManager {
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
scenePlugin.launch(MenuSceneName);
-
- if (!localUserStore.getHelpCameraSettingsShown()) {
- scenePlugin.launch(HelpCameraSettingsSceneName);//700
- }
+ scenePlugin.launch(HelpCameraSettingsSceneName);//700
}
public gameSceneIsCreated(scene: GameScene) {
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index 71d7868f..c433ed0f 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -1200,7 +1200,7 @@ ${escapedMessage}
* @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();
+ mediaManager.updateScene();
this.currentTick = time;
this.CurrentPlayer.moveUser(delta);
diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts
index 603da7b9..917dd44b 100644
--- a/front/src/Phaser/Login/EnableCameraScene.ts
+++ b/front/src/Phaser/Login/EnableCameraScene.ts
@@ -247,8 +247,7 @@ export class EnableCameraScene extends Phaser.Scene {
update(time: number, delta: number): void {
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
-
- mediaManager.setLastUpdateScene();
+ mediaManager.updateScene();
const middleX = this.getMiddleX();
this.tweens.add({
diff --git a/front/src/Phaser/Menu/HelpCameraSettingsScene.ts b/front/src/Phaser/Menu/HelpCameraSettingsScene.ts
index cc6f40c6..f7dd5c2a 100644
--- a/front/src/Phaser/Menu/HelpCameraSettingsScene.ts
+++ b/front/src/Phaser/Menu/HelpCameraSettingsScene.ts
@@ -21,7 +21,6 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
}
create(){
- localUserStore.setHelpCameraSettingsShown();
this.createHelpCameraSettings();
}
@@ -31,6 +30,9 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
this.helpCameraSettingsElement.addListener('click');
this.helpCameraSettingsElement.on('click', (event:MouseEvent) => {
+ if((event?.target as HTMLInputElement).id === 'mailto') {
+ return;
+ }
event.preventDefault();
if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') {
window.location.reload();
@@ -39,18 +41,27 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
}
});
- if(!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video){
+ if(!localUserStore.getHelpCameraSettingsShown() && (!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video)){
this.openHelpCameraSettingsOpened();
+ localUserStore.setHelpCameraSettingsShown();
}
+
+ mediaManager.setHelpCameraSettingsCallBack(() => {
+ this.openHelpCameraSettingsOpened();
+ });
}
private openHelpCameraSettingsOpened(): void{
HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none';
this.helpCameraSettingsOpened = true;
- if(window.navigator.userAgent.includes('Firefox')){
- HtmlUtils.getElementByIdOrFail('browserHelpSetting').innerHTML ='';
- }else if(window.navigator.userAgent.includes('Chrome')){
- HtmlUtils.getElementByIdOrFail('browserHelpSetting').innerHTML ='';
+ try{
+ if(window.navigator.userAgent.includes('Firefox')){
+ HtmlUtils.getElementByIdOrFail('browserHelpSetting').innerHTML ='';
+ }else if(window.navigator.userAgent.includes('Chrome')){
+ HtmlUtils.getElementByIdOrFail('browserHelpSetting').innerHTML ='';
+ }
+ }catch(err) {
+ console.error('openHelpCameraSettingsOpened => getElementByIdOrFail => error', err);
}
const middleY = this.getMiddleY();
const middleX = this.getMiddleX();
@@ -66,13 +77,13 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
private closeHelpCameraSettingsOpened(): void{
const middleX = this.getMiddleX();
- const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
+ /*const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
helpCameraSettingsInfo.innerText = '';
- helpCameraSettingsInfo.style.display = 'none';
+ helpCameraSettingsInfo.style.display = 'none';*/
this.helpCameraSettingsOpened = false;
this.tweens.add({
targets: this.helpCameraSettingsElement,
- y: -400,
+ y: -1000,
x: middleX,
duration: 1000,
ease: 'Power3',
@@ -89,15 +100,17 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
}
update(time: number, delta: number): void {
- const middleX = this.getMiddleX();
- const middleY = this.getMiddleY();
- this.tweens.add({
- targets: this.helpCameraSettingsElement,
- x: middleX,
- y: middleY,
- duration: 1000,
- ease: 'Power3'
- });
+ if(this.helpCameraSettingsOpened){
+ const middleX = this.getMiddleX();
+ const middleY = this.getMiddleY();
+ this.tweens.add({
+ targets: this.helpCameraSettingsElement,
+ x: middleX,
+ y: middleY,
+ duration: 1000,
+ ease: 'Power3'
+ });
+ }
}
public onResize(ev: UIEvent): void {
diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts
index a0b805d4..eed12333 100644
--- a/front/src/WebRtc/LayoutManager.ts
+++ b/front/src/WebRtc/LayoutManager.ts
@@ -346,7 +346,7 @@ class LayoutManager {
userInputManager.addSpaceEventListner(callBack);
}
- public removeActionButton(id: string, userInputManager: UserInputManager){
+ public removeActionButton(id: string, userInputManager?: UserInputManager){
//delete previous element
const previousDiv = this.actionButtonInformation.get(id);
if(previousDiv){
@@ -354,10 +354,45 @@ class LayoutManager {
this.actionButtonInformation.delete(id);
}
const previousEventCallback = this.actionButtonTrigger.get(id);
- if(previousEventCallback){
+ if(previousEventCallback && userInputManager){
userInputManager.removeSpaceEventListner(previousEventCallback);
}
}
+
+ public addInformation(id: string, text: string, callBack?: Function, userInputManager?: UserInputManager){
+ //delete previous element
+ for ( const [key, value] of this.actionButtonInformation ) {
+ this.removeActionButton(key, userInputManager);
+ }
+
+ //create div and text html component
+ const p = document.createElement('p');
+ p.classList.add('action-body');
+ p.innerText = text;
+
+ const div = document.createElement('div');
+ div.classList.add('action');
+ div.classList.add(id);
+ div.id = id;
+ div.appendChild(p);
+
+ this.actionButtonInformation.set(id, div);
+
+ const mainContainer = HtmlUtils.getElementByIdOrFail('main-container');
+ mainContainer.appendChild(div);
+ //add trigger action
+ if(callBack){
+ div.onpointerdown = () => {
+ callBack();
+ this.removeActionButton(id, userInputManager);
+ };
+ }
+
+ //remove it after 10 sec
+ setTimeout(() => {
+ this.removeActionButton(id, userInputManager);
+ }, 10000)
+ }
}
const layoutManager = new LayoutManager();
diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts
index 09386970..d9a91940 100644
--- a/front/src/WebRtc/MediaManager.ts
+++ b/front/src/WebRtc/MediaManager.ts
@@ -4,6 +4,8 @@ import {discussionManager, SendMessageCallback} from "./DiscussionManager";
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
import {localUserStore} from "../Connexion/LocalUserStore";
import {UserSimplePeerInterface} from "./SimplePeer";
+import {SoundMeter} from "../Phaser/Components/SoundMeter";
+
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
let videoConstraint: boolean|MediaTrackConstraints = {
@@ -26,6 +28,7 @@ export type StartScreenSharingCallback = (media: MediaStream) => void;
export type StopScreenSharingCallback = (media: MediaStream) => void;
export type ReportCallback = (message: string) => void;
export type ShowReportCallBack = (userId: string, userName: string|undefined) => void;
+export type HelpCameraSettingsCallBack = () => void;
// TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only)
export class MediaManager {
@@ -40,6 +43,7 @@ export class MediaManager {
microphoneClose: HTMLImageElement;
microphone: HTMLImageElement;
webrtcInAudio: HTMLAudioElement;
+ mySoundMeterElement: HTMLDivElement;
private webrtcOutAudio: HTMLAudioElement;
constraintsMedia : MediaStreamConstraints = {
audio: audioConstraint,
@@ -49,6 +53,8 @@ export class MediaManager {
startScreenSharingCallBacks : Set = new Set();
stopScreenSharingCallBacks : Set = new Set();
showReportModalCallBacks : Set = new Set();
+ helpCameraSettingsCallBacks : Set = new Set();
+
private microphoneBtn: HTMLDivElement;
private cinemaBtn: HTMLDivElement;
private monitorBtn: HTMLDivElement;
@@ -63,6 +69,12 @@ export class MediaManager {
private triggerCloseJistiFrame : Map = new Map();
+ private userInputManager?: UserInputManager;
+
+ private mySoundMeter?: SoundMeter|null;
+ private soundMeters: Map = new Map();
+ private soundMeterElements: Map = new Map();
+
constructor() {
this.myCamVideo = HtmlUtils.getElementByIdOrFail('myCamVideo');
@@ -121,10 +133,16 @@ export class MediaManager {
this.pingCameraStatus();
this.checkActiveUser(); //todo: desactivated in case of bug
+
+ this.mySoundMeterElement = (HtmlUtils.getElementByIdOrFail('mySoundMeter'));
+ this.mySoundMeterElement.childNodes.forEach((value: ChildNode, index) => {
+ this.mySoundMeterElement.children.item(index)?.classList.remove('active');
+ });
}
- public setLastUpdateScene(){
+ public updateScene(){
this.lastUpdateScene = new Date();
+ this.updateSoudMeter();
}
public blurCamera() {
@@ -225,6 +243,10 @@ export class MediaManager {
}).catch((err) => {
console.error(err);
this.disableCameraStyle();
+
+ layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => {
+ this.showHelpCameraSettingsCallBack();
+ }, this.userInputManager);
});
}
@@ -253,6 +275,10 @@ export class MediaManager {
}).catch((err) => {
console.error(err);
this.disableMicrophoneStyle();
+
+ layoutManager.addInformation('warning', 'Microphone access denied. Click here and check navigators permissions.', () => {
+ this.showHelpCameraSettingsCallBack();
+ }, this.userInputManager);
});
}
@@ -324,6 +350,10 @@ export class MediaManager {
this.monitorClose.style.display = "block";
this.monitor.style.display = "none";
this.monitorBtn.classList.remove("enabled");
+
+ layoutManager.addInformation('warning', 'Screen sharing access denied. Click here and check navigators permissions.', () => {
+ this.showHelpCameraSettingsCallBack();
+ }, this.userInputManager);
});
}
@@ -402,13 +432,14 @@ export class MediaManager {
}
}
- return this.getLocalStream().catch(() => {
- console.info('Error get camera, trying with video option at null');
+ return this.getLocalStream().catch((err) => {
+ console.info('Error get camera, trying with video option at null =>', err);
this.disableCameraStyle();
return this.getLocalStream().then((stream : MediaStream) => {
this.hasCamera = false;
return stream;
}).catch((err) => {
+ this.disableMicrophoneStyle();
console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err);
throw err;
});
@@ -425,6 +456,13 @@ export class MediaManager {
return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => {
this.localStream = stream;
this.myCamVideo.srcObject = this.localStream;
+
+ //init sound meter
+ this.mySoundMeter = null;
+ if(this.constraintsMedia.audio){
+ this.mySoundMeter = new SoundMeter();
+ this.mySoundMeter.connectToSource(stream, new AudioContext());
+ }
return stream;
}).catch((err: Error) => {
throw err;
@@ -451,6 +489,7 @@ export class MediaManager {
track.stop();
}
}
+ this.mySoundMeter?.stop();
}
setCamera(id: string): Promise {
@@ -496,6 +535,13 @@ export class MediaManager {
+
+
+
+
+
+
+
`;
@@ -585,6 +631,12 @@ export class MediaManager {
throw `Unable to find video for ${userId}`;
}
remoteVideo.srcObject = stream;
+
+ //sound metter
+ const soundMeter = new SoundMeter();
+ soundMeter.connectToSource(stream, new AudioContext());
+ this.soundMeters.set(userId, soundMeter);
+ this.soundMeterElements.set(userId, HtmlUtils.getElementByIdOrFail
('soundMeter-'+userId));
}
addStreamRemoteScreenSharing(userId: string, stream : MediaStream){
// In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet
@@ -600,6 +652,10 @@ export class MediaManager {
layoutManager.remove(userId);
this.remoteVideo.delete(userId);
+ this.soundMeters.get(userId)?.stop();
+ this.soundMeters.delete(userId);
+ this.soundMeterElements.delete(userId);
+
//permit to remove user in discussion part
this.removeParticipant(userId);
}
@@ -717,6 +773,7 @@ export class MediaManager {
}
public setUserInputManager(userInputManager : UserInputManager){
+ this.userInputManager = userInputManager;
discussionManager.setUserInputManager(userInputManager);
}
//check if user is active
@@ -739,6 +796,57 @@ export class MediaManager {
public setShowReportModalCallBacks(callback: ShowReportCallBack){
this.showReportModalCallBacks.add(callback);
}
+
+ public setHelpCameraSettingsCallBack(callback: HelpCameraSettingsCallBack){
+ this.helpCameraSettingsCallBacks.add(callback);
+ }
+
+ private showHelpCameraSettingsCallBack(){
+ for(const callBack of this.helpCameraSettingsCallBacks){
+ callBack();
+ }
+ }
+
+ updateSoudMeter(){
+ try{
+ const volume = parseInt(((this.mySoundMeter ? this.mySoundMeter.getVolume() : 0) / 10).toFixed(0));
+ this.setVolumeSoundMeter(volume, this.mySoundMeterElement);
+
+ for(const indexUserId of this.soundMeters.keys()){
+ const soundMeter = this.soundMeters.get(indexUserId);
+ const soundMeterElement = this.soundMeterElements.get(indexUserId);
+ if(!soundMeter || !soundMeterElement){
+ return;
+ }
+ const volumeByUser = parseInt((soundMeter.getVolume() / 10).toFixed(0));
+ this.setVolumeSoundMeter(volumeByUser, soundMeterElement);
+ }
+ }catch(err){
+ //console.error(err);
+ }
+ }
+
+ private setVolumeSoundMeter(volume: number, element: HTMLDivElement){
+ if(volume <= 0 && !element.classList.contains('active')){
+ return;
+ }
+ element.classList.remove('active');
+ if(volume <= 0){
+ return;
+ }
+ element.classList.add('active');
+ element.childNodes.forEach((value: ChildNode, index) => {
+ const elementChildre = element.children.item(index);
+ if(!elementChildre){
+ return;
+ }
+ elementChildre.classList.remove('active');
+ if((index +1) > volume){
+ return;
+ }
+ elementChildre.classList.add('active');
+ });
+ }
}
export const mediaManager = new MediaManager();
diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts
index 73a87d14..7690c27d 100644
--- a/front/src/WebRtc/SimplePeer.ts
+++ b/front/src/WebRtc/SimplePeer.ts
@@ -82,15 +82,11 @@ export class SimplePeer {
});
mediaManager.showGameOverlay();
- mediaManager.getCamera().then(() => {
-
+ mediaManager.getCamera().finally(() => {
//receive message start
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
this.receiveWebrtcStart(message);
});
-
- }).catch((err) => {
- console.error("err", err);
});
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {
diff --git a/maps/Village/sol_intérieur.png b/maps/Village/sol_intérieur.png
new file mode 100644
index 00000000..926a7dc2
Binary files /dev/null and b/maps/Village/sol_intérieur.png differ