New group call experience: Room header and PiP designs (#9351)

* Update our cancel icon

The cancel icon we're using in the app has drifted out of sync with the ones used in our designs. We also had two identical-looking icons, so this consolidates them into one.

I've simultaneously updated our chevron icons, since in the case of the 'jump to unread' timeline button, it became clear that the weight of the new close icon did not match the thinner chevron.

* Don't squish bottom/top-aligned tooltips near the edge of the screen

* Close the timeline panel when returning to the fullscreen timeline view

* Add layout switching capabilities to ElementCall

* Bring the room header in line with the group call designs

* Bring the PiP header in line with the group call designs

* Fix lints

* Clarify tooltip CSS calculations

* Test PipView

* Expand RoomHeader test coverage

* Test PipView more
This commit is contained in:
Robin 2022-10-06 22:27:28 -04:00 committed by GitHub
parent 9a3ae2398e
commit 06dbea6255
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 845 additions and 220 deletions

View file

@ -121,6 +121,7 @@ import { LargeLoader } from './LargeLoader';
import { VoiceBroadcastInfoEventType } from '../../voice-broadcast';
import { isVideoRoom } from '../../utils/video-rooms';
import { CallStore, CallStoreEvent } from "../../stores/CallStore";
import { Call } from "../../models/Call";
const DEBUG = false;
let debuglog = function(msg: string) {};
@ -178,6 +179,7 @@ export interface IRoomState {
searchHighlights?: string[];
searchInProgress?: boolean;
callState?: CallState;
activeCall: Call | null;
canPeek: boolean;
canSelfRedact: boolean;
showApps: boolean;
@ -303,6 +305,8 @@ function LocalRoomView(props: LocalRoomViewProps): ReactElement {
excludedRightPanelPhaseButtons={[]}
showButtons={false}
enableRoomOptionsMenu={false}
viewingCall={false}
activeCall={null}
/>
<main className="mx_RoomView_body" ref={props.roomView}>
<FileDropTarget parent={props.roomView.current} onFileDrop={props.onFileDrop} />
@ -353,6 +357,8 @@ function LocalRoomCreateLoader(props: ILocalRoomCreateLoaderProps): ReactElement
excludedRightPanelPhaseButtons={[]}
showButtons={false}
enableRoomOptionsMenu={false}
viewingCall={false}
activeCall={null}
/>
<div className="mx_RoomView_body">
<LargeLoader text={text} />
@ -391,6 +397,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
numUnreadMessages: 0,
searchResults: null,
callState: null,
activeCall: null,
canPeek: false,
canSelfRedact: false,
showApps: false,
@ -497,13 +504,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
if (WidgetLayoutStore.instance.hasMaximisedWidget(this.state.room)) {
// Show chat in right panel when a widget is maximised
RightPanelStore.instance.setCard({ phase: RightPanelPhases.Timeline });
} else if (
RightPanelStore.instance.isOpen &&
RightPanelStore.instance.roomPhaseHistory.some(card => (card.phase === RightPanelPhases.Timeline))
) {
// hide chat in right panel when the widget is minimized
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomSummary });
RightPanelStore.instance.togglePanel(this.state.roomId);
}
this.checkWidgets(this.state.room);
};
@ -571,8 +571,22 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
mainSplitContentType: room === null ? undefined : this.getMainSplitContentType(room),
initialEventId: null, // default to clearing this, will get set later in the method if needed
showRightPanel: RightPanelStore.instance.isOpenForRoom(roomId),
activeCall: CallStore.instance.getActiveCall(roomId),
};
if (
this.state.mainSplitContentType !== MainSplitContentType.Timeline
&& newState.mainSplitContentType === MainSplitContentType.Timeline
&& RightPanelStore.instance.isOpen
&& RightPanelStore.instance.currentCard.phase === RightPanelPhases.Timeline
&& RightPanelStore.instance.roomPhaseHistory.some(card => (card.phase === RightPanelPhases.Timeline))
) {
// We're returning to the main timeline, so hide the right panel timeline
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomSummary });
RightPanelStore.instance.togglePanel(this.state.roomId ?? null);
newState.showRightPanel = false;
}
const initialEventId = RoomViewStore.instance.getInitialEventId();
if (initialEventId) {
let initialEvent = room?.findEventById(initialEventId);
@ -701,7 +715,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
};
private onActiveCalls = () => {
if (this.state.roomId !== undefined && !CallStore.instance.hasActiveCall(this.state.roomId)) {
if (this.state.roomId === undefined) return;
const activeCall = CallStore.instance.getActiveCall(this.state.roomId);
if (activeCall === null) {
// We disconnected from the call, so stop viewing it
dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
@ -710,6 +727,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
metricsTrigger: undefined,
}, true); // Synchronous so that CallView disappears immediately
}
this.setState({ activeCall });
};
private getRoomId = () => {
@ -2404,6 +2423,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
let onForgetClick = this.onForgetClick;
let onSearchClick = this.onSearchClick;
let onInviteClick = null;
let viewingCall = false;
// Simplify the header for other main split types
switch (this.state.mainSplitContentType) {
@ -2422,12 +2442,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
RightPanelPhases.PinnedMessages,
RightPanelPhases.NotificationPanel,
];
if (!isVideoRoom(this.state.room)) {
excludedRightPanelPhaseButtons.push(RightPanelPhases.RoomSummary);
if (this.state.activeCall === null) {
excludedRightPanelPhaseButtons.push(RightPanelPhases.Timeline);
}
}
onAppsClick = null;
onForgetClick = null;
onSearchClick = null;
if (this.state.room.canInvite(this.context.credentials.userId)) {
onInviteClick = this.onInviteClick;
}
viewingCall = true;
}
return (
@ -2451,6 +2478,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
excludedRightPanelPhaseButtons={excludedRightPanelPhaseButtons}
showButtons={!this.viewsLocalRoom}
enableRoomOptionsMenu={!this.viewsLocalRoom}
viewingCall={viewingCall}
activeCall={this.state.activeCall}
/>
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
<div className={mainSplitContentClasses} ref={this.roomViewBody} data-layout={this.state.layout}>