Update sidebar layout visibility in group calls

This commit is contained in:
trevor-signal
2026-01-30 14:10:12 -05:00
committed by GitHub
parent 55300c0453
commit c24f721de0
4 changed files with 14 additions and 104 deletions

View File

@@ -327,20 +327,6 @@ export function CallScreen({
setShowRaisedHandsList(prevValue => !prevValue);
}, []);
const [sidebarViewDiffersFromGridView, setSidebarViewDiffersFromGridView] =
useState(false);
// If the user is in Sidebar view but it's no longer different from Grid view,
// automatically switch to Grid view.
useEffect(() => {
if (
!sidebarViewDiffersFromGridView &&
activeCall.viewMode === CallViewMode.Sidebar
) {
changeCallView(CallViewMode.Paginated);
}
}, [sidebarViewDiffersFromGridView, activeCall.viewMode, changeCallView]);
const [controlsHover, setControlsHover] = useState(false);
const onControlsMouseEnter = useCallback(() => {
setControlsHover(true);
@@ -459,7 +445,7 @@ export function CallScreen({
}, [showReactionPicker]);
useScreenSharingStoppedToast({ activeCall, i18n });
useViewModeChangedToast({ activeCall, i18n, sidebarViewDiffersFromGridView });
useViewModeChangedToast({ activeCall, i18n });
const currentPresenter = remoteParticipants.find(
participant => participant.presenting
@@ -1004,9 +990,6 @@ export function CallScreen({
imageDataCache={imageDataCache}
i18n={i18n}
joinedAt={activeCall.joinedAt}
onSidebarViewDiffersFromGridViewChange={
setSidebarViewDiffersFromGridView
}
remoteParticipants={activeCall.remoteParticipants}
setGroupCallVideoRequest={setGroupCallVideoRequest}
remoteAudioLevels={activeCall.remoteAudioLevels}
@@ -1087,7 +1070,6 @@ export function CallScreen({
i18n={i18n}
isGroupCall={isGroupCall}
participantCount={participantCount}
showSidebarViewOption={sidebarViewDiffersFromGridView}
togglePip={togglePip}
toggleSettings={toggleSettings}
/>
@@ -1335,11 +1317,9 @@ function renderDuration(ms: number): string {
function useViewModeChangedToast({
activeCall,
i18n,
sidebarViewDiffersFromGridView,
}: {
activeCall: ActiveCallType;
i18n: LocalizerType;
sidebarViewDiffersFromGridView: boolean;
}): void {
const { viewMode } = activeCall;
const previousViewMode = usePrevious(viewMode, viewMode);
@@ -1359,14 +1339,6 @@ function useViewModeChangedToast({
return;
}
if (
!sidebarViewDiffersFromGridView &&
previousViewMode === CallViewMode.Sidebar &&
viewMode === CallViewMode.Paginated
) {
return;
}
hideToast(VIEW_MODE_CHANGED_TOAST_KEY);
showToast({
key: VIEW_MODE_CHANGED_TOAST_KEY,
@@ -1389,7 +1361,6 @@ function useViewModeChangedToast({
hideToast,
i18n,
activeCall,
sidebarViewDiffersFromGridView,
viewMode,
previousViewMode,
presenterAci,

View File

@@ -16,13 +16,11 @@ export default {
argTypes: {
isGroupCall: { control: { type: 'boolean' } },
participantCount: { control: { type: 'number' } },
showSidebarViewOption: { control: { type: 'boolean' } },
},
args: {
i18n,
isGroupCall: false,
participantCount: 0,
showSidebarViewOption: false,
togglePip: action('toggle-pip'),
callViewMode: CallViewMode.Paginated,
changeCallView: action('change-call-view'),

View File

@@ -15,7 +15,6 @@ export type PropsType = {
isGroupCall?: boolean;
onCancel?: () => void;
participantCount: number;
showSidebarViewOption?: boolean;
togglePip?: () => void;
toggleSettings: () => void;
changeCallView?: (mode: CallViewMode) => void;
@@ -28,7 +27,6 @@ export function CallingHeader({
isGroupCall = false,
onCancel,
participantCount,
showSidebarViewOption = false,
togglePip,
toggleSettings,
}: PropsType): React.JSX.Element {
@@ -49,16 +47,12 @@ export function CallingHeader({
onClick: () => changeCallView(CallViewMode.Paginated),
value: CallViewMode.Paginated,
},
...(showSidebarViewOption
? [
{
icon: 'CallSettingsButton__Icon--SidebarView',
label: i18n('icu:calling__view_mode--overflow'),
onClick: () => changeCallView(CallViewMode.Sidebar),
value: CallViewMode.Sidebar,
},
]
: []),
{
icon: 'CallSettingsButton__Icon--SidebarView',
label: i18n('icu:calling__view_mode--overflow'),
onClick: () => changeCallView(CallViewMode.Sidebar),
value: CallViewMode.Sidebar,
},
{
icon: 'CallSettingsButton__Icon--SpeakerView',
label: i18n('icu:calling__view_mode--speaker'),

View File

@@ -68,7 +68,6 @@ type PropsType = {
imageDataCache: React.RefObject<CallingImageDataCache>;
isCallReconnecting: boolean;
joinedAt: number | null;
onSidebarViewDiffersFromGridViewChange: (differs: boolean) => void;
remoteParticipants: ReadonlyArray<GroupCallRemoteParticipantType>;
setGroupCallVideoRequest: (
_: Array<GroupCallVideoRequest>,
@@ -122,7 +121,6 @@ export function GroupCallRemoteParticipants({
i18n,
isCallReconnecting,
joinedAt,
onSidebarViewDiffersFromGridViewChange,
remoteParticipants,
setGroupCallVideoRequest,
remoteAudioLevels,
@@ -142,7 +140,10 @@ export function GroupCallRemoteParticipants({
const { invisibleDemuxIds, onParticipantVisibilityChanged } =
useInvisibleParticipants(remoteParticipants);
const minRenderedHeight = getMinRenderedHeight(callViewMode);
const minRenderedHeight =
callViewMode === CallViewMode.Paginated
? SMALL_TILES_MIN_HEIGHT
: LARGE_TILES_MIN_HEIGHT;
const isInSpeakerView =
callViewMode === CallViewMode.Speaker ||
@@ -156,7 +157,9 @@ export function GroupCallRemoteParticipants({
// 1. Figure out the maximum number of possible rows that could fit on the page.
// Could be 0 if (a) there are no participants (b) the container's height is small.
const maxRowsPerPage = getMaxRowsPerPage(maxGridHeight, minRenderedHeight);
const maxRowsPerPage = Math.floor(
maxGridHeight / (minRenderedHeight + PARTICIPANT_MARGIN)
);
// 2. Sort the participants in priority order: by `presenting` first, since presenters
// should be on the main grid, then by `speakerTime` so that the most recent speakers
@@ -225,49 +228,6 @@ export function GroupCallRemoteParticipants({
setPageIndex(gridParticipantsByPage.length - 1);
}
// Calculate whether Sidebar view would look different from Grid (Paginated) view.
// They differ when Grid view would have multiple pages.
const minRenderedHeightForGridView = getMinRenderedHeight(
CallViewMode.Paginated
);
const maxRowsPerPageForGridView = getMaxRowsPerPage(
maxGridHeight,
minRenderedHeightForGridView
);
const sidebarViewDiffersFromGridView = useMemo(() => {
if (!prioritySortedParticipants.length || !maxRowsPerPageForGridView) {
return false;
}
// When in Grid view, we've already calculated with the right params
if (isInPaginationView) {
return gridParticipantsByPage.length > 1;
}
// For other views, calculate how many would fit on the first page of Grid view
const gridViewPages = getGridParticipantsByPage({
participants: prioritySortedParticipants,
maxRowWidth,
maxPages: 1,
maxRowsPerPage: maxRowsPerPageForGridView,
minRenderedHeight: minRenderedHeightForGridView,
maxParticipantsPerPage: MAX_PARTICIPANTS_PER_PAGE,
});
return gridViewPages[0].numParticipants < prioritySortedParticipants.length;
}, [
isInPaginationView,
gridParticipantsByPage.length,
maxRowWidth,
maxRowsPerPageForGridView,
minRenderedHeightForGridView,
prioritySortedParticipants,
]);
useEffect(() => {
onSidebarViewDiffersFromGridViewChange(sidebarViewDiffersFromGridView);
}, [onSidebarViewDiffersFromGridViewChange, sidebarViewDiffersFromGridView]);
const totalParticipantsInGrid = gridParticipantsByPage.reduce(
(pageCount, { numParticipants }) => pageCount + numParticipants,
0
@@ -675,19 +635,6 @@ function participantWidthAtHeight(
return participant.videoAspectRatio * height;
}
function getMinRenderedHeight(callViewMode: CallViewMode): number {
return callViewMode === CallViewMode.Paginated
? SMALL_TILES_MIN_HEIGHT
: LARGE_TILES_MIN_HEIGHT;
}
function getMaxRowsPerPage(
maxGridHeight: number,
minRenderedHeight: number
): number {
return Math.floor(maxGridHeight / (minRenderedHeight + PARTICIPANT_MARGIN));
}
function stableParticipantComparator(
a: Readonly<{ demuxId: number }>,
b: Readonly<{ demuxId: number }>