Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@internxt/css-config": "^1.1.0",
"@internxt/eslint-config-internxt": "^2.0.1",
"@internxt/lib": "^1.4.1",
"@internxt/sdk": "1.16.3",
"@internxt/sdk": "1.17.0",
"@internxt/ui": "0.1.15",
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/0.18.5/jitsi-excalidraw-v0.18.5.tgz",
"@jitsi/js-utils": "2.6.7",
Expand Down Expand Up @@ -85,7 +85,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-meet": "https://github.com/internxt/lib-meet/releases/download/v.1.0.0/lib-meet-1.0.0.tgz",
"lib-meet": "https://github.com/internxt/lib-meet/releases/download/v.1.0.1/lib-meet-1.0.1.tgz",
"lodash-es": "4.18.1",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
Expand Down
6 changes: 4 additions & 2 deletions react/features/base/connection/actions.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,17 @@ export function _connectInternal({
let userUUID: string | undefined;

if (isAnonymous) {
userUUID = SessionStorageManager.instance.getOrCreateAnonymousUUID();
userUUID = SessionStorageManager.instance.getOrCreateUserID();
}
const { token: jwt, appId } = await MeetingService.instance.joinCall(room, {
const { token: jwt, appId, userId } = await MeetingService.instance.joinCall(room, {
name: displayName ?? name ?? "",
lastname: lastname ?? "",
anonymous: !!isAnonymous,
anonymousId: userUUID,
});

SessionStorageManager.instance.setUserID(userId);

const newOptions = get8x8Options(options, appId, room);

const connection = new JitsiMeetJS.JitsiConnection(appId, jwt, newOptions);
Expand Down
8 changes: 3 additions & 5 deletions react/features/base/connection/actions.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ import { SessionStorageManager } from '../meet/SessionStorageManager';
* @returns {Promise<void>}
*/
export async function leaveCallWithUserIdentification(roomId: string): Promise<void> {
const user = LocalStorageManager.instance.getUser();
let payload = undefined;
if (!user){
payload = { userId: SessionStorageManager.instance.getAnonymousUUID() || '' };
const userId = SessionStorageManager.instance.getUserID();
if (userId) {
return await MeetingService.instance.leaveCall(roomId, { userId });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this causes an error, does the web crash?

Copy link
Copy Markdown
Author

@TamaraFinogina TamaraFinogina May 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but the server gets to do checks and log errors. If the user reloads before joining the call, leaveCall is dispatched, but it has no user ID, so technically no need for the call

}
return await MeetingService.instance.leaveCall(roomId, payload);
}

export * from "./actions.any";
Expand Down
10 changes: 5 additions & 5 deletions react/features/base/meet/SessionStorageManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,31 @@ describe("SessionStorageManager tests", () => {
});

it("returns null when no anonymous UUID is stored", () => {
expect(SessionStorageManager.instance.getAnonymousUUID()).toBeNull();
expect(SessionStorageManager.instance.getUserID()).toBeNull();
});

it("returns the stored anonymous UUID when one exists", () => {
sessionStorage.setItem(ANON_UUID_KEY, "existing-uuid");
expect(SessionStorageManager.instance.getAnonymousUUID()).toBe("existing-uuid");
expect(SessionStorageManager.instance.getUserID()).toBe("existing-uuid");
});

it("generates and stores a UUID when none exists", () => {
const result = SessionStorageManager.instance.getOrCreateAnonymousUUID();
const result = SessionStorageManager.instance.getOrCreateUserID();
expect(result).toBe(MOCK_UUID);
expect(sessionStorage.getItem(ANON_UUID_KEY)).toBe(MOCK_UUID);
});

it("returns existing UUID without generating a new one", async () => {
sessionStorage.setItem(ANON_UUID_KEY, "pre-existing-uuid");

const result = SessionStorageManager.instance.getOrCreateAnonymousUUID();
const result = SessionStorageManager.instance.getOrCreateUserID();

expect(result).toBe("pre-existing-uuid");
expect(v4).not.toHaveBeenCalled();
});

it("does not bleed into localStorage", () => {
SessionStorageManager.instance.getOrCreateAnonymousUUID();
SessionStorageManager.instance.getOrCreateUserID();
expect(localStorage.getItem(ANON_UUID_KEY)).toBeNull();
});

Expand Down
15 changes: 10 additions & 5 deletions react/features/base/meet/SessionStorageManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { v4 } from "uuid";

export const ANON_UUID_KEY = "xAnonymousUserUUID";
export const ANON_UUID_KEY = "xMeetUserUUID";

export class SessionStorageManager {
private static _instance: SessionStorageManager;
Expand All @@ -14,20 +14,25 @@ export class SessionStorageManager {
return SessionStorageManager._instance;
}

public getOrCreateAnonymousUUID(): string {
let uuid = this.getAnonymousUUID();
public getOrCreateUserID(): string {
let uuid = this.getUserID();
if (!uuid) {
uuid = v4();
sessionStorage.setItem(ANON_UUID_KEY, uuid);
this.setUserID(uuid);
}

return uuid;
}

public getAnonymousUUID(): string | null {
public getUserID(): string | null {
return sessionStorage.getItem(ANON_UUID_KEY);
}

public setUserID(userId: string): void {
sessionStorage.setItem(ANON_UUID_KEY, userId);
}


}

export default SessionStorageManager.instance;
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ describe("MeetingService", () => {
describe("leaveCall", () => {
it("When leaving a call with valid ID, then the operation completes successfully", async () => {
const mockCallId = "call-123";
const mockPayload: LeaveCallPayload = { userId: "anon-uuid-789" };
const mockLeaveCallResponse = { success: true };

const mockMeetClient = {
Expand All @@ -193,14 +194,14 @@ describe("MeetingService", () => {

mockedGetMeet.mockReturnValue(mockMeetClient);

const result = await MeetingService.instance.leaveCall(mockCallId);
const result = await MeetingService.instance.leaveCall(mockCallId, mockPayload);

expect(mockedGetMeet).toHaveBeenCalledTimes(1);
expect(mockedGetMeet).toHaveBeenCalledWith();
expect(mockMeetClient.leaveCall).toHaveBeenCalledTimes(1);
expect(mockMeetClient.leaveCall).toHaveBeenCalledWith(mockCallId, undefined);
expect(mockMeetClient.leaveCall).toHaveBeenCalledWith(mockCallId, mockPayload);
expect(mockMeetClient.leaveCall.mock.calls[0][0]).toBe(mockCallId);
expect(mockMeetClient.leaveCall.mock.calls[0][1]).toBeUndefined();
expect(mockMeetClient.leaveCall.mock.calls[0][1]).toEqual(mockPayload);
expect(result).toEqual(mockLeaveCallResponse);
});

Expand All @@ -225,6 +226,7 @@ describe("MeetingService", () => {

it("When leaving a call fails, then an error is thrown", async () => {
const mockCallId = "call-123";
const mockPayload: LeaveCallPayload = { userId: "anon-uuid-789" };
const mockError = new Error("Failed to leave call");

const mockMeetClient = {
Expand All @@ -233,11 +235,11 @@ describe("MeetingService", () => {

mockedGetMeet.mockReturnValue(mockMeetClient);

await expect(MeetingService.instance.leaveCall(mockCallId)).rejects.toThrow(mockError);
await expect(MeetingService.instance.leaveCall(mockCallId, mockPayload)).rejects.toThrow(mockError);
expect(mockedGetMeet).toHaveBeenCalledTimes(1);
expect(mockedGetMeet).toHaveBeenCalledWith();
expect(mockMeetClient.leaveCall).toHaveBeenCalledTimes(1);
expect(mockMeetClient.leaveCall).toHaveBeenCalledWith(mockCallId, undefined);
expect(mockMeetClient.leaveCall).toHaveBeenCalledWith(mockCallId, mockPayload);
expect(mockMeetClient.leaveCall.mock.calls[0][0]).toBe(mockCallId);
});
});
Expand Down
2 changes: 1 addition & 1 deletion react/features/base/meet/services/meeting.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class MeetingService {
return await meetClient.joinCall(callId, payload);
};

public leaveCall = async (callId: string, payload?: LeaveCallPayload): Promise<void> => {
public leaveCall = async (callId: string, payload: LeaveCallPayload): Promise<void> => {
const meetClient = SdkManager.instance.getMeet();
return await meetClient.leaveCall(callId, payload);
};
Expand Down
14 changes: 7 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2655,10 +2655,10 @@
dependencies:
uuid "^11.1.0"

"@internxt/sdk@1.16.3":
version "1.16.3"
resolved "https://registry.yarnpkg.com/@internxt/sdk/-/sdk-1.16.3.tgz#b9e5fdd98352704fd78067a22da1762951deaec4"
integrity sha512-GmX9eYBOBB09wr5e9yW3gUIR3Pn2AgZBXzZd1HvzwS96AonclcEWY1/+uoZ9qLO4SdvYquiOjXfLYNJGg99ugQ==
"@internxt/sdk@1.17.0":
version "1.17.0"
resolved "https://registry.yarnpkg.com/@internxt/sdk/-/sdk-1.17.0.tgz#db04e6e9823c9932a3a24ba8fba9d38c95562441"
integrity sha512-05fVGaPJM1u5EUJHeIlta8iTQxDLkWtGoiQpwbRyk16cis5Njabq3YTDB7qA0+YNAOJsP9BaO3MAi3dx06EDyg==
dependencies:
axios "^1.16.0"

Expand Down Expand Up @@ -12484,9 +12484,9 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"

"lib-meet@https://github.com/internxt/lib-meet/releases/download/v.1.0.0/lib-meet-1.0.0.tgz":
version "1.0.0"
resolved "https://github.com/internxt/lib-meet/releases/download/v.1.0.0/lib-meet-1.0.0.tgz#c93f97512cc5e3dcf19af4b8c7b3f815869e82dd"
"lib-meet@https://github.com/internxt/lib-meet/releases/download/v.1.0.1/lib-meet-1.0.1.tgz":
version "1.0.1"
resolved "https://github.com/internxt/lib-meet/releases/download/v.1.0.1/lib-meet-1.0.1.tgz#d87723d2cf831b359719d30c9f0f05b769074f75"
dependencies:
"@hexagon/base64" "^2.0.4"
"@jitsi/js-utils" "^2.6.7"
Expand Down
Loading