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

Commit

Permalink
Allow users to join calls and video rooms without joining the beta
Browse files Browse the repository at this point in the history
With this change, joining the beta is only necessary to start a group call or create a video room. This change will not land until after Element Call has been promoted into beta.
  • Loading branch information
robintown committed Jan 20, 2023
1 parent a63da74 commit cecc5f1
Show file tree
Hide file tree
Showing 11 changed files with 23 additions and 74 deletions.
2 changes: 1 addition & 1 deletion src/Notifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ export const Notifier = {
* Some events require special handling such as showing in-app toasts
*/
_performCustomEventHandling: function (ev: MatrixEvent) {
if (ElementCall.CALL_EVENT_TYPE.names.includes(ev.getType()) && SettingsStore.getValue("feature_group_calls")) {
if (ElementCall.CALL_EVENT_TYPE.names.includes(ev.getType())) {
ToastStore.sharedInstance().addOrReplaceToast({
key: getIncomingCallToastKey(ev.getStateKey()),
priority: 100,
Expand Down
11 changes: 2 additions & 9 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -506,10 +506,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 @@ -1931,10 +1928,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 === "join")
) {
if (isVideoRoom(this.state.room) && myMembership !== "join") {
return (
<ErrorBoundary>
<div className="mx_MainSplit">
Expand All @@ -1944,7 +1938,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
onRejectButtonClicked={this.onRejectButtonClicked}
/>
</div>
;
</ErrorBoundary>
);
}
Expand Down
6 changes: 2 additions & 4 deletions src/components/views/context_menus/RoomContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import SettingsStore from "../../../settings/SettingsStore";
import DevtoolsDialog from "../dialogs/DevtoolsDialog";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";

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

const isDm = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
const isVideoRoom =
videoRoomsEnabled && (room.isElementVideoRoom() || (elementCallVideoRoomsEnabled && room.isCallRoom()));
const isVideoRoom = calcIsVideoRoom(room);

let inviteOption: JSX.Element;
if (room.canInvite(cli.getUserId()!) && !isDm) {
Expand Down
6 changes: 2 additions & 4 deletions src/components/views/right_panel/RoomSummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import ExportDialog from "../dialogs/ExportDialog";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import PosthogTrackers from "../../../PosthogTrackers";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";

interface IProps {
room: Room;
Expand Down Expand Up @@ -284,10 +285,7 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
const isRoomEncrypted = useIsEncrypted(cli, room);
const roomContext = useContext(RoomContext);
const e2eStatus = roomContext.e2eStatus;
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
const isVideoRoom =
videoRoomsEnabled && (room.isElementVideoRoom() || (elementCallVideoRoomsEnabled && room.isCallRoom()));
const isVideoRoom = calcIsVideoRoom(room);

const alias = room.getCanonicalAlias() || room.getAltAliases()[0] || "";
const header = (
Expand Down
8 changes: 3 additions & 5 deletions src/components/views/rooms/RoomHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { _t } from "../../../languageHandler";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
import { UserTab } from "../dialogs/UserTab";
import SettingsStore from "../../../settings/SettingsStore";
import RoomHeaderButtons from "../right_panel/RoomHeaderButtons";
import E2EIcon from "./E2EIcon";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
Expand Down Expand Up @@ -247,8 +246,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 ?? DEFAULTS.element_call.use_exclusively;
}, []);
Expand Down Expand Up @@ -336,7 +334,7 @@ const CallButtons: FC<CallButtonsProps> = ({ room }) => {
</>
);
}
} else if (hasLegacyCall || hasJitsiWidget) {
} else if (hasLegacyCall || hasJitsiWidget || hasGroupCall) {
return (
<>
{makeVoiceCallButton(new DisabledWithReason(_t("Ongoing call")))}
Expand Down Expand Up @@ -717,7 +715,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
}

public render(): JSX.Element {
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
7 changes: 2 additions & 5 deletions src/components/views/rooms/RoomInfoLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
import { useAsyncMemo } from "../../../hooks/useAsyncMemo";
import { useRoomState } from "../../../hooks/useRoomState";
import { useFeatureEnabled } from "../../../hooks/useSettings";
import { useRoomMemberCount, useMyRoomMembership } from "../../../hooks/useRoomMembers";
import AccessibleButton from "../elements/AccessibleButton";
import { isVideoRoom } from "../../../utils/video-rooms";

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

const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
const isVideoRoom = room.isElementVideoRoom() || (elementCallVideoRoomsEnabled && room.isCallRoom());

let iconClass: string;
let roomType: string;
if (isVideoRoom) {
if (isVideoRoom(room)) {
iconClass = "mx_RoomInfoLine_video";
roomType = _t("Video room");
} else if (joinRule === JoinRule.Public) {
Expand Down
18 changes: 2 additions & 16 deletions src/components/views/rooms/RoomPreviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,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 @@ -37,6 +36,7 @@ import RoomAvatar from "../avatars/RoomAvatar";
import MemberAvatar from "../avatars/MemberAvatar";
import { BetaPill } from "../beta/BetaCard";
import RoomInfoLine from "./RoomInfoLine";
import { isVideoRoom } from "../../../utils/video-rooms";

interface IProps {
room: Room;
Expand All @@ -50,9 +50,6 @@ 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 elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
const isVideoRoom = room.isElementVideoRoom() || (elementCallVideoRoomsEnabled && room.isCallRoom());
const myMembership = useMyRoomMembership(room);
useDispatcher(defaultDispatcher, (payload) => {
if (payload.action === Action.JoinRoomError && payload.roomId === room.roomId) {
Expand Down Expand Up @@ -158,7 +155,7 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
}

let avatarRow: JSX.Element;
if (isVideoRoom) {
if (isVideoRoom(room)) {
avatarRow = (
<>
<RoomAvatar room={room} height={50} width={50} viewAvatarOnClick />
Expand All @@ -177,17 +174,6 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
notice = _t("To view %(roomName)s, you need an invite", {
roomName: room.name,
});
} else if (isVideoRoom && !videoRoomsEnabled) {
notice =
myMembership === "join"
? _t("To view, please enable video rooms in Labs first")
: _t("To join, please enable video rooms in Labs first");

joinButtons = (
<AccessibleButton kind="primary" onClick={viewLabs}>
{_t("Show Labs settings")}
</AccessibleButton>
);
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
const plContent = plEvent ? plEvent.getContent() || {} : {};
const canChangeLevels = room.currentState.mayClientSendStateEvent(EventType.RoomPowerLevels, client);

const plEventsToLabels = {
const plEventsToLabels: { [eventType: string]: string | null } = {
// These will be translated for us later.
[EventType.RoomAvatar]: isSpaceRoom ? _td("Change space avatar") : _td("Change room avatar"),
[EventType.RoomName]: isSpaceRoom ? _td("Change space name") : _td("Change room name"),
Expand All @@ -265,16 +265,13 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
"im.vector.modular.widgets": isSpaceRoom ? null : _td("Modify widgets"),
[VoiceBroadcastInfoEventType]: _td("Voice broadcasts"),
[ElementCall.CALL_EVENT_TYPE.name]: _td("Start %(brand)s calls"),
[ElementCall.MEMBER_EVENT_TYPE.name]: _td("Join %(brand)s calls"),
};

if (SettingsStore.getValue("feature_pinning")) {
plEventsToLabels[EventType.RoomPinnedEvents] = _td("Manage pinned events");
}
// MSC3401: Native Group VoIP signaling
if (SettingsStore.getValue("feature_group_calls")) {
plEventsToLabels[ElementCall.CALL_EVENT_TYPE.name] = _td("Start %(brand)s calls");
plEventsToLabels[ElementCall.MEMBER_EVENT_TYPE.name] = _td("Join %(brand)s calls");
}

const powerLevelDescriptors: Record<string, IPowerLevelDescriptor> = {
"users_default": {
Expand Down
5 changes: 1 addition & 4 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1706,9 +1706,9 @@
"Remove messages sent by me": "Remove messages sent by me",
"Modify widgets": "Modify widgets",
"Voice broadcasts": "Voice broadcasts",
"Manage pinned events": "Manage pinned events",
"Start %(brand)s calls": "Start %(brand)s calls",
"Join %(brand)s calls": "Join %(brand)s calls",
"Manage pinned events": "Manage pinned events",
"Default role": "Default role",
"Send messages": "Send messages",
"Invite users": "Invite users",
Expand Down Expand Up @@ -2088,9 +2088,6 @@
"Leave": "Leave",
"<inviter/> invites you": "<inviter/> invites you",
"To view %(roomName)s, you need an invite": "To view %(roomName)s, you need an invite",
"To view, please enable video rooms in Labs first": "To view, please enable video rooms in Labs first",
"To join, please enable video rooms in Labs first": "To join, please enable video rooms in Labs first",
"Show Labs settings": "Show Labs settings",
"Appearance": "Appearance",
"Show rooms with unread messages first": "Show rooms with unread messages first",
"Show previews of messages": "Show previews of messages",
Expand Down
21 changes: 4 additions & 17 deletions src/models/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ export class JitsiCall extends Call {

public static get(room: Room): JitsiCall | null {
// Only supported in video rooms
if (SettingsStore.getValue("feature_video_rooms") && room.isElementVideoRoom()) {
if (room.isElementVideoRoom()) {
const apps = WidgetStore.instance.getApps(room.roomId);
// The isVideoChannel field differentiates rich Jitsi calls from bare Jitsi widgets
const jitsiWidget = apps.find((app) => WidgetType.JITSI.matches(app.type) && app.data?.isVideoChannel);
Expand Down Expand Up @@ -700,32 +700,19 @@ export class ElementCall extends Call {
}

public static get(room: Room): ElementCall | null {
// Only supported in the new group call experience or in video rooms
if (
SettingsStore.getValue("feature_group_calls") ||
(SettingsStore.getValue("feature_video_rooms") &&
SettingsStore.getValue("feature_element_call_video_rooms") &&
room.isCallRoom())
) {
const groupCall = room.client.groupCallEventHandler!.groupCalls.get(room.roomId);
if (groupCall !== undefined) return new ElementCall(groupCall, room.client);
}
const groupCall = room.client.groupCallEventHandler!.groupCalls.get(room.roomId);
if (groupCall !== undefined) return new ElementCall(groupCall, room.client);

return null;
}

public static async create(room: Room): Promise<void> {
const isVideoRoom =
SettingsStore.getValue("feature_video_rooms") &&
SettingsStore.getValue("feature_element_call_video_rooms") &&
room.isCallRoom();

const groupCall = new GroupCall(
room.client,
room,
GroupCallType.Video,
false,
isVideoRoom ? GroupCallIntent.Room : GroupCallIntent.Prompt,
room.isCallRoom() ? GroupCallIntent.Room : GroupCallIntent.Prompt,
);

await groupCall.create();
Expand Down
4 changes: 1 addition & 3 deletions src/utils/video-rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ limitations under the License.
*/

import type { Room } from "matrix-js-sdk/src/models/room";
import SettingsStore from "../settings/SettingsStore";

export const isVideoRoom = (room: Room): boolean =>
room.isElementVideoRoom() || (SettingsStore.getValue("feature_element_call_video_rooms") && room.isCallRoom());
export const isVideoRoom = (room: Room): boolean => room.isElementVideoRoom() || room.isCallRoom();

0 comments on commit cecc5f1

Please sign in to comment.