diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.tsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.tsx
index a72f4f4fc8..91b8f3a2c0 100644
--- a/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.tsx
@@ -9,24 +9,30 @@ import {
selectIsPeerAudioEnabled,
selectLocalPeerID,
selectPeerCount,
- selectPeerMetadata,
selectPermissions,
- useHMSActions,
useHMSStore,
} from '@100mslive/react-sdk';
-import { ChangeRoleIcon, HandIcon, MicOffIcon, PeopleIcon, SearchIcon, VerticalMenuIcon } from '@100mslive/react-icons';
+import {
+ AddIcon,
+ ChangeRoleIcon,
+ CrossIcon,
+ HandIcon,
+ MicOffIcon,
+ PeopleIcon,
+ SearchIcon,
+ VerticalMenuIcon,
+} from '@100mslive/react-icons';
import { Accordion, Box, config as cssConfig, Dropdown, Flex, Input, Text, textEllipsis } from '../../..';
+import { IconButton as BaseIconButton } from '../../../IconButton';
// @ts-ignore: No implicit Any
import IconButton from '../../IconButton';
import { ConnectionIndicator } from '../Connection/ConnectionIndicator';
import { RemoveParticipant } from '../RemoveParticipant';
import { RoleAccordion } from './RoleAccordion';
-import {
- ConferencingScreenElements,
- useRoomLayoutConferencingScreen,
-} from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
+import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
// @ts-ignore: No implicit Any
import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
+import { usePeerOnStageActions } from '../hooks/usePeerOnStageActions';
import { useParticipants } from '../../common/hooks';
// @ts-ignore: No implicit Any
import { getFormattedCount } from '../../common/utils';
@@ -146,10 +152,12 @@ export const ParticipantCount = () => {
export const Participant = ({
peer,
isConnected,
+ isHandRaisedAccordion,
style,
}: {
peer: HMSPeer;
isConnected: boolean;
+ isHandRaisedAccordion?: boolean;
style: React.CSSProperties;
}) => {
const localPeerId = useHMSStore(selectLocalPeerID);
@@ -175,7 +183,12 @@ export const Participant = ({
{peer.name} {localPeerId === peer.id ? '(You)' : ''}
{isConnected && peer.roleName ? (
-
+
) : null}
);
@@ -247,7 +260,17 @@ const VirtualizedParticipants = ({
* shows settings to change for a participant like changing their role
*/
const ParticipantActions = React.memo(
- ({ peerId, role, isLocal }: { peerId: string; role: string; isLocal: boolean }) => {
+ ({
+ peerId,
+ role,
+ isLocal,
+ isHandRaisedAccordion,
+ }: {
+ peerId: string;
+ role: string;
+ isLocal: boolean;
+ isHandRaisedAccordion?: boolean;
+ }) => {
const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
const canRemoveOthers = useHMSStore(selectPermissions)?.removeOthers;
@@ -264,72 +287,73 @@ const ParticipantActions = React.memo(
gap: '$8',
}}
>
-
- {isHandRaised && (
-
-
-
- )}
- {isAudioMuted ? (
-
-
-
- ) : null}
+ {isHandRaisedAccordion ? (
+
+ ) : (
+ <>
+
+ {isHandRaised && (
+
+
+
+ )}
+ {isAudioMuted ? (
+
+
+
+ ) : null}
- {shouldShowMoreActions && !isLocal ? (
-
- ) : null}
+ {shouldShowMoreActions && !isLocal ? : null}
+ >
+ )}
);
},
);
-const ParticipantMoreActions = ({
- peerId,
- role,
- elements,
- canChangeRole,
-}: {
- peerId: string;
- role: string;
- canChangeRole: boolean;
- elements: ConferencingScreenElements;
-}) => {
- const hmsActions = useHMSActions();
+const HandRaisedAccordionParticipantActions = ({ peerId, role }: { peerId: string; role: string }) => {
+ const { handleStageAction, lowerPeerHand, shouldShowStageRoleChange, isInStage } = usePeerOnStageActions({
+ peerId,
+ role,
+ });
+ return (
+ <>
+ lowerPeerHand()}
+ >
+
+
+ {shouldShowStageRoleChange && !isInStage && (
+ handleStageAction()}
+ >
+
+
+ )}
+ >
+ );
+};
+
+const ParticipantMoreActions = ({ peerId, role }: { peerId: string; role: string }) => {
const {
+ open,
+ setOpen,
bring_to_stage_label,
remove_from_stage_label,
- on_stage_role,
- off_stage_roles = [],
- skip_preview_for_role_change = false,
- } = elements.on_stage_exp || {};
- const isInStage = role === on_stage_role;
- const shouldShowStageRoleChange =
- canChangeRole &&
- ((isInStage && remove_from_stage_label) || (off_stage_roles?.includes(role) && bring_to_stage_label));
- const prevRole = useHMSStore(selectPeerMetadata(peerId))?.prevRole;
- const [open, setOpen] = useState(false);
-
- const handleStageAction = async () => {
- if (isInStage) {
- prevRole && hmsActions.changeRoleOfPeer(peerId, prevRole, true);
- } else if (on_stage_role) {
- await hmsActions.changeRoleOfPeer(peerId, on_stage_role, skip_preview_for_role_change);
- if (skip_preview_for_role_change) {
- await hmsActions.lowerRemotePeerHand(peerId);
- }
- }
- setOpen(false);
- };
-
+ handleStageAction,
+ isInStage,
+ shouldShowStageRoleChange,
+ } = usePeerOnStageActions({ peerId, role });
return (
setOpen(value)} modal={false}>
@@ -63,6 +68,9 @@ export const RoleAccordion = ({
peersInAccordion = peersInAccordion.filter(peer => peer.name.toLowerCase().includes(filter.search || ''));
}
}
+ const { bringAllToStage, bring_to_stage_label, canBringToStage, lowerAllHands } = useGroupOnStageActions({
+ peers: peersInAccordion,
+ });
useEffect(() => {
if (!isOffStageRole || !isLargeRoom) {
@@ -113,7 +121,7 @@ export const RoleAccordion = ({
) : null}
+ {isHandRaisedAccordion && (
+ <>
+
+
+
+ {canBringToStage && }
+
+ >
+ )}
);
diff --git a/packages/roomkit-react/src/Prebuilt/components/MwebLandscapePrompt.tsx b/packages/roomkit-react/src/Prebuilt/components/MwebLandscapePrompt.tsx
index b3ce28e14a..c2164f9895 100644
--- a/packages/roomkit-react/src/Prebuilt/components/MwebLandscapePrompt.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/MwebLandscapePrompt.tsx
@@ -32,7 +32,7 @@ export const MwebLandscapePrompt = () => {
// Angle check needed to diff bw mobile and desktop
setShowMwebLandscapePrompt(
match({ angle, isLandscapeHLSStream, isLandscape, type })
- .with({ isLandscapeHLSStream }, () => false)
+ .with({ isLandscapeHLSStream: true }, () => false)
.with({ angle: P.when(angle => angle && angle >= 90) }, ({ type }) => type.includes('landscape'))
.otherwise(() => isLandscape),
);
diff --git a/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx
index 9041d8f945..9ed895d2d8 100644
--- a/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx
@@ -36,7 +36,6 @@ const SecondarySection = ({
hasSidebar,
}: React.PropsWithChildren<{ tiles: TrackWithPeerAndDimensions[]; edgeToEdge?: boolean; hasSidebar?: boolean }>) => {
const tileLayoutProps = useVideoTileContext();
- console.log('secondary section', { tilesLength: tiles?.length });
if (!tiles?.length) {
return null;
}
diff --git a/packages/roomkit-react/src/Prebuilt/components/hooks/useGroupOnStageActions.tsx b/packages/roomkit-react/src/Prebuilt/components/hooks/useGroupOnStageActions.tsx
new file mode 100644
index 0000000000..fe5fafacd9
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/hooks/useGroupOnStageActions.tsx
@@ -0,0 +1,54 @@
+import { match, P } from 'ts-pattern';
+import { HMSPeer, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
+import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
+
+export const useGroupOnStageActions = ({ peers }: { peers: HMSPeer[] }) => {
+ const hmsActions = useHMSActions();
+ const { elements } = useRoomLayoutConferencingScreen();
+ const {
+ bring_to_stage_label,
+ remove_from_stage_label,
+ on_stage_role,
+ off_stage_roles = [],
+ skip_preview_for_role_change = false,
+ } = elements.on_stage_exp || {};
+ const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
+
+ const offStageRolePeers = peers.filter(peer =>
+ match({ on_stage_role, bring_to_stage_label, roleName: peer.roleName })
+ .with(
+ {
+ on_stage_role: P.when(role => !!role),
+ bring_to_stage_label: P.when(label => !!label),
+ roleName: P.when(role => !!role && off_stage_roles.includes(role)),
+ },
+ () => true,
+ )
+ .otherwise(() => false),
+ );
+
+ const lowerAllHands = async () => {
+ return Promise.all(peers.map(peer => hmsActions.lowerRemotePeerHand(peer.id)));
+ };
+
+ const bringAllToStage = () => {
+ if (!canChangeRole || !on_stage_role) {
+ return;
+ }
+ return Promise.all(
+ offStageRolePeers.map(peer => {
+ return hmsActions.changeRoleOfPeer(peer.id, on_stage_role, skip_preview_for_role_change).then(() => {
+ return skip_preview_for_role_change ? hmsActions.lowerRemotePeerHand(peer.id) : null;
+ });
+ }),
+ );
+ };
+
+ return {
+ lowerAllHands,
+ bringAllToStage,
+ canBringToStage: canChangeRole && offStageRolePeers.length > 0,
+ bring_to_stage_label,
+ remove_from_stage_label,
+ };
+};
diff --git a/packages/roomkit-react/src/Prebuilt/components/hooks/usePeerOnStageActions.tsx b/packages/roomkit-react/src/Prebuilt/components/hooks/usePeerOnStageActions.tsx
new file mode 100644
index 0000000000..000a20641f
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/hooks/usePeerOnStageActions.tsx
@@ -0,0 +1,49 @@
+import { useState } from 'react';
+import { selectPeerMetadata, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
+import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
+
+export const usePeerOnStageActions = ({ peerId, role }: { peerId: string; role: string }) => {
+ const hmsActions = useHMSActions();
+ const { elements } = useRoomLayoutConferencingScreen();
+ const {
+ bring_to_stage_label,
+ remove_from_stage_label,
+ on_stage_role,
+ off_stage_roles = [],
+ skip_preview_for_role_change = false,
+ } = elements.on_stage_exp || {};
+ const isInStage = role === on_stage_role;
+ const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
+ const shouldShowStageRoleChange =
+ canChangeRole &&
+ ((isInStage && remove_from_stage_label) || (off_stage_roles?.includes(role) && bring_to_stage_label));
+ const prevRole = useHMSStore(selectPeerMetadata(peerId))?.prevRole;
+ const [open, setOpen] = useState(false);
+
+ const lowerPeerHand = async () => {
+ await hmsActions.lowerRemotePeerHand(peerId);
+ };
+
+ const handleStageAction = async () => {
+ if (isInStage) {
+ prevRole && hmsActions.changeRoleOfPeer(peerId, prevRole, true);
+ } else if (on_stage_role) {
+ await hmsActions.changeRoleOfPeer(peerId, on_stage_role, skip_preview_for_role_change);
+ if (skip_preview_for_role_change) {
+ await lowerPeerHand();
+ }
+ }
+ setOpen(false);
+ };
+
+ return {
+ open,
+ setOpen,
+ lowerPeerHand,
+ handleStageAction,
+ shouldShowStageRoleChange,
+ isInStage,
+ bring_to_stage_label,
+ remove_from_stage_label,
+ };
+};
diff --git a/packages/roomkit-react/src/Prebuilt/layouts/SidePane.tsx b/packages/roomkit-react/src/Prebuilt/layouts/SidePane.tsx
index 5b4066b683..3225467f98 100644
--- a/packages/roomkit-react/src/Prebuilt/layouts/SidePane.tsx
+++ b/packages/roomkit-react/src/Prebuilt/layouts/SidePane.tsx
@@ -193,7 +193,6 @@ const SidePane = ({
});
if (!trackId && !SidepaneComponent) {
- console.log('sidepane not rendered', { trackId, SidepaneComponent });
return null;
}