diff --git a/packages/flat-components/src/components/UsersPanel/index.tsx b/packages/flat-components/src/components/UsersPanel/index.tsx index bee653acb5b..eb862c06746 100644 --- a/packages/flat-components/src/components/UsersPanel/index.tsx +++ b/packages/flat-components/src/components/UsersPanel/index.tsx @@ -9,10 +9,16 @@ import { User } from "../../types/user"; import { IconMic } from "../ClassroomPage/VideoAvatar/IconMic"; import { SVGCamera, SVGCameraMute, SVGMicrophoneMute } from "../FlatIcons"; +export interface UsersPanelRoomInfo { + ownerName?: string; + ownerAvatarURL?: string; +} + export interface UsersPanelProps { ownerUUID: string; userUUID: string; users: User[]; + roomInfo?: UsersPanelRoomInfo; getDeviceState?: (userUUID: string) => { camera: boolean; mic: boolean }; getVolumeLevel?: (userUUID: string) => number; onOffStageAll?: () => void; @@ -26,6 +32,7 @@ export const UsersPanel = /* @__PURE__ */ observer(function Use ownerUUID, userUUID, users, + roomInfo, getDeviceState, getVolumeLevel, onOffStageAll, @@ -37,19 +44,17 @@ export const UsersPanel = /* @__PURE__ */ observer(function Use const t = useTranslate(); const isCreator = ownerUUID === userUUID; - const owner = users.find(user => user.userUUID === ownerUUID); - const students = users.filter(user => user.userUUID !== ownerUUID); return (
- {owner && ( + {roomInfo && ( <> - + {t("teacher")}: - {owner.name} + {roomInfo.ownerName} )} @@ -69,20 +74,19 @@ export const UsersPanel = /* @__PURE__ */ observer(function Use - {t("members")} ({students.length}) + {t("members")} ({users.length}) {t("staging")} {t("whiteboard-access")} {t("camera")} {t("microphone")} - {t("raise-hand")} ( - {students.filter(user => user.isRaiseHand).length}) + {t("raise-hand")} ({users.filter(user => user.isRaiseHand).length}) - {students.map(user => ( + {users.map(user => ( (function Use ))} + {users.length === 0 && ( +
{t("no-students")}
+ )}
); diff --git a/packages/flat-components/src/components/UsersPanel/style.less b/packages/flat-components/src/components/UsersPanel/style.less index 0e3d2ec52bb..02b9eb9f46f 100644 --- a/packages/flat-components/src/components/UsersPanel/style.less +++ b/packages/flat-components/src/components/UsersPanel/style.less @@ -70,6 +70,14 @@ } } +.users-panel-list-empty { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-weaker); +} + .users-panel-list-item { font-size: 0; position: relative; diff --git a/packages/flat-i18n/locales/en.json b/packages/flat-i18n/locales/en.json index be7c6410e68..f3f0c77d2c7 100644 --- a/packages/flat-i18n/locales/en.json +++ b/packages/flat-i18n/locales/en.json @@ -27,6 +27,7 @@ "raised-hand": "(Hand raised)", "has-left": "(Has left)", "offline": "offline", + "no-students": "No students", "say-something": "Say something...", "send": "send", "teacher": "Teacher", diff --git a/packages/flat-i18n/locales/zh-CN.json b/packages/flat-i18n/locales/zh-CN.json index 4d613938d33..58f95f01c24 100644 --- a/packages/flat-i18n/locales/zh-CN.json +++ b/packages/flat-i18n/locales/zh-CN.json @@ -27,6 +27,7 @@ "raised-hand": "(已举手)", "has-left": "(已离开)", "offline": "已离线", + "no-students": "暂无学生", "agree": "通过", "me": "(我)", "cancel-hand-raising": "取消举手", diff --git a/packages/flat-pages/src/components/UsersButton.tsx b/packages/flat-pages/src/components/UsersButton.tsx index 405fe2b436a..c69f7f71897 100644 --- a/packages/flat-pages/src/components/UsersButton.tsx +++ b/packages/flat-pages/src/components/UsersButton.tsx @@ -16,16 +16,11 @@ export const UsersButton = observer(function UsersButton({ cla const t = useTranslate(); const [open, setOpen] = useState(false); + // not including teacher const users = useComputed(() => { - const { creator, speakingJoiners, handRaisingJoiners, otherJoiners, offlineJoiners } = + const { speakingJoiners, handRaisingJoiners, otherJoiners, offlineJoiners } = classroom.users; - return [ - ...speakingJoiners, - ...handRaisingJoiners, - ...(creator ? [creator] : []), - ...offlineJoiners, - ...otherJoiners, - ]; + return [...speakingJoiners, ...handRaisingJoiners, ...offlineJoiners, ...otherJoiners]; }).get(); const getDeviceState = useCallback( @@ -107,6 +102,7 @@ export const UsersButton = observer(function UsersButton({ cla getDeviceState={getDeviceState} getVolumeLevel={getVolumeLevel} ownerUUID={classroom.ownerUUID} + roomInfo={classroom.roomInfo} userUUID={classroom.userUUID} users={users} onDeviceState={classroom.updateDeviceState} diff --git a/packages/flat-stores/src/room-store.ts b/packages/flat-stores/src/room-store.ts index aad3ce5fea9..4dc19545a26 100644 --- a/packages/flat-stores/src/room-store.ts +++ b/packages/flat-stores/src/room-store.ts @@ -21,6 +21,7 @@ import { recordInfo, RoomStatus, RoomType, + usersInfo, } from "@netless/flat-server-api"; import { globalStore } from "./global-store"; import { preferencesStore } from "./preferences-store"; @@ -132,10 +133,16 @@ export class RoomStore { public async syncOrdinaryRoomInfo(roomUUID: string): Promise { const { roomInfo, ...restInfo } = await ordinaryRoomInfo(roomUUID); + // always include owner avatar url in full room info + const { [roomInfo.ownerUUID]: owner } = await usersInfo({ + roomUUID, + usersUUID: [roomInfo.ownerUUID], + }); this.updateRoom(roomUUID, roomInfo.ownerUUID, { ...restInfo, ...roomInfo, roomUUID, + ownerAvatarURL: owner.avatarURL, }); }