diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml
index 48a7bae9..3bf00b99 100644
--- a/.github/workflows/build-and-deploy.yml
+++ b/.github/workflows/build-and-deploy.yml
@@ -2,7 +2,7 @@ name: Build, push and deploy Docker image
on:
push:
- branches: [master]
+ branches: [master, develop]
release:
types: [created]
pull_request:
@@ -149,6 +149,37 @@ jobs:
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
+ - name: Write certificate
+ run: echo "${CERTS_PRIVATE_KEY}" > secret.key && chmod 0600 secret.key
+ env:
+ CERTS_PRIVATE_KEY: ${{ secrets.CERTS_PRIVATE_KEY }}
+
+ - name: Download certificate
+ run: mkdir secrets && scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i secret.key ubuntu@cert.workadventu.re:./config/live/workadventu.re/* secrets/
+
+ - name: Create namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: create namespace workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
+ continue-on-error: true
+
+ - name: Delete old certificates in namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} delete secret certificate-tls
+ continue-on-error: true
+
+ - name: Install certificates in namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} create secret tls certificate-tls --key="secrets/privkey.pem" --cert="secrets/fullchain.pem"
+
- name: Deploy
uses: thecodingmachine/deeployer-action@master
env:
@@ -168,4 +199,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- msg: Environment deployed at https://play.${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
+ msg: Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
index 06c1c58e..2036e4e6 100644
--- a/.github/workflows/continuous_integration.yml
+++ b/.github/workflows/continuous_integration.yml
@@ -52,6 +52,10 @@ jobs:
PUSHER_URL: "//localhost:8080"
working-directory: "front"
+ - name: "Svelte check"
+ run: yarn run svelte-check
+ working-directory: "front"
+
- name: "Lint"
run: yarn run lint
working-directory: "front"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 68a7016f..31f544eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,11 +12,25 @@
- The emote menu can be opened by clicking on your character.
- Clicking on one of its element will close the menu and play an emote above your character.
- This emote can be seen by other players.
+- Player names were improved. (@Kharhamel)
+ - We now create a GameObject.Text instead of GameObject.BitmapText
+ - now use the 'Press Start 2P' font family and added an outline
+ - As a result, we can now allow non-standard letters like french accents or chinese characters!
+
+- Added the contact card feature. (@Kharhamel)
+ - Click on another player to see its contact info.
+ - Premium-only feature unfortunately. I need to find a way to make it available for all.
+ - If no contact data is found (either because the user is anonymous or because no admin backend), display an error card.
+
- Mobile support has been improved
- WorkAdventure automatically sets the zoom level based on the viewport size to ensure a sensible size of the map is visible, whatever the viewport used
- Mouse wheel support to zoom in / out
- Pinch support on mobile to zoom in / out
- Improved virtual joystick size (adapts to the zoom level)
+- Redesigned intermediate scenes
+ - Redesigned Select Companion scene
+ - Redesigned Enter Your Name scene
+ - Added a new `DISPLAY_TERMS_OF_USE` environment variable to trigger the display of terms of use
- New scripting API features:
- Use `WA.loadSound(): Sound` to load / play / stop a sound
- Use `WA.showLayer(): void` to show a layer
diff --git a/back/package.json b/back/package.json
index 09d6794a..a6ff7319 100644
--- a/back/package.json
+++ b/back/package.json
@@ -38,23 +38,17 @@
"homepage": "https://github.com/thecodingmachine/workadventure#readme",
"dependencies": {
"axios": "^0.21.1",
- "body-parser": "^1.19.0",
"busboy": "^0.3.1",
"circular-json": "^0.5.9",
"debug": "^4.3.1",
"generic-type-guard": "^3.2.0",
"google-protobuf": "^3.13.0",
"grpc": "^1.24.4",
- "http-status-codes": "^1.4.0",
- "iterall": "^1.3.0",
"jsonwebtoken": "^8.5.1",
"mkdirp": "^1.0.4",
- "multer": "^1.4.2",
"prom-client": "^12.0.0",
"query-string": "^6.13.3",
"systeminformation": "^4.31.1",
- "ts-node-dev": "^1.0.0-pre.44",
- "typescript": "^3.8.3",
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
"uuidv4": "^6.0.7"
},
@@ -71,6 +65,8 @@
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"eslint": "^6.8.0",
- "jasmine": "^3.5.0"
+ "jasmine": "^3.5.0",
+ "ts-node-dev": "^1.0.0-pre.44",
+ "typescript": "^3.8.3"
}
}
diff --git a/back/src/Model/Admin.ts b/back/src/Model/Admin.ts
index 0be74b85..29b53385 100644
--- a/back/src/Model/Admin.ts
+++ b/back/src/Model/Admin.ts
@@ -1,9 +1,6 @@
import {
- BatchMessage,
- PusherToBackMessage,
ServerToAdminClientMessage,
- ServerToClientMessage,
- SubMessage, UserJoinedRoomMessage, UserLeftRoomMessage
+ UserJoinedRoomMessage, UserLeftRoomMessage
} from "../Messages/generated/messages_pb";
import {AdminSocket} from "../RoomManager";
diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts
index be3e5cd3..53d0a855 100644
--- a/back/src/Model/GameRoom.ts
+++ b/back/src/Model/GameRoom.ts
@@ -89,7 +89,10 @@ export class GameRoom {
public getUserByUuid(uuid: string): User|undefined {
return this.usersByUuid.get(uuid);
}
-
+ public getUserById(id: number): User|undefined {
+ return this.users.get(id);
+ }
+
public join(socket : UserSocket, joinRoomMessage: JoinRoomMessage): User {
const positionMessage = joinRoomMessage.getPositionmessage();
if (positionMessage === undefined) {
@@ -105,6 +108,7 @@ export class GameRoom {
this.positionNotifier,
socket,
joinRoomMessage.getTagList(),
+ joinRoomMessage.getVisitcardurl(),
joinRoomMessage.getName(),
ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList()),
joinRoomMessage.getCompanion()
diff --git a/back/src/Model/User.ts b/back/src/Model/User.ts
index 52a96b61..4a3e75ec 100644
--- a/back/src/Model/User.ts
+++ b/back/src/Model/User.ts
@@ -22,6 +22,7 @@ export class User implements Movable {
private positionNotifier: PositionNotifier,
public readonly socket: UserSocket,
public readonly tags: string[],
+ public readonly visitCardUrl: string|null,
public readonly name: string,
public readonly characterLayers: CharacterLayer[],
public readonly companion?: CompanionMessage
diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts
index c58b3d9f..a56a1ac4 100644
--- a/back/src/Services/SocketManager.ts
+++ b/back/src/Services/SocketManager.ts
@@ -299,6 +299,9 @@ export class SocketManager {
userJoinedZoneMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
userJoinedZoneMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
userJoinedZoneMessage.setFromzone(this.toProtoZone(fromZone));
+ if (thing.visitCardUrl) {
+ userJoinedZoneMessage.setVisitcardurl(thing.visitCardUrl);
+ }
userJoinedZoneMessage.setCompanion(thing.companion);
const subMessage = new SubToPusherMessage();
@@ -604,6 +607,9 @@ export class SocketManager {
userJoinedMessage.setName(thing.name);
userJoinedMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
+ if (thing.visitCardUrl) {
+ userJoinedMessage.setVisitcardurl(thing.visitCardUrl);
+ }
userJoinedMessage.setCompanion(thing.companion);
const subMessage = new SubToPusherMessage();
diff --git a/back/tests/PositionNotifierTest.ts b/back/tests/PositionNotifierTest.ts
index 24b171d9..1aaf2e13 100644
--- a/back/tests/PositionNotifierTest.ts
+++ b/back/tests/PositionNotifierTest.ts
@@ -1,10 +1,6 @@
import "jasmine";
-import {GameRoom, ConnectCallback, DisconnectCallback } from "_Model/GameRoom";
-import {Point} from "../src/Model/Websocket/MessageUserPosition";
-import { Group } from "../src/Model/Group";
import {PositionNotifier} from "../src/Model/PositionNotifier";
import {User, UserSocket} from "../src/Model/User";
-import {PointInterface} from "../src/Model/Websocket/PointInterface";
import {Zone} from "_Model/Zone";
import {Movable} from "_Model/Movable";
import {PositionInterface} from "_Model/PositionInterface";
@@ -30,14 +26,14 @@ describe("PositionNotifier", () => {
y: 500,
moving: false,
direction: 'down'
- }, false, positionNotifier, {} as UserSocket, [], 'foo', []);
+ }, false, positionNotifier, {} as UserSocket, [], null, 'foo', []);
const user2 = new User(2, 'test', '10.0.0.2', {
x: -9999,
y: -9999,
moving: false,
direction: 'down'
- }, false, positionNotifier, {} as UserSocket, [], 'foo', []);
+ }, false, positionNotifier, {} as UserSocket, [], null, 'foo', []);
positionNotifier.addZoneListener({} as ZoneSocket, 0, 0);
positionNotifier.addZoneListener({} as ZoneSocket, 0, 1);
@@ -105,14 +101,14 @@ describe("PositionNotifier", () => {
y: 500,
moving: false,
direction: 'down'
- }, false, positionNotifier, {} as UserSocket, [], 'foo', []);
+ }, false, positionNotifier, {} as UserSocket, [], null, 'foo', []);
const user2 = new User(2, 'test', '10.0.0.2', {
x: 0,
y: 0,
moving: false,
direction: 'down'
- }, false, positionNotifier, {} as UserSocket, [], 'foo', []);
+ }, false, positionNotifier, {} as UserSocket, [], null, 'foo', []);
const listener = {} as ZoneSocket;
positionNotifier.addZoneListener(listener, 0, 0);
diff --git a/back/yarn.lock b/back/yarn.lock
index 8af760c8..3ac4b0a8 100644
--- a/back/yarn.lock
+++ b/back/yarn.lock
@@ -257,11 +257,6 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-append-field@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
- integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
-
aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -370,22 +365,6 @@ bintrees@1.0.1:
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
-body-parser@^1.19.0:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
- integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
- dependencies:
- bytes "3.1.0"
- content-type "~1.0.4"
- debug "2.6.9"
- depd "~1.1.2"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- on-finished "~2.3.0"
- qs "6.7.0"
- raw-body "2.4.0"
- type-is "~1.6.17"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -427,14 +406,6 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-busboy@^0.2.11:
- version "0.2.14"
- resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
- integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
- dependencies:
- dicer "0.2.5"
- readable-stream "1.1.x"
-
busboy@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
@@ -449,11 +420,6 @@ bytebuffer@~5:
dependencies:
long "~3"
-bytes@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
cache-base@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
@@ -622,26 +588,11 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
@@ -678,7 +629,7 @@ dateformat@~1.0.4-1.2.3:
get-stdin "^4.0.1"
meow "^3.3.0"
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
+debug@^2.2.0, debug@^2.3.3:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -753,24 +704,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
- integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-dicer@0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
- integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
- dependencies:
- readable-stream "1.1.x"
- streamsearch "0.1.2"
-
dicer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
@@ -804,11 +742,6 @@ ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer "^5.0.1"
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
- integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -1255,28 +1188,12 @@ hosted-git-info@^2.1.4:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-http-errors@1.7.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
- integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.1"
- statuses ">= 1.5.0 < 2"
- toidentifier "1.0.0"
-
http-status-codes@*:
version "2.1.4"
resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.4.tgz#453d99b4bd9424254c4f6a9a3a03715923052798"
integrity sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg==
-http-status-codes@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-1.4.0.tgz#6e4c15d16ff3a9e2df03b89f3a55e1aae05fb477"
- integrity sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ==
-
-iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
+iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -1323,16 +1240,11 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-inherits@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
ini@~1.3.0:
version "1.3.7"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
@@ -1507,11 +1419,6 @@ is-windows@^1.0.2:
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
isarray@1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -1534,11 +1441,6 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-iterall@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
- integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
-
jasmine-core@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20"
@@ -1743,11 +1645,6 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-media-typer@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
- integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
meow@^3.3.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
@@ -1788,18 +1685,6 @@ micromatch@^3.1.10:
snapdragon "^0.8.1"
to-regex "^3.0.2"
-mime-db@1.44.0:
- version "1.44.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
- integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
-
-mime-types@~2.1.24:
- version "2.1.27"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
- integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
- dependencies:
- mime-db "1.44.0"
-
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -1862,20 +1747,6 @@ ms@2.1.2, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-multer@^1.4.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
- integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
- dependencies:
- append-field "^1.0.0"
- busboy "^0.2.11"
- concat-stream "^1.5.2"
- mkdirp "^0.5.1"
- object-assign "^4.1.1"
- on-finished "^2.3.0"
- type-is "^1.6.4"
- xtend "^4.0.0"
-
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
@@ -1997,7 +1868,7 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -2025,13 +1896,6 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-on-finished@^2.3.0, on-finished@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
- integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
- dependencies:
- ee-first "1.1.1"
-
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -2207,11 +2071,6 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-qs@6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
- integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
query-string@^6.13.3:
version "6.13.4"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.4.tgz#b35a9a3bd4955bce55f94feb0e819b3d0be6f66f"
@@ -2221,16 +2080,6 @@ query-string@^6.13.3:
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"
-raw-body@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
- integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -2258,17 +2107,7 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
-readable-stream@1.1.x:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readable-stream@^2.0.6, readable-stream@^2.2.2:
+readable-stream@^2.0.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -2444,11 +2283,6 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
-setprototypeof@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
- integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -2590,11 +2424,6 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"
-"statuses@>= 1.5.0 < 2":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
- integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
streamsearch@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
@@ -2640,11 +2469,6 @@ string-width@^4.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -2807,11 +2631,6 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
-toidentifier@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
- integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@@ -2889,19 +2708,6 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
-type-is@^1.6.4, type-is@~1.6.17:
- version "1.6.18"
- resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
- integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
- dependencies:
- media-typer "0.3.0"
- mime-types "~2.1.24"
-
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
typescript@^3.8.3:
version "3.9.7"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
@@ -2921,11 +2727,6 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^2.0.1"
-unpipe@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json
index 72d0aae4..2d25c58a 100644
--- a/benchmark/package-lock.json
+++ b/benchmark/package-lock.json
@@ -209,9 +209,9 @@
}
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
@@ -688,9 +688,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
- "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
},
"xtend": {
"version": "4.0.2",
diff --git a/benchmark/package.json b/benchmark/package.json
index b0cd6a23..586e97e6 100644
--- a/benchmark/package.json
+++ b/benchmark/package.json
@@ -24,7 +24,7 @@
"@types/ws": "^7.2.6",
"ts-node-dev": "^1.0.0-pre.62",
"typescript": "^4.0.2",
- "ws": "^7.3.1"
+ "ws": "^7.4.6"
},
"devDependencies": {}
}
diff --git a/benchmark/yarn.lock b/benchmark/yarn.lock
index f1209dcf..8dcffe52 100644
--- a/benchmark/yarn.lock
+++ b/benchmark/yarn.lock
@@ -148,8 +148,8 @@ get-stdin@^4.0.1:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
glob-parent@~5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
dependencies:
is-glob "^4.0.1"
@@ -515,9 +515,9 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
-ws@^7.3.1:
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"
+ws@^7.4.6:
+ version "7.4.6"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
xtend@^4.0.0:
version "4.0.2"
diff --git a/deeployer.libsonnet b/deeployer.libsonnet
index f9dd87bd..8d9c2bfd 100644
--- a/deeployer.libsonnet
+++ b/deeployer.libsonnet
@@ -11,8 +11,7 @@
"back1": {
"image": "thecodingmachine/workadventure-back:"+tag,
"host": {
- "url": "api1."+url,
- "https": "enable",
+ "url": "api1-"+url,
"containerPort": 8080
},
"ports": [8080, 50051],
@@ -30,8 +29,7 @@
"back2": {
"image": "thecodingmachine/workadventure-back:"+tag,
"host": {
- "url": "api2."+url,
- "https": "enable",
+ "url": "api2-"+url,
"containerPort": 8080
},
"ports": [8080, 50051],
@@ -50,8 +48,7 @@
"replicas": 2,
"image": "thecodingmachine/workadventure-pusher:"+tag,
"host": {
- "url": "pusher."+url,
- "https": "enable"
+ "url": "pusher-"+url,
},
"ports": [8080],
"env": {
@@ -68,27 +65,25 @@
"front": {
"image": "thecodingmachine/workadventure-front:"+tag,
"host": {
- "url": "play."+url,
- "https": "enable"
+ "url": "play-"+url,
},
"ports": [80],
"env": {
- "PUSHER_URL": "//pusher."+url,
- "UPLOADER_URL": "//uploader."+url,
+ "PUSHER_URL": "//pusher-"+url,
+ "UPLOADER_URL": "//uploader-"+url,
"ADMIN_URL": "//"+url,
"JITSI_URL": env.JITSI_URL,
"SECRET_JITSI_KEY": env.SECRET_JITSI_KEY,
"TURN_SERVER": "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443",
"JITSI_PRIVATE_MODE": if env.SECRET_JITSI_KEY != '' then "true" else "false",
- "START_ROOM_URL": "/_/global/maps."+url+"/Floor0/floor0.json"
+ "START_ROOM_URL": "/_/global/maps-"+url+"/Floor0/floor0.json"
//"GA_TRACKING_ID": "UA-10196481-11"
}
},
"uploader": {
"image": "thecodingmachine/workadventure-uploader:"+tag,
"host": {
- "url": "uploader."+url,
- "https": "enable",
+ "url": "uploader-"+url,
"containerPort": 8080
},
"ports": [8080],
@@ -98,16 +93,12 @@
"maps": {
"image": "thecodingmachine/workadventure-maps:"+tag,
"host": {
- "url": "maps."+url,
- "https": "enable"
+ "url": "maps-"+url
},
"ports": [80]
},
},
"config": {
- "https": {
- "mail": "d.negrier@thecodingmachine.com"
- },
k8sextension(k8sConf)::
k8sConf + {
back1+: {
@@ -122,6 +113,14 @@
}
}
}
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["api1-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
}
},
back2+: {
@@ -136,6 +135,14 @@
}
}
}
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["api2-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
}
},
pusher+: {
@@ -150,8 +157,46 @@
}
}
}
- }
- }
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["pusher-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ front+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["play-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ uploader+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["uploader-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ maps+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["maps-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
}
}
}
diff --git a/docs/maps/api-chat.md b/docs/maps/api-chat.md
new file mode 100644
index 00000000..49a40f97
--- /dev/null
+++ b/docs/maps/api-chat.md
@@ -0,0 +1,37 @@
+{.section-title.accent.text-primary}
+# API Chat functions reference
+
+### Sending a message in the chat
+
+```
+WA.chat.sendChatMessage(message: string, author: string): void
+```
+
+Sends a message in the chat. The message is only visible in the browser of the current user.
+
+* **message**: the message to be displayed in the chat
+* **author**: the name displayed for the author of the message. It does not have to be a real user.
+
+Example:
+
+```javascript
+WA.chat.sendChatMessage('Hello world', 'Mr Robot');
+```
+
+### Listening to messages from the chat
+
+```javascript
+WA.chat.onChatMessage(callback: (message: string) => void): void
+```
+
+Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to.
+
+* **callback**: the function that will be called when a message is received. It contains the message typed by the user.
+
+Example:
+
+```javascript
+WA.chat.onChatMessage((message => {
+ console.log('The user typed a message', message);
+}));
+```
diff --git a/docs/maps/api-controls.md b/docs/maps/api-controls.md
new file mode 100644
index 00000000..dcb0f17b
--- /dev/null
+++ b/docs/maps/api-controls.md
@@ -0,0 +1,29 @@
+{.section-title.accent.text-primary}
+# API Controls functions Reference
+
+### Disabling / restoring controls
+
+```
+WA.controls.disablePlayerControls(): void
+WA.controls.restorePlayerControls(): void
+```
+
+These 2 methods can be used to completely disable player controls and to enable them again.
+
+When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again.
+
+Example:
+
+```javascript
+WA.room.onEnterZone('myZone', () => {
+ WA.controls.disablePlayerControls();
+ WA.ui.openPopup("popupRectangle", 'This is an imporant message!', [{
+ label: "Got it!",
+ className: "primary",
+ callback: (popup) => {
+ WA.controls.restorePlayerControls();
+ popup.close();
+ }
+ }]);
+});
+```
diff --git a/docs/maps/api-deprecated.md b/docs/maps/api-deprecated.md
new file mode 100644
index 00000000..930caebe
--- /dev/null
+++ b/docs/maps/api-deprecated.md
@@ -0,0 +1,20 @@
+{.section-title.accent.text-primary}
+# API Reference - Deprecated functions
+
+The list of functions below is **deprecated**. You should not use those but. use the replacement functions.
+
+- Method `WA.sendChatMessage` is deprecated. It has been renamed to `WA.chat.sendChatMessage`.
+- Method `WA.disablePlayerControls` is deprecated. It has been renamed to `WA.controls.disablePlayerControls`.
+- Method `WA.restorePlayerControls` is deprecated. It has been renamed to `WA.controls.restorePlayerControls`.
+- Method `WA.displayBubble` is deprecated. It has been renamed to `WA.ui.displayBubble`.
+- Method `WA.removeBubble` is deprecated. It has been renamed to `WA.ui.removeBubble`.
+- Method `WA.openTab` is deprecated. It has been renamed to `WA.nav.openTab`.
+- Method `WA.loadSound` is deprecated. It has been renamed to `WA.sound.loadSound`.
+- Method `WA.goToPage` is deprecated. It has been renamed to `WA.nav.goToPage`.
+- Method `WA.goToRoom` is deprecated. It has been renamed to `WA.nav.goToRoom`.
+- Method `WA.openCoWebSite` is deprecated. It has been renamed to `WA.nav.openCoWebSite`.
+- Method `WA.closeCoWebSite` is deprecated. It has been renamed to `WA.nav.closeCoWebSite`.
+- Method `WA.openPopup` is deprecated. It has been renamed to `WA.ui.openPopup`.
+- Method `WA.onChatMessage` is deprecated. It has been renamed to `WA.chat.onChatMessage`.
+- Method `WA.onEnterZone` is deprecated. It has been renamed to `WA.room.onEnterZone`.
+- Method `WA.onLeaveZone` is deprecated. It has been renamed to `WA.room.onLeaveZone`.
diff --git a/docs/maps/api-nav.md b/docs/maps/api-nav.md
new file mode 100644
index 00000000..29323632
--- /dev/null
+++ b/docs/maps/api-nav.md
@@ -0,0 +1,68 @@
+{.section-title.accent.text-primary}
+# API Navigation functions reference
+
+### Opening a web page in a new tab
+
+```
+WA.nav.openTab(url: string): void
+```
+
+Opens the webpage at "url" in your browser, in a new tab.
+
+Example:
+
+```javascript
+WA.nav.openTab('https://www.wikipedia.org/');
+```
+
+### Opening a web page in the current tab
+
+```
+WA.nav.goToPage(url: string): void
+```
+
+Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded.
+
+Example:
+
+```javascript
+WA.nav.goToPage('https://www.wikipedia.org/');
+```
+
+### Going to a different map from the script
+
+```
+
+WA.nav.goToRoom(url: string): void
+```
+
+Load the map at url without unloading workadventure
+
+relative urls: "../subFolder/map.json[#start-layer-name]"
+global urls: "/_/global/domain/path/map.json[#start-layer-name]"
+
+Example:
+
+```javascript
+WA.nav.goToRoom("/@/tcm/workadventure/floor0") // workadventure urls
+WA.nav.goToRoom('../otherMap/map.json');
+WA.nav.goToRoom("/_/global/.json#start-layer-2")
+```
+
+### Opening/closing a web page in an iFrame
+
+```
+WA.nav.openCoWebSite(url: string): void
+WA.nav.closeCoWebSite(): void
+```
+
+Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame.
+
+Example:
+
+```javascript
+WA.nav.openCoWebSite('https://www.wikipedia.org/');
+// ...
+WA.nav.closeCoWebSite();
+```
+
diff --git a/docs/maps/api-reference.md b/docs/maps/api-reference.md
index d4316772..a39ec1db 100644
--- a/docs/maps/api-reference.md
+++ b/docs/maps/api-reference.md
@@ -1,240 +1,14 @@
{.section-title.accent.text-primary}
# API Reference
-### Sending a message in the chat
+- [Navigation functions](api-nav.md)
+- [Chat functions](api-chat.md)
+- [Room functions](api-room.md)
+- [UI functions](api-ui.md)
+- [Sound functions](api-sound.md)
+- [Controls functions](api-controls.md)
-```
-sendChatMessage(message: string, author: string): void
-```
-
-Sends a message in the chat. The message is only visible in the browser of the current user.
-
-* **message**: the message to be displayed in the chat
-* **author**: the name displayed for the author of the message. It does not have to be a real user.
-
-Example:
-
-```javascript
-WA.sendChatMessage('Hello world', 'Mr Robot');
-```
-
-### Listening to messages from the chat
-
-```javascript
-onChatMessage(callback: (message: string) => void): void
-```
-
-Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to.
-
-* **callback**: the function that will be called when a message is received. It contains the message typed by the user.
-
-Example:
-
-```javascript
-WA.onChatMessage((message => {
- console.log('The user typed a message', message);
-}));
-```
-
-### Detecting when the user enters/leaves a zone
-
-```
-onEnterZone(name: string, callback: () => void): void
-onLeaveZone(name: string, callback: () => void): void
-```
-
-Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property.
-
-
-
-
- The `zone` property, applied on a layer
-
-
-
-* **name**: the name of the zone, as defined in the `zone` property.
-* **callback**: the function that will be called when a user enters or leaves the zone.
-
-Example:
-
-```javascript
-WA.onEnterZone('myZone', () => {
- WA.sendChatMessage("Hello!", 'Mr Robot');
-})
-
-WA.onLeaveZone('myZone', () => {
- WA.sendChatMessage("Goodbye!", 'Mr Robot');
-})
-```
-
-### Opening a popup
-
-In order to open a popup window, you must first define the position of the popup on your map.
-
-You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer.
-
-
-
-
-
-
-
-
-
-
-```
-openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup
-```
-
-* **targetObject**: the name of the rectangle object defined in Tiled.
-* **message**: the message to display in the popup.
-* **buttons**: an array of action buttons defined underneath the popup.
-
-Action buttons are `ButtonDescriptor` objects containing these properties.
-
-* **label (_string_)**: The label of the button.
-* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled".
-* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed.
-
-Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object.
-
-The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called.
-
-```javascript
-class Popup {
- /**
- * Closes the popup
- */
- close() {};
-}
-```
-
-Example:
-
-```javascript
-let helloWorldPopup;
-
-// Open the popup when we enter a given zone
-helloWorldPopup = WA.onEnterZone('myZone', () => {
- WA.openPopup("popupRectangle", 'Hello world!', [{
- label: "Close",
- className: "primary",
- callback: (popup) => {
- // Close the popup when the "Close" button is pressed.
- popup.close();
- }
- });
-}]);
-
-// Close the popup when we leave the zone.
-WA.onLeaveZone('myZone', () => {
- helloWorldPopup.close();
-});
-```
-
-### Disabling / restoring controls
-
-```
-disablePlayerControls(): void
-restorePlayerControls(): void
-```
-
-These 2 methods can be used to completely disable player controls and to enable them again.
-
-When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again.
-
-Example:
-
-```javascript
-WA.onEnterZone('myZone', () => {
- WA.disablePlayerControls();
- WA.openPopup("popupRectangle", 'This is an imporant message!', [{
- label: "Got it!",
- className: "primary",
- callback: (popup) => {
- WA.restorePlayerControls();
- popup.close();
- }
- }]);
-});
-```
-
-### Opening a web page in a new tab
-
-```
-openTab(url: string): void
-```
-
-Opens the webpage at "url" in your browser, in a new tab.
-
-Example:
-
-```javascript
-WA.openTab('https://www.wikipedia.org/');
-```
-
-### Opening a web page in the current tab
-
-```
-goToPage(url: string): void
-```
-
-Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded.
-
-Example:
-
-```javascript
-WA.goToPage('https://www.wikipedia.org/');
-```
-
-### Opening/closing a web page in an iFrame
-
-```
-openCoWebSite(url: string): void
-closeCoWebSite(): void
-```
-
-Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame.
-
-Example:
-
-```javascript
-WA.openCoWebSite('https://www.wikipedia.org/');
-// ...
-WA.closeCoWebSite();
-```
-
-### Load a sound from an url
-
-```
-loadSound(url: string): Sound
-```
-
-Load a sound from an url
-
-Please note that `loadSound` returns an object of the `Sound` class
-
-The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()`
-
-The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration.
-
-Example:
-
-```javascript
-var mySound = WA.loadSound("Sound.ogg");
-var config = {
- volume : 0.5,
- loop : false,
- rate : 1,
- detune : 1,
- delay : 0,
- seek : 0,
- mute : false
-}
-mySound.play(config);
-// ...
-mySound.stop();
-```
+- [List of deprecated functions](api-deprecated.md)
### Show / Hide a layer
```
diff --git a/docs/maps/api-room.md b/docs/maps/api-room.md
new file mode 100644
index 00000000..dc7a8612
--- /dev/null
+++ b/docs/maps/api-room.md
@@ -0,0 +1,33 @@
+{.section-title.accent.text-primary}
+# API Room functions Reference
+
+### Detecting when the user enters/leaves a zone
+
+```
+WA.room.onEnterZone(name: string, callback: () => void): void
+WA.room.onLeaveZone(name: string, callback: () => void): void
+```
+
+Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property.
+
+
+
+
+ The `zone` property, applied on a layer
+
+
+
+* **name**: the name of the zone, as defined in the `zone` property.
+* **callback**: the function that will be called when a user enters or leaves the zone.
+
+Example:
+
+```javascript
+WA.room.onEnterZone('myZone', () => {
+ WA.chat.sendChatMessage("Hello!", 'Mr Robot');
+})
+
+WA.room.onLeaveZone('myZone', () => {
+ WA.chat.sendChatMessage("Goodbye!", 'Mr Robot');
+})
+```
diff --git a/docs/maps/api-sound.md b/docs/maps/api-sound.md
new file mode 100644
index 00000000..3c57ecae
--- /dev/null
+++ b/docs/maps/api-sound.md
@@ -0,0 +1,34 @@
+{.section-title.accent.text-primary}
+# API Sound functions Reference
+
+### Load a sound from an url
+
+```
+WA.sound.loadSound(url: string): Sound
+```
+
+Load a sound from an url
+
+Please note that `loadSound` returns an object of the `Sound` class
+
+The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()`
+
+The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration.
+
+Example:
+
+```javascript
+var mySound = WA.sound.loadSound("Sound.ogg");
+var config = {
+ volume : 0.5,
+ loop : false,
+ rate : 1,
+ detune : 1,
+ delay : 0,
+ seek : 0,
+ mute : false
+}
+mySound.play(config);
+// ...
+mySound.stop();
+```
diff --git a/docs/maps/api-ui.md b/docs/maps/api-ui.md
new file mode 100644
index 00000000..edda8613
--- /dev/null
+++ b/docs/maps/api-ui.md
@@ -0,0 +1,67 @@
+{.section-title.accent.text-primary}
+# API Room functions Reference
+
+### Opening a popup
+
+In order to open a popup window, you must first define the position of the popup on your map.
+
+You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer.
+
+
+
+
+
+
+
+
+
+
+```
+WA.ui.openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup
+```
+
+* **targetObject**: the name of the rectangle object defined in Tiled.
+* **message**: the message to display in the popup.
+* **buttons**: an array of action buttons defined underneath the popup.
+
+Action buttons are `ButtonDescriptor` objects containing these properties.
+
+* **label (_string_)**: The label of the button.
+* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled".
+* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed.
+
+Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object.
+
+The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called.
+
+```javascript
+class Popup {
+ /**
+ * Closes the popup
+ */
+ close() {};
+}
+```
+
+Example:
+
+```javascript
+let helloWorldPopup;
+
+// Open the popup when we enter a given zone
+helloWorldPopup = WA.room.onEnterZone('myZone', () => {
+ WA.ui.openPopup("popupRectangle", 'Hello world!', [{
+ label: "Close",
+ className: "primary",
+ callback: (popup) => {
+ // Close the popup when the "Close" button is pressed.
+ popup.close();
+ }
+ });
+}]);
+
+// Close the popup when we leave the zone.
+WA.room.onLeaveZone('myZone', () => {
+ helloWorldPopup.close();
+});
+```
diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html
index 7ef44116..aa63229f 100644
--- a/front/dist/index.tmpl.html
+++ b/front/dist/index.tmpl.html
@@ -29,7 +29,6 @@
-
WorkAdventure
@@ -47,32 +46,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/front/dist/resources/fonts/fonts.css b/front/dist/resources/fonts/fonts.css
new file mode 100644
index 00000000..a3d3cf71
--- /dev/null
+++ b/front/dist/resources/fonts/fonts.css
@@ -0,0 +1,5 @@
+/*This file is a workaround to allow phaser to load directly this font */
+@font-face {
+ font-family: "Press Start 2P";
+ src: url("/fonts/press-start-2p-latin-400-normal.woff2") format('woff2');
+}
\ No newline at end of file
diff --git a/front/dist/resources/html/CustomCharacterScene.html b/front/dist/resources/html/CustomCharacterScene.html
deleted file mode 100644
index 0bc050ea..00000000
--- a/front/dist/resources/html/CustomCharacterScene.html
+++ /dev/null
@@ -1,160 +0,0 @@
-
-
-
diff --git a/front/dist/resources/html/EnableCameraScene.html b/front/dist/resources/html/EnableCameraScene.html
deleted file mode 100644
index 2dda6cc1..00000000
--- a/front/dist/resources/html/EnableCameraScene.html
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
diff --git a/front/dist/resources/html/SelectCompanionScene.html b/front/dist/resources/html/SelectCompanionScene.html
deleted file mode 100644
index cffa7880..00000000
--- a/front/dist/resources/html/SelectCompanionScene.html
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
diff --git a/front/dist/resources/html/gameMenu.html b/front/dist/resources/html/gameMenu.html
index 6abf2753..26be2a1c 100644
--- a/front/dist/resources/html/gameMenu.html
+++ b/front/dist/resources/html/gameMenu.html
@@ -1,7 +1,4 @@
-
-
diff --git a/front/dist/resources/html/loginScene.html b/front/dist/resources/html/loginScene.html
deleted file mode 100644
index 38e798e5..00000000
--- a/front/dist/resources/html/loginScene.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
diff --git a/front/dist/resources/html/selectCharacterScene.html b/front/dist/resources/html/selectCharacterScene.html
deleted file mode 100644
index c51731df..00000000
--- a/front/dist/resources/html/selectCharacterScene.html
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
diff --git a/front/dist/resources/html/warningContainer.html b/front/dist/resources/html/warningContainer.html
index 4989c49d..832ac4da 100644
--- a/front/dist/resources/html/warningContainer.html
+++ b/front/dist/resources/html/warningContainer.html
@@ -1,7 +1,4 @@
diff --git a/front/src/Components/EnableCamera/EnableCameraScene.svelte b/front/src/Components/EnableCamera/EnableCameraScene.svelte
new file mode 100644
index 00000000..1f9ef027
--- /dev/null
+++ b/front/src/Components/EnableCamera/EnableCameraScene.svelte
@@ -0,0 +1,229 @@
+
+
+
+
+
+
diff --git a/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte b/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte
new file mode 100644
index 00000000..a22da2fa
--- /dev/null
+++ b/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte
@@ -0,0 +1,82 @@
+
+
+
+
+ {#each [...Array(NB_BARS).keys()] as i}
+
+ {/each}
+
+
+
diff --git a/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte b/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte
new file mode 100644
index 00000000..8f4de785
--- /dev/null
+++ b/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte
@@ -0,0 +1,73 @@
+
+
+
+
+
+ Refresh
+ Continue without webcam
+
+
+
+
+
diff --git a/front/dist/resources/objects/help-setting-camera-permission-chrome.png b/front/src/Components/HelpCameraSettings/images/help-setting-camera-permission-chrome.png
similarity index 100%
rename from front/dist/resources/objects/help-setting-camera-permission-chrome.png
rename to front/src/Components/HelpCameraSettings/images/help-setting-camera-permission-chrome.png
diff --git a/front/dist/resources/objects/help-setting-camera-permission-firefox.png b/front/src/Components/HelpCameraSettings/images/help-setting-camera-permission-firefox.png
similarity index 100%
rename from front/dist/resources/objects/help-setting-camera-permission-firefox.png
rename to front/src/Components/HelpCameraSettings/images/help-setting-camera-permission-firefox.png
diff --git a/front/src/Components/Login/LoginScene.svelte b/front/src/Components/Login/LoginScene.svelte
new file mode 100644
index 00000000..fe3c2c63
--- /dev/null
+++ b/front/src/Components/Login/LoginScene.svelte
@@ -0,0 +1,122 @@
+
+
+
+
+
diff --git a/front/src/Components/MyCamera.svelte b/front/src/Components/MyCamera.svelte
new file mode 100644
index 00000000..ed4154a9
--- /dev/null
+++ b/front/src/Components/MyCamera.svelte
@@ -0,0 +1,46 @@
+
+
+
+
+
+ {#if $localStreamStore.type === "success" && $localStreamStore.stream }
+
+
+ {/if}
+
+
diff --git a/front/src/Components/SelectCompanion/SelectCompanionScene.svelte b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte
new file mode 100644
index 00000000..04efe124
--- /dev/null
+++ b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte
@@ -0,0 +1,87 @@
+
+
+
+
+
diff --git a/front/src/Components/SoundMeterWidget.svelte b/front/src/Components/SoundMeterWidget.svelte
new file mode 100644
index 00000000..30650e3f
--- /dev/null
+++ b/front/src/Components/SoundMeterWidget.svelte
@@ -0,0 +1,53 @@
+
+
+
+
+ 1}>
+ 2}>
+ 3}>
+ 4}>
+ 5}>
+
diff --git a/front/src/Components/UI/AudioPlaying.svelte b/front/src/Components/UI/AudioPlaying.svelte
new file mode 100644
index 00000000..97f77429
--- /dev/null
+++ b/front/src/Components/UI/AudioPlaying.svelte
@@ -0,0 +1,52 @@
+
+
+
+
+
Audio message
+
+
+
+
+
+
diff --git a/front/src/Components/UI/ErrorDialog.svelte b/front/src/Components/UI/ErrorDialog.svelte
new file mode 100644
index 00000000..3244de24
--- /dev/null
+++ b/front/src/Components/UI/ErrorDialog.svelte
@@ -0,0 +1,48 @@
+
+
+
+
Error
+
+ {#each $errorStore as error}
+
{error}
+ {/each}
+
+
+ Close
+
+
+
+
diff --git a/front/src/Components/UI/images/megaphone.svg b/front/src/Components/UI/images/megaphone.svg
new file mode 100644
index 00000000..708f860c
--- /dev/null
+++ b/front/src/Components/UI/images/megaphone.svg
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/src/Components/VisitCard/VisitCard.svelte b/front/src/Components/VisitCard/VisitCard.svelte
new file mode 100644
index 00000000..78f10359
--- /dev/null
+++ b/front/src/Components/VisitCard/VisitCard.svelte
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+ {#if hidden}
+
+ {/if}
+
+ {#if !hidden}
+
+
+
+ {/if}
+
+
+
+
diff --git a/front/src/Components/images/cinema-close.svg b/front/src/Components/images/cinema-close.svg
new file mode 100644
index 00000000..aa1d9b17
--- /dev/null
+++ b/front/src/Components/images/cinema-close.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/dist/resources/logos/cinema.svg b/front/src/Components/images/cinema.svg
similarity index 100%
rename from front/dist/resources/logos/cinema.svg
rename to front/src/Components/images/cinema.svg
diff --git a/front/src/Components/images/logo.png b/front/src/Components/images/logo.png
new file mode 100644
index 00000000..f4440ad5
Binary files /dev/null and b/front/src/Components/images/logo.png differ
diff --git a/front/src/Components/images/microphone-close.svg b/front/src/Components/images/microphone-close.svg
new file mode 100644
index 00000000..16731829
--- /dev/null
+++ b/front/src/Components/images/microphone-close.svg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/dist/resources/logos/microphone.svg b/front/src/Components/images/microphone.svg
similarity index 100%
rename from front/dist/resources/logos/microphone.svg
rename to front/src/Components/images/microphone.svg
diff --git a/front/dist/resources/logos/monitor-close.svg b/front/src/Components/images/monitor-close.svg
similarity index 100%
rename from front/dist/resources/logos/monitor-close.svg
rename to front/src/Components/images/monitor-close.svg
diff --git a/front/dist/resources/logos/monitor.svg b/front/src/Components/images/monitor.svg
similarity index 100%
rename from front/dist/resources/logos/monitor.svg
rename to front/src/Components/images/monitor.svg
diff --git a/front/src/Components/selectCharacter/SelectCharacterScene.svelte b/front/src/Components/selectCharacter/SelectCharacterScene.svelte
new file mode 100644
index 00000000..5a37efda
--- /dev/null
+++ b/front/src/Components/selectCharacter/SelectCharacterScene.svelte
@@ -0,0 +1,92 @@
+
+
+
+
+
diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts
index 932fb1fc..8112ba17 100644
--- a/front/src/Connexion/ConnectionManager.ts
+++ b/front/src/Connexion/ConnectionManager.ts
@@ -4,7 +4,7 @@ import {RoomConnection} from "./RoomConnection";
import type {OnConnectInterface, PositionInterface, ViewportInterface} from "./ConnexionModels";
import {GameConnexionTypes, urlManager} from "../Url/UrlManager";
import {localUserStore} from "./LocalUserStore";
-import {LocalUser} from "./LocalUser";
+import {CharacterTexture, LocalUser} from "./LocalUser";
import {Room} from "./Room";
@@ -46,8 +46,8 @@ class ConnectionManager {
urlManager.pushRoomIdToUrl(room);
return Promise.resolve(room);
} else if (connexionType === GameConnexionTypes.organization || connexionType === GameConnexionTypes.anonymous || connexionType === GameConnexionTypes.empty) {
- const localUser = localUserStore.getLocalUser();
+ let localUser = localUserStore.getLocalUser();
if (localUser && localUser.jwtToken && localUser.uuid && localUser.textures) {
this.localUser = localUser;
try {
@@ -57,16 +57,42 @@ class ConnectionManager {
console.error('JWT token invalid. Did it expire? Login anonymously instead.');
await this.anonymousLogin();
}
- } else {
+ }else{
await this.anonymousLogin();
}
- let roomId: string
+
+ localUser = localUserStore.getLocalUser();
+ if(!localUser){
+ throw "Error to store local user data";
+ }
+
+ let roomId: string;
if (connexionType === GameConnexionTypes.empty) {
roomId = START_ROOM_URL;
} else {
roomId = window.location.pathname + window.location.search + window.location.hash;
}
- return Promise.resolve(new Room(roomId));
+
+ //get detail map for anonymous login and set texture in local storage
+ const room = new Room(roomId);
+ const mapDetail = await room.getMapDetail();
+ if(mapDetail.textures != undefined && mapDetail.textures.length > 0) {
+ //check if texture was changed
+ if(localUser.textures.length === 0){
+ localUser.textures = mapDetail.textures;
+ }else{
+ mapDetail.textures.forEach((newTexture) => {
+ const alreadyExistTexture = localUser?.textures.find((c) => newTexture.id === c.id);
+ if(localUser?.textures.findIndex((c) => newTexture.id === c.id) !== -1){
+ return;
+ }
+ localUser?.textures.push(newTexture)
+ });
+ }
+ this.localUser = localUser;
+ localUserStore.saveUser(localUser);
+ }
+ return Promise.resolve(room);
}
return Promise.reject(new Error('Invalid URL'));
diff --git a/front/src/Connexion/ConnexionModels.ts b/front/src/Connexion/ConnexionModels.ts
index 09447445..b5a66296 100644
--- a/front/src/Connexion/ConnexionModels.ts
+++ b/front/src/Connexion/ConnexionModels.ts
@@ -1,5 +1,3 @@
-import {PlayerAnimationDirections} from "../Phaser/Player/Animation";
-import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
import type {SignalData} from "simple-peer";
import type {RoomConnection} from "./RoomConnection";
import type {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures";
@@ -47,6 +45,7 @@ export interface MessageUserPositionInterface {
name: string;
characterLayers: BodyResourceDescriptionInterface[];
position: PointInterface;
+ visitCardUrl: string|null;
companion: string|null;
}
@@ -60,6 +59,7 @@ export interface MessageUserJoined {
name: string;
characterLayers: BodyResourceDescriptionInterface[];
position: PointInterface;
+ visitCardUrl: string | null;
companion: string|null;
}
@@ -85,11 +85,6 @@ export interface WebRtcSignalReceivedMessageInterface {
webRtcPassword: string | undefined
}
-export interface StartMapInterface {
- mapUrlStart: string,
- startInstance: string
-}
-
export interface ViewportInterface {
left: number,
top: number,
diff --git a/front/src/Connexion/LocalUser.ts b/front/src/Connexion/LocalUser.ts
index 0793a938..d240a90e 100644
--- a/front/src/Connexion/LocalUser.ts
+++ b/front/src/Connexion/LocalUser.ts
@@ -9,9 +9,8 @@ export interface CharacterTexture {
export const maxUserNameLength: number = MAX_USERNAME_LENGTH;
-export function isUserNameValid(value: string): boolean {
- const regexp = new RegExp('^[A-Za-z0-9]{1,'+maxUserNameLength+'}$');
- return regexp.test(value);
+export function isUserNameValid(value: unknown): boolean {
+ return typeof value === "string" && value.length > 0 && value.length <= maxUserNameLength && /\S/.test(value);
}
export function areCharacterLayersValid(value: string[] | null): boolean {
@@ -25,6 +24,6 @@ export function areCharacterLayersValid(value: string[] | null): boolean {
}
export class LocalUser {
- constructor(public readonly uuid:string, public readonly jwtToken: string, public readonly textures: CharacterTexture[]) {
+ constructor(public readonly uuid:string, public readonly jwtToken: string, public textures: CharacterTexture[]) {
}
}
diff --git a/front/src/Connexion/Room.ts b/front/src/Connexion/Room.ts
index 05d94440..3ae8d2ed 100644
--- a/front/src/Connexion/Room.ts
+++ b/front/src/Connexion/Room.ts
@@ -1,10 +1,17 @@
import Axios from "axios";
import {PUSHER_URL} from "../Enum/EnvironmentVariable";
+import type {CharacterTexture} from "./LocalUser";
+
+export class MapDetail{
+ constructor(public readonly mapUrl: string, public readonly textures : CharacterTexture[]|undefined) {
+ }
+}
export class Room {
public readonly id: string;
public readonly isPublic: boolean;
private mapUrl: string|undefined;
+ private textures: CharacterTexture[]|undefined;
private instance: string|undefined;
private _search: URLSearchParams;
@@ -50,10 +57,10 @@ export class Room {
return {roomId, hash}
}
- public async getMapUrl(): Promise {
- return new Promise((resolve, reject) => {
- if (this.mapUrl !== undefined) {
- resolve(this.mapUrl);
+ public async getMapDetail(): Promise {
+ return new Promise((resolve, reject) => {
+ if (this.mapUrl !== undefined && this.textures != undefined) {
+ resolve(new MapDetail(this.mapUrl, this.textures));
return;
}
@@ -61,7 +68,7 @@ export class Room {
const match = /_\/[^/]+\/(.+)/.exec(this.id);
if (!match) throw new Error('Could not extract url from "'+this.id+'"');
this.mapUrl = window.location.protocol+'//'+match[1];
- resolve(this.mapUrl);
+ resolve(new MapDetail(this.mapUrl, this.textures));
return;
} else {
// We have a private ID, we need to query the map URL from the server.
@@ -71,7 +78,7 @@ export class Room {
params: urlParts
}).then(({data}) => {
console.log('Map ', this.id, ' resolves to URL ', data.mapUrl);
- resolve(data.mapUrl);
+ resolve(data);
return;
}).catch((reason) => {
reject(reason);
diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts
index 159db5a2..dc9830c3 100644
--- a/front/src/Connexion/RoomConnection.ts
+++ b/front/src/Connexion/RoomConnection.ts
@@ -30,7 +30,7 @@ import {
EmoteEventMessage,
EmotePromptMessage,
SendUserMessage,
- BanUserMessage
+ BanUserMessage,
} from "../Messages/generated/messages_pb"
import type { UserSimplePeerInterface } from "../WebRtc/SimplePeer";
@@ -343,6 +343,7 @@ export class RoomConnection implements RoomConnection {
userId: message.getUserid(),
name: message.getName(),
characterLayers,
+ visitCardUrl: message.getVisitcardurl(),
position: ProtobufClientUtils.toPointInterface(position),
companion: companion ? companion.getName() : null
}
diff --git a/front/src/Enum/EnvironmentVariable.ts b/front/src/Enum/EnvironmentVariable.ts
index 85b63335..73f6427c 100644
--- a/front/src/Enum/EnvironmentVariable.ts
+++ b/front/src/Enum/EnvironmentVariable.ts
@@ -14,6 +14,7 @@ const POSITION_DELAY = 200; // Wait 200ms between sending position events
const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8;
export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || '4');
+export const DISPLAY_TERMS_OF_USE = process.env.DISPLAY_TERMS_OF_USE == 'true';
export const isMobile = ():boolean => ( ( window.innerWidth <= 800 ) || ( window.innerHeight <= 600 ) );
diff --git a/front/src/Phaser/Components/MobileJoystick.ts b/front/src/Phaser/Components/MobileJoystick.ts
index 46efcbc2..b3fc021b 100644
--- a/front/src/Phaser/Components/MobileJoystick.ts
+++ b/front/src/Phaser/Components/MobileJoystick.ts
@@ -28,13 +28,13 @@ export class MobileJoystick extends VirtualJoystick {
this.visible = false;
this.enable = false;
- this.scene.input.on('pointerdown', (pointer: { x: number; y: number; wasTouch: boolean; event: TouchEvent }) => {
+ this.scene.input.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
if (!pointer.wasTouch) {
return;
}
// Let's only display the joystick if there is one finger on the screen
- if (pointer.event.touches.length === 1) {
+ if ((pointer.event as TouchEvent).touches.length === 1) {
this.x = pointer.x;
this.y = pointer.y;
this.visible = true;
diff --git a/front/src/Phaser/Components/SoundMeter.ts b/front/src/Phaser/Components/SoundMeter.ts
index 1d6f7eba..53802d31 100644
--- a/front/src/Phaser/Components/SoundMeter.ts
+++ b/front/src/Phaser/Components/SoundMeter.ts
@@ -1,3 +1,5 @@
+import type {IAnalyserNode, IAudioContext, IMediaStreamAudioSourceNode} from 'standardized-audio-context';
+
/**
* Class to measure the sound volume of a media stream
*/
@@ -5,10 +7,10 @@ export class SoundMeter {
private instant: number;
private clip: number;
//private script: ScriptProcessorNode;
- private analyser: AnalyserNode|undefined;
+ private analyser: IAnalyserNode|undefined;
private dataArray: Uint8Array|undefined;
- private context: AudioContext|undefined;
- private source: MediaStreamAudioSourceNode|undefined;
+ private context: IAudioContext|undefined;
+ private source: IMediaStreamAudioSourceNode|undefined;
constructor() {
this.instant = 0.0;
@@ -16,7 +18,7 @@ export class SoundMeter {
//this.script = context.createScriptProcessor(2048, 1, 1);
}
- private init(context: AudioContext) {
+ private init(context: IAudioContext) {
this.context = context;
this.analyser = this.context.createAnalyser();
@@ -25,8 +27,12 @@ export class SoundMeter {
this.dataArray = new Uint8Array(bufferLength);
}
- public connectToSource(stream: MediaStream, context: AudioContext): void
+ public connectToSource(stream: MediaStream, context: IAudioContext): void
{
+ if (this.source !== undefined) {
+ this.stop();
+ }
+
this.init(context);
this.source = this.context?.createMediaStreamSource(stream);
@@ -81,56 +87,3 @@ export class SoundMeter {
}
-
-// Meter class that generates a number correlated to audio volume.
-// The meter class itself displays nothing, but it makes the
-// instantaneous and time-decaying volumes available for inspection.
-// It also reports on the fraction of samples that were at or near
-// the top of the measurement range.
-/*function SoundMeter(context) {
- this.context = context;
- this.instant = 0.0;
- this.slow = 0.0;
- this.clip = 0.0;
- this.script = context.createScriptProcessor(2048, 1, 1);
- const that = this;
- this.script.onaudioprocess = function(event) {
- const input = event.inputBuffer.getChannelData(0);
- let i;
- let sum = 0.0;
- let clipcount = 0;
- for (i = 0; i < input.length; ++i) {
- sum += input[i] * input[i];
- if (Math.abs(input[i]) > 0.99) {
- clipcount += 1;
- }
- }
- that.instant = Math.sqrt(sum / input.length);
- that.slow = 0.95 * that.slow + 0.05 * that.instant;
- that.clip = clipcount / input.length;
- };
-}
-
-SoundMeter.prototype.connectToSource = function(stream, callback) {
- console.log('SoundMeter connecting');
- try {
- this.mic = this.context.createMediaStreamSource(stream);
- this.mic.connect(this.script);
- // necessary to make sample run, but should not be.
- this.script.connect(this.context.destination);
- if (typeof callback !== 'undefined') {
- callback(null);
- }
- } catch (e) {
- console.error(e);
- if (typeof callback !== 'undefined') {
- callback(e);
- }
- }
-};
-
-SoundMeter.prototype.stop = function() {
- this.mic.disconnect();
- this.script.disconnect();
-};
-*/
diff --git a/front/src/Phaser/Components/SoundMeterSprite.ts b/front/src/Phaser/Components/SoundMeterSprite.ts
deleted file mode 100644
index 582617f9..00000000
--- a/front/src/Phaser/Components/SoundMeterSprite.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import Container = Phaser.GameObjects.Container;
-import type {Scene} from "phaser";
-import GameObject = Phaser.GameObjects.GameObject;
-import Rectangle = Phaser.GameObjects.Rectangle;
-
-
-export class SoundMeterSprite extends Container {
- private rectangles: Rectangle[] = new Array();
- private static readonly NB_BARS = 20;
-
- constructor(scene: Scene, x?: number, y?: number, children?: GameObject[]) {
- super(scene, x, y, children);
-
- for (let i = 0; i < SoundMeterSprite.NB_BARS; i++) {
- const rectangle = new Rectangle(scene, i * 13, 0, 10, 20, (Math.round(255 - i * 255 / SoundMeterSprite.NB_BARS) << 8) + (Math.round(i * 255 / SoundMeterSprite.NB_BARS) << 16));
- this.add(rectangle);
- this.rectangles.push(rectangle);
- }
- }
-
- /**
- * A number between 0 and 100
- *
- * @param volume
- */
- public setVolume(volume: number): void {
-
- const normalizedVolume = volume / 100 * SoundMeterSprite.NB_BARS;
- for (let i = 0; i < SoundMeterSprite.NB_BARS; i++) {
- if (normalizedVolume < i) {
- this.rectangles[i].alpha = 0.5;
- } else {
- this.rectangles[i].alpha = 1;
- }
- }
- }
-
- public getWidth(): number {
- return SoundMeterSprite.NB_BARS * 13;
- }
-
-
-
-}
diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts
index b1a85943..2ff66178 100644
--- a/front/src/Phaser/Entity/Character.ts
+++ b/front/src/Phaser/Entity/Character.ts
@@ -1,6 +1,6 @@
import {PlayerAnimationDirections, PlayerAnimationTypes} from "../Player/Animation";
import {SpeechBubble} from "./SpeechBubble";
-import BitmapText = Phaser.GameObjects.BitmapText;
+import Text = Phaser.GameObjects.Text;
import Container = Phaser.GameObjects.Container;
import Sprite = Phaser.GameObjects.Sprite;
import {TextureError} from "../../Exception/TextureError";
@@ -23,7 +23,7 @@ const interactiveRadius = 35;
export abstract class Character extends Container {
private bubble: SpeechBubble|null = null;
- private readonly playerName: BitmapText;
+ private readonly playerName: Text;
public PlayerValue: string;
public sprites: Map;
private lastDirection: PlayerAnimationDirections = PlayerAnimationDirections.Down;
@@ -41,6 +41,7 @@ export abstract class Character extends Container {
direction: PlayerAnimationDirections,
moving: boolean,
frame: string | number,
+ isClickable: boolean,
companion: string|null,
companionTexturePromise?: Promise
) {
@@ -56,11 +57,11 @@ export abstract class Character extends Container {
this.invisible = false
})
- this.playerName = new BitmapText(scene, 0, playerNameY, 'main_font', name, 7);
- this.playerName.setOrigin(0.5).setCenterAlign().setDepth(DEPTH_INGAME_TEXT_INDEX);
+ this.playerName = new Text(scene, 0, playerNameY, name, {fontFamily: '"Press Start 2P"', fontSize: '8px', strokeThickness: 2, stroke: "gray"});
+ this.playerName.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
this.add(this.playerName);
- if (this.isClickable()) {
+ if (isClickable) {
this.setInteractive({
hitArea: new Phaser.Geom.Circle(0, 0, interactiveRadius),
hitAreaCallback: Phaser.Geom.Circle.Contains, //eslint-disable-line @typescript-eslint/unbound-method
@@ -79,7 +80,7 @@ export abstract class Character extends Container {
this.setDepth(-1);
this.playAnimation(direction, moving);
-
+
if (typeof companion === 'string') {
this.addCompanion(companion, companionTexturePromise);
}
@@ -90,12 +91,10 @@ export abstract class Character extends Container {
this.companion = new Companion(this.scene, this.x, this.y, name, texturePromise);
}
}
-
- public abstract isClickable(): boolean;
public addTextures(textures: string[], frame?: string | number): void {
for (const texture of textures) {
- if(!this.scene.textures.exists(texture)){
+ if(this.scene && !this.scene.textures.exists(texture)){
throw new TextureError('texture not found');
}
const sprite = new Sprite(this.scene, 0, 0, texture, frame);
@@ -240,28 +239,28 @@ export abstract class Character extends Container {
this.scene.sys.updateList.remove(sprite);
}
}
- this.list.forEach(objectContaining => objectContaining.destroy())
+ this.list.forEach(objectContaining => objectContaining.destroy())
super.destroy();
}
-
+
playEmote(emoteKey: string) {
this.cancelPreviousEmote();
const scalingFactor = waScaleManager.uiScalingFactor * 0.05;
const emoteY = -30 - scalingFactor * 10;
-
+
this.playerName.setVisible(false);
this.emote = new Sprite(this.scene, 0, 0, emoteKey);
this.emote.setAlpha(0);
this.emote.setScale(0.1 * scalingFactor);
this.add(this.emote);
this.scene.sys.updateList.add(this.emote);
-
+
this.createStartTransition(scalingFactor, emoteY);
}
private createStartTransition(scalingFactor: number, emoteY: number) {
- this.emoteTween = this.scene.tweens.add({
+ this.emoteTween = this.scene?.tweens.add({
targets: this.emote,
props: {
scale: scalingFactor,
@@ -277,7 +276,7 @@ export abstract class Character extends Container {
}
private startPulseTransition(emoteY: number, scalingFactor: number) {
- this.emoteTween = this.scene.tweens.add({
+ this.emoteTween = this.scene?.tweens.add({
targets: this.emote,
props: {
y: emoteY * 1.3,
@@ -294,7 +293,7 @@ export abstract class Character extends Container {
}
private startExitTransition(emoteY: number) {
- this.emoteTween = this.scene.tweens.add({
+ this.emoteTween = this.scene?.tweens.add({
targets: this.emote,
props: {
alpha: 0,
diff --git a/front/src/Phaser/Entity/CustomizedCharacter.ts b/front/src/Phaser/Entity/CustomizedCharacter.ts
new file mode 100644
index 00000000..3a7f1597
--- /dev/null
+++ b/front/src/Phaser/Entity/CustomizedCharacter.ts
@@ -0,0 +1,20 @@
+import Container = Phaser.GameObjects.Container;
+import type {Scene} from "phaser";
+import Sprite = Phaser.GameObjects.Sprite;
+
+/**
+ * A sprite of a customized character (used in the Customize Scene only)
+ */
+export class CustomizedCharacter extends Container {
+ public constructor(scene: Scene, x: number, y: number, layers: string[]) {
+ super(scene, x, y);
+ this.updateSprites(layers);
+ }
+
+ public updateSprites(layers: string[]): void {
+ this.removeAll(true);
+ for (const layer of layers) {
+ this.add(new Sprite(this.scene, 0, 0, layer));
+ }
+ }
+}
diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts
index 4e00f102..32881e97 100644
--- a/front/src/Phaser/Entity/RemotePlayer.ts
+++ b/front/src/Phaser/Entity/RemotePlayer.ts
@@ -2,12 +2,15 @@ import type {GameScene} from "../Game/GameScene";
import type {PointInterface} from "../../Connexion/ConnexionModels";
import {Character} from "../Entity/Character";
import type {PlayerAnimationDirections} from "../Player/Animation";
+import {requestVisitCardsStore} from "../../Stores/GameStore";
+
/**
* Class representing the sprite of a remote player (a player that plays on another computer)
*/
export class RemotePlayer extends Character {
userId: number;
+ private visitCardUrl: string|null;
constructor(
userId: number,
@@ -18,13 +21,19 @@ export class RemotePlayer extends Character {
texturesPromise: Promise,
direction: PlayerAnimationDirections,
moving: boolean,
+ visitCardUrl: string|null,
companion: string|null,
companionTexturePromise?: Promise
) {
- super(Scene, x, y, texturesPromise, name, direction, moving, 1, companion, companionTexturePromise);
+ super(Scene, x, y, texturesPromise, name, direction, moving, 1, !!visitCardUrl, companion, companionTexturePromise);
//set data
this.userId = userId;
+ this.visitCardUrl = visitCardUrl;
+
+ this.on('pointerdown', () => {
+ requestVisitCardsStore.set(this.visitCardUrl);
+ })
}
updatePosition(position: PointInterface): void {
@@ -38,8 +47,4 @@ export class RemotePlayer extends Character {
this.companion.setTarget(position.x, position.y, position.direction as PlayerAnimationDirections);
}
}
-
- isClickable(): boolean {
- return false; //todo: make remote players clickable if they are logged in.
- }
}
diff --git a/front/src/Phaser/Game/AddPlayerInterface.ts b/front/src/Phaser/Game/AddPlayerInterface.ts
index 70c341ee..1a5176f0 100644
--- a/front/src/Phaser/Game/AddPlayerInterface.ts
+++ b/front/src/Phaser/Game/AddPlayerInterface.ts
@@ -6,5 +6,6 @@ export interface AddPlayerInterface {
name: string;
characterLayers: BodyResourceDescriptionInterface[];
position: PointInterface;
+ visitCardUrl: string|null;
companion: string|null;
}
diff --git a/front/src/Phaser/Game/DirtyScene.ts b/front/src/Phaser/Game/DirtyScene.ts
index ecc81a99..8a559310 100644
--- a/front/src/Phaser/Game/DirtyScene.ts
+++ b/front/src/Phaser/Game/DirtyScene.ts
@@ -70,7 +70,7 @@ export abstract class DirtyScene extends ResizableScene {
return this.dirty || this.objectListChanged;
}
- public onResize(ev: UIEvent): void {
+ public onResize(): void {
this.objectListChanged = true;
}
}
diff --git a/front/src/Phaser/Game/Game.ts b/front/src/Phaser/Game/Game.ts
index 01aecf9f..e267e80a 100644
--- a/front/src/Phaser/Game/Game.ts
+++ b/front/src/Phaser/Game/Game.ts
@@ -21,14 +21,22 @@ export class Game extends Phaser.Game {
constructor(GameConfig: Phaser.Types.Core.GameConfig) {
super(GameConfig);
- window.addEventListener('resize', (event) => {
+ this.scale.on(Phaser.Scale.Events.RESIZE, () => {
+ for (const scene of this.scene.getScenes(true)) {
+ if (scene instanceof ResizableScene) {
+ scene.onResize();
+ }
+ }
+ })
+
+ /*window.addEventListener('resize', (event) => {
// Let's trigger the onResize method of any active scene that is a ResizableScene
for (const scene of this.scene.getScenes(true)) {
if (scene instanceof ResizableScene) {
scene.onResize(event);
}
}
- });
+ });*/
}
public step(time: number, delta: number)
diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts
index 9b699889..a694b32e 100644
--- a/front/src/Phaser/Game/GameManager.ts
+++ b/front/src/Phaser/Game/GameManager.ts
@@ -2,11 +2,13 @@ import {GameScene} from "./GameScene";
import {connectionManager} from "../../Connexion/ConnectionManager";
import type {Room} from "../../Connexion/Room";
import {MenuScene, MenuSceneName} from "../Menu/MenuScene";
-import {HelpCameraSettingsScene, HelpCameraSettingsSceneName} from "../Menu/HelpCameraSettingsScene";
import {LoginSceneName} from "../Login/LoginScene";
import {SelectCharacterSceneName} from "../Login/SelectCharacterScene";
import {EnableCameraSceneName} from "../Login/EnableCameraScene";
import {localUserStore} from "../../Connexion/LocalUserStore";
+import {get} from "svelte/store";
+import {requestedCameraState, requestedMicrophoneState} from "../../Stores/MediaStore";
+import {helpCameraSettingsVisibleStore} from "../../Stores/HelpCameraSettingsStore";
@@ -71,11 +73,11 @@ export class GameManager {
public async loadMap(room: Room, scenePlugin: Phaser.Scenes.ScenePlugin): Promise {
const roomID = room.id;
- const mapUrl = await room.getMapUrl();
+ const mapDetail = await room.getMapDetail();
const gameIndex = scenePlugin.getIndex(roomID);
if(gameIndex === -1){
- const game : Phaser.Scene = new GameScene(room, mapUrl);
+ const game : Phaser.Scene = new GameScene(room, mapDetail.mapUrl);
scenePlugin.add(roomID, game, false);
}
}
@@ -84,7 +86,11 @@ export class GameManager {
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
scenePlugin.launch(MenuSceneName);
- scenePlugin.launch(HelpCameraSettingsSceneName);//700
+
+ if(!localUserStore.getHelpCameraSettingsShown() && (!get(requestedMicrophoneState) || !get(requestedCameraState))){
+ helpCameraSettingsVisibleStore.set(true);
+ localUserStore.setHelpCameraSettingsShown();
+ }
}
public gameSceneIsCreated(scene: GameScene) {
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index f494b553..09785e0b 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -1,4 +1,4 @@
-import {gameManager} from "./GameManager";
+import {gameManager, HasMovedEvent} from "./GameManager";
import type {
GroupCreatedUpdatedMessageInterface,
MessageUserJoined,
@@ -9,7 +9,7 @@ import type {
PositionInterface,
RoomJoinedMessageInterface
} from "../../Connexion/ConnexionModels";
-import { hasMovedEventName, Player , requestEmoteEventName} from "../Player/Player";
+import {hasMovedEventName, Player, requestEmoteEventName} from "../Player/Player";
import {
DEBUG_MODE,
JITSI_PRIVATE_MODE,
@@ -21,7 +21,6 @@ import type {
ITiledMapLayer,
ITiledMapLayerProperty,
ITiledMapObject,
- ITiledText,
ITiledMapTileLayer,
ITiledTileSet
} from "../Map/ITiledMap";
@@ -81,8 +80,9 @@ import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import DOMElement = Phaser.GameObjects.DOMElement;
-import type { Subscription } from "rxjs";
-import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
+import EVENT_TYPE =Phaser.Scenes.Events
+import type {Subscription} from "rxjs";
+import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
import RenderTexture = Phaser.GameObjects.RenderTexture;
import Tilemap = Phaser.Tilemaps.Tilemap;
@@ -161,6 +161,7 @@ export class GameScene extends DirtyScene implements CenterListener {
private createPromise: Promise;
private createPromiseResolve!: (value?: void | PromiseLike) => void;
private iframeSubscriptionList!: Array;
+ private peerStoreUnsubscribe!: () => void;
MapUrlFile: string;
RoomId: string;
instance: string;
@@ -229,11 +230,11 @@ export class GameScene extends DirtyScene implements CenterListener {
this.load.image(joystickBaseKey, joystickBaseImg);
this.load.image(joystickThumbKey, joystickThumbImg);
}
- //todo: in an emote manager.
- this.load.spritesheet('emote-music', 'resources/emotes/pipo-popupemotes005.png', {
- frameHeight: 32,
- frameWidth: 32,
- });
+ this.load.audio('audio-webrtc-in', '/resources/objects/webrtc-in.mp3');
+ this.load.audio('audio-webrtc-out', '/resources/objects/webrtc-out.mp3');
+ //this.load.audio('audio-report-message', '/resources/objects/report-message.mp3');
+ this.sound.pauseOnBlur = false;
+
this.load.on(FILE_LOAD_ERROR, (file: { src: string }) => {
// If we happen to be in HTTP and we are trying to load a URL in HTTPS only... (this happens only in dev environments)
if (window.location.protocol === 'http:' && file.src === this.MapUrlFile && file.src.startsWith('http:') && this.originalMapUrl === undefined) {
@@ -280,6 +281,14 @@ export class GameScene extends DirtyScene implements CenterListener {
this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', { frameWidth: 32, frameHeight: 32 });
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
+ //eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (this.load as any).rexWebFont({
+ custom: {
+ families: ['Press Start 2P'],
+ urls: ['/resources/fonts/fonts.css'],
+ testString: 'abcdefg'
+ },
+ });
//this function must stay at the end of preload function
addLoader(this);
@@ -508,6 +517,21 @@ export class GameScene extends DirtyScene implements CenterListener {
}
this.emoteManager = new EmoteManager(this);
+
+ let oldPeerNumber = 0;
+ this.peerStoreUnsubscribe = peerStore.subscribe((peers) => {
+ const newPeerNumber = peers.size;
+ if (newPeerNumber > oldPeerNumber) {
+ this.sound.play('audio-webrtc-in', {
+ volume: 0.2
+ });
+ } else if (newPeerNumber < oldPeerNumber) {
+ this.sound.play('audio-webrtc-out', {
+ volume: 0.2
+ });
+ }
+ oldPeerNumber = newPeerNumber;
+ });
}
/**
@@ -540,6 +564,7 @@ export class GameScene extends DirtyScene implements CenterListener {
characterLayers: message.characterLayers,
name: message.name,
position: message.position,
+ visitCardUrl: message.visitCardUrl,
companion: message.companion
}
this.addPlayer(userMessage);
@@ -888,10 +913,16 @@ ${escapedMessage}
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(() => {
this.userInputManager.restoreControls();
}));
-
- let scriptedBubbleSprite: Sprite;
- this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(() => {
- scriptedBubbleSprite = new Sprite(this, this.CurrentPlayer.x + 25, this.CurrentPlayer.y, 'circleSprite-white');
+ this.iframeSubscriptionList.push(iframeListener.loadPageStream.subscribe((url:string)=>{
+ this.loadNextGame(url).then(()=>{
+ this.events.once(EVENT_TYPE.POST_UPDATE,()=>{
+ this.onMapExit(url);
+ })
+ })
+ }));
+ let scriptedBubbleSprite : Sprite;
+ this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{
+ scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white');
scriptedBubbleSprite.setDisplayOrigin(48, 48);
this.add.existing(scriptedBubbleSprite);
}));
@@ -1004,6 +1035,9 @@ ${escapedMessage}
this.userInputManager.destroy();
this.pinchManager?.destroy();
this.emoteManager.destroy();
+ this.peerStoreUnsubscribe();
+
+ mediaManager.hideGameOverlay();
for (const iframeEvents of this.iframeSubscriptionList) {
iframeEvents.unsubscribe();
@@ -1115,10 +1149,10 @@ ${escapedMessage}
}
//todo: push that into the gameManager
- private loadNextGame(exitSceneIdentifier: string) : void{
+ private loadNextGame(exitSceneIdentifier: string) : Promise{
const { roomId, hash } = Room.getIdFromIdentifier(exitSceneIdentifier, this.MapUrlFile, this.instance);
const room = new Room(roomId);
- gameManager.loadMap(room, this.scene).catch(() => {});
+ return gameManager.loadMap(room, this.scene).catch(() => {});
}
private startUser(layer: ITiledMapTileLayer): PositionInterface {
@@ -1192,7 +1226,10 @@ ${escapedMessage}
this.companion,
this.companion !== null ? lazyLoadCompanionResource(this.load, this.companion) : undefined
);
- this.CurrentPlayer.on('pointerdown', () => {
+ this.CurrentPlayer.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
+ if (pointer.wasTouch && (pointer.event as TouchEvent).touches.length > 1) {
+ return; //we don't want the menu to open when pinching on a touch screen.
+ }
this.emoteManager.getMenuImages().then((emoteMenuElements) => this.CurrentPlayer.openOrCloseEmoteMenu(emoteMenuElements))
})
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
@@ -1392,6 +1429,7 @@ ${escapedMessage}
texturesPromise,
addPlayerData.position.direction as PlayerAnimationDirections,
addPlayerData.position.moving,
+ addPlayerData.visitCardUrl,
addPlayerData.companion,
addPlayerData.companion !== null ? lazyLoadCompanionResource(this.load, addPlayerData.companion) : undefined
);
@@ -1498,8 +1536,8 @@ ${escapedMessage}
this.connection?.emitActionableEvent(itemId, eventName, state, parameters);
}
- public onResize(ev: UIEvent): void {
- super.onResize(ev);
+ public onResize(): void {
+ super.onResize();
this.reposition();
// Send new viewport to server
diff --git a/front/src/Phaser/Game/SoundManager.ts b/front/src/Phaser/Game/SoundManager.ts
index f0210494..47614fca 100644
--- a/front/src/Phaser/Game/SoundManager.ts
+++ b/front/src/Phaser/Game/SoundManager.ts
@@ -17,7 +17,9 @@ class SoundManager {
return res(sound);
}
loadPlugin.audio(soundUrl, soundUrl);
- loadPlugin.once('filecomplete-audio-' + soundUrl, () => res(soundManager.add(soundUrl)));
+ loadPlugin.once('filecomplete-audio-' + soundUrl, () => {
+ res(soundManager.add(soundUrl));
+ });
loadPlugin.start();
});
this.soundPromises.set(soundUrl,soundPromise);
diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts
index 8b9a9a7a..715cb67d 100644
--- a/front/src/Phaser/Login/CustomizeScene.ts
+++ b/front/src/Phaser/Login/CustomizeScene.ts
@@ -2,30 +2,32 @@ import {EnableCameraSceneName} from "./EnableCameraScene";
import Rectangle = Phaser.GameObjects.Rectangle;
import {loadAllLayers} from "../Entity/PlayerTexturesLoadingManager";
import Sprite = Phaser.GameObjects.Sprite;
-import Container = Phaser.GameObjects.Container;
import {gameManager} from "../Game/GameManager";
import {localUserStore} from "../../Connexion/LocalUserStore";
import {addLoader} from "../Components/Loader";
import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
import {AbstractCharacterScene} from "./AbstractCharacterScene";
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
-import { MenuScene } from "../Menu/MenuScene";
import { SelectCharacterSceneName } from "./SelectCharacterScene";
+import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStore";
+import {waScaleManager} from "../Services/WaScaleManager";
+import {isMobile} from "../../Enum/EnvironmentVariable";
+import {CustomizedCharacter} from "../Entity/CustomizedCharacter";
export const CustomizeSceneName = "CustomizeScene";
-export const CustomizeSceneKey = "CustomizeScene";
-const customizeSceneKey = 'customizeScene';
-
export class CustomizeScene extends AbstractCharacterScene {
private Rectangle!: Rectangle;
private selectedLayers: number[] = [0];
- private containersRow: Container[][] = [];
- private activeRow:number = 0;
+ private containersRow: CustomizedCharacter[][] = [];
+ public activeRow:number = 0;
private layers: BodyResourceDescriptionInterface[][] = [];
- private customizeSceneElement!: Phaser.GameObjects.DOMElement;
+ protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
+
+ private moveHorizontally: number = 0;
+ private moveVertically: number = 0;
constructor() {
super({
@@ -34,9 +36,7 @@ export class CustomizeScene extends AbstractCharacterScene {
}
preload() {
- this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
- this.layers = loadAllLayers(this.load);
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
if(bodyResourceDescription.level == undefined || bodyResourceDescription.level < 0 || bodyResourceDescription.level > 5 ){
@@ -44,43 +44,28 @@ export class CustomizeScene extends AbstractCharacterScene {
}
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
});
+ this.lazyloadingAttempt = true;
});
+ this.layers = loadAllLayers(this.load);
+ this.lazyloadingAttempt = false;
+
+
//this function must stay at the end of preload function
addLoader(this);
}
create() {
- this.customizeSceneElement = this.add.dom(-1000, 0).createFromCache(customizeSceneKey);
- this.centerXDomElement(this.customizeSceneElement, 150);
- MenuScene.revealMenusAfterInit(this.customizeSceneElement, customizeSceneKey);
-
- this.customizeSceneElement.addListener('click');
- this.customizeSceneElement.on('click', (event:MouseEvent) => {
- event.preventDefault();
- if((event?.target as HTMLInputElement).id === 'customizeSceneButtonLeft') {
- this.moveCursorHorizontally(-1);
- }else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonRight') {
- this.moveCursorHorizontally(1);
- }else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonDown') {
- this.moveCursorVertically(1);
- }else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonUp') {
- this.moveCursorVertically(-1);
- }else if((event?.target as HTMLInputElement).id === 'customizeSceneFormBack') {
- if(this.activeRow > 0){
- this.moveCursorVertically(-1);
- }else{
- this.backToPreviousScene();
- }
- }else if((event?.target as HTMLButtonElement).id === 'customizeSceneFormSubmit') {
- if(this.activeRow < 5){
- this.moveCursorVertically(1);
- }else{
- this.nextSceneToCamera();
- }
- }
+ customCharacterSceneVisibleStore.set(true);
+ this.events.addListener('wake', () => {
+ waScaleManager.saveZoom();
+ waScaleManager.zoomModifier = isMobile() ? 3 : 1;
+ customCharacterSceneVisibleStore.set(true);
});
+ waScaleManager.saveZoom();
+ waScaleManager.zoomModifier = isMobile() ? 3 : 1;
+
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 3, 32, 33)
this.Rectangle.setStrokeStyle(2, 0xFFFFFF);
this.add.existing(this.Rectangle);
@@ -100,10 +85,13 @@ export class CustomizeScene extends AbstractCharacterScene {
this.backToPreviousScene();
});
- this.input.keyboard.on('keyup-RIGHT', () => this.moveCursorHorizontally(1));
- this.input.keyboard.on('keyup-LEFT', () => this.moveCursorHorizontally(-1));
- this.input.keyboard.on('keyup-DOWN', () => this.moveCursorVertically(1));
- this.input.keyboard.on('keyup-UP', () => this.moveCursorVertically(-1));
+ // Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods
+ // because if 2 such events are fired close to one another, it makes the whole application crawl to a halt (for a reason I cannot
+ // explain, the list of sprites managed by the update list become immense
+ this.input.keyboard.on('keyup-RIGHT', () => this.moveHorizontally = 1);
+ this.input.keyboard.on('keyup-LEFT', () => this.moveHorizontally = -1);
+ this.input.keyboard.on('keyup-DOWN', () => this.moveVertically = 1);
+ this.input.keyboard.on('keyup-UP', () => this.moveVertically = -1);
const customCursorPosition = localUserStore.getCustomCursorPosition();
if (customCursorPosition) {
@@ -116,7 +104,15 @@ export class CustomizeScene extends AbstractCharacterScene {
this.onResize();
}
- private moveCursorHorizontally(index: number): void {
+ public moveCursorHorizontally(index: number): void {
+ this.moveHorizontally = index;
+ }
+
+ public moveCursorVertically(index: number): void {
+ this.moveVertically = index;
+ }
+
+ private doMoveCursorHorizontally(index: number): void {
this.selectedLayers[this.activeRow] += index;
if (this.selectedLayers[this.activeRow] < 0) {
this.selectedLayers[this.activeRow] = 0
@@ -128,27 +124,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.saveInLocalStorage();
}
- private moveCursorVertically(index:number): void {
-
- if(index === -1 && this.activeRow === 5){
- const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
- button.innerHTML = `Next `;
- }
-
- if(index === 1 && this.activeRow === 4){
- const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
- button.innerText = 'Finish';
- }
-
- if(index === -1 && this.activeRow === 1){
- const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
- button.innerText = `Return`;
- }
-
- if(index === 1 && this.activeRow === 0){
- const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
- button.innerHTML = `Back `;
- }
+ private doMoveCursorVertically(index:number): void {
this.activeRow += index;
if (this.activeRow < 0) {
@@ -197,20 +173,20 @@ export class CustomizeScene extends AbstractCharacterScene {
* @param selectedItem, The number of the item select (0 for black body...)
*/
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) {
- return new Container(this, x, y,this.getContainerChildren(layerNumber,selectedItem));
+ return new CustomizedCharacter(this, x, y, this.getContainerChildren(layerNumber,selectedItem));
}
- private getContainerChildren(layerNumber: number, selectedItem: number): Array {
- const children: Array = new Array();
+ private getContainerChildren(layerNumber: number, selectedItem: number): Array {
+ const children: Array = new Array();
for (let j = 0; j <= layerNumber; j++) {
if (j === layerNumber) {
- children.push(this.generateLayers(0, 0, this.layers[j][selectedItem].name));
+ children.push(this.layers[j][selectedItem].name);
} else {
const layer = this.selectedLayers[j];
if (layer === undefined) {
continue;
}
- children.push(this.generateLayers(0, 0, this.layers[j][layer].name));
+ children.push(this.layers[j][layer].name);
}
}
return children;
@@ -247,33 +223,47 @@ export class CustomizeScene extends AbstractCharacterScene {
* @return a new sprite
*/
private generateLayers(x: number, y: number, name: string): Sprite {
- return new Sprite(this, x, y, name);
+ //return new Sprite(this, x, y, name);
+ return this.add.sprite(0, 0, name);
}
private updateSelectedLayer() {
for(let i = 0; i < this.containersRow.length; i++){
for(let j = 0; j < this.containersRow[i].length; j++){
- const children = this.getContainerChildren(i, j);
- this.containersRow[i][j].removeAll(true);
- this.containersRow[i][j].add(children);
+ const children = this.getContainerChildren(i, j);
+ this.containersRow[i][j].updateSprites(children);
}
}
}
update(time: number, delta: number): void {
+ if(this.lazyloadingAttempt){
+ this.moveLayers();
+ this.lazyloadingAttempt = false;
+ }
+
+ if (this.moveHorizontally !== 0) {
+ this.doMoveCursorHorizontally(this.moveHorizontally);
+ this.moveHorizontally = 0;
+ }
+ if (this.moveVertically !== 0) {
+ this.doMoveCursorVertically(this.moveVertically);
+ this.moveVertically = 0;
+ }
}
+
+
+
public onResize(): void {
this.moveLayers();
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
-
- this.centerXDomElement(this.customizeSceneElement, 150);
}
- private nextSceneToCamera(){
+ public nextSceneToCamera(){
const layers: string[] = [];
let i = 0;
for (const layerItem of this.selectedLayers) {
@@ -288,12 +278,16 @@ export class CustomizeScene extends AbstractCharacterScene {
gameManager.setCharacterLayers(layers);
this.scene.sleep(CustomizeSceneName);
- this.scene.remove(SelectCharacterSceneName);
+ waScaleManager.restoreZoom();
+ this.events.removeListener('wake');
gameManager.tryResumingGame(this, EnableCameraSceneName);
+ customCharacterSceneVisibleStore.set(false);
}
- private backToPreviousScene(){
+ public backToPreviousScene(){
this.scene.sleep(CustomizeSceneName);
+ waScaleManager.restoreZoom();
this.scene.run(SelectCharacterSceneName);
+ customCharacterSceneVisibleStore.set(false);
}
}
diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts
index 6002da7b..ba27cd07 100644
--- a/front/src/Phaser/Login/EnableCameraScene.ts
+++ b/front/src/Phaser/Login/EnableCameraScene.ts
@@ -3,7 +3,6 @@ import {TextField} from "../Components/TextField";
import Image = Phaser.GameObjects.Image;
import {mediaManager} from "../../WebRtc/MediaManager";
import {SoundMeter} from "../Components/SoundMeter";
-import {SoundMeterSprite} from "../Components/SoundMeterSprite";
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
import {touchScreenManager} from "../../Touch/TouchScreenManager";
import {PinchManager} from "../UserInput/PinchManager";
@@ -11,304 +10,41 @@ import Zone = Phaser.GameObjects.Zone;
import { MenuScene } from "../Menu/MenuScene";
import {ResizableScene} from "./ResizableScene";
import {
- audioConstraintStore,
enableCameraSceneVisibilityStore,
- localStreamStore,
- mediaStreamConstraintsStore,
- videoConstraintStore
} from "../../Stores/MediaStore";
-import type {Unsubscriber} from "svelte/store";
export const EnableCameraSceneName = "EnableCameraScene";
-enum LoginTextures {
- playButton = "play_button",
- icon = "icon",
- mainFont = "main_font",
- arrowRight = "arrow_right",
- arrowUp = "arrow_up"
-}
-
-const enableCameraSceneKey = 'enableCameraScene';
export class EnableCameraScene extends ResizableScene {
- private textField!: TextField;
- private cameraNameField!: TextField;
- private arrowLeft!: Image;
- private arrowRight!: Image;
- private arrowDown!: Image;
- private arrowUp!: Image;
- private microphonesList: MediaDeviceInfo[] = new Array();
- private camerasList: MediaDeviceInfo[] = new Array();
- private cameraSelected: number = 0;
- private microphoneSelected: number = 0;
- private soundMeter: SoundMeter;
- private soundMeterSprite!: SoundMeterSprite;
- private microphoneNameField!: TextField;
-
- private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
-
- private mobileTapZone!: Zone;
- private localStreamStoreUnsubscriber!: Unsubscriber;
constructor() {
super({
key: EnableCameraSceneName
});
- this.soundMeter = new SoundMeter();
}
preload() {
-
- this.load.html(enableCameraSceneKey, 'resources/html/EnableCameraScene.html');
-
- this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
- this.load.image(LoginTextures.arrowRight, "resources/objects/arrow_right.png");
- this.load.image(LoginTextures.arrowUp, "resources/objects/arrow_up.png");
- // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
- this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
}
create() {
- this.enableCameraSceneElement = this.add.dom(-1000, 0).createFromCache(enableCameraSceneKey);
- this.centerXDomElement(this.enableCameraSceneElement, 300);
-
- MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
-
- const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
- continuingButton.addEventListener('click', (e) => {
- e.preventDefault();
- this.login();
- });
-
- if (touchScreenManager.supportTouchScreen) {
- new PinchManager(this);
- }
- //this.scale.setZoom(ZOOM_LEVEL);
- //Phaser.Display.Align.In.BottomCenter(this.pressReturnField, zone);
-
- /* FIX ME */
- this.textField = new TextField(this, this.scale.width / 2, 20, '');
-
- // For mobile purposes - we need a big enough touchable area.
- this.mobileTapZone = this.add.zone(this.scale.width / 2,this.scale.height - 30,200,50)
- .setInteractive().on("pointerdown", () => {
- this.login();
- });
-
- this.cameraNameField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 60, '');
-
- this.microphoneNameField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 40, '');
-
- this.arrowRight = new Image(this, 0, 0, LoginTextures.arrowRight);
- this.arrowRight.setVisible(false);
- this.arrowRight.setInteractive().on('pointerdown', this.nextCam.bind(this));
- this.add.existing(this.arrowRight);
-
- this.arrowLeft = new Image(this, 0, 0, LoginTextures.arrowRight);
- this.arrowLeft.setVisible(false);
- this.arrowLeft.flipX = true;
- this.arrowLeft.setInteractive().on('pointerdown', this.previousCam.bind(this));
- this.add.existing(this.arrowLeft);
-
- this.arrowUp = new Image(this, 0, 0, LoginTextures.arrowUp);
- this.arrowUp.setVisible(false);
- this.arrowUp.setInteractive().on('pointerdown', this.previousMic.bind(this));
- this.add.existing(this.arrowUp);
-
- this.arrowDown = new Image(this, 0, 0, LoginTextures.arrowUp);
- this.arrowDown.setVisible(false);
- this.arrowDown.flipY = true;
- this.arrowDown.setInteractive().on('pointerdown', this.nextMic.bind(this));
- this.add.existing(this.arrowDown);
-
this.input.keyboard.on('keyup-ENTER', () => {
this.login();
});
- HtmlUtils.getElementByIdOrFail('webRtcSetup').classList.add('active');
-
- this.localStreamStoreUnsubscriber = localStreamStore.subscribe((result) => {
- if (result.type === 'error') {
- // TODO: proper handling of the error
- throw result.error;
- }
-
- this.getDevices();
- if (result.stream !== null) {
- this.setupStream(result.stream);
- }
- });
- /*const mediaPromise = mediaManager.getCamera();
- mediaPromise.then(this.getDevices.bind(this));
- mediaPromise.then(this.setupStream.bind(this));*/
-
- this.input.keyboard.on('keydown-RIGHT', this.nextCam.bind(this));
- this.input.keyboard.on('keydown-LEFT', this.previousCam.bind(this));
- this.input.keyboard.on('keydown-DOWN', this.nextMic.bind(this));
- this.input.keyboard.on('keydown-UP', this.previousMic.bind(this));
-
- this.soundMeterSprite = new SoundMeterSprite(this, 50, 50);
- this.soundMeterSprite.setVisible(false);
- this.add.existing(this.soundMeterSprite);
-
- this.onResize();
-
enableCameraSceneVisibilityStore.showEnableCameraScene();
}
- private previousCam(): void {
- if (this.cameraSelected === 0 || this.camerasList.length === 0) {
- return;
- }
- this.cameraSelected--;
- videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
-
- //mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
- }
-
- private nextCam(): void {
- if (this.cameraSelected === this.camerasList.length - 1 || this.camerasList.length === 0) {
- return;
- }
- this.cameraSelected++;
- videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
-
- // TODO: the change of camera should be OBSERVED (reactive)
- //mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
- }
-
- private previousMic(): void {
- if (this.microphoneSelected === 0 || this.microphonesList.length === 0) {
- return;
- }
- this.microphoneSelected--;
- audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
- //mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
- }
-
- private nextMic(): void {
- if (this.microphoneSelected === this.microphonesList.length - 1 || this.microphonesList.length === 0) {
- return;
- }
- this.microphoneSelected++;
- audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
- // TODO: the change of camera should be OBSERVED (reactive)
- //mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
- }
-
- /**
- * Function called each time a camera is changed
- */
- private setupStream(stream: MediaStream): void {
- const img = HtmlUtils.getElementByIdOrFail('webRtcSetupNoVideo');
- img.style.display = 'none';
-
- const div = HtmlUtils.getElementByIdOrFail('myCamVideoSetup');
- div.srcObject = stream;
-
- this.soundMeter.connectToSource(stream, new window.AudioContext());
- this.soundMeterSprite.setVisible(true);
-
- this.updateWebCamName();
- }
-
- private updateWebCamName(): void {
- if (this.camerasList.length > 1) {
- let label = this.camerasList[this.cameraSelected].label;
- // remove text in parenthesis
- label = label.replace(/\([^()]*\)/g, '').trim();
- // remove accents
- label = label.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
- this.cameraNameField.text = label;
-
- this.arrowRight.setVisible(this.cameraSelected < this.camerasList.length - 1);
- this.arrowLeft.setVisible(this.cameraSelected > 0);
- }
- if (this.microphonesList.length > 1) {
- let label = this.microphonesList[this.microphoneSelected].label;
- // remove text in parenthesis
- label = label.replace(/\([^()]*\)/g, '').trim();
- // remove accents
- label = label.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
-
- this.microphoneNameField.text = label;
-
- this.arrowDown.setVisible(this.microphoneSelected < this.microphonesList.length - 1);
- this.arrowUp.setVisible(this.microphoneSelected > 0);
-
- }
- }
-
public onResize(): void {
- let div = HtmlUtils.getElementByIdOrFail('myCamVideoSetup');
- let bounds = div.getBoundingClientRect();
- if (!div.srcObject) {
- div = HtmlUtils.getElementByIdOrFail('webRtcSetup');
- bounds = div.getBoundingClientRect();
- }
-
- this.textField.x = this.game.renderer.width / 2;
- this.mobileTapZone.x = this.game.renderer.width / 2;
- this.cameraNameField.x = this.game.renderer.width / 2;
- this.microphoneNameField.x = this.game.renderer.width / 2;
-
- this.cameraNameField.y = bounds.top / this.scale.zoom - 8;
-
- this.soundMeterSprite.x = this.game.renderer.width / 2 - this.soundMeterSprite.getWidth() / 2;
- this.soundMeterSprite.y = bounds.bottom / this.scale.zoom + 16;
-
- this.microphoneNameField.y = this.soundMeterSprite.y + 22;
-
- this.arrowRight.x = bounds.right / this.scale.zoom + 16;
- this.arrowRight.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
-
- this.arrowLeft.x = bounds.left / this.scale.zoom - 16;
- this.arrowLeft.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
-
- this.arrowDown.x = this.microphoneNameField.x + this.microphoneNameField.width / 2 + 16;
- this.arrowDown.y = this.microphoneNameField.y;
-
- this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
- this.arrowUp.y = this.microphoneNameField.y;
-
- const actionBtn = document.querySelector('#enableCameraScene .action');
- if (actionBtn !== null) {
- actionBtn.style.top = (this.scale.height - 65) + 'px';
- }
}
update(time: number, delta: number): void {
- this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
-
- this.centerXDomElement(this.enableCameraSceneElement, 300);
}
- private login(): void {
- HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none';
- this.soundMeter.stop();
-
+ public login(): void {
enableCameraSceneVisibilityStore.hideEnableCameraScene();
- this.localStreamStoreUnsubscriber();
- //mediaManager.stopCamera();
- //mediaManager.stopMicrophone();
this.scene.sleep(EnableCameraSceneName);
gameManager.goToStartingMap(this.scene);
}
-
- private async getDevices() {
- // TODO: switch this in a store.
- const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
- this.microphonesList = [];
- this.camerasList = [];
- for (const mediaDeviceInfo of mediaDeviceInfos) {
- if (mediaDeviceInfo.kind === 'audioinput') {
- this.microphonesList.push(mediaDeviceInfo);
- } else if (mediaDeviceInfo.kind === 'videoinput') {
- this.camerasList.push(mediaDeviceInfo);
- }
- }
- this.updateWebCamName();
- }
}
diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts
index 435592f2..39a8f5f3 100644
--- a/front/src/Phaser/Login/LoginScene.ts
+++ b/front/src/Phaser/Login/LoginScene.ts
@@ -1,17 +1,12 @@
import {gameManager} from "../Game/GameManager";
import {SelectCharacterSceneName} from "./SelectCharacterScene";
import {ResizableScene} from "./ResizableScene";
-import { localUserStore } from "../../Connexion/LocalUserStore";
-import {MenuScene} from "../Menu/MenuScene";
-import { isUserNameValid } from "../../Connexion/LocalUser";
+import {loginSceneVisibleStore} from "../../Stores/LoginSceneStore";
export const LoginSceneName = "LoginScene";
-const loginSceneKey = 'loginScene';
-
export class LoginScene extends ResizableScene {
- private loginSceneElement!: Phaser.GameObjects.DOMElement;
private name: string = '';
constructor() {
@@ -22,65 +17,25 @@ export class LoginScene extends ResizableScene {
}
preload() {
- this.load.html(loginSceneKey, 'resources/html/loginScene.html');
}
create() {
- this.loginSceneElement = this.add.dom(-1000, 0).createFromCache(loginSceneKey);
- this.centerXDomElement(this.loginSceneElement, 200);
- MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey);
-
- const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
- const inputElement = this.loginSceneElement.getChildByID('loginSceneName') as HTMLInputElement;
- inputElement.value = localUserStore.getName() ?? '';
- inputElement.focus();
- inputElement.addEventListener('keypress', (event: KeyboardEvent) => {
- if(inputElement.value.length > 7){
- event.preventDefault();
- return;
- }
- pErrorElement.innerHTML = '';
- if(inputElement.value && !isUserNameValid(inputElement.value)){
- pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
- }
- if (event.key === 'Enter') {
- event.preventDefault();
- this.login(inputElement);
- return;
- }
- });
-
- const continuingButton = this.loginSceneElement.getChildByID('loginSceneFormSubmit') as HTMLButtonElement;
- continuingButton.addEventListener('click', (e) => {
- e.preventDefault();
- this.login(inputElement);
- });
+ loginSceneVisibleStore.set(true);
}
- private login(inputElement: HTMLInputElement): void {
- const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
- this.name = inputElement.value;
- if (this.name === '') {
- pErrorElement.innerHTML = 'The name is empty';
- return
- }
- if(!isUserNameValid(this.name)){
- pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
- return
- }
- if (this.name === '') return
- gameManager.setPlayerName(this.name);
+ public login(name: string): void {
+ name = name.trim();
+ gameManager.setPlayerName(name);
this.scene.stop(LoginSceneName)
gameManager.tryResumingGame(this, SelectCharacterSceneName);
- this.scene.remove(LoginSceneName)
+ this.scene.remove(LoginSceneName);
+ loginSceneVisibleStore.set(false);
}
update(time: number, delta: number): void {
-
}
- public onResize(ev: UIEvent): void {
- this.centerXDomElement(this.loginSceneElement, 200);
+ public onResize(): void {
}
}
diff --git a/front/src/Phaser/Login/ResizableScene.ts b/front/src/Phaser/Login/ResizableScene.ts
index 39e2d74b..d06cb66c 100644
--- a/front/src/Phaser/Login/ResizableScene.ts
+++ b/front/src/Phaser/Login/ResizableScene.ts
@@ -2,7 +2,7 @@ import {Scene} from "phaser";
import DOMElement = Phaser.GameObjects.DOMElement;
export abstract class ResizableScene extends Scene {
- public abstract onResize(ev: UIEvent): void;
+ public abstract onResize(): void;
/**
* Centers the DOM element on the X axis.
@@ -17,7 +17,7 @@ export abstract class ResizableScene extends Scene {
&& object.node
&& object.node.getBoundingClientRect().width > 0
? (object.node.getBoundingClientRect().width / 2 / this.scale.zoom)
- : (300 / this.scale.zoom)
+ : (defaultWidth / this.scale.zoom)
);
}
}
diff --git a/front/src/Phaser/Login/SelectCharacterMobileScene.ts b/front/src/Phaser/Login/SelectCharacterMobileScene.ts
index b9c4b5a8..0d8e49d5 100644
--- a/front/src/Phaser/Login/SelectCharacterMobileScene.ts
+++ b/front/src/Phaser/Login/SelectCharacterMobileScene.ts
@@ -4,49 +4,50 @@ export class SelectCharacterMobileScene extends SelectCharacterScene {
create(){
super.create();
+ this.onResize();
this.selectedRectangle.destroy();
}
- protected defineSetupPlayer(numero: number){
+ protected defineSetupPlayer(num: number){
const deltaX = 30;
const deltaY = 2;
let [playerX, playerY] = this.getCharacterPosition();
let playerVisible = true;
let playerScale = 1.5;
- let playserOpactity = 1;
+ let playerOpacity = 1;
- if( this.currentSelectUser !== numero ){
+ if( this.currentSelectUser !== num ){
playerVisible = false;
}
- if( numero === (this.currentSelectUser + 1) ){
+ if( num === (this.currentSelectUser + 1) ){
playerY -= deltaY;
playerX += deltaX;
playerScale = 0.8;
- playserOpactity = 0.6;
+ playerOpacity = 0.6;
playerVisible = true;
}
- if( numero === (this.currentSelectUser + 2) ){
+ if( num === (this.currentSelectUser + 2) ){
playerY -= deltaY;
playerX += (deltaX * 2);
playerScale = 0.8;
- playserOpactity = 0.6;
+ playerOpacity = 0.6;
playerVisible = true;
}
- if( numero === (this.currentSelectUser - 1) ){
+ if( num === (this.currentSelectUser - 1) ){
playerY -= deltaY;
playerX -= deltaX;
playerScale = 0.8;
- playserOpactity = 0.6;
+ playerOpacity = 0.6;
playerVisible = true;
}
- if( numero === (this.currentSelectUser - 2) ){
+ if( num === (this.currentSelectUser - 2) ){
playerY -= deltaY;
playerX -= (deltaX * 2);
playerScale = 0.8;
- playserOpactity = 0.6;
+ playerOpacity = 0.6;
playerVisible = true;
}
- return {playerX, playerY, playerScale, playserOpactity, playerVisible}
+ return {playerX, playerY, playerScale, playerOpacity, playerVisible}
}
/**
diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts
index ecbb9c64..0f590840 100644
--- a/front/src/Phaser/Login/SelectCharacterScene.ts
+++ b/front/src/Phaser/Login/SelectCharacterScene.ts
@@ -10,13 +10,13 @@ import {AbstractCharacterScene} from "./AbstractCharacterScene";
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
import {touchScreenManager} from "../../Touch/TouchScreenManager";
import {PinchManager} from "../UserInput/PinchManager";
-import {MenuScene} from "../Menu/MenuScene";
+import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore";
+import {waScaleManager} from "../Services/WaScaleManager";
+import {isMobile} from "../../Enum/EnvironmentVariable";
//todo: put this constants in a dedicated file
export const SelectCharacterSceneName = "SelectCharacterScene";
-const selectCharacterKey = 'selectCharacterScene';
-
export class SelectCharacterScene extends AbstractCharacterScene {
protected readonly nbCharactersPerRow = 6;
protected selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
@@ -25,8 +25,11 @@ export class SelectCharacterScene extends AbstractCharacterScene {
protected selectedRectangle!: Rectangle;
- protected selectCharacterSceneElement!: Phaser.GameObjects.DOMElement;
protected currentSelectUser = 0;
+ protected pointerClicked: boolean = false;
+ protected pointerTimer: number = 0;
+
+ protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
constructor() {
super({
@@ -35,50 +38,41 @@ export class SelectCharacterScene extends AbstractCharacterScene {
}
preload() {
- this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
this.playerModels.push(bodyResourceDescription);
});
- })
+ this.lazyloadingAttempt = true;
+ });
this.playerModels = loadAllDefaultModels(this.load);
+ this.lazyloadingAttempt = false;
//this function must stay at the end of preload function
addLoader(this);
}
create() {
-
- this.selectCharacterSceneElement = this.add.dom(-1000, 0).createFromCache(selectCharacterKey);
- this.centerXDomElement(this.selectCharacterSceneElement, 150);
- MenuScene.revealMenusAfterInit(this.selectCharacterSceneElement, selectCharacterKey);
-
- this.selectCharacterSceneElement.addListener('click');
- this.selectCharacterSceneElement.on('click', (event:MouseEvent) => {
- event.preventDefault();
- if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
- this.moveToLeft();
- }else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
- this.moveToRight();
- }else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormSubmit') {
- this.nextSceneToCameraScene();
- }else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormCustomYourOwnSubmit') {
- this.nextSceneToCustomizeScene();
- }
+ selectCharacterSceneVisibleStore.set(true);
+ this.events.addListener('wake', () => {
+ waScaleManager.saveZoom();
+ waScaleManager.zoomModifier = isMobile() ? 2 : 1;
+ selectCharacterSceneVisibleStore.set(true);
});
if (touchScreenManager.supportTouchScreen) {
new PinchManager(this);
}
+ waScaleManager.saveZoom();
+ waScaleManager.zoomModifier = isMobile() ? 2 : 1;
+
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
this.selectedRectangle.setDepth(2);
/*create user*/
this.createCurrentPlayer();
- const playerNumber = localUserStore.getPlayerCharacterIndex();
this.input.keyboard.on('keyup-ENTER', () => {
return this.nextSceneToCameraScene();
@@ -98,7 +92,7 @@ export class SelectCharacterScene extends AbstractCharacterScene {
});
}
- protected nextSceneToCameraScene(): void {
+ public nextSceneToCameraScene(): void {
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
return;
}
@@ -106,23 +100,33 @@ export class SelectCharacterScene extends AbstractCharacterScene {
return;
}
this.scene.stop(SelectCharacterSceneName);
+ waScaleManager.restoreZoom();
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
gameManager.tryResumingGame(this, EnableCameraSceneName);
- this.scene.remove(SelectCharacterSceneName);
+ this.players = [];
+ selectCharacterSceneVisibleStore.set(false);
+ this.events.removeListener('wake');
}
- protected nextSceneToCustomizeScene(): void {
+ public nextSceneToCustomizeScene(): void {
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
return;
}
this.scene.sleep(SelectCharacterSceneName);
+ waScaleManager.restoreZoom();
this.scene.run(CustomizeSceneName);
+ selectCharacterSceneVisibleStore.set(false);
}
createCurrentPlayer(): void {
for (let i = 0; i c.texture.key === playerResource.name)){
+ continue;
+ }
+
const [middleX, middleY] = this.getCharacterPosition();
const player = this.physics.add.sprite(middleX, middleY, playerResource.name, 0);
this.setUpPlayer(player, i);
@@ -133,15 +137,22 @@ export class SelectCharacterScene extends AbstractCharacterScene {
repeat: -1
});
player.setInteractive().on("pointerdown", () => {
- if(this.currentSelectUser === i){
+ if (this.pointerClicked) {
return;
}
+ if (this.currentSelectUser === i) {
+ return;
+ }
+ //To not trigger two time the pointerdown events :
+ // We set a boolean to true so that pointerdown events does nothing when the boolean is true
+ // We set a timer that we decrease in update function to not trigger the pointerdown events twice
+ this.pointerClicked = true;
+ this.pointerTimer = 250;
this.currentSelectUser = i;
this.moveUser();
});
this.players.push(player);
}
-
this.selectedPlayer = this.players[this.currentSelectUser];
this.selectedPlayer.play(this.playerModels[this.currentSelectUser].name);
}
@@ -154,7 +165,7 @@ export class SelectCharacterScene extends AbstractCharacterScene {
this.updateSelectedPlayer();
}
- protected moveToLeft(){
+ public moveToLeft(){
if(this.currentSelectUser === 0){
return;
}
@@ -162,7 +173,7 @@ export class SelectCharacterScene extends AbstractCharacterScene {
this.moveUser();
}
- protected moveToRight(){
+ public moveToRight(){
if(this.currentSelectUser === (this.players.length - 1)){
return;
}
@@ -186,35 +197,35 @@ export class SelectCharacterScene extends AbstractCharacterScene {
this.moveUser();
}
- protected defineSetupPlayer(numero: number){
+ protected defineSetupPlayer(num: number){
const deltaX = 32;
const deltaY = 32;
let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the
- playerX = ( (playerX - (deltaX * 2.5)) + ((deltaX) * (numero % this.nbCharactersPerRow)) ); // calcul position on line users
- playerY = ( (playerY - (deltaY * 2)) + ((deltaY) * ( Math.floor(numero / this.nbCharactersPerRow) )) ); // calcul position on column users
+ playerX = ( (playerX - (deltaX * 2.5)) + ((deltaX) * (num % this.nbCharactersPerRow)) ); // calcul position on line users
+ playerY = ( (playerY - (deltaY * 2)) + ((deltaY) * ( Math.floor(num / this.nbCharactersPerRow) )) ); // calcul position on column users
const playerVisible = true;
const playerScale = 1;
- const playserOpactity = 1;
+ const playerOpacity = 1;
// if selected
- if( numero === this.currentSelectUser ){
+ if( num === this.currentSelectUser ){
this.selectedRectangle.setX(playerX);
this.selectedRectangle.setY(playerY);
}
- return {playerX, playerY, playerScale, playserOpactity, playerVisible}
+ return {playerX, playerY, playerScale, playerOpacity, playerVisible}
}
- protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, numero: number){
+ protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, num: number){
- const {playerX, playerY, playerScale, playserOpactity, playerVisible} = this.defineSetupPlayer(numero);
+ const {playerX, playerY, playerScale, playerOpacity, playerVisible} = this.defineSetupPlayer(num);
player.setBounce(0.2);
- player.setCollideWorldBounds(true);
+ player.setCollideWorldBounds(false);
player.setVisible( playerVisible );
player.setScale(playerScale, playerScale);
- player.setAlpha(playserOpactity);
+ player.setAlpha(playerOpacity);
player.setX(playerX);
player.setY(playerY);
}
@@ -238,12 +249,23 @@ export class SelectCharacterScene extends AbstractCharacterScene {
}
update(time: number, delta: number): void {
+ // pointerTimer is set to 250 when pointerdown events is trigger
+ // After 250ms, pointerClicked is set to false and the pointerdown events can be trigger again
+ this.pointerTimer -= delta;
+ if (this.pointerTimer <= 0) {
+ this.pointerClicked = false;
+ }
+
+ if(this.lazyloadingAttempt){
+ //re-render players list
+ this.createCurrentPlayer();
+ this.moveUser();
+ this.lazyloadingAttempt = false;
+ }
}
- public onResize(ev: UIEvent): void {
+ public onResize(): void {
//move position of user
this.moveUser();
-
- this.centerXDomElement(this.selectCharacterSceneElement, 150);
}
}
diff --git a/front/src/Phaser/Login/SelectCompanionScene.ts b/front/src/Phaser/Login/SelectCompanionScene.ts
index 203fd557..4c29f942 100644
--- a/front/src/Phaser/Login/SelectCompanionScene.ts
+++ b/front/src/Phaser/Login/SelectCompanionScene.ts
@@ -10,18 +10,21 @@ import { getAllCompanionResources } from "../Companion/CompanionTexturesLoadingM
import {touchScreenManager} from "../../Touch/TouchScreenManager";
import {PinchManager} from "../UserInput/PinchManager";
import { MenuScene } from "../Menu/MenuScene";
+import {selectCompanionSceneVisibleStore} from "../../Stores/SelectCompanionStore";
+import {waScaleManager} from "../Services/WaScaleManager";
+import {isMobile} from "../../Enum/EnvironmentVariable";
export const SelectCompanionSceneName = "SelectCompanionScene";
-const selectCompanionSceneKey = 'selectCompanionScene';
-
export class SelectCompanionScene extends ResizableScene {
private selectedCompanion!: Phaser.Physics.Arcade.Sprite;
private companions: Array = new Array();
private companionModels: Array = [];
+ private saveZoom: number = 0;
- private selectCompanionSceneElement!: Phaser.GameObjects.DOMElement;
private currentCompanion = 0;
+ private pointerClicked: boolean = false;
+ private pointerTimer: number = 0;
constructor() {
super({
@@ -30,8 +33,6 @@ export class SelectCompanionScene extends ResizableScene {
}
preload() {
- this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
-
getAllCompanionResources(this.load).forEach(model => {
this.companionModels.push(model);
});
@@ -42,30 +43,17 @@ export class SelectCompanionScene extends ResizableScene {
create() {
- this.selectCompanionSceneElement = this.add.dom(-1000, 0).createFromCache(selectCompanionSceneKey);
- this.centerXDomElement(this.selectCompanionSceneElement, 150);
- MenuScene.revealMenusAfterInit(this.selectCompanionSceneElement, selectCompanionSceneKey);
+ selectCompanionSceneVisibleStore.set(true);
- this.selectCompanionSceneElement.addListener('click');
- this.selectCompanionSceneElement.on('click', (event:MouseEvent) => {
- event.preventDefault();
- if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
- this.moveToLeft();
- }else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
- this.moveToRight();
- }else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormSubmit') {
- this.nextScene();
- }else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormBack') {
- this._nextScene();
- }
- });
+ waScaleManager.saveZoom();
+ waScaleManager.zoomModifier = isMobile() ? 2 : 1;
if (touchScreenManager.supportTouchScreen) {
new PinchManager(this);
}
// input events
- this.input.keyboard.on('keyup-ENTER', this.nextScene.bind(this));
+ this.input.keyboard.on('keyup-ENTER', this.selectCompanion.bind(this));
this.input.keyboard.on('keydown-RIGHT', this.moveToRight.bind(this));
this.input.keyboard.on('keydown-LEFT', this.moveToLeft.bind(this));
@@ -86,21 +74,28 @@ export class SelectCompanionScene extends ResizableScene {
}
update(time: number, delta: number): void {
-
+ // pointerTimer is set to 250 when pointerdown events is trigger
+ // After 250ms, pointerClicked is set to false and the pointerdown events can be trigger again
+ this.pointerTimer -= delta;
+ if (this.pointerTimer <= 0) {
+ this.pointerClicked = false;
+ }
}
- private nextScene(): void {
+ public selectCompanion(): void {
localUserStore.setCompanion(this.companionModels[this.currentCompanion].name);
gameManager.setCompanion(this.companionModels[this.currentCompanion].name);
- this._nextScene();
+ this.closeScene();
}
- private _nextScene(){
+ public closeScene(){
// next scene
this.scene.stop(SelectCompanionSceneName);
+ waScaleManager.restoreZoom();
gameManager.tryResumingGame(this, EnableCameraSceneName);
this.scene.remove(SelectCompanionSceneName);
+ selectCompanionSceneVisibleStore.set(false);
}
private createCurrentCompanion(): void {
@@ -117,6 +112,14 @@ export class SelectCompanionScene extends ResizableScene {
});
companion.setInteractive().on("pointerdown", () => {
+ if (this.pointerClicked) {
+ return;
+ }
+ //To not trigger two time the pointerdown events :
+ // We set a boolean to true so that pointerdown events does nothing when the boolean is true
+ // We set a timer that we decrease in update function to not trigger the pointerdown events twice
+ this.pointerClicked = true;
+ this.pointerTimer = 250;
this.currentCompanion = i;
this.moveCompanion();
});
@@ -126,10 +129,8 @@ export class SelectCompanionScene extends ResizableScene {
this.selectedCompanion = this.companions[this.currentCompanion];
}
- public onResize(ev: UIEvent): void {
+ public onResize(): void {
this.moveCompanion();
-
- this.centerXDomElement(this.selectCompanionSceneElement, 150);
}
private updateSelectedCompanion(): void {
@@ -147,15 +148,7 @@ export class SelectCompanionScene extends ResizableScene {
this.updateSelectedCompanion();
}
- private moveToLeft(){
- if(this.currentCompanion === 0){
- return;
- }
- this.currentCompanion -= 1;
- this.moveCompanion();
- }
-
- private moveToRight(){
+ public moveToRight(){
if(this.currentCompanion === (this.companions.length - 1)){
return;
}
@@ -163,38 +156,46 @@ export class SelectCompanionScene extends ResizableScene {
this.moveCompanion();
}
- private defineSetupCompanion(numero: number){
+ public moveToLeft(){
+ if(this.currentCompanion === 0){
+ return;
+ }
+ this.currentCompanion -= 1;
+ this.moveCompanion();
+ }
+
+ private defineSetupCompanion(num: number){
const deltaX = 30;
const deltaY = 2;
let [companionX, companionY] = this.getCompanionPosition();
let companionVisible = true;
let companionScale = 1.5;
let companionOpactity = 1;
- if( this.currentCompanion !== numero ){
+ if( this.currentCompanion !== num ){
companionVisible = false;
}
- if( numero === (this.currentCompanion + 1) ){
+ if( num === (this.currentCompanion + 1) ){
companionY -= deltaY;
companionX += deltaX;
companionScale = 0.8;
companionOpactity = 0.6;
companionVisible = true;
}
- if( numero === (this.currentCompanion + 2) ){
+ if( num === (this.currentCompanion + 2) ){
companionY -= deltaY;
companionX += (deltaX * 2);
companionScale = 0.8;
companionOpactity = 0.6;
companionVisible = true;
}
- if( numero === (this.currentCompanion - 1) ){
+ if( num === (this.currentCompanion - 1) ){
companionY -= deltaY;
companionX -= deltaX;
companionScale = 0.8;
companionOpactity = 0.6;
companionVisible = true;
}
- if( numero === (this.currentCompanion - 2) ){
+ if( num === (this.currentCompanion - 2) ){
companionY -= deltaY;
companionX -= (deltaX * 2);
companionScale = 0.8;
diff --git a/front/src/Phaser/Menu/HelpCameraSettingsScene.ts b/front/src/Phaser/Menu/HelpCameraSettingsScene.ts
deleted file mode 100644
index 6bc520c0..00000000
--- a/front/src/Phaser/Menu/HelpCameraSettingsScene.ts
+++ /dev/null
@@ -1,152 +0,0 @@
-import {mediaManager} from "../../WebRtc/MediaManager";
-import {HtmlUtils} from "../../WebRtc/HtmlUtils";
-import {localUserStore} from "../../Connexion/LocalUserStore";
-import {DirtyScene} from "../Game/DirtyScene";
-import {get} from "svelte/store";
-import {requestedCameraState, requestedMicrophoneState} from "../../Stores/MediaStore";
-
-export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
-const helpCameraSettings = 'helpCameraSettings';
-/**
- * The scene that show how to permit Camera and Microphone access if there are not already allowed
- */
-export class HelpCameraSettingsScene extends DirtyScene {
- private helpCameraSettingsElement!: Phaser.GameObjects.DOMElement;
- private helpCameraSettingsOpened: boolean = false;
-
- constructor() {
- super({key: HelpCameraSettingsSceneName});
- }
-
- preload() {
- this.load.html(helpCameraSettings, 'resources/html/helpCameraSettings.html');
- }
-
- create(){
- this.createHelpCameraSettings();
- }
-
- private createHelpCameraSettings() : void {
- const middleX = this.getMiddleX();
- this.helpCameraSettingsElement = this.add.dom(middleX, -800, undefined, {overflow: 'scroll'}).createFromCache(helpCameraSettings);
- 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();
- }else if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormContinue') {
- this.closeHelpCameraSettingsOpened();
- }
- });
-
- if(!localUserStore.getHelpCameraSettingsShown() && (!get(requestedMicrophoneState) || !get(requestedCameraState))){
- this.openHelpCameraSettingsOpened();
- localUserStore.setHelpCameraSettingsShown();
- }
-
- mediaManager.setHelpCameraSettingsCallBack(() => {
- this.openHelpCameraSettingsOpened();
- });
- }
-
- private openHelpCameraSettingsOpened(): void{
- HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none';
- this.helpCameraSettingsOpened = true;
- 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();
- this.tweens.add({
- targets: this.helpCameraSettingsElement,
- y: middleY,
- x: middleX,
- duration: 1000,
- ease: 'Power3',
- overflow: 'scroll'
- });
-
- this.dirty = true;
- }
-
- private closeHelpCameraSettingsOpened(): void{
- const middleX = this.getMiddleX();
- /*const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
- helpCameraSettingsInfo.innerText = '';
- helpCameraSettingsInfo.style.display = 'none';*/
- this.helpCameraSettingsOpened = false;
- this.tweens.add({
- targets: this.helpCameraSettingsElement,
- y: -1000,
- x: middleX,
- duration: 1000,
- ease: 'Power3',
- overflow: 'scroll'
- });
-
- this.dirty = true;
- }
-
- private revealMenusAfterInit(menuElement: Phaser.GameObjects.DOMElement, rootDomId: string) {
- //Dom elements will appear inside the viewer screen when creating before being moved out of it, which create a flicker effect.
- //To prevent this, we put a 'hidden' attribute on the root element, we remove it only after the init is done.
- setTimeout(() => {
- (menuElement.getChildByID(rootDomId) as HTMLElement).hidden = false;
- }, 250);
- }
-
- update(time: number, delta: number): void {
- this.dirty = false;
- }
-
- public onResize(ev: UIEvent): void {
- super.onResize(ev);
- 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'
- });
- this.dirty = true;
- }
- }
-
- private getMiddleX() : number{
- return (this.scale.width / 2) -
- (
- this.helpCameraSettingsElement
- && this.helpCameraSettingsElement.node
- && this.helpCameraSettingsElement.node.getBoundingClientRect().width > 0
- ? (this.helpCameraSettingsElement.node.getBoundingClientRect().width / (2 * this.scale.zoom))
- : (400 / 2)
- );
- }
-
- private getMiddleY() : number{
- const middleY = ((this.scale.height) - (
- (this.helpCameraSettingsElement
- && this.helpCameraSettingsElement.node
- && this.helpCameraSettingsElement.node.getBoundingClientRect().height > 0
- ? this.helpCameraSettingsElement.node.getBoundingClientRect().height : 400 /*FIXME to use a const will be injected in HTMLElement*/)/this.scale.zoom)) / 2;
- return (middleY > 0 ? middleY : 0);
- }
-
- public isDirty(): boolean {
- return this.dirty;
- }
-}
-
diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts
index b7f31aad..7ed366f7 100644
--- a/front/src/Phaser/Player/Player.ts
+++ b/front/src/Phaser/Player/Player.ts
@@ -26,7 +26,7 @@ export class Player extends Character {
companion: string|null,
companionTexturePromise?: Promise
) {
- super(Scene, x, y, texturesPromise, name, direction, moving, 1, companion, companionTexturePromise);
+ super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise);
//the current player model should be push away by other players to prevent conflict
this.getBody().setImmovable(false);
@@ -102,10 +102,6 @@ export class Player extends Character {
}
}
- isClickable(): boolean {
- return true;
- }
-
openEmoteMenu(emotes:RadialMenuItem[]): void {
this.cancelPreviousEmote();
this.emoteMenu = new RadialMenu(this.scene, this.x, this.y, emotes)
diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts
index ca8b668d..abfd2a8b 100644
--- a/front/src/Phaser/Services/WaScaleManager.ts
+++ b/front/src/Phaser/Services/WaScaleManager.ts
@@ -2,6 +2,8 @@ import {HdpiManager} from "./HdpiManager";
import ScaleManager = Phaser.Scale.ScaleManager;
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
import type {Game} from "../Game/Game";
+import {ResizableScene} from "../Login/ResizableScene";
+import {HtmlUtils} from "../../WebRtc/HtmlUtils";
class WaScaleManager {
@@ -9,6 +11,7 @@ class WaScaleManager {
private scaleManager!: ScaleManager;
private game!: Game;
private actualZoom: number = 1;
+ private _saveZoom: number = 1;
public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) {
this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber);
@@ -30,7 +33,7 @@ class WaScaleManager {
const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({width: width * devicePixelRatio, height: height * devicePixelRatio});
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
- this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
+ this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio)
this.scaleManager.resize(gameSize.width, gameSize.height);
// Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves
@@ -38,6 +41,19 @@ class WaScaleManager {
style.width = Math.ceil(realSize.width / devicePixelRatio) + 'px';
style.height = Math.ceil(realSize.height / devicePixelRatio) + 'px';
+ // Resize the game element at the same size at the canvas
+ const gameStyle = HtmlUtils.getElementByIdOrFail('game').style;
+ gameStyle.width = style.width;
+ gameStyle.height = style.height;
+
+ // Note: onResize will be called twice (once here and once in Game.ts), but we have no better way.
+ for (const scene of this.game.scene.getScenes(true)) {
+ if (scene instanceof ResizableScene) {
+ // We are delaying the call to the "render" event because otherwise, the "camera" coordinates are not correctly updated.
+ scene.events.once(Phaser.Scenes.Events.RENDER, () => scene.onResize());
+ }
+ }
+
this.game.markDirty();
}
@@ -50,6 +66,15 @@ class WaScaleManager {
this.applyNewSize();
}
+ public saveZoom(): void {
+ this._saveZoom = this.hdpiManager.zoomModifier;
+ }
+
+ public restoreZoom(): void{
+ this.hdpiManager.zoomModifier = this._saveZoom;
+ this.applyNewSize();
+ }
+
/**
* This is used to scale back the ui components to counter-act the zoom.
*/
diff --git a/front/src/Stores/CustomCharacterStore.ts b/front/src/Stores/CustomCharacterStore.ts
new file mode 100644
index 00000000..4bef7768
--- /dev/null
+++ b/front/src/Stores/CustomCharacterStore.ts
@@ -0,0 +1,3 @@
+import { derived, writable, Writable } from "svelte/store";
+
+export const customCharacterSceneVisibleStore = writable(false);
\ No newline at end of file
diff --git a/front/src/Stores/ErrorStore.ts b/front/src/Stores/ErrorStore.ts
new file mode 100644
index 00000000..2f1e3e40
--- /dev/null
+++ b/front/src/Stores/ErrorStore.ts
@@ -0,0 +1,33 @@
+import {writable} from "svelte/store";
+
+/**
+ * A store that contains a list of error messages to be displayed.
+ */
+function createErrorStore() {
+ const { subscribe, set, update } = writable([]);
+
+ return {
+ subscribe,
+ addErrorMessage: (e: string|Error): void => {
+ update((messages: string[]) => {
+ let message: string;
+ if (e instanceof Error) {
+ message = e.message;
+ } else {
+ message = e;
+ }
+
+ if (!messages.includes(message)) {
+ messages.push(message);
+ }
+
+ return messages;
+ });
+ },
+ clearMessages: (): void => {
+ set([]);
+ }
+ };
+}
+
+export const errorStore = createErrorStore();
diff --git a/front/src/Stores/Errors/BrowserTooOldError.ts b/front/src/Stores/Errors/BrowserTooOldError.ts
new file mode 100644
index 00000000..bf934443
--- /dev/null
+++ b/front/src/Stores/Errors/BrowserTooOldError.ts
@@ -0,0 +1,8 @@
+export class BrowserTooOldError extends Error {
+ static NAME = 'BrowserTooOldError';
+
+ constructor() {
+ super('Unable to access your camera or microphone. Your browser is too old. Please consider upgrading your browser or try using a recent version of Chrome.');
+ this.name = BrowserTooOldError.NAME;
+ }
+}
diff --git a/front/src/Stores/Errors/WebviewOnOldIOS.ts b/front/src/Stores/Errors/WebviewOnOldIOS.ts
new file mode 100644
index 00000000..06c03f0e
--- /dev/null
+++ b/front/src/Stores/Errors/WebviewOnOldIOS.ts
@@ -0,0 +1,8 @@
+export class WebviewOnOldIOS extends Error {
+ static NAME = 'WebviewOnOldIOS';
+
+ constructor() {
+ super('Your iOS version cannot use video/audio in the browser unless you are using Safari. Please switch to Safari or upgrade iOS to 14.3 or above.');
+ this.name = WebviewOnOldIOS.NAME;
+ }
+}
diff --git a/front/src/Stores/GameStore.ts b/front/src/Stores/GameStore.ts
index ee975f23..8899aa12 100644
--- a/front/src/Stores/GameStore.ts
+++ b/front/src/Stores/GameStore.ts
@@ -1,3 +1,5 @@
-import { derived, writable, Writable } from "svelte/store";
+import { writable } from "svelte/store";
export const userMovingStore = writable(false);
+
+export const requestVisitCardsStore = writable(null);
diff --git a/front/src/Stores/HelpCameraSettingsStore.ts b/front/src/Stores/HelpCameraSettingsStore.ts
new file mode 100644
index 00000000..88373dab
--- /dev/null
+++ b/front/src/Stores/HelpCameraSettingsStore.ts
@@ -0,0 +1,3 @@
+import { writable } from "svelte/store";
+
+export const helpCameraSettingsVisibleStore = writable(false);
diff --git a/front/src/Stores/LoginSceneStore.ts b/front/src/Stores/LoginSceneStore.ts
new file mode 100644
index 00000000..6e2ea18b
--- /dev/null
+++ b/front/src/Stores/LoginSceneStore.ts
@@ -0,0 +1,3 @@
+import { writable } from "svelte/store";
+
+export const loginSceneVisibleStore = writable(false);
diff --git a/front/src/Stores/MediaStore.ts b/front/src/Stores/MediaStore.ts
index 9e53aa3b..d622511e 100644
--- a/front/src/Stores/MediaStore.ts
+++ b/front/src/Stores/MediaStore.ts
@@ -4,6 +4,10 @@ import {localUserStore} from "../Connexion/LocalUserStore";
import {ITiledMapGroupLayer, ITiledMapObjectLayer, ITiledMapTileLayer} from "../Phaser/Map/ITiledMap";
import {userMovingStore} from "./GameStore";
import {HtmlUtils} from "../WebRtc/HtmlUtils";
+import {BrowserTooOldError} from "./Errors/BrowserTooOldError";
+import {errorStore} from "./ErrorStore";
+import {isIOS} from "../WebRtc/DeviceUtils";
+import {WebviewOnOldIOS} from "./Errors/WebviewOnOldIOS";
/**
* A store that contains the camera state requested by the user (on or off).
@@ -209,10 +213,14 @@ function createVideoConstraintStore() {
return {
subscribe,
- setDeviceId: (deviceId: string) => update((constraints) => {
- constraints.deviceId = {
- exact: deviceId
- };
+ setDeviceId: (deviceId: string|undefined) => update((constraints) => {
+ if (deviceId !== undefined) {
+ constraints.deviceId = {
+ exact: deviceId
+ };
+ } else {
+ delete constraints.deviceId;
+ }
return constraints;
}),
@@ -241,15 +249,19 @@ function createAudioConstraintStore() {
return {
subscribe,
- setDeviceId: (deviceId: string) => update((constraints) => {
+ setDeviceId: (deviceId: string|undefined) => update((constraints) => {
selectedDeviceId = deviceId;
if (typeof(constraints) === 'boolean') {
constraints = {}
}
- constraints.deviceId = {
- exact: selectedDeviceId
- };
+ if (deviceId !== undefined) {
+ constraints.deviceId = {
+ exact: selectedDeviceId
+ };
+ } else {
+ delete constraints.deviceId;
+ }
return constraints;
})
@@ -410,13 +422,21 @@ export const localStreamStore = derived, LocalS
error: new Error('Unable to access your camera or microphone. You need to use a HTTPS connection.'),
constraints
});
- } else {
- //throw new Error('Unable to access your camera or microphone. Your browser is too old.');
+ return;
+ } else if (isIOS()) {
set({
type: 'error',
- error: new Error('Unable to access your camera or microphone. Your browser is too old.'),
+ error: new WebviewOnOldIOS(),
constraints
});
+ return;
+ } else {
+ set({
+ type: 'error',
+ error: new BrowserTooOldError(),
+ constraints
+ });
+ return;
}
}
@@ -508,3 +528,87 @@ export const obtainedMediaConstraintStore = derived(localStreamStore, ($localStr
return $localStreamStore.constraints;
});
+/**
+ * Device list
+ */
+export const deviceListStore = readable([], function start(set) {
+ let deviceListCanBeQueried = false;
+
+ const queryDeviceList = () => {
+ // Note: so far, we are ignoring any failures.
+ navigator.mediaDevices.enumerateDevices().then((mediaDeviceInfos) => {
+ set(mediaDeviceInfos);
+ }).catch((e) => {
+ console.error(e);
+ throw e;
+ });
+ };
+
+ const unsubscribe = localStreamStore.subscribe((streamResult) => {
+ if (streamResult.type === "success" && streamResult.stream !== null) {
+ if (deviceListCanBeQueried === false) {
+ queryDeviceList();
+ deviceListCanBeQueried = true;
+ }
+ }
+ });
+
+ if (navigator.mediaDevices) {
+ navigator.mediaDevices.addEventListener('devicechange', queryDeviceList);
+ }
+
+ return function stop() {
+ unsubscribe();
+ if (navigator.mediaDevices) {
+ navigator.mediaDevices.removeEventListener('devicechange', queryDeviceList);
+ }
+ };
+});
+
+export const cameraListStore = derived(deviceListStore, ($deviceListStore) => {
+ return $deviceListStore.filter(device => device.kind === 'videoinput');
+});
+
+export const microphoneListStore = derived(deviceListStore, ($deviceListStore) => {
+ return $deviceListStore.filter(device => device.kind === 'audioinput');
+});
+
+// TODO: detect the new webcam and automatically switch on it.
+cameraListStore.subscribe((devices) => {
+ // If the selected camera is unplugged, let's remove the constraint on deviceId
+ const constraints = get(videoConstraintStore);
+ if (!constraints.deviceId) {
+ return;
+ }
+
+ // If we cannot find the device ID, let's remove it.
+ // @ts-ignore
+ if (!devices.find(device => device.deviceId === constraints.deviceId.exact)) {
+ videoConstraintStore.setDeviceId(undefined);
+ }
+});
+
+microphoneListStore.subscribe((devices) => {
+ // If the selected camera is unplugged, let's remove the constraint on deviceId
+ const constraints = get(audioConstraintStore);
+ if (typeof constraints === 'boolean') {
+ return;
+ }
+ if (!constraints.deviceId) {
+ return;
+ }
+
+ // If we cannot find the device ID, let's remove it.
+ // @ts-ignore
+ if (!devices.find(device => device.deviceId === constraints.deviceId.exact)) {
+ audioConstraintStore.setDeviceId(undefined);
+ }
+});
+
+localStreamStore.subscribe(streamResult => {
+ if (streamResult.type === 'error') {
+ if (streamResult.error.name === BrowserTooOldError.NAME || streamResult.error.name === WebviewOnOldIOS.NAME) {
+ errorStore.addErrorMessage(streamResult.error);
+ }
+ }
+});
diff --git a/front/src/Stores/ScreenSharingStore.ts b/front/src/Stores/ScreenSharingStore.ts
index a55f5ab2..ec5aa46f 100644
--- a/front/src/Stores/ScreenSharingStore.ts
+++ b/front/src/Stores/ScreenSharingStore.ts
@@ -126,7 +126,7 @@ export const screenSharingLocalStreamStore = derived;
if (navigator.getDisplayMedia) {
currentStreamPromise = navigator.getDisplayMedia({constraints});
- } else if (navigator.mediaDevices.getDisplayMedia) {
+ } else if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
currentStreamPromise = navigator.mediaDevices.getDisplayMedia({constraints});
} else {
stopScreenSharing();
@@ -169,6 +169,7 @@ export const screenSharingLocalStreamStore = derived {
- if (!navigator.getDisplayMedia && !navigator.mediaDevices.getDisplayMedia) {
+ if (!navigator.getDisplayMedia && (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia)) {
set(false);
return;
}
diff --git a/front/src/Stores/SelectCharacterStore.ts b/front/src/Stores/SelectCharacterStore.ts
new file mode 100644
index 00000000..094eaef3
--- /dev/null
+++ b/front/src/Stores/SelectCharacterStore.ts
@@ -0,0 +1,3 @@
+import { derived, writable, Writable } from "svelte/store";
+
+export const selectCharacterSceneVisibleStore = writable(false);
\ No newline at end of file
diff --git a/front/src/Stores/SelectCompanionStore.ts b/front/src/Stores/SelectCompanionStore.ts
new file mode 100644
index 00000000..e66f5de3
--- /dev/null
+++ b/front/src/Stores/SelectCompanionStore.ts
@@ -0,0 +1,3 @@
+import { derived, writable, Writable } from "svelte/store";
+
+export const selectCompanionSceneVisibleStore = writable(false);
diff --git a/front/src/Stores/SoundPlayingStore.ts b/front/src/Stores/SoundPlayingStore.ts
new file mode 100644
index 00000000..cf1d681c
--- /dev/null
+++ b/front/src/Stores/SoundPlayingStore.ts
@@ -0,0 +1,22 @@
+import { writable } from "svelte/store";
+
+/**
+ * A store that contains the URL of the sound currently playing
+ */
+function createSoundPlayingStore() {
+ const { subscribe, set, update } = writable(null);
+
+ return {
+ subscribe,
+ playSound: (url: string) => {
+ set(url);
+ },
+ soundEnded: () => {
+ set(null);
+ }
+
+
+ };
+}
+
+export const soundPlayingStore = createSoundPlayingStore();
diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts
index f00f6ecb..1fb28487 100644
--- a/front/src/WebRtc/CoWebsiteManager.ts
+++ b/front/src/WebRtc/CoWebsiteManager.ts
@@ -1,6 +1,7 @@
import {HtmlUtils} from "./HtmlUtils";
import {Subject} from "rxjs";
import {iframeListener} from "../Api/IframeListener";
+import {touchScreenManager} from "../Touch/TouchScreenManager";
enum iframeStates {
closed = 1,
@@ -11,12 +12,17 @@ enum iframeStates {
const cowebsiteDivId = 'cowebsite'; // the id of the whole container.
const cowebsiteMainDomId = 'cowebsite-main'; // the id of the parent div of the iframe.
const cowebsiteAsideDomId = 'cowebsite-aside'; // the id of the parent div of the iframe.
-const cowebsiteCloseButtonId = 'cowebsite-close';
+export const cowebsiteCloseButtonId = 'cowebsite-close';
const cowebsiteFullScreenButtonId = 'cowebsite-fullscreen';
const cowebsiteOpenFullScreenImageId = 'cowebsite-fullscreen-open';
const cowebsiteCloseFullScreenImageId = 'cowebsite-fullscreen-close';
const animationTime = 500; //time used by the css transitions, in ms.
+interface TouchMoveCoordinates {
+ x: number;
+ y: number;
+}
+
class CoWebsiteManager {
private opened: iframeStates = iframeStates.closed;
@@ -32,6 +38,7 @@ class CoWebsiteManager {
private resizing: boolean = false;
private cowebsiteMainDom: HTMLDivElement;
private cowebsiteAsideDom: HTMLDivElement;
+ private previousTouchMoveCoordinates: TouchMoveCoordinates|null = null; //only use on touchscreens to track touch movement
get width(): number {
return this.cowebsiteDiv.clientWidth;
@@ -62,32 +69,61 @@ class CoWebsiteManager {
this.cowebsiteMainDom = HtmlUtils.getElementByIdOrFail(cowebsiteMainDomId);
this.cowebsiteAsideDom = HtmlUtils.getElementByIdOrFail(cowebsiteAsideDomId);
- this.initResizeListeners();
+ if (touchScreenManager.supportTouchScreen) {
+ this.initResizeListeners(true);
+ }
+ this.initResizeListeners(false);
- HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId).addEventListener('click', () => {
+ const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
+ buttonCloseFrame.addEventListener('click', () => {
+ buttonCloseFrame.blur();
this.closeCoWebsite();
});
- HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId).addEventListener('click', () => {
+
+ const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
+ buttonFullScreenFrame.addEventListener('click', () => {
+ buttonFullScreenFrame.blur();
this.fullscreen();
});
}
- private initResizeListeners() {
- const movecallback = (event:MouseEvent) => {
- this.verticalMode ? this.height += event.movementY / this.getDevicePixelRatio() : this.width -= event.movementX / this.getDevicePixelRatio();
+ private initResizeListeners(touchMode:boolean) {
+ const movecallback = (event:MouseEvent|TouchEvent) => {
+ let x, y;
+ if (event.type === 'mousemove') {
+ x = (event as MouseEvent).movementX / this.getDevicePixelRatio();
+ y = (event as MouseEvent).movementY / this.getDevicePixelRatio();
+ } else {
+ const touchEvent = (event as TouchEvent).touches[0];
+ const last = {x: touchEvent.pageX, y: touchEvent.pageY};
+ const previous = this.previousTouchMoveCoordinates as TouchMoveCoordinates;
+ this.previousTouchMoveCoordinates = last;
+ x = last.x - previous.x;
+ y = last.y - previous.y;
+ }
+
+
+ this.verticalMode ? this.height += y : this.width -= x;
this.fire();
}
- this.cowebsiteAsideDom.addEventListener('mousedown', (event) => {
+ this.cowebsiteAsideDom.addEventListener( touchMode ? 'touchstart' : 'mousedown', (event) => {
this.resizing = true;
this.getIframeDom().style.display = 'none';
+ if (touchMode) {
+ const touchEvent = (event as TouchEvent).touches[0];
+ this.previousTouchMoveCoordinates = {x: touchEvent.pageX, y: touchEvent.pageY};
+ }
- document.addEventListener('mousemove', movecallback);
+ document.addEventListener(touchMode ? 'touchmove' : 'mousemove', movecallback);
});
- document.addEventListener('mouseup', (event) => {
+ document.addEventListener(touchMode ? 'touchend' : 'mouseup', (event) => {
if (!this.resizing) return;
- document.removeEventListener('mousemove', movecallback);
+ if (touchMode) {
+ this.previousTouchMoveCoordinates = null;
+ }
+ document.removeEventListener(touchMode ? 'touchmove' : 'mousemove', movecallback);
this.getIframeDom().style.display = 'block';
this.resizing = false;
});
@@ -152,7 +188,10 @@ class CoWebsiteManager {
setTimeout(() => {
this.fire();
}, animationTime)
- }).catch(() => this.closeCoWebsite());
+ }).catch((err) => {
+ console.error('Error loadCoWebsite => ', err);
+ this.closeCoWebsite()
+ });
}
/**
@@ -166,7 +205,10 @@ class CoWebsiteManager {
setTimeout(() => {
this.fire();
}, animationTime);
- }).catch(() => this.closeCoWebsite());
+ }).catch((err) => {
+ console.error('Error insertCoWebsite => ', err);
+ this.closeCoWebsite();
+ });
}
public closeCoWebsite(): Promise {
diff --git a/front/src/WebRtc/DeviceUtils.ts b/front/src/WebRtc/DeviceUtils.ts
new file mode 100644
index 00000000..91a3dc31
--- /dev/null
+++ b/front/src/WebRtc/DeviceUtils.ts
@@ -0,0 +1,12 @@
+export function isIOS(): boolean {
+ return [
+ 'iPad Simulator',
+ 'iPhone Simulator',
+ 'iPod Simulator',
+ 'iPad',
+ 'iPhone',
+ 'iPod'
+ ].includes(navigator.platform)
+ // iPad on iOS 13 detection
+ || (navigator.userAgent.includes("Mac") && "ontouchend" in document)
+}
diff --git a/front/src/WebRtc/DiscussionManager.ts b/front/src/WebRtc/DiscussionManager.ts
index 9bbfac5a..504ee91b 100644
--- a/front/src/WebRtc/DiscussionManager.ts
+++ b/front/src/WebRtc/DiscussionManager.ts
@@ -171,6 +171,8 @@ export class DiscussionManager {
const date = new Date();
if(isMe){
name = 'Me';
+ } else {
+ name = HtmlUtils.escapeHtml(name);
}
pMessage.innerHTML = `${name}
diff --git a/front/src/WebRtc/HtmlUtils.ts b/front/src/WebRtc/HtmlUtils.ts
index 86f38216..942e553f 100644
--- a/front/src/WebRtc/HtmlUtils.ts
+++ b/front/src/WebRtc/HtmlUtils.ts
@@ -35,7 +35,12 @@ export class HtmlUtils {
const urlRegex = /(https?:\/\/[^\s]+)/g;
text = HtmlUtils.escapeHtml(text);
return text.replace(urlRegex, (url: string) => {
- return '' + url + ' ';
+ const link = document.createElement('a');
+ link.href = url;
+ link.target = "_blank";
+ const text = document.createTextNode(url);
+ link.appendChild(text);
+ return link.outerHTML;
});
}
diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts
index 7b8416d5..0d8a05f2 100644
--- a/front/src/WebRtc/MediaManager.ts
+++ b/front/src/WebRtc/MediaManager.ts
@@ -8,32 +8,11 @@ import { SoundMeter } from "../Phaser/Components/SoundMeter";
import { DISABLE_NOTIFICATIONS } from "../Enum/EnvironmentVariable";
import {
gameOverlayVisibilityStore, localStreamStore,
- mediaStreamConstraintsStore,
- requestedCameraState,
- requestedMicrophoneState
} from "../Stores/MediaStore";
import {
- requestedScreenSharingState,
- screenSharingAvailableStore,
screenSharingLocalStreamStore
} from "../Stores/ScreenSharingStore";
-
-declare const navigator: any; // eslint-disable-line @typescript-eslint/no-explicit-any
-
-const videoConstraint: boolean | MediaTrackConstraints = {
- width: { min: 640, ideal: 1280, max: 1920 },
- height: { min: 400, ideal: 720 },
- frameRate: { ideal: localUserStore.getVideoQualityValue() },
- facingMode: "user",
- resizeMode: 'crop-and-scale',
- aspectRatio: 1.777777778
-};
-const audioConstraint: boolean | MediaTrackConstraints = {
- //TODO: make these values configurable in the game settings menu and store them in localstorage
- autoGainControl: false,
- echoCancellation: true,
- noiseSuppression: true
-};
+import {helpCameraSettingsVisibleStore} from "../Stores/HelpCameraSettingsStore";
export type UpdatedLocalStreamCallback = (media: MediaStream | null) => void;
export type StartScreenSharingCallback = (media: MediaStream) => void;
@@ -42,31 +21,17 @@ export type ReportCallback = (message: string) => void;
export type ShowReportCallBack = (userId: string, userName: string | undefined) => void;
export type HelpCameraSettingsCallBack = () => void;
+import {cowebsiteCloseButtonId} from "./CoWebsiteManager";
+
export class MediaManager {
- localStream: MediaStream | null = null;
- localScreenCapture: MediaStream | null = null;
private remoteVideo: Map = new Map();
- myCamVideo: HTMLVideoElement;
- cinemaClose: HTMLImageElement;
- cinema: HTMLImageElement;
- monitorClose: HTMLImageElement;
- monitor: HTMLImageElement;
- microphoneClose: HTMLImageElement;
- microphone: HTMLImageElement;
- webrtcInAudio: HTMLAudioElement;
//FIX ME SOUNDMETER: check stalability of sound meter calculation
//mySoundMeterElement: HTMLDivElement;
- private webrtcOutAudio: HTMLAudioElement;
- updatedLocalStreamCallBacks: Set = new Set();
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;
private focused: boolean = true;
@@ -82,54 +47,6 @@ export class MediaManager {
constructor() {
- this.myCamVideo = HtmlUtils.getElementByIdOrFail('myCamVideo');
- this.webrtcInAudio = HtmlUtils.getElementByIdOrFail('audio-webrtc-in');
- this.webrtcOutAudio = HtmlUtils.getElementByIdOrFail('audio-webrtc-out');
- this.webrtcInAudio.volume = 0.2;
- this.webrtcOutAudio.volume = 0.2;
-
- this.microphoneBtn = HtmlUtils.getElementByIdOrFail('btn-micro');
- this.microphoneClose = HtmlUtils.getElementByIdOrFail('microphone-close');
- this.microphoneClose.style.display = "none";
- this.microphoneClose.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- requestedMicrophoneState.enableMicrophone();
- });
- this.microphone = HtmlUtils.getElementByIdOrFail('microphone');
- this.microphone.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- requestedMicrophoneState.disableMicrophone();
- });
-
- this.cinemaBtn = HtmlUtils.getElementByIdOrFail('btn-video');
- this.cinemaClose = HtmlUtils.getElementByIdOrFail('cinema-close');
- this.cinemaClose.style.display = "none";
- this.cinemaClose.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- requestedCameraState.enableWebcam();
- });
- this.cinema = HtmlUtils.getElementByIdOrFail('cinema');
- this.cinema.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- requestedCameraState.disableWebcam();
- });
-
- this.monitorBtn = HtmlUtils.getElementByIdOrFail('btn-monitor');
- this.monitorClose = HtmlUtils.getElementByIdOrFail('monitor-close');
- this.monitorClose.style.display = "block";
- this.monitorClose.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- //this.enableScreenSharing();
- requestedScreenSharingState.enableScreenSharing();
- });
- this.monitor = HtmlUtils.getElementByIdOrFail('monitor');
- this.monitor.style.display = "none";
- this.monitor.addEventListener('click', (e: MouseEvent) => {
- e.preventDefault();
- //this.disableScreenSharing();
- requestedScreenSharingState.disableScreenSharing();
- });
-
this.pingCameraStatus();
//FIX ME SOUNDMETER: check stability of sound meter calculation
@@ -144,87 +61,43 @@ export class MediaManager {
localStreamStore.subscribe((result) => {
if (result.type === 'error') {
console.error(result.error);
- layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => {
- this.showHelpCameraSettingsCallBack();
+ layoutManager.addInformation('warning', 'Camera access denied. Click here and check your browser permissions.', () => {
+ helpCameraSettingsVisibleStore.set(true);
}, this.userInputManager);
return;
}
-
- if (result.constraints.video !== false) {
- HtmlUtils.getElementByIdOrFail('div-myCamVideo').classList.remove('hide');
- } else {
- HtmlUtils.getElementByIdOrFail('div-myCamVideo').classList.add('hide');
- }/*
- if (result.constraints.audio !== false) {
- this.enableMicrophoneStyle();
- } else {
- this.disableMicrophoneStyle();
- }*/
-
- this.localStream = result.stream;
- this.myCamVideo.srcObject = this.localStream;
-
- // TODO: migrate all listeners to the store directly.
- this.triggerUpdatedLocalStreamCallbacks(result.stream);
});
- requestedCameraState.subscribe((enabled) => {
- if (enabled) {
- this.enableCameraStyle();
- } else {
- this.disableCameraStyle();
- }
- });
- requestedMicrophoneState.subscribe((enabled) => {
- if (enabled) {
- this.enableMicrophoneStyle();
- } else {
- this.disableMicrophoneStyle();
- }
- });
- //let screenSharingStream : MediaStream|null;
+ let isScreenSharing = false;
screenSharingLocalStreamStore.subscribe((result) => {
if (result.type === 'error') {
console.error(result.error);
- layoutManager.addInformation('warning', 'Screen sharing denied. Click here and check navigators permissions.', () => {
- this.showHelpCameraSettingsCallBack();
+ layoutManager.addInformation('warning', 'Screen sharing denied. Click here and check your browser permissions.', () => {
+ helpCameraSettingsVisibleStore.set(true);
}, this.userInputManager);
return;
}
if (result.stream !== null) {
- this.enableScreenSharingStyle();
- mediaManager.localScreenCapture = result.stream;
-
- // TODO: migrate this out of MediaManager
- this.triggerStartedScreenSharingCallbacks(result.stream);
-
- //screenSharingStream = result.stream;
-
+ isScreenSharing = true;
this.addScreenSharingActiveVideo('me', DivImportance.Normal);
HtmlUtils.getElementByIdOrFail('screen-sharing-me').srcObject = result.stream;
} else {
- this.disableScreenSharingStyle();
- this.removeActiveScreenSharingVideo('me');
-
- // FIXME: we need the old stream that is being stopped!
- if (this.localScreenCapture) {
- this.triggerStoppedScreenSharingCallbacks(this.localScreenCapture);
- this.localScreenCapture = null;
+ if (isScreenSharing) {
+ isScreenSharing = false;
+ this.removeActiveScreenSharingVideo('me');
}
-
- //screenSharingStream = null;
}
});
- screenSharingAvailableStore.subscribe((available) => {
+ /*screenSharingAvailableStore.subscribe((available) => {
if (available) {
document.querySelector('.btn-monitor')?.classList.remove('hide');
} else {
document.querySelector('.btn-monitor')?.classList.add('hide');
}
- });
+ });*/
}
public updateScene(){
@@ -232,49 +105,18 @@ export class MediaManager {
//this.updateSoudMeter();
}
- public onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
- this.updatedLocalStreamCallBacks.add(callback);
- }
-
- public onStartScreenSharing(callback: StartScreenSharingCallback): void {
- this.startScreenSharingCallBacks.add(callback);
- }
-
- public onStopScreenSharing(callback: StopScreenSharingCallback): void {
- this.stopScreenSharingCallBacks.add(callback);
- }
-
- removeUpdateLocalStreamEventListener(callback: UpdatedLocalStreamCallback): void {
- this.updatedLocalStreamCallBacks.delete(callback);
- }
-
- private triggerUpdatedLocalStreamCallbacks(stream: MediaStream | null): void {
- for (const callback of this.updatedLocalStreamCallBacks) {
- callback(stream);
- }
- }
-
- private triggerStartedScreenSharingCallbacks(stream: MediaStream): void {
- for (const callback of this.startScreenSharingCallBacks) {
- callback(stream);
- }
- }
-
- private triggerStoppedScreenSharingCallbacks(stream: MediaStream): void {
- for (const callback of this.stopScreenSharingCallBacks) {
- callback(stream);
- }
- }
-
public showGameOverlay(): void {
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
gameOverlay.classList.add('active');
- const buttonCloseFrame = HtmlUtils.getElementByIdOrFail('cowebsite-close');
+ const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
const functionTrigger = () => {
this.triggerCloseJitsiFrameButton();
}
- buttonCloseFrame.removeEventListener('click', functionTrigger);
+ buttonCloseFrame.removeEventListener('click', () => {
+ buttonCloseFrame.blur();
+ functionTrigger();
+ });
gameOverlayVisibilityStore.showGameOverlay();
}
@@ -283,53 +125,22 @@ export class MediaManager {
const gameOverlay = HtmlUtils.getElementByIdOrFail('game-overlay');
gameOverlay.classList.remove('active');
- const buttonCloseFrame = HtmlUtils.getElementByIdOrFail('cowebsite-close');
+ const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
const functionTrigger = () => {
this.triggerCloseJitsiFrameButton();
}
- buttonCloseFrame.addEventListener('click', functionTrigger);
+ buttonCloseFrame.addEventListener('click', () => {
+ buttonCloseFrame.blur();
+ functionTrigger();
+ });
gameOverlayVisibilityStore.hideGameOverlay();
}
- 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");
- }
-
- 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");
- }
-
- private enableScreenSharingStyle(){
- this.monitorClose.style.display = "none";
- this.monitor.style.display = "block";
- this.monitorBtn.classList.add("enabled");
- }
-
- private disableScreenSharingStyle(){
- this.monitorClose.style.display = "block";
- this.monitor.style.display = "none";
- this.monitorBtn.classList.remove("enabled");
- }
addActiveVideo(user: UserSimplePeerInterface, userName: string = "") {
- this.webrtcInAudio.play();
+
const userId = '' + user.userId
userName = userName.toUpperCase();
@@ -345,7 +156,7 @@ export class MediaManager {
Report/Block
-
+
@@ -382,7 +193,7 @@ export class MediaManager {
userId = this.getScreenSharingId(userId);
const html = `
-
+
`;
@@ -477,10 +288,6 @@ export class MediaManager {
this.removeActiveVideo(this.getScreenSharingId(userId))
}
- playWebrtcOutSound(): void {
- this.webrtcOutAudio.play();
- }
-
isConnecting(userId: string): void {
const connectingSpinnerDiv = this.getSpinner(userId);
if (connectingSpinnerDiv === null) {
@@ -595,16 +402,6 @@ export class MediaManager {
this.showReportModalCallBacks.add(callback);
}
- public setHelpCameraSettingsCallBack(callback: HelpCameraSettingsCallBack) {
- this.helpCameraSettingsCallBacks.add(callback);
- }
-
- private showHelpCameraSettingsCallBack() {
- for (const callBack of this.helpCameraSettingsCallBacks) {
- callBack();
- }
- }
-
//FIX ME SOUNDMETER: check stalability of sound meter calculation
/*updateSoudMeter(){
try{
@@ -650,12 +447,32 @@ export class MediaManager {
public getNotification(){
//Get notification
if (!DISABLE_NOTIFICATIONS && window.Notification && Notification.permission !== "granted") {
- Notification.requestPermission().catch((err) => {
- console.error(`Notification permission error`, err);
- });
+ if (this.checkNotificationPromise()) {
+ Notification.requestPermission().catch((err) => {
+ console.error(`Notification permission error`, err);
+ });
+ } else {
+ Notification.requestPermission();
+ }
}
}
+ /**
+ * Return true if the browser supports the modern version of the Notification API (which is Promise based) or false
+ * if we are on Safari...
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
+ */
+ private checkNotificationPromise(): boolean {
+ try {
+ Notification.requestPermission().then();
+ } catch(e) {
+ return false;
+ }
+
+ return true;
+ }
+
public createNotification(userName: string){
if(this.focused){
return;
diff --git a/front/src/WebRtc/ScreenSharingPeer.ts b/front/src/WebRtc/ScreenSharingPeer.ts
index f1786ef3..d797f59b 100644
--- a/front/src/WebRtc/ScreenSharingPeer.ts
+++ b/front/src/WebRtc/ScreenSharingPeer.ts
@@ -19,7 +19,7 @@ export class ScreenSharingPeer extends Peer {
public _connected: boolean = false;
private userId: number;
- constructor(user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
+ constructor(user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection, stream: MediaStream | null) {
super({
initiator: initiator ? initiator : false,
//reconnectTimer: 10000,
@@ -60,6 +60,7 @@ export class ScreenSharingPeer extends Peer {
const message = JSON.parse(chunk.toString('utf8'));
if (message.streamEnded !== true) {
console.error('Unexpected message on screen sharing peer connection');
+ return;
}
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
});
@@ -81,7 +82,9 @@ export class ScreenSharingPeer extends Peer {
this._onFinish();
});
- this.pushScreenSharingToRemoteUser();
+ if (stream) {
+ this.addStream(stream);
+ }
}
private sendWebrtcScreenSharingSignal(data: unknown) {
@@ -141,16 +144,6 @@ export class ScreenSharingPeer extends Peer {
}
}
- private pushScreenSharingToRemoteUser() {
- const localScreenCapture: MediaStream | null = mediaManager.localScreenCapture;
- if(!localScreenCapture){
- return;
- }
-
- this.addStream(localScreenCapture);
- return;
- }
-
public stopPushingScreenSharingToRemoteUser(stream: MediaStream) {
this.removeStream(stream);
this.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, streamEnded: true})));
diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts
index 4633374d..2a502bab 100644
--- a/front/src/WebRtc/SimplePeer.ts
+++ b/front/src/WebRtc/SimplePeer.ts
@@ -15,7 +15,10 @@ import {connectionManager} from "../Connexion/ConnectionManager";
import {GameConnexionTypes} from "../Url/UrlManager";
import {blackListManager} from "./BlackListManager";
import {get} from "svelte/store";
-import {localStreamStore, obtainedMediaConstraintStore} from "../Stores/MediaStore";
+import {localStreamStore, LocalStreamStoreValue, obtainedMediaConstraintStore} from "../Stores/MediaStore";
+import {screenSharingLocalStreamStore} from "../Stores/ScreenSharingStore";
+import {DivImportance, layoutManager} from "./LayoutManager";
+import {HtmlUtils} from "./HtmlUtils";
export interface UserSimplePeerInterface{
userId: number;
@@ -39,9 +42,9 @@ export class SimplePeer {
private PeerScreenSharingConnectionArray: Map
= new Map();
private PeerConnectionArray: Map = new Map();
- private readonly sendLocalVideoStreamCallback: UpdatedLocalStreamCallback;
private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
+ private readonly unsubscribers: (() => void)[] = [];
private readonly peerConnectionListeners: Array = new Array();
private readonly userId: number;
private lastWebrtcUserName: string|undefined;
@@ -49,13 +52,32 @@ export class SimplePeer {
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.
- this.sendLocalVideoStreamCallback = this.sendLocalVideoStream.bind(this);
this.sendLocalScreenSharingStreamCallback = this.sendLocalScreenSharingStream.bind(this);
this.stopLocalScreenSharingStreamCallback = this.stopLocalScreenSharingStream.bind(this);
- mediaManager.onUpdateLocalStream(this.sendLocalVideoStreamCallback);
- mediaManager.onStartScreenSharing(this.sendLocalScreenSharingStreamCallback);
- mediaManager.onStopScreenSharing(this.stopLocalScreenSharingStreamCallback);
+ this.unsubscribers.push(localStreamStore.subscribe((streamResult) => {
+ this.sendLocalVideoStream(streamResult);
+ }));
+
+ let localScreenCapture: MediaStream|null = null;
+
+ this.unsubscribers.push(screenSharingLocalStreamStore.subscribe((streamResult) => {
+ if (streamResult.type === 'error') {
+ // Let's ignore screen sharing errors, we will deal with those in a different way.
+ return;
+ }
+
+ if (streamResult.stream !== null) {
+ localScreenCapture = streamResult.stream;
+ this.sendLocalScreenSharingStream(localScreenCapture);
+ } else {
+ if (localScreenCapture) {
+ this.stopLocalScreenSharingStream(localScreenCapture);
+ localScreenCapture = null;
+ }
+ }
+ }));
+
this.userId = Connection.getUserId();
this.initialise();
}
@@ -106,13 +128,19 @@ export class SimplePeer {
if(!user.initiator){
return;
}
- this.createPeerConnection(user);
+ const streamResult = get(localStreamStore);
+ let stream : MediaStream | null = null;
+ if (streamResult.type === 'success' && streamResult.stream) {
+ stream = streamResult.stream;
+ }
+
+ this.createPeerConnection(user, stream);
}
/**
* create peer connection to bind users
*/
- private createPeerConnection(user : UserSimplePeerInterface) : VideoPeer | null {
+ private createPeerConnection(user : UserSimplePeerInterface, localStream: MediaStream | null) : VideoPeer | null {
const peerConnection = this.PeerConnectionArray.get(user.userId)
if (peerConnection) {
if (peerConnection.destroyed) {
@@ -122,11 +150,11 @@ export class SimplePeer {
if (!peerConnexionDeleted) {
throw 'Error to delete peer connection';
}
- this.createPeerConnection(user);
+ //return this.createPeerConnection(user, localStream);
} else {
peerConnection.toClose = false;
+ return null;
}
- return null;
}
let name = user.name;
@@ -144,7 +172,7 @@ export class SimplePeer {
this.lastWebrtcUserName = user.webRtcUser;
this.lastWebrtcPassword = user.webRtcPassword;
- const peer = new VideoPeer(user, user.initiator ? user.initiator : false, this.Connection);
+ const peer = new VideoPeer(user, user.initiator ? user.initiator : false, this.Connection, localStream);
//permit to send message
mediaManager.addSendMessageCallback(user.userId,(message: string) => {
@@ -155,8 +183,9 @@ export class SimplePeer {
// 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!
peer.on('connect', () => {
- if (mediaManager.localScreenCapture) {
- this.sendLocalScreenSharingStreamToUser(user.userId);
+ const streamResult = get(screenSharingLocalStreamStore);
+ if (streamResult.type === 'success' && streamResult.stream !== null) {
+ this.sendLocalScreenSharingStreamToUser(user.userId, streamResult.stream);
}
});
@@ -175,7 +204,7 @@ export class SimplePeer {
/**
* create peer connection to bind users
*/
- private createPeerScreenSharingConnection(user : UserSimplePeerInterface) : ScreenSharingPeer | null{
+ private createPeerScreenSharingConnection(user : UserSimplePeerInterface, stream: MediaStream | null) : ScreenSharingPeer | null{
const peerConnection = this.PeerScreenSharingConnectionArray.get(user.userId);
if(peerConnection){
if(peerConnection.destroyed){
@@ -185,7 +214,7 @@ export class SimplePeer {
if(!peerConnexionDeleted){
throw 'Error to delete peer connection';
}
- this.createPeerConnection(user);
+ this.createPeerConnection(user, stream);
}else {
peerConnection.toClose = false;
}
@@ -204,7 +233,7 @@ export class SimplePeer {
user.webRtcPassword = this.lastWebrtcPassword;
}
- const peer = new ScreenSharingPeer(user, user.initiator ? user.initiator : false, this.Connection);
+ const peer = new ScreenSharingPeer(user, user.initiator ? user.initiator : false, this.Connection, stream);
this.PeerScreenSharingConnectionArray.set(user.userId, peer);
for (const peerConnectionListener of this.peerConnectionListeners) {
@@ -217,7 +246,6 @@ export class SimplePeer {
* This is triggered twice. Once by the server, and once by a remote client disconnecting
*/
private closeConnection(userId : number) {
- mediaManager.playWebrtcOutSound();
try {
const peer = this.PeerConnectionArray.get(userId);
if (peer === undefined) {
@@ -234,7 +262,7 @@ export class SimplePeer {
const userIndex = this.Users.findIndex(user => user.userId === userId);
if(userIndex < 0){
- throw 'Couln\'t delete user';
+ throw 'Couldn\'t delete user';
} else {
this.Users.splice(userIndex, 1);
}
@@ -294,7 +322,9 @@ export class SimplePeer {
* Unregisters any held event handler.
*/
public unregister() {
- mediaManager.removeUpdateLocalStreamEventListener(this.sendLocalVideoStreamCallback);
+ for (const unsubscriber of this.unsubscribers) {
+ unsubscriber();
+ }
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -302,7 +332,13 @@ export class SimplePeer {
try {
//if offer type, create peer connection
if(data.signal.type === "offer"){
- this.createPeerConnection(data);
+ const streamResult = get(localStreamStore);
+ let stream : MediaStream | null = null;
+ if (streamResult.type === 'success' && streamResult.stream) {
+ stream = streamResult.stream;
+ }
+
+ this.createPeerConnection(data, stream);
}
const peer = this.PeerConnectionArray.get(data.userId);
if (peer !== undefined) {
@@ -318,18 +354,26 @@ export class SimplePeer {
private receiveWebrtcScreenSharingSignal(data: WebRtcSignalReceivedMessageInterface) {
if (blackListManager.isBlackListed(data.userId)) return;
console.log("receiveWebrtcScreenSharingSignal", data);
+ const streamResult = get(screenSharingLocalStreamStore);
+ let stream : MediaStream | null = null;
+ if (streamResult.type === 'success' && streamResult.stream !== null) {
+ stream = streamResult.stream;
+ }
+
try {
//if offer type, create peer connection
if(data.signal.type === "offer"){
- this.createPeerScreenSharingConnection(data);
+ this.createPeerScreenSharingConnection(data, stream);
}
const peer = this.PeerScreenSharingConnectionArray.get(data.userId);
if (peer !== undefined) {
peer.signal(data.signal);
} else {
console.error('Could not find peer whose ID is "'+data.userId+'" in receiveWebrtcScreenSharingSignal');
- console.info('tentative to create new peer connexion');
- this.sendLocalScreenSharingStreamToUser(data.userId);
+ console.info('Attempt to create new peer connexion');
+ if (stream) {
+ this.sendLocalScreenSharingStreamToUser(data.userId, stream);
+ }
}
} catch (e) {
console.error(`receiveWebrtcSignal => ${data.userId}`, e);
@@ -339,21 +383,19 @@ export class SimplePeer {
}
}
- private pushVideoToRemoteUser(userId : number) {
+ private pushVideoToRemoteUser(userId: number, streamResult: LocalStreamStoreValue) {
try {
const PeerConnection = this.PeerConnectionArray.get(userId);
if (!PeerConnection) {
throw new Error('While adding media, cannot find user with ID ' + userId);
}
- const result = get(localStreamStore);
+ PeerConnection.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, ...streamResult.constraints})));
- PeerConnection.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, ...result.constraints})));
-
- if (result.type === 'error') {
+ if (streamResult.type === 'error') {
return;
}
- const localStream: MediaStream | null = result.stream;
+ const localStream: MediaStream | null = streamResult.stream;
if(!localStream){
return;
@@ -370,15 +412,11 @@ export class SimplePeer {
}
}
- private pushScreenSharingToRemoteUser(userId : number) {
+ private pushScreenSharingToRemoteUser(userId: number, localScreenCapture: MediaStream) {
const PeerConnection = this.PeerScreenSharingConnectionArray.get(userId);
if (!PeerConnection) {
throw new Error('While pushing screen sharing, cannot find user with ID ' + userId);
}
- const localScreenCapture: MediaStream | null = mediaManager.localScreenCapture;
- if(!localScreenCapture){
- return;
- }
for (const track of localScreenCapture.getTracks()) {
PeerConnection.addTrack(track, localScreenCapture);
@@ -386,23 +424,18 @@ export class SimplePeer {
return;
}
- public sendLocalVideoStream(){
+ public sendLocalVideoStream(streamResult: LocalStreamStoreValue){
for (const user of this.Users) {
- this.pushVideoToRemoteUser(user.userId);
+ this.pushVideoToRemoteUser(user.userId, streamResult);
}
}
/**
* Triggered locally when clicking on the screen sharing button
*/
- public sendLocalScreenSharingStream() {
- if (!mediaManager.localScreenCapture) {
- console.error('Could not find localScreenCapture to share')
- return;
- }
-
+ public sendLocalScreenSharingStream(localScreenCapture: MediaStream) {
for (const user of this.Users) {
- this.sendLocalScreenSharingStreamToUser(user.userId);
+ this.sendLocalScreenSharingStreamToUser(user.userId, localScreenCapture);
}
}
@@ -415,11 +448,11 @@ export class SimplePeer {
}
}
- private sendLocalScreenSharingStreamToUser(userId: number): void {
+ private sendLocalScreenSharingStreamToUser(userId: number, localScreenCapture: MediaStream): void {
if (blackListManager.isBlackListed(userId)) return;
// If a connection already exists with user (because it is already sharing a screen with us... let's use this connection)
if (this.PeerScreenSharingConnectionArray.has(userId)) {
- this.pushScreenSharingToRemoteUser(userId);
+ this.pushScreenSharingToRemoteUser(userId, localScreenCapture);
return;
}
@@ -427,7 +460,7 @@ export class SimplePeer {
userId,
initiator: true
};
- const PeerConnectionScreenSharing = this.createPeerScreenSharingConnection(screenSharingUser);
+ const PeerConnectionScreenSharing = this.createPeerScreenSharingConnection(screenSharingUser, localScreenCapture);
if (!PeerConnectionScreenSharing) {
return;
}
diff --git a/front/src/WebRtc/VideoPeer.ts b/front/src/WebRtc/VideoPeer.ts
index 32e8e97f..5ca8952c 100644
--- a/front/src/WebRtc/VideoPeer.ts
+++ b/front/src/WebRtc/VideoPeer.ts
@@ -27,7 +27,7 @@ export class VideoPeer extends Peer {
private onBlockSubscribe: Subscription;
private onUnBlockSubscribe: Subscription;
- constructor(public user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
+ constructor(public user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection, localStream: MediaStream | null) {
super({
initiator: initiator ? initiator : false,
//reconnectTimer: 10000,
@@ -107,7 +107,7 @@ export class VideoPeer extends Peer {
this._onFinish();
});
- this.pushVideoToRemoteUser();
+ this.pushVideoToRemoteUser(localStream);
this.onBlockSubscribe = blackListManager.onBlockStream.subscribe((userId) => {
if (userId === this.userId) {
this.toggleRemoteStream(false);
@@ -190,9 +190,8 @@ export class VideoPeer extends Peer {
}
}
- private pushVideoToRemoteUser() {
+ private pushVideoToRemoteUser(localStream: MediaStream | null) {
try {
- const localStream: MediaStream | null = mediaManager.localStream;
this.write(new Buffer(JSON.stringify({type: MESSAGE_TYPE_CONSTRAINT, ...get(obtainedMediaConstraintStore)})));
if(!localStream){
diff --git a/front/src/ambient.d.ts b/front/src/ambient.d.ts
new file mode 100644
index 00000000..eee8d6c1
--- /dev/null
+++ b/front/src/ambient.d.ts
@@ -0,0 +1,38 @@
+/**
+ * These declarations tell TypeScript that we allow import of images, e.g.
+ * ```
+
+
+ ```
+ */
+declare module "*.gif" {
+ const value: string;
+ export = value;
+}
+
+declare module "*.jpg" {
+ const value: string;
+ export = value;
+}
+
+declare module "*.jpeg" {
+ const value: string;
+ export = value;
+}
+
+declare module "*.png" {
+ const value: string;
+ export = value;
+}
+
+declare module "*.svg" {
+ const value: string;
+ export = value;
+}
+
+declare module "*.webp" {
+ const value: string;
+ export = value;
+}
diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts
index 61a3c890..59930447 100644
--- a/front/src/iframe_api.ts
+++ b/front/src/iframe_api.ts
@@ -1,339 +1,124 @@
-import type { ChatEvent } from "./Api/Events/ChatEvent";
-import { IframeEvent, IframeEventMap, isIframeResponseEventWrapper } from "./Api/Events/IframeEvent";
-import { isUserInputChatEvent, UserInputChatEvent } from "./Api/Events/UserInputChatEvent";
-import { Subject } from "rxjs";
-import { EnterLeaveEvent, isEnterLeaveEvent } from "./Api/Events/EnterLeaveEvent";
-import type { OpenPopupEvent } from "./Api/Events/OpenPopupEvent";
-import { isButtonClickedEvent } from "./Api/Events/ButtonClickedEvent";
-import type { ClosePopupEvent } from "./Api/Events/ClosePopupEvent";
-import type { OpenTabEvent } from "./Api/Events/OpenTabEvent";
-import type { GoToPageEvent } from "./Api/Events/GoToPageEvent";
-import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent";
-import type { LayerEvent } from "./Api/Events/LayerEvent";
-import type { SetPropertyEvent } from "./Api/Events/setPropertyEvent";
-import { GameStateEvent, isGameStateEvent } from './Api/Events/GameStateEvent';
-import { HasPlayerMovedEvent, HasPlayerMovedEventCallback, isHasPlayerMovedEvent } from './Api/Events/HasPlayerMovedEvent';
-import { DataLayerEvent, isDataLayerEvent } from "./Api/Events/DataLayerEvent";
-import type { ITiledMap } from "./Phaser/Map/ITiledMap";
-import type { MenuItemRegisterEvent } from "./Api/Events/MenuItemRegisterEvent";
-import { isMenuItemClickedEvent } from "./Api/Events/MenuItemClickedEvent";
-import type { PlaySoundEvent } from "./Api/Events/PlaySoundEvent";
-import type { StopSoundEvent } from "./Api/Events/StopSoundEvent";
-import type { LoadSoundEvent } from "./Api/Events/LoadSoundEvent";
-import SoundConfig = Phaser.Types.Sound.SoundConfig;
+import {registeredCallbacks} from "./Api/iframe/registeredCallbacks";
+import {
+ IframeResponseEvent,
+ IframeResponseEventMap,
+ isIframeResponseEventWrapper,
+ TypedMessageEvent
+} from "./Api/Events/IframeEvent";
+import chat from "./Api/iframe/chat";
+import type {IframeCallback} from './Api/iframe/IframeApiContribution';
+import nav from "./Api/iframe/nav";
+import controls from "./Api/iframe/controls";
+import ui from "./Api/iframe/ui";
+import sound from "./Api/iframe/sound";
+import room from "./Api/iframe/room";
+import type {ButtonDescriptor} from "./Api/iframe/Ui/ButtonDescriptor";
+import type {Popup} from "./Api/iframe/Ui/Popup";
+import type {Sound} from "./Api/iframe/Sound/Sound";
-interface WorkAdventureApi {
- sendChatMessage(message: string, author: string): void;
- onChatMessage(callback: (message: string) => void): void;
- onEnterZone(name: string, callback: () => void): void;
- onLeaveZone(name: string, callback: () => void): void;
- openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup;
- openTab(url: string): void;
- goToPage(url: string): void;
- openCoWebSite(url: string): void;
- closeCoWebSite(): void;
- disablePlayerControls() : void;
- restorePlayerControls() : void;
- displayBubble() : void;
- removeBubble() : void;
- showLayer(layer: string) : void;
- hideLayer(layer: string) : void;
- setProperty(layerName: string, propertyName: string, propertyValue: string | number | boolean | undefined): void;
- disablePlayerControls(): void;
- restorePlayerControls(): void;
- displayBubble(): void;
- removeBubble(): void;
- loadSound(url : string): Sound;
- registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void
- getCurrentUser(): Promise
- getCurrentRoom(): Promise
- onPlayerMove(callback: (playerMovedEvent: HasPlayerMovedEvent) => void): void
-}
+const wa = {
+ ui,
+ nav,
+ controls,
+ chat,
+ sound,
+ room,
-interface User {
- id: string | undefined
- nickName: string | null
- tags: string[]
-}
-
-interface Room {
- id: string
- mapUrl: string
- map: ITiledMap
- startLayer: string | null
-}
-
-declare global {
- // eslint-disable-next-line no-var
- var WA: WorkAdventureApi
-
-}
-
-type ChatMessageCallback = (message: string) => void;
-type ButtonClickedCallback = (popup: Popup) => void;
-
-const userInputChatStream: Subject = new Subject();
-const enterStreams: Map> = new Map>();
-const leaveStreams: Map> = new Map>();
-const popups: Map = new Map();
-const popupCallbacks: Map> = new Map>();
-const menuCallbacks: Map void> = new Map()
-let popupId = 0;
-interface ButtonDescriptor {
- /**
- * The label of the button
- */
- label: string,
- /**
- * The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled"
- */
- className?: "normal" | "primary" | "success" | "warning" | "error" | "disabled",
- /**
- * Callback called if the button is pressed
- */
- callback: ButtonClickedCallback,
-}
-
-export class Popup {
- constructor(private id: number) {
- }
+ // All methods below are deprecated and should not be used anymore.
+ // They are kept here for backward compatibility.
/**
- * Closes the popup
+ * @deprecated Use WA.chat.sendChatMessage instead
*/
- public close(): void {
- window.parent.postMessage({
- 'type': 'closePopup',
- 'data': {
- 'popupId': this.id,
- } as ClosePopupEvent
- }, '*');
- }
-}
-
-export class Sound {
- constructor(private url: string) {
- window.parent.postMessage({
- "type" : 'loadSound',
- "data": {
- url: this.url,
- } as LoadSoundEvent
-
- },'*');
- }
-
- public play(config : SoundConfig) {
- window.parent.postMessage({
- "type" : 'playSound',
- "data": {
- url: this.url,
- config
- } as PlaySoundEvent
-
- },'*');
- return this.url;
- }
- public stop() {
- window.parent.postMessage({
- "type" : 'stopSound',
- "data": {
- url: this.url,
- } as StopSoundEvent
-
- },'*');
- return this.url;
- }
-
-}
-
-function getGameState(): Promise {
- if (immutableData) {
- return Promise.resolve(immutableData);
- }
- else {
- return new Promise((resolver, thrower) => {
- gameStateResolver.push(resolver);
- window.parent.postMessage({
- type: "getState"
- }, "*")
- })
- }
-}
-
-function getDataLayer(): Promise {
- return new Promise((resolver, thrower) => {
- dataLayerResolver.push(resolver);
- postToParent({
- type: "getDataLayer",
- data: undefined
- })
- })
-}
-
-const gameStateResolver: Array<(event: GameStateEvent) => void> = []
-const dataLayerResolver: Array<(event: DataLayerEvent) => void> = []
-let immutableData: GameStateEvent;
-
-const callbackPlayerMoved: Array<(event: HasPlayerMovedEvent) => void> = []
-
-function postToParent(content: IframeEvent) {
- window.parent.postMessage(content, "*")
-}
-
-window.WA = {
-
- onPlayerMove(callback: HasPlayerMovedEventCallback): void {
- callbackPlayerMoved.push(callback);
- postToParent({
- type: "onPlayerMove",
- data: undefined
- })
+ sendChatMessage(message: string, author: string): void {
+ console.warn('Method WA.sendChatMessage is deprecated. Please use WA.chat.sendChatMessage instead');
+ chat.sendChatMessage(message, author);
},
-
- getCurrentUser(): Promise {
- return getGameState().then((gameState) => {
- return {id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags};
- })
- },
-
- getCurrentRoom(): Promise {
- return getGameState().then((gameState) => {
- return getDataLayer().then((mapJson) => {
- return {id: gameState.roomId, map: mapJson.data as ITiledMap, mapUrl: gameState.mapUrl, startLayer: gameState.startLayerName};
- })
- })
- },
-
/**
- * Send a message in the chat.
- * Only the local user will receive this message.
+ * @deprecated Use WA.chat.disablePlayerControls instead
*/
- sendChatMessage(message: string, author: string) {
- window.parent.postMessage({
- 'type': 'chat',
- 'data': {
- 'message': message,
- 'author': author
- } as ChatEvent
- }, '*');
- },
-
- showLayer(layer: string) : void {
- window.parent.postMessage({
- 'type' : 'showLayer',
- 'data' : {
- 'name' : layer
- } as LayerEvent
- }, '*');
- },
-
- hideLayer(layer: string) : void {
- window.parent.postMessage({
- 'type' : 'hideLayer',
- 'data' : {
- 'name' : layer
- } as LayerEvent
- }, '*');
- },
-
- setProperty(layerName: string, propertyName: string, propertyValue: string | number | boolean | undefined): void {
- window.parent.postMessage({
- 'type' : 'setProperty',
- 'data' : {
- 'layerName' : layerName,
- 'propertyName' : propertyName,
- 'propertyValue' : propertyValue
- } as SetPropertyEvent
- }, '*');
- },
-
disablePlayerControls(): void {
- window.parent.postMessage({ 'type': 'disablePlayerControls' }, '*');
+ console.warn('Method WA.disablePlayerControls is deprecated. Please use WA.controls.disablePlayerControls instead');
+ controls.disablePlayerControls();
},
+ /**
+ * @deprecated Use WA.controls.restorePlayerControls instead
+ */
restorePlayerControls(): void {
- window.parent.postMessage({ 'type': 'restorePlayerControls' }, '*');
+ console.warn('Method WA.restorePlayerControls is deprecated. Please use WA.controls.restorePlayerControls instead');
+ controls.restorePlayerControls();
},
+ /**
+ * @deprecated Use WA.ui.displayBubble instead
+ */
displayBubble(): void {
- window.parent.postMessage({ 'type': 'displayBubble' }, '*');
+ console.warn('Method WA.displayBubble is deprecated. Please use WA.ui.displayBubble instead');
+ ui.displayBubble();
},
+ /**
+ * @deprecated Use WA.ui.removeBubble instead
+ */
removeBubble(): void {
- window.parent.postMessage({ 'type': 'removeBubble' }, '*');
+ console.warn('Method WA.removeBubble is deprecated. Please use WA.ui.removeBubble instead');
+ ui.removeBubble();
},
+ /**
+ * @deprecated Use WA.nav.openTab instead
+ */
openTab(url: string): void {
- window.parent.postMessage({
- "type": 'openTab',
- "data": {
- url
- } as OpenTabEvent
- }, '*');
+ console.warn('Method WA.openTab is deprecated. Please use WA.nav.openTab instead');
+ nav.openTab(url);
},
+ /**
+ * @deprecated Use WA.sound.loadSound instead
+ */
loadSound(url: string) : Sound {
- return new Sound(url);
+ console.warn('Method WA.loadSound is deprecated. Please use WA.sound.loadSound instead');
+ return sound.loadSound(url);
},
- goToPage(url : string) : void{
- window.parent.postMessage({
- "type": 'goToPage',
- "data": {
- url
- } as GoToPageEvent
- }, '*');
+ /**
+ * @deprecated Use WA.nav.goToPage instead
+ */
+ goToPage(url : string) : void {
+ console.warn('Method WA.goToPage is deprecated. Please use WA.nav.goToPage instead');
+ nav.goToPage(url);
},
- openCoWebSite(url: string): void {
- window.parent.postMessage({
- "type": 'openCoWebSite',
- "data": {
- url
- } as OpenCoWebSiteEvent
- }, '*');
+ /**
+ * @deprecated Use WA.nav.goToRoom instead
+ */
+ goToRoom(url: string): void {
+ console.warn('Method WA.goToRoom is deprecated. Please use WA.nav.goToRoom instead');
+ nav.goToRoom(url);
},
+ /**
+ * @deprecated Use WA.nav.openCoWebSite instead
+ */openCoWebSite(url: string): void {
+ console.warn('Method WA.openCoWebSite is deprecated. Please use WA.nav.openCoWebSite instead');
+ nav.openCoWebSite(url);
+ },
+
+ /**
+ * @deprecated Use WA.nav.closeCoWebSite instead
+ */
closeCoWebSite(): void {
- window.parent.postMessage({
- "type": 'closeCoWebSite'
- }, '*');
+ console.warn('Method WA.closeCoWebSite is deprecated. Please use WA.nav.closeCoWebSite instead');
+ nav.closeCoWebSite();
},
+ /**
+ * @deprecated Use WA.controls.restorePlayerControls instead
+ */
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
- popupId++;
- const popup = new Popup(popupId);
- const btnMap = new Map void>();
- popupCallbacks.set(popupId, btnMap);
- let id = 0;
- for (const button of buttons) {
- const callback = button.callback;
- if (callback) {
- btnMap.set(id, () => {
- callback(popup);
- });
- }
- id++;
- }
-
-
- window.parent.postMessage({
- 'type': 'openPopup',
- 'data': {
- popupId,
- targetObject,
- message,
- buttons: buttons.map((button) => {
- return {
- label: button.label,
- className: button.className
- };
- })
- } as OpenPopupEvent
- }, '*');
-
- popups.set(popupId, popup)
- return popup;
+ console.warn('Method WA.openPopup is deprecated. Please use WA.ui.openPopup instead');
+ return ui.openPopup(targetObject, message, buttons);
},
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void {
@@ -346,75 +131,53 @@ window.WA = {
}, '*');
},
/**
- * Listen to messages sent by the local user, in the chat.
+ * @deprecated Use WA.chat.onChatMessage instead
*/
- onChatMessage(callback: ChatMessageCallback): void {
- userInputChatStream.subscribe((userInputChatEvent) => {
- callback(userInputChatEvent.message);
- });
+ onChatMessage(callback: (message: string) => void): void {
+ console.warn('Method WA.onChatMessage is deprecated. Please use WA.chat.onChatMessage instead');
+ chat.onChatMessage(callback);
},
+ /**
+ * @deprecated Use WA.room.onEnterZone instead
+ */
onEnterZone(name: string, callback: () => void): void {
- let subject = enterStreams.get(name);
- if (subject === undefined) {
- subject = new Subject();
- enterStreams.set(name, subject);
- }
- subject.subscribe(callback);
+ console.warn('Method WA.onEnterZone is deprecated. Please use WA.room.onEnterZone instead');
+ room.onEnterZone(name, callback);
},
+ /**
+ * @deprecated Use WA.room.onLeaveZone instead
+ */
onLeaveZone(name: string, callback: () => void): void {
- let subject = leaveStreams.get(name);
- if (subject === undefined) {
- subject = new Subject();
- leaveStreams.set(name, subject);
- }
- subject.subscribe(callback);
+ console.warn('Method WA.onLeaveZone is deprecated. Please use WA.room.onLeaveZone instead');
+ room.onLeaveZone(name, callback);
},
+};
+
+export type WorkAdventureApi = typeof wa;
+
+declare global {
+
+ interface Window {
+ WA: WorkAdventureApi
+ }
+ let WA: WorkAdventureApi
}
-window.addEventListener('message', message => {
+window.WA = wa;
+
+window.addEventListener('message', (message: TypedMessageEvent>) => {
if (message.source !== window.parent) {
return; // Skip message in this event listener
}
-
const payload = message.data;
-
console.debug(payload);
if (isIframeResponseEventWrapper(payload)) {
const payloadData = payload.data;
- if (payload.type === 'userInputChat' && isUserInputChatEvent(payloadData)) {
- userInputChatStream.next(payloadData);
- } else if (payload.type === 'enterEvent' && isEnterLeaveEvent(payloadData)) {
- enterStreams.get(payloadData.name)?.next();
- } else if (payload.type === 'leaveEvent' && isEnterLeaveEvent(payloadData)) {
- leaveStreams.get(payloadData.name)?.next();
- } else if (payload.type === 'buttonClickedEvent' && isButtonClickedEvent(payloadData)) {
- const callback = popupCallbacks.get(payloadData.popupId)?.get(payloadData.buttonId);
- const popup = popups.get(payloadData.popupId);
- if (popup === undefined) {
- throw new Error('Could not find popup with ID "' + payloadData.popupId + '"');
- }
- if (callback) {
- callback(popup);
- }
- } else if (payload.type == "gameState" && isGameStateEvent(payloadData)) {
- gameStateResolver.forEach(resolver => {
- resolver(payloadData);
- })
- immutableData = payloadData;
- } else if (payload.type == "hasPlayerMoved" && isHasPlayerMovedEvent(payloadData)) {
- callbackPlayerMoved.forEach(callback => {
- callback(payloadData);
- })
- } else if (payload.type == "dataLayer" && isDataLayerEvent(payloadData)) {
- dataLayerResolver.forEach(resolver => {
- resolver(payloadData);
- })
- } else if (payload.type == "menuItemClicked" && isMenuItemClickedEvent(payloadData)) {
- const callback = menuCallbacks.get(payloadData.menuItem);
- if (callback) {
- callback(payloadData.menuItem)
- }
+
+ const callback = registeredCallbacks[payload.type] as IframeCallback | undefined
+ if (callback?.typeChecker(payloadData)) {
+ callback?.callback(payloadData)
}
}
diff --git a/front/src/index.ts b/front/src/index.ts
index 2cdcaa19..90d4c612 100644
--- a/front/src/index.ts
+++ b/front/src/index.ts
@@ -9,11 +9,10 @@ import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene";
import {SelectCompanionScene} from "./Phaser/Login/SelectCompanionScene";
import {EnableCameraScene} from "./Phaser/Login/EnableCameraScene";
import {CustomizeScene} from "./Phaser/Login/CustomizeScene";
-import {ResizableScene} from "./Phaser/Login/ResizableScene";
+import WebFontLoaderPlugin from 'phaser3-rex-plugins/plugins/webfontloader-plugin.js';
import {EntryScene} from "./Phaser/Login/EntryScene";
import {coWebsiteManager} from "./WebRtc/CoWebsiteManager";
import {MenuScene} from "./Phaser/Menu/MenuScene";
-import {HelpCameraSettingsScene} from "./Phaser/Menu/HelpCameraSettingsScene";
import {localUserStore} from "./Connexion/LocalUserStore";
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
import {iframeListener} from "./Api/IframeListener";
@@ -96,7 +95,7 @@ const config: GameConfig = {
ErrorScene,
CustomizeScene,
MenuScene,
- HelpCameraSettingsScene],
+ ],
//resolution: window.devicePixelRatio / 2,
fps: fps,
dom: {
@@ -107,6 +106,13 @@ const config: GameConfig = {
roundPixels: true,
antialias: false
},
+ plugins: {
+ global: [{
+ key: 'rexWebFontLoader',
+ plugin: WebFontLoaderPlugin,
+ start: true
+ }]
+ },
physics: {
default: "arcade",
arcade: {
@@ -145,7 +151,9 @@ iframeListener.init();
const app = new App({
target: HtmlUtils.getElementByIdOrFail('svelte-overlay'),
- props: { },
+ props: {
+ game: game
+ },
})
export default app
diff --git a/front/src/rex-plugins.d.ts b/front/src/rex-plugins.d.ts
index d5457702..2e160315 100644
--- a/front/src/rex-plugins.d.ts
+++ b/front/src/rex-plugins.d.ts
@@ -7,6 +7,10 @@ declare module 'phaser3-rex-plugins/plugins/gestures-plugin.js' {
const content: any; // eslint-disable-line
export default content;
}
+declare module 'phaser3-rex-plugins/plugins/webfontloader-plugin.js' {
+ const content: any; // eslint-disable-line
+ export default content;
+}
declare module 'phaser3-rex-plugins/plugins/gestures.js' {
export const Pinch: any; // eslint-disable-line
}
diff --git a/front/style/cowebsite-mobile.scss b/front/style/cowebsite-mobile.scss
index 85b41511..48a6689e 100644
--- a/front/style/cowebsite-mobile.scss
+++ b/front/style/cowebsite-mobile.scss
@@ -28,6 +28,7 @@
aside {
height: 30px;
+ min-height: 30px;
cursor: ns-resize;
flex-direction: column;
diff --git a/front/style/cowebsite.scss b/front/style/cowebsite.scss
index 2ed1ef69..e508b58d 100644
--- a/front/style/cowebsite.scss
+++ b/front/style/cowebsite.scss
@@ -13,6 +13,8 @@
iframe {
width: 100%;
height: 100%;
+ max-width: 100vw;
+ max-height: 100vh;
}
}
diff --git a/front/style/fonts.scss b/front/style/fonts.scss
new file mode 100644
index 00000000..a49d3967
--- /dev/null
+++ b/front/style/fonts.scss
@@ -0,0 +1,9 @@
+@import "~@fontsource/press-start-2p/index.css";
+
+*{
+ font-family: PixelFont-7,monospace;
+}
+
+.nes-btn {
+ font-family: "Press Start 2P";
+}
diff --git a/front/style/index.scss b/front/style/index.scss
index 67e85c5b..7ed141cd 100644
--- a/front/style/index.scss
+++ b/front/style/index.scss
@@ -1,4 +1,5 @@
@import "cowebsite.scss";
@import "cowebsite-mobile.scss";
-@import "style.css";
-@import "mobile-style.scss";
\ No newline at end of file
+@import "style";
+@import "mobile-style.scss";
+@import "fonts.scss";
diff --git a/front/style/mobile-style.scss b/front/style/mobile-style.scss
index 21753ebd..1b37053a 100644
--- a/front/style/mobile-style.scss
+++ b/front/style/mobile-style.scss
@@ -1,9 +1,24 @@
+@media (hover: none) {
+ /**
+ * If we cannot hover over elements, let's display camera button in full.
+ */
+ .btn-cam-action {
+ div {
+ transform: translateY(0px);
+ }
+ }
+}
+
@media screen and (max-width: 700px),
screen and (max-height: 700px){
- video#myCamVideo {
+ video.myCamVideo {
width: 150px;
}
+ .div-myCamVideo.hide {
+ right: -160px;
+ }
+
.sidebar {
width: 20%;
min-width: 200px;
@@ -22,21 +37,6 @@
}
}
- .btn-cam-action {
- min-width: 150px;
-
- &:hover{
- transform: translateY(20px);
- }
- div {
- margin: 0 1%;
- &:hover {
- background-color: #666;
- }
- margin-bottom: 30px;
- }
- }
-
.main-section {
position: absolute;
width: 100%;
diff --git a/front/style/style.css b/front/style/style.scss
similarity index 94%
rename from front/style/style.css
rename to front/style/style.scss
index a3bbfa1d..beed1db5 100644
--- a/front/style/style.css
+++ b/front/style/style.scss
@@ -133,11 +133,12 @@ body .message-info.warning{
outline: none;
}
-.video-container#div-myCamVideo{
+.video-container.div-myCamVideo{
border: none;
+ background-color: transparent;
}
-#div-myCamVideo {
+.div-myCamVideo {
position: absolute;
right: 15px;
bottom: 30px;
@@ -146,11 +147,13 @@ body .message-info.warning{
transition: right 350ms;
}
-#div-myCamVideo.hide {
+.div-myCamVideo.hide {
right: -20vw;
}
-video#myCamVideo{
+video.myCamVideo{
+ background-color: #00000099;
+ max-height: 20vh;
width: 15vw;
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
@@ -212,7 +215,9 @@ video#myCamVideo{
/*btn animation*/
.btn-cam-action div{
cursor: url('./images/cursor_pointer.png'), pointer;
- /*position: absolute;*/
+ display: flex;
+ align-items: center;
+ justify-content: center;
border: solid 0px black;
width: 44px;
height: 44px;
@@ -267,8 +272,6 @@ video#myCamVideo{
.btn-cam-action div img{
height: 22px;
width: 30px;
- top: calc(48px - 37px);
- left: calc(48px - 41px);
position: relative;
cursor: url('./images/cursor_pointer.png'), pointer;
}
@@ -331,48 +334,15 @@ video#myCamVideo{
}
}
-.webrtcsetup{
- display: none;
- position: absolute;
- top: 140px;
- left: 0;
- right: 0;
- margin-left: auto;
- margin-right: auto;
- height: 50%;
- width: 50%;
- border: white 6px solid;
-}
-.webrtcsetup .background-img {
- position: relative;
- display: block;
- width: 40%;
- height: 60%;
- margin-left: auto;
- margin-right: auto;
- top: 50%;
- transform: translateY(-50%);
-}
-#myCamVideoSetup {
- width: 100%;
- height: 100%;
- -webkit-transform: scaleX(-1);
- transform: scaleX(-1);
-}
-.webrtcsetup.active{
- display: block;
-}
-
-
/* New layout */
body {
margin: 0;
- height: 100vh;
- width: 100vw;
+ height: 100%;
+ width: 100%;
}
.main-container {
- height: 100vh;
- width: 100vw;
+ height: 100%;
+ width: 100%;
position: absolute;
}
@@ -397,7 +367,6 @@ body {
}
#game {
- width: 100%;
position: relative; /* Position relative is needed for the game-overlay. */
}
@@ -618,7 +587,6 @@ input[type=range]:focus::-ms-fill-upper {
/* Let's make sure videos are vertically centered if they need to be cropped */
.media-container {
display: flex;
- justify-content: center;
flex-direction: column;
overflow: hidden;
border-radius: 15px;
@@ -840,35 +808,6 @@ input[type=range]:focus::-ms-fill-upper {
}
-
-/*audio html when audio message playing*/
-.main-container .audio-playing {
- position: absolute;
- width: 200px;
- height: 54px;
- right: -210px;
- top: 40px;
- transition: all 0.1s ease-out;
- background-color: black;
- border-radius: 30px 0 0 30px;
- display: inline-flex;
-}
-
-.main-container .audio-playing.active{
- right: 0;
-}
-.main-container .audio-playing img{
- /*width: 30px;*/
- border-radius: 50%;
- background-color: #ffda01;
- padding: 10px;
-}
-.main-container .audio-playing p{
- color: white;
- margin-left: 10px;
- margin-top: 14px;
-}
-
/* VIDEO QUALITY */
.main-console div.setting h1{
color: white;
@@ -1136,6 +1075,10 @@ div.modal-report-user{
color: white;
}
+.discussion .messages .message p a:visited{
+ color: white;
+}
+
.discussion .send-message{
position: absolute;
bottom: 45px;
@@ -1244,4 +1187,22 @@ div.action.danger p.action-body{
width: 100%;
height: 100%;
pointer-events: none;
+
+ & > div {
+ position: relative;
+ width: 100%;
+ height: 100%;
+
+ & > div {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ }
+
+ & > div.scrollable {
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ pointer-events: auto;
+ }
+ }
}
diff --git a/front/tests/Phaser/Connexion/LocalUserTest.ts b/front/tests/Phaser/Connexion/LocalUserTest.ts
index 25b54005..4ba20745 100644
--- a/front/tests/Phaser/Connexion/LocalUserTest.ts
+++ b/front/tests/Phaser/Connexion/LocalUserTest.ts
@@ -19,8 +19,14 @@ describe("isUserNameValid()", () => {
it("should not validate spaces", () => {
expect(isUserNameValid(' ')).toBe(false);
});
- it("should not validate special characters", () => {
- expect(isUserNameValid('a&-')).toBe(false);
+ it("should validate special characters", () => {
+ expect(isUserNameValid('%&-')).toBe(true);
+ });
+ it("should validate accents", () => {
+ expect(isUserNameValid('éàëè')).toBe(true);
+ });
+ it("should validate chinese characters", () => {
+ expect(isUserNameValid('中文鍵盤')).toBe(true);
});
});
diff --git a/front/webpack.config.ts b/front/webpack.config.ts
index cc87572a..3a69b74a 100644
--- a/front/webpack.config.ts
+++ b/front/webpack.config.ts
@@ -7,6 +7,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import sveltePreprocess from 'svelte-preprocess';
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import NodePolyfillPlugin from 'node-polyfill-webpack-plugin';
+import {DISPLAY_TERMS_OF_USE} from "./src/Enum/EnvironmentVariable";
const mode = process.env.NODE_ENV ?? 'development';
const isProduction = mode === 'production';
@@ -88,7 +89,16 @@ module.exports = {
preprocess: sveltePreprocess({
scss: true,
sass: true,
- })
+ }),
+ onwarn: function (warning: { code: string }, handleWarning: (warning: { code: string }) => void) {
+ // See https://github.com/sveltejs/svelte/issues/4946#issuecomment-662168782
+
+ if (warning.code === 'a11y-no-onchange') { return }
+ if (warning.code === 'a11y-autofocus') { return }
+
+ // process as usual
+ handleWarning(warning);
+ }
}
}
},
@@ -102,9 +112,17 @@ module.exports = {
}
},
{
- test: /\.(ttf|eot|svg|png|gif|jpg)$/,
+ test: /\.(eot|svg|png|gif|jpg)$/,
exclude: /node_modules/,
type: 'asset'
+ },
+ {
+ test: /\.(woff(2)?|ttf)$/,
+ type: 'asset',
+ generator: {
+ filename: 'fonts/[name][ext]'
+ }
+
}
],
},
@@ -167,7 +185,8 @@ module.exports = {
'JITSI_PRIVATE_MODE': null,
'START_ROOM_URL': null,
'MAX_USERNAME_LENGTH': 8,
- 'MAX_PER_GROUP': 4
+ 'MAX_PER_GROUP': 4,
+ 'DISPLAY_TERMS_OF_USE': false,
})
],
diff --git a/front/yarn.lock b/front/yarn.lock
index bbdf0e06..e64a76c1 100644
--- a/front/yarn.lock
+++ b/front/yarn.lock
@@ -30,6 +30,13 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
+"@babel/runtime@^7.14.0":
+ version "7.14.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
+ integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@discoveryjs/json-ext@^0.5.0":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d"
@@ -50,6 +57,11 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
+"@fontsource/press-start-2p@^4.3.0":
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/@fontsource/press-start-2p/-/press-start-2p-4.3.0.tgz#37124387f7fbfe7792b5fc9a1906b80d9aeda4c6"
+ integrity sha512-gmS4070EoZp5/6NUJ+tBnvtDiSmFcR+S+ClAOJ8NGFXDWOkO12yMnyGJEJaDCNCAMX0s2TQCcmr6qWKx5ad3RQ==
+
"@nodelib/fs.scandir@2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
@@ -639,7 +651,7 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
-anymatch@~3.1.1:
+anymatch@~3.1.1, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@@ -773,6 +785,14 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+automation-events@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/automation-events/-/automation-events-4.0.1.tgz#93acef8a457cbea65f16fdcef8f349fd2fafe298"
+ integrity sha512-8bQx+PVtNDMD5F2H40cQs7oexZve3Z0xC9fWRQT4fltF65f/WsSpjM4jpulL4K4yLLB71oi4/xVJJCJ5I/Kjbw==
+ dependencies:
+ "@babel/runtime" "^7.14.0"
+ tslib "^2.2.0"
+
available-typed-arrays@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
@@ -1092,7 +1112,7 @@ caniuse-lite@^1.0.30001219:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa"
integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==
-chalk@^2.0.0:
+chalk@^2.0.0, chalk@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -1143,6 +1163,21 @@ chokidar@^2.1.8:
optionalDependencies:
fsevents "^1.2.7"
+chokidar@^3.4.1:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
+ integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
chrome-trace-event@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
@@ -1382,7 +1417,7 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
-cross-spawn@^6.0.0:
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -1621,9 +1656,9 @@ dns-equal@^1.0.0:
integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0=
dns-packet@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a"
- integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f"
+ integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -2345,7 +2380,7 @@ fsevents@^1.2.7:
bindings "^1.5.0"
nan "^2.12.1"
-fsevents@~2.3.1:
+fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -2409,7 +2444,7 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0:
+glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -2586,6 +2621,11 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
+hosted-git-info@^2.1.4:
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
@@ -3157,7 +3197,7 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
-json-parse-better-errors@^1.0.2:
+json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
@@ -3262,6 +3302,16 @@ linked-list-typescript@^1.0.11:
resolved "https://registry.yarnpkg.com/linked-list-typescript/-/linked-list-typescript-1.0.15.tgz#faeed93cf9203f102e2158c29edcddda320abe82"
integrity sha512-RIyUu9lnJIyIaMe63O7/aFv/T2v3KsMFuXMBbUQCHX+cgtGro86ETDj5ed0a8gQL2+DFjzYYsgVG4I36/cUwgw==
+load-json-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+ strip-bom "^3.0.0"
+
loader-runner@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
@@ -3376,6 +3426,11 @@ memory-fs@^0.4.1:
errno "^0.1.3"
readable-stream "^2.0.1"
+memorystream@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+ integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
+
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -3509,6 +3564,11 @@ mkdirp@^0.5.1, mkdirp@^0.5.5:
dependencies:
minimist "^1.2.5"
+mri@^1.1.0:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
+ integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -3637,6 +3697,16 @@ node-releases@^1.1.71:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
+normalize-package-data@^2.3.2:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -3649,6 +3719,21 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+npm-run-all@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
+ integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ chalk "^2.4.1"
+ cross-spawn "^6.0.5"
+ memorystream "^0.3.1"
+ minimatch "^3.0.4"
+ pidtree "^0.3.0"
+ read-pkg "^3.0.0"
+ shell-quote "^1.6.1"
+ string.prototype.padend "^3.0.0"
+
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -3879,6 +3964,14 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5:
pbkdf2 "^3.0.3"
safe-buffer "^5.1.1"
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
@@ -3967,6 +4060,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+ dependencies:
+ pify "^3.0.0"
+
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -4014,11 +4114,21 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d"
integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
+pidtree@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
+ integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
+
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+
pify@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
@@ -4268,6 +4378,15 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
+read-pkg@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+ dependencies:
+ load-json-file "^4.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^3.0.0"
+
readable-stream@^2.0.1, readable-stream@^2.0.2:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
@@ -4306,6 +4425,13 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
rechoir@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca"
@@ -4313,6 +4439,11 @@ rechoir@^0.7.0:
dependencies:
resolve "^1.9.0"
+regenerator-runtime@^0.13.4:
+ version "0.13.7"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
+ integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
+
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@@ -4419,7 +4550,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.9.0:
+resolve@^1.10.0, resolve@^1.9.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
@@ -4478,6 +4609,13 @@ rxjs@^6.6.3:
dependencies:
tslib "^1.9.0"
+sade@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
+ integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==
+ dependencies:
+ mri "^1.1.0"
+
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -4554,7 +4692,7 @@ selfsigned@^1.10.8:
dependencies:
node-forge "^0.10.0"
-semver@^5.5.0:
+"semver@2 || 3 || 4 || 5", semver@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -4689,6 +4827,11 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+shell-quote@^1.6.1:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
+ integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
+
signal-exit@^3.0.0, signal-exit@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -4842,6 +4985,32 @@ source-map@^0.7.3, source-map@~0.7.2:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
+spdx-correct@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+ integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+ integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.9"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f"
+ integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==
+
spdy-transport@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
@@ -4877,6 +5046,15 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+standardized-audio-context@^25.2.4:
+ version "25.2.4"
+ resolved "https://registry.yarnpkg.com/standardized-audio-context/-/standardized-audio-context-25.2.4.tgz#d64dbdd70615171ec90d1b7151a0d945af94cf3d"
+ integrity sha512-uQKZXRnXrPVO1V6SwZ7PiV3RkQqRY3n7i6Q8nbTXYvoz8NftRNzfOIlwefpuC8LVLUUs9dhbKTpP+WOA82dkBw==
+ dependencies:
+ "@babel/runtime" "^7.14.0"
+ automation-events "^4.0.1"
+ tslib "^2.2.0"
+
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -4926,6 +5104,15 @@ string-width@^4.2.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
+string.prototype.padend@^3.0.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz#6858ca4f35c5268ebd5e8615e1327d55f59ee311"
+ integrity sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.18.0-next.2"
+
string.prototype.trimend@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
@@ -5025,6 +5212,21 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
+svelte-check@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-2.1.0.tgz#3ee8ad86068256346ebca862bbee8417a757fc53"
+ integrity sha512-kKLXkFt0XZTn+O1fnilGTQ1SFLsOFF+lXp1YjPfeN9nX+Y3ZpELtZSQCkbuK6HMkWugFvsOM17FCOSa1mfrEFA==
+ dependencies:
+ chalk "^4.0.0"
+ chokidar "^3.4.1"
+ glob "^7.1.6"
+ import-fresh "^3.2.1"
+ minimist "^1.2.5"
+ sade "^1.7.4"
+ source-map "^0.7.3"
+ svelte-preprocess "^4.0.0"
+ typescript "*"
+
svelte-dev-helper@^1.1.9:
version "1.1.9"
resolved "https://registry.yarnpkg.com/svelte-dev-helper/-/svelte-dev-helper-1.1.9.tgz#7d187db5c6cdbbd64d75a32f91b8998bde3273c3"
@@ -5044,7 +5246,7 @@ svelte-loader@^3.1.1:
svelte-dev-helper "^1.1.9"
svelte-hmr "^0.12.3"
-svelte-preprocess@^4.7.3:
+svelte-preprocess@^4.0.0, svelte-preprocess@^4.7.3:
version "4.7.3"
resolved "https://registry.yarnpkg.com/svelte-preprocess/-/svelte-preprocess-4.7.3.tgz#454fa059c2400b15e7a3caeca18993cff9df0e96"
integrity sha512-Zx1/xLeGOIBlZMGPRCaXtlMe4ZA0faato5Dc3CosEqwu75MIEPuOstdkH6cy+RYTUYynoxzNaDxkPX4DbrPwRA==
@@ -5207,7 +5409,7 @@ tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2.0.3:
+tslib@^2.0.3, tslib@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
@@ -5249,6 +5451,11 @@ type-is@~1.6.17, type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
+typescript@*:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
+ integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
+
typescript@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
@@ -5374,6 +5581,14 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0:
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+validate-npm-package-license@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -5616,9 +5831,9 @@ wrappy@1:
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
- integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e"
+ integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==
dependencies:
async-limiter "~1.0.0"
diff --git a/maps/tests/deprecated_functions.json b/maps/tests/deprecated_functions.json
new file mode 100644
index 00000000..a4c035f7
--- /dev/null
+++ b/maps/tests/deprecated_functions.json
@@ -0,0 +1,164 @@
+{ "compressionlevel":-1,
+ "height":10,
+ "infinite":false,
+ "layers":[
+ {
+ "data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+ "height":10,
+ "id":1,
+ "name":"floor",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":10,
+ "id":6,
+ "name":"triggerZone",
+ "opacity":1,
+ "properties":[
+ {
+ "name":"zone",
+ "type":"string",
+ "value":"myTrigger"
+ }],
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":10,
+ "id":7,
+ "name":"popupZone",
+ "opacity":1,
+ "properties":[
+ {
+ "name":"zone",
+ "type":"string",
+ "value":"popupZone"
+ }],
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":10,
+ "id":2,
+ "name":"start",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "draworder":"topdown",
+ "id":3,
+ "name":"floorLayer",
+ "objects":[
+ {
+ "height":147.135497146101,
+ "id":1,
+ "name":"myPopup2",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":104.442827410047,
+ "x":142.817125079855,
+ "y":147.448134926559
+ },
+ {
+ "height":132.434722966794,
+ "id":2,
+ "name":"myPopup1",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":125.735549178518,
+ "x":13.649632619596,
+ "y":50.8502491249093
+ },
+ {
+ "height":67,
+ "id":3,
+ "name":"",
+ "rotation":0,
+ "text":
+ {
+ "fontfamily":"Sans Serif",
+ "pixelsize":11,
+ "text":"Test:\nWalk on top carpet\nResult:\nA message \"Don't step on my carpet\" is displayed\nIn the console, deprecation warnings MUST be displayed",
+ "wrap":true
+ },
+ "type":"",
+ "visible":true,
+ "width":252.4375,
+ "x":2.78125,
+ "y":2.5
+ },
+ {
+ "height":67,
+ "id":4,
+ "name":"",
+ "rotation":0,
+ "text":
+ {
+ "fontfamily":"Sans Serif",
+ "pixelsize":11,
+ "text":"Test:\nWalk on bottom carpet\nResult:\nA series of 2 popups open. A bubble opens. The player cannot move until popup closes.\nWhen the player leaves the zone, the bubble closes.\nIn the console, deprecation warnings MUST be displayed",
+ "wrap":true
+ },
+ "type":"",
+ "visible":true,
+ "width":252.438,
+ "x":-1.71899999999999,
+ "y":163.5
+ }],
+ "opacity":1,
+ "type":"objectgroup",
+ "visible":true,
+ "x":0,
+ "y":0
+ }],
+ "nextlayerid":8,
+ "nextobjectid":5,
+ "orientation":"orthogonal",
+ "properties":[
+ {
+ "name":"script",
+ "type":"string",
+ "value":"deprecated_script.js"
+ }],
+ "renderorder":"right-down",
+ "tiledversion":"2021.03.23",
+ "tileheight":32,
+ "tilesets":[
+ {
+ "columns":11,
+ "firstgid":1,
+ "image":"tileset1.png",
+ "imageheight":352,
+ "imagewidth":352,
+ "margin":0,
+ "name":"tileset1",
+ "spacing":0,
+ "tilecount":121,
+ "tileheight":32,
+ "tilewidth":32
+ }],
+ "tilewidth":32,
+ "type":"map",
+ "version":1.5,
+ "width":10
+}
\ No newline at end of file
diff --git a/maps/tests/deprecated_script.js b/maps/tests/deprecated_script.js
new file mode 100644
index 00000000..4a889a8a
--- /dev/null
+++ b/maps/tests/deprecated_script.js
@@ -0,0 +1,79 @@
+console.log('SCRIPT LAUNCHED');
+//WA.sendChatMessage('Hi, my name is Poly and I repeat what you say!', 'Poly Parrot');
+var isFirstTimeTuto = false;
+var textFirstPopup = 'Hey ! This is how to open start a discussion with someone ! You can be 4 max in a booble';
+var textSecondPopup = 'You can also use the chat to communicate ! ';
+var targetObjectTutoBubble ='myPopup1';
+var targetObjectTutoChat ='myPopup2';
+var popUpExplanation = undefined;
+function launchTuto (){
+ WA.openPopup(targetObjectTutoBubble, textFirstPopup, [
+ {
+ label: "Next",
+ className: "popUpElement",
+ callback: (popup) => {
+ popup.close();
+
+ WA.openPopup(targetObjectTutoChat, textSecondPopup, [
+ {
+ label: "Open Chat",
+ className: "popUpElement",
+ callback: (popup1) => {
+ WA.sendChatMessage("Hey you can talk here too ! ", 'WA Guide');
+ popup1.close();
+ WA.restorePlayerControls();
+ }
+ }
+
+ ])
+ }
+ }
+ ]);
+ WA.disablePlayerControls();
+
+}
+WA.onChatMessage((message => {
+ console.log('CHAT MESSAGE RECEIVED BY SCRIPT');
+ WA.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot');
+}));
+
+WA.onEnterZone('myTrigger', () => {
+ WA.sendChatMessage("Don't step on my carpet!", 'Poly Parrot');
+})
+
+WA.onLeaveZone('popupZone', () => {
+})
+
+WA.onEnterZone('notExist', () => {
+ WA.sendChatMessage("YOU SHOULD NEVER SEE THIS", 'Poly Parrot');
+})
+
+WA.onEnterZone('popupZone', () => {
+ WA.displayBubble();
+ if (!isFirstTimeTuto) {
+ isFirstTimeTuto = true;
+ launchTuto();
+ }
+ else popUpExplanation = WA.openPopup(targetObjectTutoChat,'Do you want to review the explanation ? ', [
+ {
+ label: "No",
+ className: "popUpElementReviewexplanation",
+ callback: (popup) => {
+ popup.close();
+ }
+ },
+ {
+ label: "Yes",
+ className: "popUpElementReviewexplanation",
+ callback: (popup) => {
+ popup.close();
+ launchTuto();
+ }
+ }
+ ])
+});
+
+WA.onLeaveZone('popupZone', () => {
+ if (popUpExplanation !== undefined) popUpExplanation.close();
+ WA.removeBubble();
+})
diff --git a/maps/tests/goToPageScript.js b/maps/tests/goToPageScript.js
index 2b2cf33b..bccbc5d2 100644
--- a/maps/tests/goToPageScript.js
+++ b/maps/tests/goToPageScript.js
@@ -1,14 +1,16 @@
+///
var zoneName = "popUpGoToPageZone";
var urlPricing = "https://workadventu.re/pricing";
var urlGettingStarted = "https://workadventu.re/getting-started";
-var isCoWebSiteOpened = false;
+var urlRelativeMap = "script_api.json";
+var isCoWebSiteOpened = false;
WA.onChatMessage((message => {
- WA.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot');
+ WA.sendChatMessage('Poly Parrot says: "' + message + '"', 'Poly Parrot');
}));
WA.onEnterZone(zoneName, () => {
- WA.openPopup("popUp","Open Links",[
+ WA.openPopup("popUp", "Open Links", [
{
label: "Open Tab",
className: "popUpElement",
@@ -18,27 +20,34 @@ WA.onEnterZone(zoneName, () => {
})
},
{
- label: "Go To Page", className : "popUpElement",
- callback:(popup => {
+ label: "Go To Page", className: "popUpElement",
+ callback: (popup => {
WA.goToPage(urlPricing);
popup.close();
})
- }
- ,
+ },
{
- label: "openCoWebSite", className : "popUpElement",
- callback:(popup => {
+ label: "openCoWebSite", className: "popUpElement",
+ callback: (popup => {
WA.openCoWebSite(urlPricing);
isCoWebSiteOpened = true;
popup.close();
})
+ }, {
+ label: "load grouped map",
+ className: "popUpElement",
+ callback: (popup => {
+ WA.goToRoom(urlRelativeMap);
+ popup.close();
+ })
+
}]);
})
WA.onLeaveZone(zoneName, () => {
- if (isCoWebSiteOpened) {
+ if(isCoWebSiteOpened) {
WA.closeCoWebSite();
isCoWebSiteOpened = false;
}
diff --git a/maps/tests/help_camera_setting.json b/maps/tests/help_camera_setting.json
new file mode 100644
index 00000000..2dcdec3a
--- /dev/null
+++ b/maps/tests/help_camera_setting.json
@@ -0,0 +1,164 @@
+{ "compressionlevel":-1,
+ "height":10,
+ "infinite":false,
+ "layers":[
+ {
+ "data":[33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 49, 50, 50, 50, 50, 50, 50, 50, 50, 51],
+ "height":10,
+ "id":3,
+ "name":"bottom",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":10,
+ "id":1,
+ "name":"start",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":10,
+ "x":0,
+ "y":0
+ },
+ {
+ "draworder":"topdown",
+ "id":2,
+ "name":"floorLayer",
+ "objects":[
+ {
+ "height":254.57168784029,
+ "id":1,
+ "name":"",
+ "rotation":0,
+ "text":
+ {
+ "fontfamily":"Sans Serif",
+ "pixelsize":12,
+ "text":"Test 1 : \nBlock permission to camera and\/or microphone access.\n\nResult 1 :\nOrange popup show at the bottom of the screen.\nIf you click on it, the HelpCameraSetting popup open.\n\nTest 2 : \nReload the page and block permission to camera and\/or microphone access on the camera setting page.\n\nResult 2 : \nOrange popup show at the bottom of the screen.\nIf you click on it, the HelpCameraSetting popup open.\n",
+ "wrap":true
+ },
+ "type":"",
+ "visible":true,
+ "width":295.278811252269,
+ "x":12.2517014519056,
+ "y":49.3021778584392
+ }],
+ "opacity":1,
+ "type":"objectgroup",
+ "visible":true,
+ "x":0,
+ "y":0
+ }],
+ "nextlayerid":6,
+ "nextobjectid":2,
+ "orientation":"orthogonal",
+ "renderorder":"right-down",
+ "tiledversion":"1.4.3",
+ "tileheight":32,
+ "tilesets":[
+ {
+ "columns":8,
+ "firstgid":1,
+ "image":"Validation\/tileset_dungeon.png",
+ "imageheight":256,
+ "imagewidth":256,
+ "margin":0,
+ "name":"dungeon",
+ "spacing":0,
+ "tilecount":64,
+ "tileheight":32,
+ "tiles":[
+ {
+ "id":0,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":1,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":2,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":5,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":8,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":10,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":16,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":17,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":18,
+ "properties":[
+ {
+ "name":"collides",
+ "type":"bool",
+ "value":true
+ }]
+ }],
+ "tilewidth":32
+ }],
+ "tilewidth":32,
+ "type":"map",
+ "version":1.4,
+ "width":10
+}
\ No newline at end of file
diff --git a/maps/tests/index.html b/maps/tests/index.html
index 527b435f..2ef0216c 100644
--- a/maps/tests/index.html
+++ b/maps/tests/index.html
@@ -42,6 +42,14 @@
Testing scripting API with a script
+
+
+ Success Failure Pending
+
+
+ Testing goToPage script Api
+
+
Success Failure Pending
@@ -50,6 +58,14 @@
Testing scripting API loadSound() function
+
+
+ Success Failure Pending
+
+
+ Testing scripting API deprecated function
+
+
Success Failure Pending
@@ -82,6 +98,14 @@
Test energy consumption
+
+
+ Success Failure Pending
+
+
+ Test the HelpCameraSettingScene
+
+
Success Failure Pending
diff --git a/maps/tests/script.js b/maps/tests/script.js
index 4a889a8a..b300700f 100644
--- a/maps/tests/script.js
+++ b/maps/tests/script.js
@@ -7,21 +7,21 @@ var targetObjectTutoBubble ='myPopup1';
var targetObjectTutoChat ='myPopup2';
var popUpExplanation = undefined;
function launchTuto (){
- WA.openPopup(targetObjectTutoBubble, textFirstPopup, [
+ WA.ui.openPopup(targetObjectTutoBubble, textFirstPopup, [
{
label: "Next",
className: "popUpElement",
callback: (popup) => {
popup.close();
- WA.openPopup(targetObjectTutoChat, textSecondPopup, [
+ WA.ui.openPopup(targetObjectTutoChat, textSecondPopup, [
{
label: "Open Chat",
className: "popUpElement",
callback: (popup1) => {
- WA.sendChatMessage("Hey you can talk here too ! ", 'WA Guide');
+ WA.chat.sendChatMessage("Hey you can talk here too ! ", 'WA Guide');
popup1.close();
- WA.restorePlayerControls();
+ WA.controls.restorePlayerControls();
}
}
@@ -29,32 +29,32 @@ function launchTuto (){
}
}
]);
- WA.disablePlayerControls();
+ WA.controls.disablePlayerControls();
}
-WA.onChatMessage((message => {
+WA.chat.onChatMessage((message => {
console.log('CHAT MESSAGE RECEIVED BY SCRIPT');
- WA.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot');
+ WA.chat.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot');
}));
-WA.onEnterZone('myTrigger', () => {
- WA.sendChatMessage("Don't step on my carpet!", 'Poly Parrot');
+WA.room.onEnterZone('myTrigger', () => {
+ WA.chat.sendChatMessage("Don't step on my carpet!", 'Poly Parrot');
})
-WA.onLeaveZone('popupZone', () => {
+WA.room.onLeaveZone('popupZone', () => {
})
-WA.onEnterZone('notExist', () => {
- WA.sendChatMessage("YOU SHOULD NEVER SEE THIS", 'Poly Parrot');
+WA.room.onEnterZone('notExist', () => {
+ WA.chat.sendChatMessage("YOU SHOULD NEVER SEE THIS", 'Poly Parrot');
})
-WA.onEnterZone('popupZone', () => {
- WA.displayBubble();
+WA.room.onEnterZone('popupZone', () => {
+ WA.ui.displayBubble();
if (!isFirstTimeTuto) {
isFirstTimeTuto = true;
launchTuto();
}
- else popUpExplanation = WA.openPopup(targetObjectTutoChat,'Do you want to review the explanation ? ', [
+ else popUpExplanation = WA.ui.openPopup(targetObjectTutoChat,'Do you want to review the explanation ? ', [
{
label: "No",
className: "popUpElementReviewexplanation",
@@ -73,7 +73,7 @@ WA.onEnterZone('popupZone', () => {
])
});
-WA.onLeaveZone('popupZone', () => {
+WA.room.onLeaveZone('popupZone', () => {
if (popUpExplanation !== undefined) popUpExplanation.close();
- WA.removeBubble();
+ WA.ui.removeBubble();
})
diff --git a/maps/yarn.lock b/maps/yarn.lock
index 041c70ed..cc8a82fa 100644
--- a/maps/yarn.lock
+++ b/maps/yarn.lock
@@ -617,9 +617,9 @@ get-stdin@^4.0.1:
integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
glob-parent@^5.0.0, glob-parent@~5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
- integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto
index 3a5afb57..52d58d6d 100644
--- a/messages/protos/messages.proto
+++ b/messages/protos/messages.proto
@@ -157,6 +157,7 @@ message UserJoinedMessage {
repeated CharacterLayerMessage characterLayers = 3;
PositionMessage position = 4;
CompanionMessage companion = 5;
+ string visitCardUrl = 6;
}
message UserLeftMessage {
@@ -274,6 +275,7 @@ message JoinRoomMessage {
repeated string tag = 6;
string IPAddress = 7;
CompanionMessage companion = 8;
+ string visitCardUrl = 9;
}
message UserJoinedZoneMessage {
@@ -283,6 +285,7 @@ message UserJoinedZoneMessage {
PositionMessage position = 4;
Zone fromZone = 5;
CompanionMessage companion = 6;
+ string visitCardUrl = 7;
}
message UserLeftZoneMessage {
diff --git a/messages/yarn.lock b/messages/yarn.lock
index af71c938..564da3f4 100644
--- a/messages/yarn.lock
+++ b/messages/yarn.lock
@@ -1823,9 +1823,9 @@ getpass@^0.1.1:
assert-plus "^1.0.0"
glob-parent@^5.0.0, glob-parent@^5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
- integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
diff --git a/pusher/package.json b/pusher/package.json
index 7edf3d5d..63188032 100644
--- a/pusher/package.json
+++ b/pusher/package.json
@@ -38,23 +38,16 @@
"homepage": "https://github.com/thecodingmachine/workadventure#readme",
"dependencies": {
"axios": "^0.21.1",
- "body-parser": "^1.19.0",
"busboy": "^0.3.1",
"circular-json": "^0.5.9",
"debug": "^4.3.1",
"generic-type-guard": "^3.2.0",
"google-protobuf": "^3.13.0",
"grpc": "^1.24.4",
- "http-status-codes": "^1.4.0",
- "iterall": "^1.3.0",
"jsonwebtoken": "^8.5.1",
"mkdirp": "^1.0.4",
- "multer": "^1.4.2",
"prom-client": "^12.0.0",
"query-string": "^6.13.3",
- "systeminformation": "^4.31.1",
- "ts-node-dev": "^1.0.0-pre.44",
- "typescript": "^3.8.3",
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
"uuidv4": "^6.0.7"
},
@@ -71,6 +64,8 @@
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"eslint": "^6.8.0",
- "jasmine": "^3.5.0"
+ "jasmine": "^3.5.0",
+ "ts-node-dev": "^1.0.0-pre.44",
+ "typescript": "^3.8.3"
}
}
diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts
index a5aa47cc..317848c0 100644
--- a/pusher/src/Controller/AuthenticateController.ts
+++ b/pusher/src/Controller/AuthenticateController.ts
@@ -110,12 +110,10 @@ export class AuthenticateController extends BaseController {
private anonymLogin(){
this.App.options("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
this.addCorsHeaders(res);
-
res.end();
});
- this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
-
+ this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn('Login request was aborted');
})
diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts
index 6d120f50..b2079953 100644
--- a/pusher/src/Controller/IoSocketController.ts
+++ b/pusher/src/Controller/IoSocketController.ts
@@ -1,5 +1,5 @@
import {CharacterLayer, ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.."
-import {GameRoomPolicyTypes, PusherRoom} from "../Model/PusherRoom";
+import {GameRoomPolicyTypes} from "../Model/PusherRoom";
import {PointInterface} from "../Model/Websocket/PointInterface";
import {
SetPlayerDetailsMessage,
@@ -12,8 +12,11 @@ import {
WebRtcSignalToServerMessage,
PlayGlobalMessage,
ReportPlayerMessage,
- EmoteEventMessage,
- QueryJitsiJwtMessage, SendUserMessage, ServerToClientMessage, CompanionMessage, EmotePromptMessage
+ QueryJitsiJwtMessage,
+ SendUserMessage,
+ ServerToClientMessage,
+ CompanionMessage,
+ EmotePromptMessage,
} from "../Messages/generated/messages_pb";
import {UserMovesMessage} from "../Messages/generated/messages_pb";
import {TemplatedApp} from "uWebSockets.js"
@@ -21,7 +24,7 @@ import {parse} from "query-string";
import {jwtTokenManager} from "../Services/JWTTokenManager";
import {adminApi, CharacterTexture, FetchMemberDataByUuidResponse} from "../Services/AdminApi";
import {SocketManager, socketManager} from "../Services/SocketManager";
-import {emitError, emitInBatch} from "../Services/IoSocketHelpers";
+import {emitInBatch} from "../Services/IoSocketHelpers";
import {ADMIN_API_TOKEN, ADMIN_API_URL, SOCKET_IDLE_TIMER} from "../Enum/EnvironmentVariable";
import {Zone} from "_Model/Zone";
import {ExAdminSocketInterface} from "_Model/Websocket/ExAdminSocketInterface";
@@ -164,6 +167,7 @@ export class IoSocketController {
const userUuid = await jwtTokenManager.getUserUuidFromToken(token, IPAddress, roomId);
let memberTags: string[] = [];
+ let memberVisitCardUrl: string|null = null;
let memberMessages: unknown;
let memberTextures: CharacterTexture[] = [];
const room = await socketManager.getOrCreateRoom(roomId);
@@ -172,6 +176,7 @@ export class IoSocketController {
let userData : FetchMemberDataByUuidResponse = {
uuid: v4(),
tags: [],
+ visitCardUrl: null,
textures: [],
messages: [],
anonymous: true
@@ -199,6 +204,7 @@ export class IoSocketController {
}
memberMessages = userData.messages;
memberTags = userData.tags;
+ memberVisitCardUrl = userData.visitCardUrl;
memberTextures = userData.textures;
if (!room.public && room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY && (userData.anonymous === true || !room.canAccess(memberTags))) {
throw new Error('Insufficient privileges to access this room')
@@ -235,6 +241,7 @@ export class IoSocketController {
characterLayers: characterLayerObjs,
messages: memberMessages,
tags: memberTags,
+ visitCardUrl: memberVisitCardUrl,
textures: memberTextures,
position: {
x: x,
@@ -373,6 +380,7 @@ export class IoSocketController {
client.messages = ws.messages;
client.name = ws.name;
client.tags = ws.tags;
+ client.visitCardUrl = ws.visitCardUrl;
client.textures = ws.textures;
client.characterLayers = ws.characterLayers;
client.companion = ws.companion;
diff --git a/pusher/src/Model/Websocket/ExSocketInterface.ts b/pusher/src/Model/Websocket/ExSocketInterface.ts
index 5b9a4f7e..98759142 100644
--- a/pusher/src/Model/Websocket/ExSocketInterface.ts
+++ b/pusher/src/Model/Websocket/ExSocketInterface.ts
@@ -40,6 +40,7 @@ export interface ExSocketInterface extends WebSocket, Identificable {
disconnecting: boolean,
messages: unknown,
tags: string[],
+ visitCardUrl: string|null,
textures: CharacterTexture[],
backConnection: BackConnection,
listenedZones: Set;
diff --git a/pusher/src/Model/Zone.ts b/pusher/src/Model/Zone.ts
index 5c50ef00..318a119b 100644
--- a/pusher/src/Model/Zone.ts
+++ b/pusher/src/Model/Zone.ts
@@ -30,7 +30,7 @@ export type MovesCallback = (thing: Movable, position: PositionInterface, listen
export type LeavesCallback = (thing: Movable, listener: User) => void;*/
export class UserDescriptor {
- private constructor(public readonly userId: number, private name: string, private characterLayers: CharacterLayerMessage[], private position: PositionMessage, private companion?: CompanionMessage) {
+ private constructor(public readonly userId: number, private name: string, private characterLayers: CharacterLayerMessage[], private position: PositionMessage, private visitCardUrl: string | null, private companion?: CompanionMessage) {
if (!Number.isInteger(this.userId)) {
throw new Error('UserDescriptor.userId is not an integer: '+this.userId);
}
@@ -41,7 +41,7 @@ export class UserDescriptor {
if (position === undefined) {
throw new Error('Missing position');
}
- return new UserDescriptor(message.getUserid(), message.getName(), message.getCharacterlayersList(), position, message.getCompanion());
+ return new UserDescriptor(message.getUserid(), message.getName(), message.getCharacterlayersList(), position, message.getVisitcardurl(), message.getCompanion());
}
public update(userMovedMessage: UserMovedMessage) {
@@ -59,7 +59,10 @@ export class UserDescriptor {
userJoinedMessage.setName(this.name);
userJoinedMessage.setCharacterlayersList(this.characterLayers);
userJoinedMessage.setPosition(this.position);
- userJoinedMessage.setCompanion(this.companion)
+ if (this.visitCardUrl) {
+ userJoinedMessage.setVisitcardurl(this.visitCardUrl);
+ }
+ userJoinedMessage.setCompanion(this.companion);
return userJoinedMessage;
}
diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts
index bd8edeb6..fbd7a070 100644
--- a/pusher/src/Services/AdminApi.ts
+++ b/pusher/src/Services/AdminApi.ts
@@ -36,6 +36,7 @@ export interface CharacterTexture {
export interface FetchMemberDataByUuidResponse {
uuid: string;
tags: string[];
+ visitCardUrl: string|null;
textures: CharacterTexture[];
messages: unknown[];
anonymous?: boolean;
diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts
index 3bf8467a..319d2b5e 100644
--- a/pusher/src/Services/SocketManager.ts
+++ b/pusher/src/Services/SocketManager.ts
@@ -24,7 +24,12 @@ import {
AdminPusherToBackMessage,
ServerToAdminClientMessage,
EmoteEventMessage,
- UserJoinedRoomMessage, UserLeftRoomMessage, AdminMessage, BanMessage, RefreshRoomMessage, EmotePromptMessage
+ UserJoinedRoomMessage,
+ UserLeftRoomMessage,
+ AdminMessage,
+ BanMessage,
+ RefreshRoomMessage,
+ EmotePromptMessage,
} from "../Messages/generated/messages_pb";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
import {JITSI_ISS, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
@@ -156,6 +161,9 @@ export class SocketManager implements ZoneEventListener {
joinRoomMessage.setName(client.name);
joinRoomMessage.setPositionmessage(ProtobufUtils.toPositionMessage(client.position));
joinRoomMessage.setTagList(client.tags);
+ if (client.visitCardUrl) {
+ joinRoomMessage.setVisitcardurl(client.visitCardUrl);
+ }
joinRoomMessage.setCompanion(client.companion);
for (const characterLayer of client.characterLayers) {
@@ -294,6 +302,7 @@ export class SocketManager implements ZoneEventListener {
throw 'reported socket user not found';
}
//TODO report user on admin application
+ //todo: move to back because this fail if the reported player is in another pusher.
await adminApi.reportPlayer(reportedSocket.userUuid, reportPlayerMessage.getReportcomment(), client.userUuid, client.roomId.split('/')[2])
} catch (e) {
console.error('An error occurred on "handleReportMessage"');
diff --git a/pusher/yarn.lock b/pusher/yarn.lock
index 8af760c8..88a20475 100644
--- a/pusher/yarn.lock
+++ b/pusher/yarn.lock
@@ -257,11 +257,6 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-append-field@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
- integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
-
aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -370,22 +365,6 @@ bintrees@1.0.1:
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
-body-parser@^1.19.0:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
- integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
- dependencies:
- bytes "3.1.0"
- content-type "~1.0.4"
- debug "2.6.9"
- depd "~1.1.2"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- on-finished "~2.3.0"
- qs "6.7.0"
- raw-body "2.4.0"
- type-is "~1.6.17"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -427,14 +406,6 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-busboy@^0.2.11:
- version "0.2.14"
- resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
- integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
- dependencies:
- dicer "0.2.5"
- readable-stream "1.1.x"
-
busboy@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
@@ -449,11 +420,6 @@ bytebuffer@~5:
dependencies:
long "~3"
-bytes@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
cache-base@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
@@ -622,26 +588,11 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
@@ -678,7 +629,7 @@ dateformat@~1.0.4-1.2.3:
get-stdin "^4.0.1"
meow "^3.3.0"
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
+debug@^2.2.0, debug@^2.3.3:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -753,24 +704,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
- integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-dicer@0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
- integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
- dependencies:
- readable-stream "1.1.x"
- streamsearch "0.1.2"
-
dicer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
@@ -804,11 +742,6 @@ ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer "^5.0.1"
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
- integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -1255,28 +1188,12 @@ hosted-git-info@^2.1.4:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-http-errors@1.7.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
- integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.1"
- statuses ">= 1.5.0 < 2"
- toidentifier "1.0.0"
-
http-status-codes@*:
version "2.1.4"
resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.4.tgz#453d99b4bd9424254c4f6a9a3a03715923052798"
integrity sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg==
-http-status-codes@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-1.4.0.tgz#6e4c15d16ff3a9e2df03b89f3a55e1aae05fb477"
- integrity sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ==
-
-iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
+iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -1323,16 +1240,11 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-inherits@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
ini@~1.3.0:
version "1.3.7"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
@@ -1507,11 +1419,6 @@ is-windows@^1.0.2:
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
isarray@1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -1534,11 +1441,6 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-iterall@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
- integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
-
jasmine-core@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20"
@@ -1743,11 +1645,6 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-media-typer@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
- integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
meow@^3.3.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
@@ -1788,18 +1685,6 @@ micromatch@^3.1.10:
snapdragon "^0.8.1"
to-regex "^3.0.2"
-mime-db@1.44.0:
- version "1.44.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
- integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
-
-mime-types@~2.1.24:
- version "2.1.27"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
- integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
- dependencies:
- mime-db "1.44.0"
-
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -1862,20 +1747,6 @@ ms@2.1.2, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-multer@^1.4.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
- integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
- dependencies:
- append-field "^1.0.0"
- busboy "^0.2.11"
- concat-stream "^1.5.2"
- mkdirp "^0.5.1"
- object-assign "^4.1.1"
- on-finished "^2.3.0"
- type-is "^1.6.4"
- xtend "^4.0.0"
-
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
@@ -1997,7 +1868,7 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -2025,13 +1896,6 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-on-finished@^2.3.0, on-finished@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
- integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
- dependencies:
- ee-first "1.1.1"
-
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -2207,11 +2071,6 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-qs@6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
- integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
query-string@^6.13.3:
version "6.13.4"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.4.tgz#b35a9a3bd4955bce55f94feb0e819b3d0be6f66f"
@@ -2221,16 +2080,6 @@ query-string@^6.13.3:
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"
-raw-body@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
- integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -2258,17 +2107,7 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
-readable-stream@1.1.x:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readable-stream@^2.0.6, readable-stream@^2.2.2:
+readable-stream@^2.0.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -2444,11 +2283,6 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
-setprototypeof@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
- integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -2590,11 +2424,6 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"
-"statuses@>= 1.5.0 < 2":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
- integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
streamsearch@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
@@ -2640,11 +2469,6 @@ string-width@^4.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -2723,11 +2547,6 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
-systeminformation@^4.31.1:
- version "4.31.1"
- resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.31.1.tgz#2e02c26987494d4b6a4d2d83138724593bc98d50"
- integrity sha512-dVCDWNMN8ncMZo5vbMCA5dpAdMgzafK2ucuJy5LFmGtp1cG6farnPg8QNvoOSky9SkFoEX1Aw0XhcOFV6TnLYA==
-
table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@@ -2807,11 +2626,6 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
-toidentifier@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
- integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@@ -2889,19 +2703,6 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
-type-is@^1.6.4, type-is@~1.6.17:
- version "1.6.18"
- resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
- integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
- dependencies:
- media-typer "0.3.0"
- mime-types "~2.1.24"
-
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
typescript@^3.8.3:
version "3.9.7"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
@@ -2921,11 +2722,6 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^2.0.1"
-unpipe@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
diff --git a/uploader/package.json b/uploader/package.json
index 27e1d146..62b55c07 100644
--- a/uploader/package.json
+++ b/uploader/package.json
@@ -37,18 +37,12 @@
},
"homepage": "https://github.com/thecodingmachine/workadventure#readme",
"dependencies": {
- "body-parser": "^1.19.0",
"busboy": "^0.3.1",
"debug": "^4.3.1",
- "http-status-codes": "^1.4.0",
- "iterall": "^1.3.0",
"jsonwebtoken": "^8.5.1",
- "multer": "^1.4.2",
"mkdirp": "^1.0.4",
"prom-client": "^12.0.0",
"query-string": "^6.13.3",
- "ts-node-dev": "^1.0.0-pre.44",
- "typescript": "^3.8.3",
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
"uuidv4": "^6.0.7"
},
@@ -64,6 +58,8 @@
"@types/mkdirp": "^1.0.1",
"@types/uuidv4": "^5.0.0",
"eslint": "^6.8.0",
- "jasmine": "^3.5.0"
+ "jasmine": "^3.5.0",
+ "ts-node-dev": "^1.0.0-pre.44",
+ "typescript": "^3.8.3"
}
}
diff --git a/uploader/yarn.lock b/uploader/yarn.lock
index 5b6741ac..897bd82d 100644
--- a/uploader/yarn.lock
+++ b/uploader/yarn.lock
@@ -205,11 +205,6 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-append-field@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
- integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
-
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
@@ -247,22 +242,6 @@ bintrees@1.0.1:
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
-body-parser@^1.19.0:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
- integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
- dependencies:
- bytes "3.1.0"
- content-type "~1.0.4"
- debug "2.6.9"
- depd "~1.1.2"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- on-finished "~2.3.0"
- qs "6.7.0"
- raw-body "2.4.0"
- type-is "~1.6.17"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -288,14 +267,6 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-busboy@^0.2.11:
- version "0.2.14"
- resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
- integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
- dependencies:
- dicer "0.2.5"
- readable-stream "1.1.x"
-
busboy@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
@@ -303,11 +274,6 @@ busboy@^0.3.1:
dependencies:
dicer "0.3.0"
-bytes@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -404,26 +370,6 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
-content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
-core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -455,13 +401,6 @@ dateformat@~1.0.4-1.2.3:
get-stdin "^4.0.1"
meow "^3.3.0"
-debug@2.6.9:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
debug@^4.0.1, debug@^4.1.1, debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
@@ -484,19 +423,6 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
-depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
- integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
-dicer@0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
- integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
- dependencies:
- readable-stream "1.1.x"
- streamsearch "0.1.2"
-
dicer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
@@ -530,11 +456,6 @@ ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer "^5.0.1"
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
- integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -763,9 +684,9 @@ get-stdin@^4.0.1:
integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
glob-parent@^5.0.0, glob-parent@~5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
- integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
@@ -815,28 +736,12 @@ hosted-git-info@^2.1.4:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-http-errors@1.7.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
- integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.1"
- statuses ">= 1.5.0 < 2"
- toidentifier "1.0.0"
-
http-status-codes@*:
version "2.1.4"
resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.4.tgz#453d99b4bd9424254c4f6a9a3a03715923052798"
integrity sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg==
-http-status-codes@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-1.4.0.tgz#6e4c15d16ff3a9e2df03b89f3a55e1aae05fb477"
- integrity sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ==
-
-iconv-lite@0.4.24, iconv-lite@^0.4.24:
+iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -876,16 +781,11 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-inherits@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
inquirer@^7.0.0:
version "7.3.3"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
@@ -961,26 +861,11 @@ is-utf8@^0.2.0:
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-iterall@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
- integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
-
jasmine-core@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20"
@@ -1134,11 +1019,6 @@ map-obj@^1.0.0, map-obj@^1.0.1:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
-media-typer@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
- integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
meow@^3.3.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
@@ -1155,18 +1035,6 @@ meow@^3.3.0:
redent "^1.0.0"
trim-newlines "^1.0.0"
-mime-db@1.44.0:
- version "1.44.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
- integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
-
-mime-types@~2.1.24:
- version "2.1.27"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
- integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
- dependencies:
- mime-db "1.44.0"
-
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -1196,11 +1064,6 @@ mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -1211,20 +1074,6 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-multer@^1.4.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
- integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
- dependencies:
- append-field "^1.0.0"
- busboy "^0.2.11"
- concat-stream "^1.5.2"
- mkdirp "^0.5.1"
- object-assign "^4.1.1"
- on-finished "^2.3.0"
- type-is "^1.6.4"
- xtend "^4.0.0"
-
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
@@ -1255,18 +1104,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-object-assign@^4.0.1, object-assign@^4.1.1:
+object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-on-finished@^2.3.0, on-finished@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
- integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
- dependencies:
- ee-first "1.1.1"
-
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -1370,11 +1212,6 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
progress@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
@@ -1392,11 +1229,6 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-qs@6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
- integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
query-string@^6.13.3:
version "6.13.7"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.7.tgz#af53802ff6ed56f3345f92d40a056f93681026ee"
@@ -1406,16 +1238,6 @@ query-string@^6.13.3:
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"
-raw-body@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
- integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -1433,29 +1255,6 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
-readable-stream@1.1.x:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readable-stream@^2.2.2:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
@@ -1540,11 +1339,6 @@ safe-buffer@^5.0.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -1567,11 +1361,6 @@ semver@^7.3.2:
dependencies:
lru-cache "^6.0.0"
-setprototypeof@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
- integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -1647,11 +1436,6 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-"statuses@>= 1.5.0 < 2":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
- integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
streamsearch@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
@@ -1680,18 +1464,6 @@ string-width@^4.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
@@ -1790,11 +1562,6 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
-toidentifier@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
- integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@@ -1873,19 +1640,6 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
-type-is@^1.6.4, type-is@~1.6.17:
- version "1.6.18"
- resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
- integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
- dependencies:
- media-typer "0.3.0"
- mime-types "~2.1.24"
-
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
typescript@^3.8.3:
version "3.9.7"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
@@ -1895,11 +1649,6 @@ uWebSockets.js@uNetworking/uWebSockets.js#v18.5.0:
version "18.5.0"
resolved "https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/9b1605d2db82981cafe69dbe356e10ce412f5805"
-unpipe@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
uri-js@^4.2.2:
version "4.4.0"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602"
@@ -1907,11 +1656,6 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
-util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
uuid@8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
diff --git a/website/.dockerignore b/website/.dockerignore
deleted file mode 100644
index 576c21a2..00000000
--- a/website/.dockerignore
+++ /dev/null
@@ -1,5 +0,0 @@
-/dist/
-/node_modules/
-/dist/bundle.js
-/yarn-error.log
-/Dockerfile