diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 395cf556b8..9bb90e607a 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -22,14 +22,14 @@ import { User } from "matrix-js-sdk/src/models/user"; import { Direction } from 'matrix-js-sdk/src/models/event-timeline'; import { EventType } from "matrix-js-sdk/src/@types/event"; import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers'; -import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; +import { Element as ChildElement, parseFragment as parseHtml } from "parse5"; import { logger } from "matrix-js-sdk/src/logger"; import { IContent } from 'matrix-js-sdk/src/models/event'; import { SlashCommand as SlashCommandEvent } from "matrix-analytics-events/types/typescript/SlashCommand"; import { MatrixClientPeg } from './MatrixClientPeg'; import dis from './dispatcher/dispatcher'; -import { _t, _td, newTranslatableError, ITranslatableError } from './languageHandler'; +import { _t, _td, ITranslatableError, newTranslatableError } from './languageHandler'; import Modal from './Modal'; import MultiInviter from './utils/MultiInviter'; import { linkifyAndSanitizeHtml } from './HtmlUtils'; @@ -933,7 +933,7 @@ export const Commands = [ command: 'addwidget', args: '', description: _td('Adds a custom widget by URL to the room'), - isEnabled: () => SettingsStore.getValue(UIFeature.Widgets), + isEnabled: () => SettingsStore.getValue(UIFeature.Widgets) && shouldShowComponent(UIComponent.AddIntegrations), runFn: function(roomId, widgetUrl) { if (!widgetUrl) { return reject(newTranslatableError("Please supply a widget URL or embed code")); diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 5315b8f1cd..e9fdd29eda 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -44,6 +44,8 @@ import RoomBreadcrumbs from "../views/rooms/RoomBreadcrumbs"; import SettingsStore from "../../settings/SettingsStore"; import UserMenu from "./UserMenu"; import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts"; +import { shouldShowComponent } from "../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../settings/UIFeature"; interface IProps { isMinimized: boolean; @@ -368,7 +370,7 @@ export default class LeftPanel extends React.Component { let rightButton: JSX.Element; if (this.state.showBreadcrumbs === BreadcrumbsMode.Labs) { rightButton = ; - } else if (this.state.activeSpace === MetaSpace.Home) { + } else if (this.state.activeSpace === MetaSpace.Home && shouldShowComponent(UIComponent.ExploreRooms)) { rightButton = = ({ room, onClose }) => { - { SettingsStore.getValue(UIFeature.Widgets) && } + { + SettingsStore.getValue(UIFeature.Widgets) + && shouldShowComponent(UIComponent.AddIntegrations) + && + } ; }; diff --git a/src/components/views/rooms/NewRoomIntro.tsx b/src/components/views/rooms/NewRoomIntro.tsx index a83130b61f..667145d0a9 100644 --- a/src/components/views/rooms/NewRoomIntro.tsx +++ b/src/components/views/rooms/NewRoomIntro.tsx @@ -135,7 +135,7 @@ const NewRoomIntro = () => { } let buttons; - if (parentSpace) { + if (parentSpace && shouldShowComponent(UIComponent.InviteUsers)) { buttons =
{ // align the context menu's icons with the icon which opened the context menu @@ -210,6 +212,14 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => { const communityId = CommunityPrototypeStore.instance.getSelectedCommunityId(); const canAddRooms = activeSpace?.currentState?.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); + const canCreateRooms = shouldShowComponent(UIComponent.CreateRooms); + const canExploreRooms = shouldShowComponent(UIComponent.ExploreRooms); + + // If the user can't do anything on the plus menu, don't show it. This aims to target the + // plus menu shown on the Home tab primarily: the user has options to use the menu for + // communities and spaces, but is at risk of no options on the Home tab. + const canShowPlusMenu = canCreateRooms || canExploreRooms || activeSpace || communityId; + let contextMenu: JSX.Element; if (mainMenuDisplayed) { let ContextMenuComponent; @@ -320,12 +330,12 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => { ; } else if (plusMenuDisplayed) { - contextMenu = - + let startChatOpt: JSX.Element; + let createRoomOpt: JSX.Element; + let joinRoomOpt: JSX.Element; + + if (canCreateRooms) { + startChatOpt = ( { closePlusMenu(); }} /> + ); + createRoomOpt = ( { closePlusMenu(); }} /> + ); + } + if (canExploreRooms) { + joinRoomOpt = ( { closePlusMenu(); }} /> + ); + } + + contextMenu = + + { startChatOpt } + { createRoomOpt } + { joinRoomOpt } ; } @@ -397,13 +425,13 @@ const RoomListHeader = ({ spacePanelDisabled, onVisibilityChange }: IProps) => { return
{ contextMenuButton } { pendingRoomJoinSpinner } - + /> } { contextMenu }
; diff --git a/src/settings/UIFeature.ts b/src/settings/UIFeature.ts index 9f149c4564..b7f107254a 100644 --- a/src/settings/UIFeature.ts +++ b/src/settings/UIFeature.ts @@ -36,7 +36,33 @@ export enum UIFeature { } export enum UIComponent { + /** + * Components that lead to a user being invited. + */ InviteUsers = "UIComponent.sendInvites", + + /** + * Components that lead to a room being created that aren't already + * guarded by some other condition (ie: "only if you can edit this + * space" is *not* guarded by this component, but "start DM" is). + */ CreateRooms = "UIComponent.roomCreation", + + /** + * Components that lead to a Space being created that aren't already + * guarded by some other condition (ie: "only if you can add subspaces" + * is *not* guarded by this component, but "create new space" is). + */ CreateSpaces = "UIComponent.spaceCreation", + + /** + * Components that lead to the public room directory. + */ + ExploreRooms = "UIComponent.exploreRooms", + + /** + * Components that lead to the user being able to easily add widgets + * and integrations to the room, such as from the room information card. + */ + AddIntegrations = "UIComponent.addIntegrations", } diff --git a/src/utils/space.tsx b/src/utils/space.tsx index 338ddec811..078d7068b2 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -44,6 +44,8 @@ import SpacePreferencesDialog, { SpacePreferenceTab } from "../components/views/ import PosthogTrackers from "../PosthogTrackers"; import { ButtonEvent } from "../components/views/elements/AccessibleButton"; import { AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoomPayload"; +import { shouldShowComponent } from "../customisations/helpers/UIComponents"; +import { UIComponent } from "../settings/UIFeature"; export const shouldShowSpaceSettings = (space: Room) => { const userId = space.client.getUserId(); @@ -110,8 +112,10 @@ export const showCreateNewRoom = async (space: Room): Promise => { }; export const shouldShowSpaceInvite = (space: Room) => - (space?.getMyMembership() === "join" && space.canInvite(space.client.getUserId())) || - space.getJoinRule() === JoinRule.Public; + ( + (space?.getMyMembership() === "join" && space.canInvite(space.client.getUserId())) || + space.getJoinRule() === JoinRule.Public + ) && shouldShowComponent(UIComponent.InviteUsers); export const showSpaceInvite = (space: Room, initialText = ""): void => { if (space.getJoinRule() === "public") {