diff --git a/client/public/img/UserCameraAvatar.png b/client/public/img/UserCameraAvatar.png
new file mode 100644
index 0000000..9a2dabc
Binary files /dev/null and b/client/public/img/UserCameraAvatar.png differ
diff --git a/client/src/components/SessionUsersPanel.tsx b/client/src/components/SessionUsersPanel.tsx
index ec2ec9e..10fa2e4 100644
--- a/client/src/components/SessionUsersPanel.tsx
+++ b/client/src/components/SessionUsersPanel.tsx
@@ -4,6 +4,9 @@ import DraggableContainer from "./DraggableContainer";
import { useWebRTC } from "../hooks/useWebRTC";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
+import type { Session } from "../types/Session";
+import { getGuestId } from "../lib/guestId";
+import { useMe } from "../hooks/useAuth";
const LOCAL_CAMERAS_COUNT = 1;
@@ -11,12 +14,14 @@ interface SessionUsersPanelProps {
roomId: string;
autoJoin?: boolean;
mode?: "full" | "mini";
+ session?: Session;
}
function SessionUsersPanel({
roomId,
autoJoin = false,
mode = "full",
+ session,
}: SessionUsersPanelProps) {
const {
localStream,
@@ -29,6 +34,22 @@ function SessionUsersPanel({
} = useWebRTC(roomId, autoJoin);
const hasLocalStream = localStream !== null;
+ const { data: user } = useMe();
+
+ // Определяем, является ли локальный пользователь организатором сессии
+ const isLocalUserOrganizer = session
+ ? !!(session.userId && user?.id === session.userId) ||
+ !!(session.guestId && getGuestId() === session.guestId)
+ : false;
+
+ // Функция для определения, является ли конкретный участник организатором
+ const isParticipantOrganizer = (participantId: string) => {
+ if (!session) return false;
+ return (
+ (session.userId && participantId === session.userId) ||
+ (session.guestId && participantId === session.guestId)
+ );
+ };
// Логируем изменения hasLocalStream для отладки
useEffect(() => {
@@ -180,8 +201,8 @@ function SessionUsersPanel({
name="Вы"
isMuted={isLocalAudioMuted}
isVideoOff={isLocalVideoMuted}
- isControlDisabled={false}
- isAdmin={true}
+ hasControl={false}
+ isAdmin={isLocalUserOrganizer}
isLocal={true}
mediaStream={localStream}
onMute={toggleAudio}
@@ -214,8 +235,8 @@ function SessionUsersPanel({
isMuted={participant.isMuted || false}
isVideoOff={participant.isVideoOff || false}
isSpeaking={participant.isSpeaking}
- isControlDisabled={true}
- isAdmin={false}
+ hasControl={false}
+ isAdmin={isParticipantOrganizer(participant.id) || undefined}
mediaStream={participant.stream}
hasLocalMediaPermission={hasLocalStream}
onMute={() => console.log(`Mute user ${participant.id}`)}
diff --git a/client/src/components/popups/ParticipantsPopup.tsx b/client/src/components/popups/ParticipantsPopup.tsx
index cc862c7..4297afe 100644
--- a/client/src/components/popups/ParticipantsPopup.tsx
+++ b/client/src/components/popups/ParticipantsPopup.tsx
@@ -1,6 +1,5 @@
import PopupWrapper from "../PopupWrapper";
import ActionsPopover from "../ui/ActionsPopover";
-import MicrophoneFilledIcon from "../icons/MicrophoneFilledIcon";
import VideoOffFilledIcon from "../icons/VideoOffFilledIcon";
import HandRaisedFilledIcon from "../icons/HandRaisedFilledIcon";
import XMarkFilledIcon from "../icons/XMarkFilledIcon";
@@ -160,19 +159,32 @@ function ParticipantItem({
// Логируем каждый рендер
console.log(
- `[ParticipantItem RENDER] ${isLocal ? "Local" : "Remote"} ${
- participant.id.slice(0, 8)
- } - isMuted=${isMuted}, isVideoOff=${isVideoOff}, hasStream=${!!participant.stream}`
+ `[ParticipantItem RENDER] ${
+ isLocal ? "Local" : "Remote"
+ } ${participant.id.slice(
+ 0,
+ 8
+ )} - isMuted=${isMuted}, isVideoOff=${isVideoOff}, hasStream=${!!participant.stream}`
);
// Логируем состояние участника для отладки
useEffect(() => {
console.log(
- `[ParticipantItem] ${isLocal ? "Local" : "Remote"} ${
- participant.id.slice(0, 8)
- } - isMuted: ${isMuted}, isVideoOff: ${isVideoOff}, participant.isMuted: ${participant.isMuted}, participant.isVideoOff: ${participant.isVideoOff}`
+ `[ParticipantItem] ${isLocal ? "Local" : "Remote"} ${participant.id.slice(
+ 0,
+ 8
+ )} - isMuted: ${isMuted}, isVideoOff: ${isVideoOff}, participant.isMuted: ${
+ participant.isMuted
+ }, participant.isVideoOff: ${participant.isVideoOff}`
);
- }, [isMuted, isVideoOff, isLocal, participant.id, participant.isMuted, participant.isVideoOff]);
+ }, [
+ isMuted,
+ isVideoOff,
+ isLocal,
+ participant.id,
+ participant.isMuted,
+ participant.isVideoOff,
+ ]);
// Определяем, является ли этот конкретный участник организатором сессии
const isThisParticipantOrganizer =
@@ -220,7 +232,7 @@ function ParticipantItem({
{name}
- {isMuted && ( -