Skip to content

Commit

Permalink
Allow joining calls and video rooms without enabling the labs flags
Browse files Browse the repository at this point in the history
Since Element Call has now reached production on Element X, Element Web needs to be able to at least participate in group calls. Starting a group call or creating a video room will still require the labs flags, for now.

Note that Jitsi-based video rooms are also affected by this change. This is not because we intend to delabs them (rather, we intend to get rid of them in favor of Element Call video rooms), but because it's easiest to handle both video room variants consistently.
  • Loading branch information
robintown committed Sep 27, 2024
1 parent 8962e8c commit 5937eaa
Show file tree
Hide file tree
Showing 16 changed files with 75 additions and 194 deletions.
7 changes: 1 addition & 6 deletions src/Notifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,7 @@ class NotifierClass extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents
const thisUserHasConnectedDevice =
room && MatrixRTCSession.callMembershipsForRoom(room).some((m) => m.sender === cli.getUserId());

if (
EventType.CallNotify === ev.getType() &&
SettingsStore.getValue("feature_group_calls") &&
(ev.getAge() ?? 0) < 10000 &&
!thisUserHasConnectedDevice
) {
if (EventType.CallNotify === ev.getType() && (ev.getAge() ?? 0) < 10000 && !thisUserHasConnectedDevice) {
const content = ev.getContent();
const roomId = ev.getRoomId();
if (typeof content.call_id !== "string") {
Expand Down
10 changes: 2 additions & 8 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -614,10 +614,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
};

private getMainSplitContentType = (room: Room): MainSplitContentType => {
if (
(SettingsStore.getValue("feature_group_calls") && this.context.roomViewStore.isViewingCall()) ||
isVideoRoom(room)
) {
if (this.context.roomViewStore.isViewingCall() || isVideoRoom(room)) {
return MainSplitContentType.Call;
}
if (this.context.widgetLayoutStore.hasMaximisedWidget(room)) {
Expand Down Expand Up @@ -2183,10 +2180,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}

const myMembership = this.state.room.getMyMembership();
if (
isVideoRoom(this.state.room) &&
!(SettingsStore.getValue("feature_video_rooms") && myMembership === KnownMembership.Join)
) {
if (isVideoRoom(this.state.room) && myMembership !== KnownMembership.Join) {
return (
<ErrorBoundary>
<div className="mx_MainSplit">
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/context_menus/RoomContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
import { UIComponent } from "../../../settings/UIFeature";
import { DeveloperToolsOption } from "./DeveloperToolsOption";
import { tagRoom } from "../../../utils/room/tagRoom";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";
import { usePinnedEvents } from "../../../hooks/usePinnedEvents";

interface IProps extends IContextMenuProps {
Expand Down Expand Up @@ -105,7 +105,7 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
}

const isDm = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
const isVideoRoom = useIsVideoRoom(room);
const isVideoRoom = calcIsVideoRoom(room);
const canInvite = useEventEmitterState(cli, RoomMemberEvent.PowerLevel, () => room.canInvite(cli.getUserId()!));
let inviteOption: JSX.Element | undefined;
if (canInvite && !isDm && shouldShowComponent(UIComponent.InviteUsers)) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/right_panel/RightPanelTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Action } from "../../../dispatcher/actions";
import SettingsStore from "../../../settings/SettingsStore";
import { UIComponent, UIFeature } from "../../../settings/UIFeature";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";

function shouldShowTabsForPhase(phase?: RightPanelPhases): boolean {
const tabs = [
Expand Down Expand Up @@ -48,7 +48,7 @@ export const RightPanelTabs: React.FC<Props> = ({ phase, room }): JSX.Element |
}
});

const isVideoRoom = useIsVideoRoom(room);
const isVideoRoom = room !== undefined && calcIsVideoRoom(room);

if (!shouldShowTabsForPhase(phase)) return null;

Expand Down
4 changes: 2 additions & 2 deletions src/components/views/right_panel/RoomSummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import { useDispatcher } from "../../../hooks/useDispatcher";
import { Action } from "../../../dispatcher/actions";
import { Key } from "../../../Keyboard";
import { useTransition } from "../../../hooks/useTransition";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";
import { usePinnedEvents } from "../../../hooks/usePinnedEvents";
import { ReleaseAnnouncement } from "../../structures/ReleaseAnnouncement.tsx";

Expand Down Expand Up @@ -219,7 +219,7 @@ const RoomSummaryCard: React.FC<IProps> = ({
const isRoomEncrypted = useIsEncrypted(cli, room);
const roomContext = useContext(RoomContext);
const e2eStatus = roomContext.e2eStatus;
const isVideoRoom = useIsVideoRoom(room);
const isVideoRoom = calcIsVideoRoom(room);

const roomState = useRoomState(room);
const directRoomsList = useAccountData<Record<string, string[]>>(room.client, EventType.Direct);
Expand Down
76 changes: 24 additions & 52 deletions src/components/views/rooms/LegacyRoomHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ const CallButtons: FC<CallButtonsProps> = ({ room }) => {
const [busy, setBusy] = useState(false);
const showButtons = useSettingValue<boolean>("showCallButtonsInComposer");
const groupCallsEnabled = useFeatureEnabled("feature_group_calls");
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
const isVideoRoom = useMemo(() => videoRoomsEnabled && calcIsVideoRoom(room), [videoRoomsEnabled, room]);
const isVideoRoom = useMemo(() => calcIsVideoRoom(room), [room]);
const useElementCallExclusively = useMemo(() => {
return SdkConfig.get("element_call").use_exclusively;
}, []);
Expand Down Expand Up @@ -290,53 +289,13 @@ const CallButtons: FC<CallButtonsProps> = ({ room }) => {

if (isVideoRoom || !showButtons) {
return null;
} else if (groupCallsEnabled) {
if (useElementCallExclusively) {
if (hasGroupCall) {
return makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_ongoing_call")));
} else if (mayCreateElementCalls) {
return makeVideoCallButton("element");
} else {
return makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_no_perms_start_video_call")));
}
} else if (hasLegacyCall || hasJitsiWidget) {
return (
<>
{makeVoiceCallButton(new DisabledWithReason(_t("voip|disabled_ongoing_call")))}
{makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_ongoing_call")))}
</>
);
} else if (functionalMembers.length <= 1) {
return (
<>
{makeVoiceCallButton(new DisabledWithReason(_t("voip|disabled_no_one_here")))}
{makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_no_one_here")))}
</>
);
} else if (functionalMembers.length === 2) {
return (
<>
{makeVoiceCallButton("legacy_or_jitsi")}
{makeVideoCallButton("legacy_or_element")}
</>
);
} else if (mayEditWidgets) {
return (
<>
{makeVoiceCallButton("legacy_or_jitsi")}
{makeVideoCallButton(mayCreateElementCalls ? "jitsi_or_element" : "legacy_or_jitsi")}
</>
);
} else if (groupCallsEnabled && useElementCallExclusively) {
if (hasGroupCall) {
return makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_ongoing_call")));
} else if (mayCreateElementCalls) {
return makeVideoCallButton("element");
} else {
const videoCallBehavior = mayCreateElementCalls
? "element"
: new DisabledWithReason(_t("voip|disabled_no_perms_start_video_call"));
return (
<>
{makeVoiceCallButton(new DisabledWithReason(_t("voip|disabled_no_perms_start_voice_call")))}
{makeVideoCallButton(videoCallBehavior)}
</>
);
return makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_no_perms_start_video_call")));
}
} else if (hasLegacyCall || hasJitsiWidget) {
return (
Expand All @@ -352,18 +311,31 @@ const CallButtons: FC<CallButtonsProps> = ({ room }) => {
{makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_no_one_here")))}
</>
);
} else if (functionalMembers.length === 2 || mayEditWidgets) {
} else if (functionalMembers.length === 2) {
return (
<>
{makeVoiceCallButton("legacy_or_jitsi")}
{makeVideoCallButton(groupCallsEnabled ? "legacy_or_element" : "legacy_or_jitsi")}
</>
);
} else if (mayEditWidgets) {
return (
<>
{makeVoiceCallButton("legacy_or_jitsi")}
{makeVideoCallButton("legacy_or_jitsi")}
{makeVideoCallButton(
groupCallsEnabled && mayCreateElementCalls ? "jitsi_or_element" : "legacy_or_jitsi",
)}
</>
);
} else {
const videoCallBehavior =
groupCallsEnabled && mayCreateElementCalls
? "element"
: new DisabledWithReason(_t("voip|disabled_no_perms_start_video_call"));
return (
<>
{makeVoiceCallButton(new DisabledWithReason(_t("voip|disabled_no_perms_start_voice_call")))}
{makeVideoCallButton(new DisabledWithReason(_t("voip|disabled_no_perms_start_video_call")))}
{makeVideoCallButton(videoCallBehavior)}
</>
);
}
Expand Down Expand Up @@ -745,7 +717,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
}

public render(): React.ReactNode {
const isVideoRoom = SettingsStore.getValue("feature_video_rooms") && calcIsVideoRoom(this.props.room);
const isVideoRoom = calcIsVideoRoom(this.props.room);

let roomAvatar: JSX.Element | null = null;
if (this.props.room) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/rooms/RoomHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import PosthogTrackers from "../../../PosthogTrackers";
import { VideoRoomChatButton } from "./RoomHeader/VideoRoomChatButton";
import { RoomKnocksBar } from "./RoomKnocksBar";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";
import { notificationLevelToIndicator } from "../../../utils/notifications";
import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton";
import { ButtonEvent } from "../elements/AccessibleButton";
Expand Down Expand Up @@ -225,7 +225,7 @@ export default function RoomHeader({
}

const roomContext = useContext(RoomContext);
const isVideoRoom = useIsVideoRoom(room);
const isVideoRoom = calcIsVideoRoom(room);
const showChatButton =
isVideoRoom ||
roomContext.mainSplitContentType === MainSplitContentType.MaximisedWidget ||
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/rooms/RoomInfoLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useAsyncMemo } from "../../../hooks/useAsyncMemo";
import { useRoomState } from "../../../hooks/useRoomState";
import { useRoomMemberCount, useMyRoomMembership } from "../../../hooks/useRoomMembers";
import AccessibleButton from "../elements/AccessibleButton";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";

interface IProps {
room: Room;
Expand All @@ -37,7 +37,7 @@ const RoomInfoLine: FC<IProps> = ({ room }) => {
const membership = useMyRoomMembership(room);
const memberCount = useRoomMemberCount(room);

const isVideoRoom = useIsVideoRoom(room, true);
const isVideoRoom = calcIsVideoRoom(room);

let iconClass: string;
let roomType: string;
Expand Down
30 changes: 7 additions & 23 deletions src/components/views/rooms/RoomPreviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { UserTab } from "../dialogs/UserTab";
import { EffectiveMembership, getEffectiveMembership } from "../../../utils/membership";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { useDispatcher } from "../../../hooks/useDispatcher";
import { useFeatureEnabled } from "../../../hooks/useSettings";
import { useRoomState } from "../../../hooks/useRoomState";
import { useMyRoomMembership } from "../../../hooks/useRoomMembers";
import AccessibleButton from "../elements/AccessibleButton";
Expand All @@ -29,7 +28,7 @@ import RoomAvatar from "../avatars/RoomAvatar";
import MemberAvatar from "../avatars/MemberAvatar";
import { BetaPill } from "../beta/BetaCard";
import RoomInfoLine from "./RoomInfoLine";
import { useIsVideoRoom } from "../../../utils/video-rooms";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";

interface IProps {
room: Room;
Expand All @@ -43,8 +42,7 @@ interface IProps {
// and viewing invite reasons to achieve parity with the default invite screen.
const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButtonClicked }) => {
const cli = useContext(MatrixClientContext);
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
const isVideoRoom = useIsVideoRoom(room, true);
const isVideoRoom = calcIsVideoRoom(room);
const myMembership = useMyRoomMembership(room);
useDispatcher(defaultDispatcher, (payload) => {
if (payload.action === Action.JoinRoomError && payload.roomId === room.roomId) {
Expand Down Expand Up @@ -164,24 +162,6 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
avatarRow = <RoomAvatar room={room} size="50px" viewAvatarOnClick />;
}

let notice: string | null = null;
if (cannotJoin) {
notice = _t("room|join_failed_needs_invite", {
roomName: room.name,
});
} else if (isVideoRoom && !videoRoomsEnabled) {
notice =
myMembership === KnownMembership.Join
? _t("room|view_failed_enable_video_rooms")
: _t("room|join_failed_enable_video_rooms");

joinButtons = (
<AccessibleButton kind="primary" onClick={viewLabs}>
{_t("room|show_labs_settings")}
</AccessibleButton>
);
}

return (
<div className="mx_RoomPreviewCard">
{inviterSection}
Expand All @@ -192,7 +172,11 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
<RoomInfoLine room={room} />
<RoomTopic room={room} className="mx_RoomPreviewCard_topic" />
{room.getJoinRule() === "public" && <RoomFacePile room={room} />}
{notice ? <div className="mx_RoomPreviewCard_notice">{notice}</div> : null}
{cannotJoin ? (
<div className="mx_RoomPreviewCard_notice">
{_t("room|join_failed_needs_invite", { roomName: room.name })}
</div>
) : null}
<div className="mx_RoomPreviewCard_joinButtons">{joinButtons}</div>
</div>
);
Expand Down
8 changes: 4 additions & 4 deletions src/hooks/room/useRoomCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ export const useRoomCall = (
if (useElementCallExclusively && !hasJitsiWidget) {
return [PlatformCallType.ElementCall];
}
if (hasGroupCall && WidgetType.CALL.matches(groupCall.widget.type)) {
// only allow joining the ongoing Element call if there is one.
return [PlatformCallType.ElementCall];
}
}
if (hasGroupCall && WidgetType.CALL.matches(groupCall.widget.type)) {
// only allow joining the ongoing Element call if there is one.
return [PlatformCallType.ElementCall];
}
return options;
}, [
Expand Down
3 changes: 0 additions & 3 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,6 @@
"inviter_unknown": "Unknown",
"invites_you_text": "<inviter/> invites you",
"join_button_account": "Sign Up",
"join_failed_enable_video_rooms": "To join, please enable video rooms in Labs first",
"join_failed_needs_invite": "To view %(roomName)s, you need an invite",
"join_the_discussion": "Join the discussion",
"join_title": "Join the room to participate",
Expand Down Expand Up @@ -2086,7 +2085,6 @@
},
"this_room_button": "Search this room"
},
"show_labs_settings": "Show Labs settings",
"status_bar": {
"delete_all": "Delete all",
"exceeded_resource_limit": "Your message wasn't sent because this homeserver has exceeded a resource limit. Please <a>contact your service administrator</a> to continue using the service.",
Expand Down Expand Up @@ -2117,7 +2115,6 @@
},
"uploading_single_file": "Uploading %(filename)s"
},
"view_failed_enable_video_rooms": "To view, please enable video rooms in Labs first",
"waiting_for_join_subtitle": "Once invited users have joined %(brand)s, you will be able to chat and the room will be end-to-end encrypted",
"waiting_for_join_title": "Waiting for users to join %(brand)s"
},
Expand Down
Loading

0 comments on commit 5937eaa

Please sign in to comment.