commit
ee906dc52b
@ -1,5 +1,10 @@
|
|||||||
## Version develop
|
## Version develop
|
||||||
|
|
||||||
|
### Bugfix
|
||||||
|
- Moving a discussion over a user will now add this user to the discussion
|
||||||
|
- Being in a silent zone new forces mediaConstraints to false (#1508)
|
||||||
|
- Fixes for the emote menu (#1501)
|
||||||
|
|
||||||
## Version 1.5.0
|
## Version 1.5.0
|
||||||
### Updates
|
### Updates
|
||||||
- Added support for login with OpenID Connect
|
- Added support for login with OpenID Connect
|
||||||
|
@ -181,6 +181,7 @@ export class GameRoom {
|
|||||||
|
|
||||||
private updateUserGroup(user: User): void {
|
private updateUserGroup(user: User): void {
|
||||||
user.group?.updatePosition();
|
user.group?.updatePosition();
|
||||||
|
user.group?.searchForNearbyUsers();
|
||||||
|
|
||||||
if (user.silent) {
|
if (user.silent) {
|
||||||
return;
|
return;
|
||||||
@ -206,6 +207,7 @@ export class GameRoom {
|
|||||||
const group: Group = new Group(
|
const group: Group = new Group(
|
||||||
this.roomUrl,
|
this.roomUrl,
|
||||||
[user, closestUser],
|
[user, closestUser],
|
||||||
|
this.groupRadius,
|
||||||
this.connectCallback,
|
this.connectCallback,
|
||||||
this.disconnectCallback,
|
this.disconnectCallback,
|
||||||
this.positionNotifier
|
this.positionNotifier
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ConnectCallback, DisconnectCallback } from "./GameRoom";
|
import { ConnectCallback, DisconnectCallback, GameRoom } from "./GameRoom";
|
||||||
import { User } from "./User";
|
import { User } from "./User";
|
||||||
import { PositionInterface } from "_Model/PositionInterface";
|
import { PositionInterface } from "_Model/PositionInterface";
|
||||||
import { Movable } from "_Model/Movable";
|
import { Movable } from "_Model/Movable";
|
||||||
import { PositionNotifier } from "_Model/PositionNotifier";
|
import { PositionNotifier } from "_Model/PositionNotifier";
|
||||||
import { gaugeManager } from "../Services/GaugeManager";
|
|
||||||
import { MAX_PER_GROUP } from "../Enum/EnvironmentVariable";
|
import { MAX_PER_GROUP } from "../Enum/EnvironmentVariable";
|
||||||
|
import type { Zone } from "../Model/Zone";
|
||||||
|
|
||||||
export class Group implements Movable {
|
export class Group implements Movable {
|
||||||
private static nextId: number = 1;
|
private static nextId: number = 1;
|
||||||
@ -13,13 +13,14 @@ export class Group implements Movable {
|
|||||||
private users: Set<User>;
|
private users: Set<User>;
|
||||||
private x!: number;
|
private x!: number;
|
||||||
private y!: number;
|
private y!: number;
|
||||||
private hasEditedGauge: boolean = false;
|
|
||||||
private wasDestroyed: boolean = false;
|
private wasDestroyed: boolean = false;
|
||||||
private roomId: string;
|
private roomId: string;
|
||||||
|
private currentZone: Zone | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
users: User[],
|
users: User[],
|
||||||
|
private groupRadius: number,
|
||||||
private connectCallback: ConnectCallback,
|
private connectCallback: ConnectCallback,
|
||||||
private disconnectCallback: DisconnectCallback,
|
private disconnectCallback: DisconnectCallback,
|
||||||
private positionNotifier: PositionNotifier
|
private positionNotifier: PositionNotifier
|
||||||
@ -28,13 +29,6 @@ export class Group implements Movable {
|
|||||||
this.users = new Set<User>();
|
this.users = new Set<User>();
|
||||||
this.id = Group.nextId;
|
this.id = Group.nextId;
|
||||||
Group.nextId++;
|
Group.nextId++;
|
||||||
//we only send a event for prometheus metrics if the group lives more than 5 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.wasDestroyed) {
|
|
||||||
this.hasEditedGauge = true;
|
|
||||||
gaugeManager.incNbGroupsPerRoomGauge(roomId);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
users.forEach((user: User) => {
|
users.forEach((user: User) => {
|
||||||
this.join(user);
|
this.join(user);
|
||||||
@ -85,9 +79,22 @@ export class Group implements Movable {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
|
|
||||||
if (oldX === undefined) {
|
if (oldX === undefined) {
|
||||||
this.positionNotifier.enter(this);
|
this.currentZone = this.positionNotifier.enter(this);
|
||||||
} else {
|
} else {
|
||||||
this.positionNotifier.updatePosition(this, { x, y }, { x: oldX, y: oldY });
|
this.currentZone = this.positionNotifier.updatePosition(this, { x, y }, { x: oldX, y: oldY });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchForNearbyUsers(): void {
|
||||||
|
if (!this.currentZone) return;
|
||||||
|
|
||||||
|
for (const user of this.positionNotifier.getAllUsersInSquareAroundZone(this.currentZone)) {
|
||||||
|
if (user.group || this.isFull()) return; //we ignore users that are already in a group.
|
||||||
|
const distance = GameRoom.computeDistanceBetweenPositions(user.getPosition(), this.getPosition());
|
||||||
|
if (distance < this.groupRadius) {
|
||||||
|
this.join(user);
|
||||||
|
this.updatePosition();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +133,6 @@ export class Group implements Movable {
|
|||||||
* Usually used when there is only one user left.
|
* Usually used when there is only one user left.
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
if (this.hasEditedGauge) gaugeManager.decNbGroupsPerRoomGauge(this.roomId);
|
|
||||||
for (const user of this.users) {
|
for (const user of this.users) {
|
||||||
this.leave(user);
|
this.leave(user);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, Zone } fr
|
|||||||
import { Movable } from "_Model/Movable";
|
import { Movable } from "_Model/Movable";
|
||||||
import { PositionInterface } from "_Model/PositionInterface";
|
import { PositionInterface } from "_Model/PositionInterface";
|
||||||
import { ZoneSocket } from "../RoomManager";
|
import { ZoneSocket } from "../RoomManager";
|
||||||
import { User } from "_Model/User";
|
import { User } from "../Model/User";
|
||||||
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
import { EmoteEventMessage } from "../Messages/generated/messages_pb";
|
||||||
|
|
||||||
interface ZoneDescriptor {
|
interface ZoneDescriptor {
|
||||||
@ -20,6 +20,17 @@ interface ZoneDescriptor {
|
|||||||
j: number;
|
j: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* getNearbyDescriptorsMatrix(middleZoneDescriptor: ZoneDescriptor): Generator<ZoneDescriptor> {
|
||||||
|
for (let n = 0; n < 9; n++) {
|
||||||
|
const i = middleZoneDescriptor.i + ((n % 3) - 1);
|
||||||
|
const j = middleZoneDescriptor.j + (Math.floor(n / 3) - 1);
|
||||||
|
|
||||||
|
if (i >= 0 && j >= 0) {
|
||||||
|
yield { i, j };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PositionNotifier {
|
export class PositionNotifier {
|
||||||
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
||||||
|
|
||||||
@ -41,14 +52,15 @@ export class PositionNotifier {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public enter(thing: Movable): void {
|
public enter(thing: Movable): Zone {
|
||||||
const position = thing.getPosition();
|
const position = thing.getPosition();
|
||||||
const zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
const zoneDesc = this.getZoneDescriptorFromCoordinates(position.x, position.y);
|
||||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||||
zone.enter(thing, null, position);
|
zone.enter(thing, null, position);
|
||||||
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updatePosition(thing: Movable, newPosition: PositionInterface, oldPosition: PositionInterface): void {
|
public updatePosition(thing: Movable, newPosition: PositionInterface, oldPosition: PositionInterface): Zone {
|
||||||
// Did we change zone?
|
// Did we change zone?
|
||||||
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(oldPosition.x, oldPosition.y);
|
const oldZoneDesc = this.getZoneDescriptorFromCoordinates(oldPosition.x, oldPosition.y);
|
||||||
const newZoneDesc = this.getZoneDescriptorFromCoordinates(newPosition.x, newPosition.y);
|
const newZoneDesc = this.getZoneDescriptorFromCoordinates(newPosition.x, newPosition.y);
|
||||||
@ -62,9 +74,11 @@ export class PositionNotifier {
|
|||||||
|
|
||||||
// Enter new zone
|
// Enter new zone
|
||||||
newZone.enter(thing, oldZone, newPosition);
|
newZone.enter(thing, oldZone, newPosition);
|
||||||
|
return newZone;
|
||||||
} else {
|
} else {
|
||||||
const zone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
const zone = this.getZone(oldZoneDesc.i, oldZoneDesc.j);
|
||||||
zone.move(thing, newPosition);
|
zone.move(thing, newPosition);
|
||||||
|
return zone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,4 +120,16 @@ export class PositionNotifier {
|
|||||||
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
|
||||||
zone.emitEmoteEvent(emoteEventMessage);
|
zone.emitEmoteEvent(emoteEventMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public *getAllUsersInSquareAroundZone(zone: Zone): Generator<User> {
|
||||||
|
const zoneDescriptor = this.getZoneDescriptorFromCoordinates(zone.x, zone.y);
|
||||||
|
for (const d of getNearbyDescriptorsMatrix(zoneDescriptor)) {
|
||||||
|
const zone = this.getZone(d.i, d.j);
|
||||||
|
for (const thing of zone.getThings()) {
|
||||||
|
if (thing instanceof User) {
|
||||||
|
yield thing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,15 +52,6 @@ class GaugeManager {
|
|||||||
this.nbClientsGauge.dec();
|
this.nbClientsGauge.dec();
|
||||||
this.nbClientsPerRoomGauge.dec({ room: roomId });
|
this.nbClientsPerRoomGauge.dec({ room: roomId });
|
||||||
}
|
}
|
||||||
|
|
||||||
incNbGroupsPerRoomGauge(roomId: string): void {
|
|
||||||
this.nbGroupsPerRoomCounter.inc({ room: roomId });
|
|
||||||
this.nbGroupsPerRoomGauge.inc({ room: roomId });
|
|
||||||
}
|
|
||||||
|
|
||||||
decNbGroupsPerRoomGauge(roomId: string): void {
|
|
||||||
this.nbGroupsPerRoomGauge.dec({ room: roomId });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const gaugeManager = new GaugeManager();
|
export const gaugeManager = new GaugeManager();
|
||||||
|
67
back/tests/getNearbyDescriptorsMatrixTest.ts
Normal file
67
back/tests/getNearbyDescriptorsMatrixTest.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import "jasmine";
|
||||||
|
import { getNearbyDescriptorsMatrix } from "../src/Model/PositionNotifier";
|
||||||
|
|
||||||
|
describe("getNearbyDescriptorsMatrix", () => {
|
||||||
|
it("should create a matrix of coordinates in a square around the parameter", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 1, j: 1 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 0, j: 0 },
|
||||||
|
{ i: 1, j: 0 },
|
||||||
|
{ i: 2, j: 0 },
|
||||||
|
{ i: 0, j: 1 },
|
||||||
|
{ i: 1, j: 1 },
|
||||||
|
{ i: 2, j: 1 },
|
||||||
|
{ i: 0, j: 2 },
|
||||||
|
{ i: 1, j: 2 },
|
||||||
|
{ i: 2, j: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a matrix of coordinates in a square around the parameter bis", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 8, j: 3 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 7, j: 2 },
|
||||||
|
{ i: 8, j: 2 },
|
||||||
|
{ i: 9, j: 2 },
|
||||||
|
{ i: 7, j: 3 },
|
||||||
|
{ i: 8, j: 3 },
|
||||||
|
{ i: 9, j: 3 },
|
||||||
|
{ i: 7, j: 4 },
|
||||||
|
{ i: 8, j: 4 },
|
||||||
|
{ i: 9, j: 4 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not create a matrix with negative coordinates", () => {
|
||||||
|
const matrix = [];
|
||||||
|
for (const d of getNearbyDescriptorsMatrix({ i: 0, j: 0 })) {
|
||||||
|
matrix.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{ i: 0, j: 0 },
|
||||||
|
{ i: 1, j: 0 },
|
||||||
|
{ i: 0, j: 1 },
|
||||||
|
{ i: 1, j: 1 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*it("should not create a matrix with coordinates bigger than its dimmensions", () => {
|
||||||
|
const matrix = getNearbyDescriptorsMatrix({i: 4, j: 4}, 5, 5);
|
||||||
|
|
||||||
|
expect(matrix).toEqual([
|
||||||
|
{i: 3,j: 3},
|
||||||
|
{i: 4,j: 3},
|
||||||
|
{i: 3,j: 4},
|
||||||
|
{i: 4,j: 4},
|
||||||
|
])
|
||||||
|
});*/
|
||||||
|
});
|
BIN
front/dist/resources/objects/talk.png
vendored
BIN
front/dist/resources/objects/talk.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 389 B |
@ -50,7 +50,7 @@
|
|||||||
"phaser": "^3.54.0",
|
"phaser": "^3.54.0",
|
||||||
"phaser-animated-tiles": "workadventure/phaser-animated-tiles#da68bbededd605925621dd4f03bd27e69284b254",
|
"phaser-animated-tiles": "workadventure/phaser-animated-tiles#da68bbededd605925621dd4f03bd27e69284b254",
|
||||||
"phaser3-rex-plugins": "^1.1.42",
|
"phaser3-rex-plugins": "^1.1.42",
|
||||||
"posthog-js": "^1.13.12",
|
"posthog-js": "^1.14.1",
|
||||||
"queue-typescript": "^1.0.1",
|
"queue-typescript": "^1.0.1",
|
||||||
"quill": "1.3.6",
|
"quill": "1.3.6",
|
||||||
"quill-delta-to-html": "^0.12.0",
|
"quill-delta-to-html": "^0.12.0",
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { POSTHOG_API_KEY, POSTHOG_URL } from "../Enum/EnvironmentVariable";
|
import { POSTHOG_API_KEY, POSTHOG_URL } from "../Enum/EnvironmentVariable";
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
declare let window: any;
|
||||||
|
|
||||||
class AnalyticsClient {
|
class AnalyticsClient {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -8,6 +10,8 @@ class AnalyticsClient {
|
|||||||
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
||||||
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
||||||
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL, disable_cookie: true });
|
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL, disable_cookie: true });
|
||||||
|
//the posthog toolbar need a reference in window to be able to work
|
||||||
|
window.posthog = posthog;
|
||||||
return posthog;
|
return posthog;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -15,10 +19,10 @@ class AnalyticsClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
identifyUser(uuid: string) {
|
identifyUser(uuid: string, email: string | null) {
|
||||||
this.posthogPromise
|
this.posthogPromise
|
||||||
.then((posthog) => {
|
.then((posthog) => {
|
||||||
posthog.identify(uuid, { uuid, wa: true });
|
posthog.identify(uuid, { uuid, email, wa: true });
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}
|
}
|
||||||
@ -39,10 +43,10 @@ class AnalyticsClient {
|
|||||||
.catch();
|
.catch();
|
||||||
}
|
}
|
||||||
|
|
||||||
enteredRoom(roomId: string) {
|
enteredRoom(roomId: string, roomGroup: string | null) {
|
||||||
this.posthogPromise
|
this.posthogPromise
|
||||||
.then((posthog) => {
|
.then((posthog) => {
|
||||||
posthog.capture("$pageView", { roomId });
|
posthog.capture("$pageView", { roomId, roomGroup });
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import {onDestroy} from "svelte";
|
import {onDestroy} from "svelte";
|
||||||
|
|
||||||
function screenSharingClick(): void {
|
function screenSharingClick(): void {
|
||||||
|
if (isSilent) return;
|
||||||
if ($requestedScreenSharingState === true) {
|
if ($requestedScreenSharingState === true) {
|
||||||
requestedScreenSharingState.disableScreenSharing();
|
requestedScreenSharingState.disableScreenSharing();
|
||||||
} else {
|
} else {
|
||||||
@ -23,6 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cameraClick(): void {
|
function cameraClick(): void {
|
||||||
|
if (isSilent) return;
|
||||||
if ($requestedCameraState === true) {
|
if ($requestedCameraState === true) {
|
||||||
requestedCameraState.disableWebcam();
|
requestedCameraState.disableWebcam();
|
||||||
} else {
|
} else {
|
||||||
@ -31,6 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function microphoneClick(): void {
|
function microphoneClick(): void {
|
||||||
|
if (isSilent) return;
|
||||||
if ($requestedMicrophoneState === true) {
|
if ($requestedMicrophoneState === true) {
|
||||||
requestedMicrophoneState.disableMicrophone();
|
requestedMicrophoneState.disableMicrophone();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import logoWA from "../images/logo-WA-min.png"
|
import logoWA from "../images/logo-WA-pixel.png"
|
||||||
|
import logoTalk from "../images/logo-message-pixel.png"
|
||||||
import {menuVisiblilityStore} from "../../Stores/MenuStore";
|
import {menuVisiblilityStore} from "../../Stores/MenuStore";
|
||||||
|
import {chatVisibilityStore} from "../../Stores/ChatStore";
|
||||||
import {get} from "svelte/store";
|
import {get} from "svelte/store";
|
||||||
|
|
||||||
function showMenu(){
|
function showMenu(){
|
||||||
menuVisiblilityStore.set(!get(menuVisiblilityStore))
|
menuVisiblilityStore.set(!get(menuVisiblilityStore))
|
||||||
}
|
}
|
||||||
|
function showChat(){
|
||||||
|
chatVisibilityStore.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
function onKeyDown(e: KeyboardEvent) {
|
function onKeyDown(e: KeyboardEvent) {
|
||||||
if (e.key === "Tab") {
|
if (e.key === "Tab") {
|
||||||
@ -18,17 +23,23 @@
|
|||||||
|
|
||||||
<main class="menuIcon">
|
<main class="menuIcon">
|
||||||
<img src={logoWA} alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu}>
|
<img src={logoWA} alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu}>
|
||||||
|
<img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat}>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
|
display: inline-grid;
|
||||||
margin: 25px;
|
margin: 25px;
|
||||||
img {
|
img {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
margin: 3px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.menuIcon img:hover{
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
margin: 3px;
|
margin: 3px;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
BIN
front/src/Components/images/logo-WA-pixel.png
Normal file
BIN
front/src/Components/images/logo-WA-pixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
front/src/Components/images/logo-message-pixel.png
Normal file
BIN
front/src/Components/images/logo-message-pixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 389 B |
@ -112,7 +112,7 @@ class ConnectionManager {
|
|||||||
const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then(
|
const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then(
|
||||||
(res) => res.data
|
(res) => res.data
|
||||||
);
|
);
|
||||||
this.localUser = new LocalUser(data.userUuid, data.textures);
|
this.localUser = new LocalUser(data.userUuid, data.textures, data.email);
|
||||||
this.authToken = data.authToken;
|
this.authToken = data.authToken;
|
||||||
localUserStore.saveUser(this.localUser);
|
localUserStore.saveUser(this.localUser);
|
||||||
localUserStore.setAuthToken(this.authToken);
|
localUserStore.setAuthToken(this.authToken);
|
||||||
@ -196,7 +196,7 @@ class ConnectionManager {
|
|||||||
return Promise.reject(new Error("Invalid URL"));
|
return Promise.reject(new Error("Invalid URL"));
|
||||||
}
|
}
|
||||||
if (this.localUser) {
|
if (this.localUser) {
|
||||||
analyticsClient.identifyUser(this.localUser.uuid);
|
analyticsClient.identifyUser(this.localUser.uuid, this.localUser.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.serviceWorker = new _ServiceWorker();
|
this.serviceWorker = new _ServiceWorker();
|
||||||
|
@ -24,5 +24,9 @@ export function areCharacterLayersValid(value: string[] | null): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LocalUser {
|
export class LocalUser {
|
||||||
constructor(public readonly uuid: string, public textures: CharacterTexture[]) {}
|
constructor(
|
||||||
|
public readonly uuid: string,
|
||||||
|
public textures: CharacterTexture[],
|
||||||
|
public email: string | null = null
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ export class Room {
|
|||||||
private instance: string | undefined;
|
private instance: string | undefined;
|
||||||
private readonly _search: URLSearchParams;
|
private readonly _search: URLSearchParams;
|
||||||
private _contactPage: string | undefined;
|
private _contactPage: string | undefined;
|
||||||
|
private _group: string | null = null;
|
||||||
|
|
||||||
private constructor(private roomUrl: URL) {
|
private constructor(private roomUrl: URL) {
|
||||||
this.id = roomUrl.pathname;
|
this.id = roomUrl.pathname;
|
||||||
@ -104,6 +105,7 @@ export class Room {
|
|||||||
console.log("Map ", this.id, " resolves to URL ", data.mapUrl);
|
console.log("Map ", this.id, " resolves to URL ", data.mapUrl);
|
||||||
this._mapUrl = data.mapUrl;
|
this._mapUrl = data.mapUrl;
|
||||||
this._textures = data.textures;
|
this._textures = data.textures;
|
||||||
|
this._group = data.group;
|
||||||
this._authenticationMandatory = data.authenticationMandatory || false;
|
this._authenticationMandatory = data.authenticationMandatory || false;
|
||||||
this._iframeAuthentication = data.iframeAuthentication;
|
this._iframeAuthentication = data.iframeAuthentication;
|
||||||
this._contactPage = data.contactPage || CONTACT_URL;
|
this._contactPage = data.contactPage || CONTACT_URL;
|
||||||
@ -133,25 +135,6 @@ export class Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
private parsePrivateUrl(url: string): { organizationSlug: string; worldSlug: string; roomSlug?: string } {
|
|
||||||
const regex = /@\/([^/]+)\/([^/]+)(?:\/([^/]*))?/gm;
|
|
||||||
const match = regex.exec(url);
|
|
||||||
if (!match) {
|
|
||||||
throw new Error("Invalid URL " + url);
|
|
||||||
}
|
|
||||||
const results: { organizationSlug: string; worldSlug: string; roomSlug?: string } = {
|
|
||||||
organizationSlug: match[1],
|
|
||||||
worldSlug: match[2],
|
|
||||||
};
|
|
||||||
if (match[3] !== undefined) {
|
|
||||||
results.roomSlug = match[3];
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isDisconnected(): boolean {
|
public isDisconnected(): boolean {
|
||||||
const alone = this._search.get("alone");
|
const alone = this._search.get("alone");
|
||||||
if (alone && alone !== "0" && alone.toLowerCase() !== "false") {
|
if (alone && alone !== "0" && alone.toLowerCase() !== "false") {
|
||||||
@ -204,4 +187,8 @@ export class Room {
|
|||||||
get contactPage(): string | undefined {
|
get contactPage(): string | undefined {
|
||||||
return this._contactPage;
|
return this._contactPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get group(): string | null {
|
||||||
|
return this._group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
|
||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
|
||||||
|
|
||||||
export const openChatIconName = "openChatIcon";
|
|
||||||
export class OpenChatIcon extends Phaser.GameObjects.Image {
|
|
||||||
constructor(scene: Phaser.Scene, x: number, y: number) {
|
|
||||||
super(scene, x, y, openChatIconName, 3);
|
|
||||||
scene.add.existing(this);
|
|
||||||
this.setScrollFactor(0, 0);
|
|
||||||
this.setOrigin(0, 1);
|
|
||||||
this.setInteractive();
|
|
||||||
//this.setVisible(false);
|
|
||||||
this.setDepth(DEPTH_INGAME_TEXT_INDEX);
|
|
||||||
|
|
||||||
this.on("pointerup", () => chatVisibilityStore.set(true));
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,7 +38,6 @@ import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
|||||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||||
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
||||||
import { addLoader, removeLoader } from "../Components/Loader";
|
import { addLoader, removeLoader } from "../Components/Loader";
|
||||||
import { OpenChatIcon, openChatIconName } from "../Components/OpenChatIcon";
|
|
||||||
import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
|
import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
|
||||||
import { RemotePlayer } from "../Entity/RemotePlayer";
|
import { RemotePlayer } from "../Entity/RemotePlayer";
|
||||||
import type { ActionableItem } from "../Items/ActionableItem";
|
import type { ActionableItem } from "../Items/ActionableItem";
|
||||||
@ -174,7 +173,6 @@ export class GameScene extends DirtyScene {
|
|||||||
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
||||||
private iframeSubscriptionList!: Array<Subscription>;
|
private iframeSubscriptionList!: Array<Subscription>;
|
||||||
private peerStoreUnsubscribe!: () => void;
|
private peerStoreUnsubscribe!: () => void;
|
||||||
private chatVisibilityUnsubscribe!: () => void;
|
|
||||||
private emoteUnsubscribe!: () => void;
|
private emoteUnsubscribe!: () => void;
|
||||||
private emoteMenuUnsubscribe!: () => void;
|
private emoteMenuUnsubscribe!: () => void;
|
||||||
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
||||||
@ -197,7 +195,6 @@ export class GameScene extends DirtyScene {
|
|||||||
private outlinedItem: ActionableItem | null = null;
|
private outlinedItem: ActionableItem | null = null;
|
||||||
public userInputManager!: UserInputManager;
|
public userInputManager!: UserInputManager;
|
||||||
private isReconnecting: boolean | undefined = undefined;
|
private isReconnecting: boolean | undefined = undefined;
|
||||||
private openChatIcon!: OpenChatIcon;
|
|
||||||
private playerName!: string;
|
private playerName!: string;
|
||||||
private characterLayers!: string[];
|
private characterLayers!: string[];
|
||||||
private companion!: string | null;
|
private companion!: string | null;
|
||||||
@ -245,7 +242,6 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.load.image(openChatIconName, "resources/objects/talk.png");
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
this.load.image(joystickBaseKey, joystickBaseImg);
|
this.load.image(joystickBaseKey, joystickBaseImg);
|
||||||
this.load.image(joystickThumbKey, joystickThumbImg);
|
this.load.image(joystickThumbKey, joystickThumbImg);
|
||||||
@ -432,7 +428,7 @@ export class GameScene extends DirtyScene {
|
|||||||
|
|
||||||
gameManager.gameSceneIsCreated(this);
|
gameManager.gameSceneIsCreated(this);
|
||||||
urlManager.pushRoomIdToUrl(this.room);
|
urlManager.pushRoomIdToUrl(this.room);
|
||||||
analyticsClient.enteredRoom(this.room.id);
|
analyticsClient.enteredRoom(this.room.id, this.room.group);
|
||||||
contactPageStore.set(this.room.contactPage);
|
contactPageStore.set(this.room.contactPage);
|
||||||
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
@ -584,8 +580,6 @@ export class GameScene extends DirtyScene {
|
|||||||
this.outlinedItem?.activate();
|
this.outlinedItem?.activate();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.openChatIcon = new OpenChatIcon(this, 2, this.game.renderer.height - 2);
|
|
||||||
|
|
||||||
this.reposition();
|
this.reposition();
|
||||||
|
|
||||||
// From now, this game scene will be notified of reposition events
|
// From now, this game scene will be notified of reposition events
|
||||||
@ -618,10 +612,6 @@ export class GameScene extends DirtyScene {
|
|||||||
oldPeerNumber = newPeerNumber;
|
oldPeerNumber = newPeerNumber;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chatVisibilityUnsubscribe = chatVisibilityStore.subscribe((v) => {
|
|
||||||
this.openChatIcon.setVisible(!v);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.emoteUnsubscribe = emoteStore.subscribe((emoteKey) => {
|
this.emoteUnsubscribe = emoteStore.subscribe((emoteKey) => {
|
||||||
if (emoteKey) {
|
if (emoteKey) {
|
||||||
this.CurrentPlayer?.playEmote(emoteKey);
|
this.CurrentPlayer?.playEmote(emoteKey);
|
||||||
@ -1327,7 +1317,6 @@ ${escapedMessage}
|
|||||||
this.pinchManager?.destroy();
|
this.pinchManager?.destroy();
|
||||||
this.emoteManager.destroy();
|
this.emoteManager.destroy();
|
||||||
this.peerStoreUnsubscribe();
|
this.peerStoreUnsubscribe();
|
||||||
this.chatVisibilityUnsubscribe();
|
|
||||||
this.emoteUnsubscribe();
|
this.emoteUnsubscribe();
|
||||||
this.emoteMenuUnsubscribe();
|
this.emoteMenuUnsubscribe();
|
||||||
this.biggestAvailableAreaStoreUnsubscribe();
|
this.biggestAvailableAreaStoreUnsubscribe();
|
||||||
@ -1802,8 +1791,6 @@ ${escapedMessage}
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
private reposition(): void {
|
private reposition(): void {
|
||||||
this.openChatIcon.setY(this.game.renderer.height - 2);
|
|
||||||
|
|
||||||
// Recompute camera offset if needed
|
// Recompute camera offset if needed
|
||||||
biggestAvailableAreaStore.recompute();
|
biggestAvailableAreaStore.recompute();
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,11 @@ function createVideoConstraintStore() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store containing if user is silent, so if he is in silent zone. This permit to show et hide camera of user
|
||||||
|
*/
|
||||||
|
export const isSilentStore = writable(false);
|
||||||
|
|
||||||
export const videoConstraintStore = createVideoConstraintStore();
|
export const videoConstraintStore = createVideoConstraintStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,6 +239,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
audioConstraintStore,
|
audioConstraintStore,
|
||||||
privacyShutdownStore,
|
privacyShutdownStore,
|
||||||
cameraEnergySavingStore,
|
cameraEnergySavingStore,
|
||||||
|
isSilentStore,
|
||||||
],
|
],
|
||||||
(
|
(
|
||||||
[
|
[
|
||||||
@ -245,6 +251,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
$audioConstraintStore,
|
$audioConstraintStore,
|
||||||
$privacyShutdownStore,
|
$privacyShutdownStore,
|
||||||
$cameraEnergySavingStore,
|
$cameraEnergySavingStore,
|
||||||
|
$isSilentStore,
|
||||||
],
|
],
|
||||||
set
|
set
|
||||||
) => {
|
) => {
|
||||||
@ -294,6 +301,11 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
//currentAudioConstraint = false;
|
//currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($isSilentStore === true) {
|
||||||
|
currentVideoConstraint = false;
|
||||||
|
currentAudioConstraint = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Let's make the changes only if the new value is different from the old one.
|
// Let's make the changes only if the new value is different from the old one.
|
||||||
if (
|
if (
|
||||||
previousComputedVideoConstraint != currentVideoConstraint ||
|
previousComputedVideoConstraint != currentVideoConstraint ||
|
||||||
@ -607,13 +619,3 @@ localStreamStore.subscribe((streamResult) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* A store containing the real active media is mobile
|
|
||||||
*/
|
|
||||||
export const obtainedMediaConstraintIsMobileStore = writable(false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A store containing if user is silent, so if he is in silent zone. This permit to show et hide camera of user
|
|
||||||
*/
|
|
||||||
export const isSilentStore = writable(false);
|
|
||||||
|
@ -4494,10 +4494,10 @@ postcss@^8.2.10:
|
|||||||
nanoid "^3.1.23"
|
nanoid "^3.1.23"
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
|
|
||||||
posthog-js@^1.13.12:
|
posthog-js@^1.14.1:
|
||||||
version "1.13.12"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.13.12.tgz#b54efcb92de43724c889048135ccaae3dc4b874c"
|
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.14.1.tgz#68553b9074c686784b994b3f433ad035b241deaa"
|
||||||
integrity sha512-MU1I0zSVhdCcnWI8jAZLtbNJmjfg9AnhUDq5dUzNkb0qPXtNz17BekalnNwDMKs0Zlek3UCOVsIpyc85M+VRNA==
|
integrity sha512-gVFk6fsTxG9T+5oqZghffYovENSrs05v3hQMiRQENtGlsHGpt1fnoQ52En8Vg5brMxqLv1XZO4lMgm12/ubH0Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/types" "^6.11.0"
|
"@sentry/types" "^6.11.0"
|
||||||
fflate "^0.4.1"
|
fflate "^0.4.1"
|
||||||
|
@ -148,6 +148,7 @@ export class AuthenticateController extends BaseController {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
authToken,
|
authToken,
|
||||||
userUuid,
|
userUuid,
|
||||||
|
email,
|
||||||
roomUrl,
|
roomUrl,
|
||||||
mapUrlStart,
|
mapUrlStart,
|
||||||
organizationMemberToken,
|
organizationMemberToken,
|
||||||
|
@ -60,6 +60,7 @@ export class MapController extends BaseController {
|
|||||||
mapUrl,
|
mapUrl,
|
||||||
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY,
|
||||||
roomSlug: "", // Deprecated
|
roomSlug: "", // Deprecated
|
||||||
|
group: null,
|
||||||
tags: [],
|
tags: [],
|
||||||
textures: [],
|
textures: [],
|
||||||
contactPage: undefined,
|
contactPage: undefined,
|
||||||
|
Loading…
Reference in New Issue
Block a user