Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions lang/main-es.json
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@
"participants": "Participantes",
"participant": "Participante",
"upToParticipants": "Hasta {{num}} participantes",
"participantsNotAvailable": "Participantes no disponibles",
"upgrade": "Actualizar",
"upgradeMessage": "Meet no está disponible con tu plan. \nActualiza ahora para empezar a realizar reuniones privadas."
},
Expand Down
1 change: 1 addition & 0 deletions lang/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@
"participants": "Participants",
"participant": "Participant",
"upToParticipants": "Up to {{num}} participants",
"participantsNotAvailable": "Participants not available",
"upgrade": "Upgrade",
"upgradeMessage": "Meet is not available with your plan. \nUpgrade now to start private meetings."
},
Expand Down
17 changes: 15 additions & 2 deletions react/features/base/meet/views/PreMeeting/PreMeetingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ const PreMeetingScreen = ({
const [isNameInputFocused, setIsNameInputFocused] = useState(false);
const [isCreatingMeeting, setIsCreatingMeeting] = useState(false);
const [meetingUsersData, setMeetingUsersData] = useState<MeetingUser[]>([]);
const [isLoadingParticipants, setIsLoadingParticipants] = useState(false);
const [participantsLoadError, setParticipantsLoadError] = useState(false);

const userData = useUserData();
const [openLogin, setOpenLogin] = useState<boolean>(true);

Expand Down Expand Up @@ -246,8 +249,16 @@ const PreMeetingScreen = ({

const getUsersInMeeting = async () => {
if (!isInNewMeeting) {
const meetingUsers = await MeetingService.instance.getCurrentUsersInCall(room);
setMeetingUsersData(meetingUsers);
setIsLoadingParticipants(true);
setParticipantsLoadError(false);
try {
const meetingUsers = await MeetingService.instance.getCurrentUsersInCall(room);
setMeetingUsersData(meetingUsers);
} catch {
setParticipantsLoadError(true);
} finally {
setIsLoadingParticipants(false);
}
}
};

Expand Down Expand Up @@ -355,6 +366,8 @@ const PreMeetingScreen = ({
setUserName={setName}
setIsNameInputFocused={setIsNameInputFocused}
participants={meetingUsersData}
isLoadingParticipants={isLoadingParticipants}
participantsLoadError={participantsLoadError}
joinConference={async () => {
if (createConference) {
setIsCreatingMeeting(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import { Avatar } from "@internxt/ui";
import React from "react";
import { Avatar } from "@internxt/ui";
import { MeetingUser } from "../../../services/types/meeting.types";

const ParticipantsList = ({
participants,
translate,
}: {
interface ParticipantsListProps {
participants: MeetingUser[];
translate: (key: string) => string;
}) => {
}

const ParticipantsList = ({ participants, translate }: ParticipantsListProps) => {
const participantsNumber = participants.length;
return (
<div className="flex flex-col items-center justify-center space-y-5">
<div className="flex flex-col items-center justify-center">
<span className="text-xl font-semibold text-white">{translate("meet.internxtMeet")}</span>

<span className="text-base font-normal text-white/75">
{participantsNumber}{" "}
{participantsNumber === 1
? translate("meet.preMeeting.participant")
: translate("meet.preMeeting.participants")}
</span>
</div>
return (
<div className="flex flex-col items-center justify-center mb-5">
<span className="text-base font-normal text-white/75">
{participantsNumber}{" "}
{participantsNumber === 1
? translate("meet.preMeeting.participant")
: translate("meet.preMeeting.participants")}
</span>
<div className="flex items-center">
<div className="flex -space-x-3">
{participants.map((participant, index) => (
<div key={index} className="relative rounded-full bg-gray-90 dark:bg-gray-1 border border-white/15">
{participants.map((participant) => (
<div
key={participant.userId}
className="relative rounded-full bg-gray-90 dark:bg-gray-1 border border-white/15"
>
<Avatar
fullName={participant.name}
src={participant?.avatar}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,73 @@ import NameInputSection from "./NameInputSection";
import ParticipantsList from "./ParticipantsList";
import VideoPreviewSection from "./VideoPreviewSection";

const Spinner = () => (
<svg
className="animate-spin h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="#636367"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="#636367"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
);

interface ParticipantsStatusProps {
isCreatingConference?: boolean;
isLoadingParticipants?: boolean;
participantsLoadError?: boolean;
participants: MeetingUser[];
maxParticipants: number;
translate: (key: string, options?: Record<string, unknown>) => string;
}

const ParticipantsStatus = ({
isCreatingConference,
isLoadingParticipants,
participantsLoadError,
participants,
maxParticipants,
translate: t,
}: ParticipantsStatusProps) => {
if (isCreatingConference) {
return (
<span className="text-base font-normal text-white/75">
{t("meet.preMeeting.upToParticipants", { num: maxParticipants })}
</span>
);
}

if (isLoadingParticipants) {
return (
<div className="flex h-6 items-center justify-center mb-5">
<Spinner />
</div>
);
}

if (participantsLoadError) {
return (
<span className="text-base font-normal text-white/75 mb-5">
{t("meet.preMeeting.participantsNotAvailable")}
</span>
);
}

return <ParticipantsList participants={participants} translate={t} />;
};

interface PreMeetingModalProps {
/**
* The video track to render as preview
Expand Down Expand Up @@ -50,6 +117,16 @@ interface PreMeetingModalProps {
*/
participants: MeetingUser[];

/**
* Flag to indicate if participants are loading
*/
isLoadingParticipants?: boolean;

/**
* Flag to indicate if there was an error loading participants
*/
participantsLoadError?: boolean;

/**
* Join conference handler
*/
Expand Down Expand Up @@ -88,6 +165,8 @@ const PreMeetingModal = ({
setUserName,
setIsNameInputFocused,
participants,
isLoadingParticipants,
participantsLoadError,
joinConference,
disableJoinButton,
flipX,
Expand Down Expand Up @@ -119,19 +198,17 @@ const PreMeetingModal = ({
/>
<MediaControlsWrapper />
<div className="border border-b border-white/15"/>
{isCreatingConference ? (
<div className="flex flex-col items-center justify-center space-y-5">
<div className="flex flex-col items-center justify-center">
<span className="text-xl font-semibold text-white">{t("meet.internxtMeet")}</span>

<span className="text-base font-normal text-white/75">
{t("meet.preMeeting.upToParticipants", { num })}
</span>
</div>
</div>
) : (
<ParticipantsList participants={participants} translate={t} />
)}
<div className="flex flex-col items-center justify-center">
<span className="text-xl font-semibold text-white">{t("meet.internxtMeet")}</span>
<ParticipantsStatus
isCreatingConference={isCreatingConference}
isLoadingParticipants={isLoadingParticipants}
participantsLoadError={participantsLoadError}
participants={participants}
maxParticipants={num}
translate={t}
/>
</div>
{!!errorMessage && (
<div className="max-w-[264px]">
<ErrorMessage message={errorMessage} />
Expand Down