Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
New group call experience: Room header call buttons (#9311)
Browse files Browse the repository at this point in the history
* Make useEventEmitterState more efficient

By not invoking the initializing function on every render

* Make useWidgets more efficient

By not calling WidgetStore on every render

* Add new group call experience Labs flag

* Add viewingCall field to RoomViewStore state

Currently has no effect, but in the future this will signal to RoomView to show the call or call lobby.

* Add element_call.use_exclusively config flag

As documented in element-web, this will tell the app to use Element Call exclusively for calls, disabling Jitsi and legacy 1:1 calls.

* Make placeCall return a promise

So that the UI can know when placeCall completes

* Update start call buttons to new group call designs

Since RoomView doesn't do anything with viewingCall yet, these buttons won't have any effect when starting native group calls, but the logic is at least all there and ready to be hooked up.

* Allow calls to be detected if the new group call experience is enabled

* Test the RoomHeader changes

* Iterate code
  • Loading branch information
robintown authored Sep 25, 2022
1 parent 12e3ba8 commit d077ea1
Show file tree
Hide file tree
Showing 16 changed files with 1,007 additions and 125 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
"@percy/cypress": "^3.1.1",
"@sentry/types": "^6.10.0",
"@sinonjs/fake-timers": "^9.1.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^12.1.5",
"@types/classnames": "^2.2.11",
"@types/commonmark": "^0.27.4",
Expand Down
1 change: 1 addition & 0 deletions src/IConfigOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export interface IConfigOptions {
};
element_call: {
url: string;
use_exclusively: boolean;
};

logout_redirect_url?: string;
Expand Down
8 changes: 4 additions & 4 deletions src/LegacyCallHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -820,10 +820,10 @@ export default class LegacyCallHandler extends EventEmitter {
}
}

public placeCall(roomId: string, type?: CallType, transferee?: MatrixCall): void {
public async placeCall(roomId: string, type?: CallType, transferee?: MatrixCall): Promise<void> {
// We might be using managed hybrid widgets
if (isManagedHybridWidgetEnabled()) {
addManagedHybridWidget(roomId);
await addManagedHybridWidget(roomId);
return;
}

Expand Down Expand Up @@ -870,9 +870,9 @@ export default class LegacyCallHandler extends EventEmitter {
} else if (members.length === 2) {
logger.info(`Place ${type} call in ${roomId}`);

this.placeMatrixCall(roomId, type, transferee);
await this.placeMatrixCall(roomId, type, transferee);
} else { // > 2
this.placeJitsiCall(roomId, type);
await this.placeJitsiCall(roomId, type);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/SdkConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const DEFAULTS: IConfigOptions = {
},
element_call: {
url: "https://call.element.io",
use_exclusively: false,
},

// @ts-ignore - we deliberately use the camelCase version here so we trigger
Expand Down
21 changes: 6 additions & 15 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
import { EventType } from 'matrix-js-sdk/src/@types/event';
import { RoomState, RoomStateEvent } from 'matrix-js-sdk/src/models/room-state';
import { EventTimelineSet } from "matrix-js-sdk/src/models/event-timeline-set";
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { throttle } from "lodash";
import { MatrixError } from 'matrix-js-sdk/src/http-api';
import { ClientEvent } from "matrix-js-sdk/src/client";
Expand Down Expand Up @@ -149,7 +149,7 @@ interface IRoomProps extends MatrixClientProps {
enum MainSplitContentType {
Timeline,
MaximisedWidget,
Video, // immersive voip
Call,
}
export interface IRoomState {
room?: Room;
Expand Down Expand Up @@ -299,7 +299,6 @@ function LocalRoomView(props: LocalRoomViewProps): ReactElement {
e2eStatus={E2EStatus.Normal}
onAppsClick={null}
appsShown={false}
onCallPlaced={null}
excludedRightPanelPhaseButtons={[]}
showButtons={false}
enableRoomOptionsMenu={false}
Expand Down Expand Up @@ -350,7 +349,6 @@ function LocalRoomCreateLoader(props: ILocalRoomCreateLoaderProps): ReactElement
e2eStatus={E2EStatus.Normal}
onAppsClick={null}
appsShown={false}
onCallPlaced={null}
excludedRightPanelPhaseButtons={[]}
showButtons={false}
enableRoomOptionsMenu={false}
Expand Down Expand Up @@ -517,7 +515,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

private getMainSplitContentType = (room: Room) => {
if (SettingsStore.getValue("feature_video_rooms") && isVideoRoom(room)) {
return MainSplitContentType.Video;
return MainSplitContentType.Call;
}
if (WidgetLayoutStore.instance.hasMaximisedWidget(room)) {
return MainSplitContentType.MaximisedWidget;
Expand Down Expand Up @@ -1660,10 +1658,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
return ret;
}

private onCallPlaced = (type: CallType): void => {
LegacyCallHandler.instance.placeCall(this.state.room?.roomId, type);
};

private onAppsClick = () => {
dis.dispatch({
action: "appsDrawer",
Expand Down Expand Up @@ -2330,7 +2324,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

const mainClasses = classNames("mx_RoomView", {
mx_RoomView_inCall: Boolean(activeCall),
mx_RoomView_immersive: this.state.mainSplitContentType === MainSplitContentType.Video,
mx_RoomView_immersive: this.state.mainSplitContentType === MainSplitContentType.Call,
});

const showChatEffects = SettingsStore.getValue('showChatEffects');
Expand Down Expand Up @@ -2371,7 +2365,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
{ previewBar }
</>;
break;
case MainSplitContentType.Video: {
case MainSplitContentType.Call: {
mainSplitContentClassName = "mx_MainSplit_video";
mainSplitBody = <>
<VideoRoomView room={this.state.room} resizing={this.state.resizing} />
Expand All @@ -2382,7 +2376,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const mainSplitContentClasses = classNames("mx_RoomView_body", mainSplitContentClassName);

let excludedRightPanelPhaseButtons = [RightPanelPhases.Timeline];
let onCallPlaced = this.onCallPlaced;
let onAppsClick = this.onAppsClick;
let onForgetClick = this.onForgetClick;
let onSearchClick = this.onSearchClick;
Expand All @@ -2399,13 +2392,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
onForgetClick = null;
onSearchClick = null;
break;
case MainSplitContentType.Video:
case MainSplitContentType.Call:
excludedRightPanelPhaseButtons = [
RightPanelPhases.ThreadPanel,
RightPanelPhases.PinnedMessages,
RightPanelPhases.NotificationPanel,
];
onCallPlaced = null;
onAppsClick = null;
onForgetClick = null;
onSearchClick = null;
Expand All @@ -2432,7 +2424,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
e2eStatus={this.state.e2eStatus}
onAppsClick={this.state.hasPinnedWidgets ? onAppsClick : null}
appsShown={this.state.showApps}
onCallPlaced={onCallPlaced}
excludedRightPanelPhaseButtons={excludedRightPanelPhaseButtons}
showButtons={!this.viewsLocalRoom}
enableRoomOptionsMenu={!this.viewsLocalRoom}
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/right_panel/RoomSummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const Button: React.FC<IButtonProps> = ({ children, className, onClick }) => {
};

export const useWidgets = (room: Room) => {
const [apps, setApps] = useState<IApp[]>(WidgetStore.instance.getApps(room.roomId));
const [apps, setApps] = useState<IApp[]>(() => WidgetStore.instance.getApps(room.roomId));

const updateApps = useCallback(() => {
// Copy the array so that we always trigger a re-render, as some updates mutate the array of apps/settings
Expand Down
Loading

0 comments on commit d077ea1

Please sign in to comment.