);
- return ReactDOM.createPortal(modalContent, bodyElement);
+ return createPortal(modalContent, bodyElement);
};
export default PermissionModal;
diff --git a/react/features/base/meet/services/__tests__/meeting.service.test.ts b/react/features/base/meet/services/__tests__/meeting.service.test.ts
index 20c5798f3d91..a6ed1facfb02 100644
--- a/react/features/base/meet/services/__tests__/meeting.service.test.ts
+++ b/react/features/base/meet/services/__tests__/meeting.service.test.ts
@@ -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 = {
@@ -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);
});
@@ -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 = {
@@ -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);
});
});
diff --git a/react/features/base/meet/services/meeting.service.ts b/react/features/base/meet/services/meeting.service.ts
index 4e643b3e0f74..bac11b1225fc 100644
--- a/react/features/base/meet/services/meeting.service.ts
+++ b/react/features/base/meet/services/meeting.service.ts
@@ -34,7 +34,7 @@ class MeetingService {
return await meetClient.joinCall(callId, payload);
};
- public leaveCall = async (callId: string, payload?: LeaveCallPayload): Promise => {
+ public leaveCall = async (callId: string, payload: LeaveCallPayload): Promise => {
const meetClient = SdkManager.instance.getMeet();
return await meetClient.leaveCall(callId, payload);
};
diff --git a/react/features/base/meet/views/Conference/components/Header.tsx b/react/features/base/meet/views/Conference/components/Header.tsx
index c8cad049a39e..c4e348851cf8 100644
--- a/react/features/base/meet/views/Conference/components/Header.tsx
+++ b/react/features/base/meet/views/Conference/components/Header.tsx
@@ -1,5 +1,5 @@
import { Header as IntxHeader } from "@internxt/ui";
-import { SquaresFour, UserFocus } from "@phosphor-icons/react";
+import { SquaresFourIcon, UserFocusIcon } from "@phosphor-icons/react";
import React from "react";
import ConferenceTimer from "./ConferenceTimer";
@@ -47,10 +47,10 @@ const RightContent = React.memo(({ mode, translate, onSetModeClicked }: RightCon
className="flex flex-row justify-center items-center space-x-2 p-[10px] bg-black/50 border border-white/10 rounded-2xl"
>
{mode === "gallery" ? <>
- {translate("meet.meeting.button.gallery")}
+ {translate("meet.meeting.button.gallery")}
>
: <>
- {translate("meet.meeting.button.speaker")}
+ {translate("meet.meeting.button.speaker")}
>}
);
diff --git a/react/features/base/meet/views/Conference/components/InviteUserModal.tsx b/react/features/base/meet/views/Conference/components/InviteUserModal.tsx
index b7cbe4c92371..d0bfdf916c8d 100644
--- a/react/features/base/meet/views/Conference/components/InviteUserModal.tsx
+++ b/react/features/base/meet/views/Conference/components/InviteUserModal.tsx
@@ -1,5 +1,5 @@
import { Button, TransparentModal } from "@internxt/ui";
-import { Check, Link, X } from "@phosphor-icons/react";
+import { CheckIcon, LinkIcon, XIcon } from "@phosphor-icons/react";
import React, { useState } from "react";
import { getDecodedURI } from "../../../../util/uri";
import { MAX_SIZE_PARTICIPANTS } from "../../../constants";
@@ -37,7 +37,7 @@ const InviteUserModal = ({ isOpen, onClose, translate, participantsCount, invite
className="absolute right-5 top-4 hover:bg-gray-700 rounded-lg transition-colors text-gray-400 hover:text-white"
aria-label="Close dialog"
>
-
+
{translate("meet.invite.invitePeople")}
@@ -54,7 +54,7 @@ const InviteUserModal = ({ isOpen, onClose, translate, participantsCount, invite
-
+
{copied ? (
-
+
{translate("meet.invite.copied")}
) : (
diff --git a/react/features/base/meet/views/Conference/components/LeaveWithMessageDialog.tsx b/react/features/base/meet/views/Conference/components/LeaveWithMessageDialog.tsx
new file mode 100644
index 000000000000..6d03f47a8d78
--- /dev/null
+++ b/react/features/base/meet/views/Conference/components/LeaveWithMessageDialog.tsx
@@ -0,0 +1,71 @@
+import React, { useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import { makeStyles } from 'tss-react/mui';
+
+import Dialog from '../../../../ui/components/web/Dialog';
+
+const useStyles = makeStyles()(theme => {
+ return {
+ dialog: {
+ marginBottom: theme.spacing(1)
+ },
+
+ title: {
+ fontSize: '1.25rem',
+ fontWeight: 'bold',
+ textAlign: 'left'
+ },
+
+ text: {
+ fontSize: '1.25rem'
+ }
+ };
+});
+
+/**
+ * The type of the React {@code Component} props of {@link LeaveReasonDialog}.
+ */
+interface IProps {
+
+ /**
+ * Callback invoked when {@code LeaveReasonDialog} is unmounted.
+ */
+ onClose: () => void;
+
+ /**
+ * The title to display in the dialog.
+ */
+ title?: string;
+
+ message?: string;
+}
+
+/**
+ * A React {@code Component} for displaying a dialog with a reason that ended the conference.
+ *
+ * @param {IProps} props - Component's props.
+ * @returns {JSX}
+ */
+const LeaveWithMessageDialog = ({ onClose, title, message }: IProps) => {
+ const { classes } = useStyles();
+ const { t } = useTranslation();
+
+ useEffect(() => () => {
+ onClose?.();
+ }, []);
+
+ return (
+
+ );
+};
+
+export default LeaveWithMessageDialog;
\ No newline at end of file
diff --git a/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx b/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx
index 65595453d6f3..0e2db7858722 100644
--- a/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx
+++ b/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx
@@ -1,4 +1,4 @@
-import { CaretDown, CaretUp, CheckCircle, MonitorArrowUp } from "@phosphor-icons/react";
+import { CaretDownIcon, CaretUpIcon, CheckCircleIcon, MonitorArrowUpIcon } from "@phosphor-icons/react";
import React, { useRef, useState } from "react";
import { WithTranslation } from "react-i18next";
import { connect, useSelector } from "react-redux";
@@ -93,9 +93,9 @@ const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProp
{isLocalSharing ? (
-
+
) : (
-
+
)}
{isLocalSharing
@@ -139,7 +139,7 @@ const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProp
: "opacity-30 cursor-not-allowed"
}`}
>
-
+
)}
@@ -171,7 +171,7 @@ const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProp
: "opacity-30 cursor-not-allowed"
}`}
>
-
+
)}
diff --git a/react/features/base/meet/views/Home/components/auth/PasswordInput.tsx b/react/features/base/meet/views/Home/components/auth/PasswordInput.tsx
index da4e6950a5fb..2f97fcc638e6 100644
--- a/react/features/base/meet/views/Home/components/auth/PasswordInput.tsx
+++ b/react/features/base/meet/views/Home/components/auth/PasswordInput.tsx
@@ -1,4 +1,4 @@
-import { Eye, EyeSlash } from "@phosphor-icons/react";
+import { EyeIcon, EyeSlashIcon } from "@phosphor-icons/react";
import React, { useState } from "react";
import { FieldError, Path, UseFormRegister, ValidationRule } from "react-hook-form";
import { IFormValues } from "../../types";
@@ -85,7 +85,7 @@ const PasswordInput = ({
tabIndex={0}
className="absolute right-4 top-1/2 flex -translate-y-1/2 cursor-pointer items-center justify-center text-gray-100"
>
- {showPassword ?
:
}
+ {showPassword ?
:
}
{error &&
{error.message}
}
diff --git a/react/features/base/meet/views/Home/containers/AuthModal.tsx b/react/features/base/meet/views/Home/containers/AuthModal.tsx
index 43bc6d59eebe..09d29734ced7 100644
--- a/react/features/base/meet/views/Home/containers/AuthModal.tsx
+++ b/react/features/base/meet/views/Home/containers/AuthModal.tsx
@@ -1,5 +1,5 @@
import { Modal } from "@internxt/ui";
-import { X } from "@phosphor-icons/react";
+import { XIcon } from "@phosphor-icons/react";
import React, { useEffect, useState } from "react";
import { LoginCredentials } from "../../../services/types/command.types";
import { WebAuthButton } from "../components/auth/WebAuthButton";
@@ -103,7 +103,7 @@ const ModalHeader: React.FC<{
{isLoginView ? translate("meet.auth.modal.title") : translate("meet.auth.modal.signup.createAccountTitle")}
);
diff --git a/react/features/base/meet/views/Home/containers/ScheduleModal.tsx b/react/features/base/meet/views/Home/containers/ScheduleModal.tsx
index efeefc43af4c..96430b99a122 100644
--- a/react/features/base/meet/views/Home/containers/ScheduleModal.tsx
+++ b/react/features/base/meet/views/Home/containers/ScheduleModal.tsx
@@ -1,5 +1,5 @@
import { Button, Input, Modal } from "@internxt/ui";
-import { Copy, X } from "@phosphor-icons/react";
+import { CopyIcon, XIcon } from "@phosphor-icons/react";
import React, { useState } from "react";
interface ScheduleMeetingModalProps {
@@ -32,7 +32,7 @@ const ScheduleMeetingModal: React.FC
= ({
return (
{translate("meet.modals.schedule.title")}
@@ -57,7 +57,7 @@ const ScheduleMeetingModal: React.FC
= ({
onClick={handleCopy}
className="absolute right-1.5 top-1 h-8 w-8 rounded-full items-center justify-center flex hover:bg-[#0066FF1A] active:bg-[#0066FF40] transition-colors duration-200"
>
-
+
{copied && (
diff --git a/react/features/base/meet/views/PreMeeting/PreMeetingScreen.tsx b/react/features/base/meet/views/PreMeeting/PreMeetingScreen.tsx
index 57647dc1f66b..804883a7466a 100644
--- a/react/features/base/meet/views/PreMeeting/PreMeetingScreen.tsx
+++ b/react/features/base/meet/views/PreMeeting/PreMeetingScreen.tsx
@@ -271,9 +271,10 @@ const PreMeetingScreen = ({
getUsersInMeeting();
}
- if (userData?.name) {
+ const name = storageManager.getDisplayName() || userData?.name;
+ if (name) {
dispatchUpdateSettings({
- displayName: userData.name,
+ displayName: name,
});
}
}, []);
@@ -297,28 +298,12 @@ const PreMeetingScreen = ({
}
};
- const updateNameInStorage = (name: string) => {
- try {
- const user = storageManager.getUser();
-
- if (user) {
- const updatedUser = {
- ...user,
- name: name,
- };
-
- storageManager.setUser(updatedUser);
- }
- } catch (error) {
- console.error("Error updating user name in localStorage:", error);
- }
- };
const setName = (displayName: string) => {
dispatchUpdateSettings({
displayName,
});
- updateNameInStorage(displayName);
+ storageManager.setDisplayName(displayName);
};
const onLogout = () => {
@@ -389,7 +374,7 @@ const PreMeetingScreen = ({
disableJoinButton={disableJoinButton || isCreatingMeeting}
flipX={flipX}
isCreatingConference={!!createConference}
- errorMessage={errorMessage}
+ errorMessage={t(errorMessage)}
/>
{triggerText}
-
- {item.value === selectedDeviceId && }
+ {item.value === selectedDeviceId && }
{item.label}
diff --git a/react/features/base/meet/views/Settings/SettingsDialog.tsx b/react/features/base/meet/views/Settings/SettingsDialog.tsx
index a3e22b4605c3..f26b116322cc 100644
--- a/react/features/base/meet/views/Settings/SettingsDialog.tsx
+++ b/react/features/base/meet/views/Settings/SettingsDialog.tsx
@@ -1,4 +1,4 @@
-import { Icon, X } from "@phosphor-icons/react";
+import { Icon, XIcon } from "@phosphor-icons/react";
import React, { ComponentType, useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -177,7 +177,7 @@ const SettingsDialog: React.FC = ({
className="absolute right-5 top-4 hover:bg-gray-700 rounded-lg transition-colors text-gray-400 hover:text-white"
aria-label="Close dialog"
>
-
+
{/* Tab content */}
diff --git a/react/features/base/meet/views/Settings/SettingsDialogWrapper.tsx b/react/features/base/meet/views/Settings/SettingsDialogWrapper.tsx
index ee09c7e5eac6..0021cb18be25 100644
--- a/react/features/base/meet/views/Settings/SettingsDialogWrapper.tsx
+++ b/react/features/base/meet/views/Settings/SettingsDialogWrapper.tsx
@@ -1,4 +1,4 @@
-import { ArrowSquareOut } from "@phosphor-icons/react";
+import { ArrowSquareOutIcon } from "@phosphor-icons/react";
import React, { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -38,7 +38,7 @@ const SettingsDialogWrapper: React.FC = ({ generalTabs, defaultTab, disp
id: "manage-account",
label: t("settings.account.manage"),
onClick: () => window.open(EXTERNAL_ACCOUNT_URL, "_blank", "noopener,noreferrer"),
- Icon: ArrowSquareOut,
+ Icon: ArrowSquareOutIcon,
},
];
diff --git a/react/features/conference/actions.web.ts b/react/features/conference/actions.web.ts
index 7697f665ac65..ab79ebfb22c6 100644
--- a/react/features/conference/actions.web.ts
+++ b/react/features/conference/actions.web.ts
@@ -5,7 +5,7 @@ import { getJitsiMeetGlobalNSConnectionTimes } from '../base/util/helpers';
import { getBackendSafeRoomName } from '../base/util/uri';
import { DISMISS_CALENDAR_NOTIFICATION } from './actionTypes';
-import LeaveReasonDialog from './components/web/LeaveReasonDialog.web';
+import LeaveWithMessageDialog from '../base/meet/views/Conference/components/LeaveWithMessageDialog';
import logger from './logger';
/**
@@ -15,11 +15,12 @@ import logger from './logger';
*
* @returns {Promise} Resolved when the dialog is closed.
*/
-export function openLeaveReasonDialog(title?: string) {
+export function openLeaveReasonDialog(title?: string, message?: string) {
return (dispatch: IStore['dispatch']): Promise => new Promise(resolve => {
- dispatch(openDialog('LeaveReasonDialog', LeaveReasonDialog, {
+ dispatch(openDialog('LeaveWithMessageDialog', LeaveWithMessageDialog, {
onClose: resolve,
- title
+ title,
+ message
}));
});
}
diff --git a/react/features/conference/middleware.web.ts b/react/features/conference/middleware.web.ts
index abfe1f15787a..44db75122dfc 100644
--- a/react/features/conference/middleware.web.ts
+++ b/react/features/conference/middleware.web.ts
@@ -2,7 +2,6 @@ import i18next from 'i18next';
import { ENDPOINT_MESSAGE_RECEIVED, KICKED_OUT } from '../base/conference/actionTypes';
import { hangup } from '../base/connection/actions.web';
-import { getParticipantDisplayName } from '../base/participants/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { openAllowToggleCameraDialog, setCameraFacingMode } from '../base/tracks/actions.web';
import { CAMERA_FACING_MODE_MESSAGE } from '../base/tracks/constants';
@@ -25,24 +24,20 @@ MiddlewareRegistry.register(store => next => action => {
case KICKED_OUT: {
const { dispatch, getState } = store;
- const { participant } = action;
const { room } = getState()["features/base/conference"];
// we need to first finish dispatching or the notification can be cleared out
const result = next(action);
- const participantDisplayName
- = getParticipantDisplayName(store.getState, participant.getId());
- const roomId = room ?? "";
+ const roomId = room ?? "";
- dispatch(
+ dispatch(
hangup(
true,
roomId,
- participantDisplayName
- ? i18next.t("dialog.kickTitle", { participantDisplayName })
- : i18next.t("dialog.kickSystemTitle"),
- true
+ i18next.t("dialog.kickDuplicateTitle"),
+ true,
+ i18next.t("dialog.kickDuplicateMessage"),
)
);
diff --git a/react/features/settings/components/web/audio/AudioSettingsContent.tsx b/react/features/settings/components/web/audio/AudioSettingsContent.tsx
index 1f650a386586..229d621551b3 100644
--- a/react/features/settings/components/web/audio/AudioSettingsContent.tsx
+++ b/react/features/settings/components/web/audio/AudioSettingsContent.tsx
@@ -16,7 +16,7 @@ import { isNoiseSuppressionEnabled } from "../../../../noise-suppression/functio
import { isPrejoinPageVisible } from "../../../../prejoin/functions";
import { createLocalAudioTracks } from "../../../functions.web";
-import { Microphone, SpeakerSimpleHigh } from "@phosphor-icons/react";
+import { MicrophoneIcon, SpeakerSimpleHighIcon } from "@phosphor-icons/react";
import MicrophoneEntry from "./MicrophoneEntry";
import SpeakerEntry from "./SpeakerEntry";
@@ -305,7 +305,7 @@ const AudioSettingsContent = ({
}
+ icon={() => }
id={speakerHeaderId}
text={t("settings.speakers")}
/>
@@ -321,7 +321,7 @@ const AudioSettingsContent = ({
}
+ icon={() => }
id={microphoneHeaderId}
text={t("settings.microphones")}
/>
diff --git a/react/features/settings/components/web/video/VideoSettingsContent.tsx b/react/features/settings/components/web/video/VideoSettingsContent.tsx
index 133610f637fa..1ddbf7345001 100644
--- a/react/features/settings/components/web/video/VideoSettingsContent.tsx
+++ b/react/features/settings/components/web/video/VideoSettingsContent.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { makeStyles } from "tss-react/mui";
-import { VideoCamera } from "@phosphor-icons/react";
+import { VideoCameraIcon } from "@phosphor-icons/react";
import { IReduxState, IStore } from "../../../../app/types";
import { IconImage } from "../../../../base/icons/svg";
import { Video } from "../../../../base/media/components/index.web";
@@ -362,7 +362,7 @@ const VideoSettingsContent = ({
{selectedTrack && _renderPreviewEntry(selectedTrack)}
}
+ icon={() => }
text={t("meet.settings.video.videoInput")}
accessibilityLabel={t("meet.settings.video.videoInput")}
/>
diff --git a/static/offline.html b/static/offline.html
index 293949eb85ce..76f4397df10e 100644
--- a/static/offline.html
+++ b/static/offline.html
@@ -8,7 +8,7 @@
-
+