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

Commit

Permalink
Implement MSC3827: Filtering of /publicRooms by room type (#8866)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonBrandner authored Jun 24, 2022
1 parent 18c21d7 commit 663bca5
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 21 deletions.
5 changes: 5 additions & 0 deletions res/css/views/dialogs/_SpotlightDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ limitations under the License.
justify-content: space-between;
align-items: center;
margin-bottom: $spacing-8;

.mx_SpotlightDialog_options {
display: flex;
gap: $spacing-4;
}
}

& + .mx_SpotlightDialog_section {
Expand Down
56 changes: 46 additions & 10 deletions src/components/views/dialogs/spotlight/SpotlightDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import classNames from "classnames";
import { capitalize, sum } from "lodash";
import { WebSearch as WebSearchEvent } from "@matrix-org/analytics-events/types/typescript/WebSearch";
import { IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces";
import { IPublicRoomsChunkRoom, MatrixClient, RoomMember } from "matrix-js-sdk/src/matrix";
import { IPublicRoomsChunkRoom, MatrixClient, RoomMember, RoomType } from "matrix-js-sdk/src/matrix";
import { Room } from "matrix-js-sdk/src/models/room";
import { normalize } from "matrix-js-sdk/src/utils";
import React, {
Expand Down Expand Up @@ -89,6 +89,8 @@ import { Option } from "./Option";
import { PublicRoomResultDetails } from "./PublicRoomResultDetails";
import { RoomResultDetails } from "./RoomResultDetails";
import { TooltipOption } from "./TooltipOption";
import LabelledCheckbox from "../../elements/LabelledCheckbox";
import { useFeatureEnabled } from "../../../../hooks/useSettings";

const MAX_RECENT_SEARCHES = 10;
const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons
Expand All @@ -103,6 +105,18 @@ function refIsForRecentlyViewed(ref: RefObject<HTMLElement>): boolean {
return ref.current?.id?.startsWith("mx_SpotlightDialog_button_recentlyViewed_") === true;
}

function getRoomTypes(showRooms: boolean, showSpaces: boolean): Set<RoomType | null> | null {
const roomTypes = new Set<RoomType | null>();

// This is what servers not implementing MSC3827 are expecting
if (showRooms && !showSpaces) return null;

if (showRooms) roomTypes.add(null);
if (showSpaces) roomTypes.add(RoomType.Space);

return roomTypes;
}

enum Section {
People,
Rooms,
Expand Down Expand Up @@ -277,14 +291,19 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
const [inviteLinkCopied, setInviteLinkCopied] = useState<boolean>(false);
const trimmedQuery = useMemo(() => query.trim(), [query]);

const exploringPublicSpacesEnabled = useFeatureEnabled("feature_exploring_public_spaces");

const { loading: publicRoomsLoading, publicRooms, protocols, config, setConfig, search: searchPublicRooms } =
usePublicRoomDirectory();
const [showRooms, setShowRooms] = useState(true);
const [showSpaces, setShowSpaces] = useState(false);
const { loading: peopleLoading, users, search: searchPeople } = useUserDirectory();
const { loading: profileLoading, profile, search: searchProfileInfo } = useProfileInfo();
const searchParams: [IDirectoryOpts] = useMemo(() => ([{
query: trimmedQuery,
roomTypes: getRoomTypes(showRooms, showSpaces),
limit: SECTION_LIMIT,
}]), [trimmedQuery]);
}]), [trimmedQuery, showRooms, showSpaces]);
useDebouncedCallback(
filter === Filter.PublicRooms,
searchPublicRooms,
Expand Down Expand Up @@ -624,15 +643,32 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
<div className="mx_SpotlightDialog_section mx_SpotlightDialog_results" role="group">
<div className="mx_SpotlightDialog_sectionHeader">
<h4>{ _t("Suggestions") }</h4>
<NetworkDropdown
protocols={protocols}
config={config ?? null}
setConfig={setConfig}
/>
</div>
<div>
{ results[Section.PublicRooms].slice(0, SECTION_LIMIT).map(resultMapper) }
<div className="mx_SpotlightDialog_options">
{ exploringPublicSpacesEnabled && <>
<LabelledCheckbox
label={_t("Show rooms")}
value={showRooms}
onChange={setShowRooms}
/>
<LabelledCheckbox
label={_t("Show spaces")}
value={showSpaces}
onChange={setShowSpaces}
/>
</> }
<NetworkDropdown
protocols={protocols}
config={config ?? null}
setConfig={setConfig}
/>
</div>
</div>
<div> { (showRooms || showSpaces)
? results[Section.PublicRooms].slice(0, SECTION_LIMIT).map(resultMapper)
: <div className="mx_SpotlightDialog_otherSearches_messageSearchText">
{ _t("You cannot search for rooms that are neither a room nor a space") }
</div>
} </div>
</div>
);
}
Expand Down
22 changes: 20 additions & 2 deletions src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,31 @@ export class LabsSettingToggle extends React.Component<ILabsSettingToggleProps>
interface IState {
showHiddenReadReceipts: boolean;
showJumpToDate: boolean;
showExploringPublicSpaces: boolean;
}

export default class LabsUserSettingsTab extends React.Component<{}, IState> {
constructor(props: {}) {
super(props);

MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc2285").then((showHiddenReadReceipts) => {
const cli = MatrixClientPeg.get();

cli.doesServerSupportUnstableFeature("org.matrix.msc2285").then((showHiddenReadReceipts) => {
this.setState({ showHiddenReadReceipts });
});

MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3030").then((showJumpToDate) => {
cli.doesServerSupportUnstableFeature("org.matrix.msc3030").then((showJumpToDate) => {
this.setState({ showJumpToDate });
});

cli.doesServerSupportUnstableFeature("org.matrix.msc3827").then((showExploringPublicSpaces) => {
this.setState({ showExploringPublicSpaces });
});

this.state = {
showHiddenReadReceipts: false,
showJumpToDate: false,
showExploringPublicSpaces: false,
};
}

Expand Down Expand Up @@ -133,6 +141,16 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> {
);
}

if (this.state.showExploringPublicSpaces) {
groups.getOrCreate(LabGroup.Spaces, []).push(
<SettingsFlag
key="feature_exploring_public_spaces"
name="feature_exploring_public_spaces"
level={SettingLevel.DEVICE}
/>,
);
}

labsSections = <>
{ sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
<div className="mx_SettingsTab_section" key={group}>
Expand Down
11 changes: 5 additions & 6 deletions src/components/views/spaces/SpaceCreateMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import React, { ComponentProps, RefObject, SyntheticEvent, KeyboardEvent, useCon
import classNames from "classnames";
import { RoomType } from "matrix-js-sdk/src/@types/event";
import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
import { HistoryVisibility, Preset } from "matrix-js-sdk/src/@types/partials";
import { HistoryVisibility, Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
import { logger } from "matrix-js-sdk/src/logger";

import { _t } from "../../../languageHandler";
Expand All @@ -37,6 +37,7 @@ import GenericFeatureFeedbackDialog from "../dialogs/GenericFeatureFeedbackDialo
import SettingsStore from "../../../settings/SettingsStore";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { MatrixClientPeg } from "../../../MatrixClientPeg";

export const createSpace = async (
name: string,
Expand All @@ -51,6 +52,9 @@ export const createSpace = async (
createOpts: {
name,
preset: isPublic ? Preset.PublicChat : Preset.PrivateChat,
visibility: (isPublic && await MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827"))
? Visibility.Public
: Visibility.Private,
power_level_content_override: {
// Only allow Admins to write to the timeline to prevent hidden sync spam
events_default: 100,
Expand Down Expand Up @@ -80,11 +84,6 @@ const SpaceCreateMenuType = ({ title, description, className, onClick }) => {
);
};

enum Visibility {
Public,
Private,
}

const spaceNameValidator = withValidation({
rules: [
{
Expand Down
6 changes: 5 additions & 1 deletion src/components/views/spaces/SpaceSettingsVisibilityTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { useLocalEcho } from "../../../hooks/useLocalEcho";
import JoinRuleSettings from "../settings/JoinRuleSettings";
import { useRoomState } from "../../../hooks/useRoomState";
import SettingsFieldset from "../settings/SettingsFieldset";
import { useAsyncMemo } from "../../../hooks/useAsyncMemo";

interface IProps {
matrixClient: MatrixClient;
Expand All @@ -38,6 +39,9 @@ interface IProps {

const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn }: IProps) => {
const [error, setError] = useState("");
const serverSupportsExploringSpaces = useAsyncMemo<boolean>(async () => {
return cli.doesServerSupportUnstableFeature("org.matrix.msc3827");
}, [cli], false);

const userId = cli.getUserId();

Expand Down Expand Up @@ -103,7 +107,7 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
canSetCanonicalAlias={canSetCanonical}
canSetAliases={true}
canonicalAliasEvent={canonicalAliasEv}
hidePublishSetting={true}
hidePublishSetting={!serverSupportsExploringSpaces}
/>
</>;
}
Expand Down
8 changes: 6 additions & 2 deletions src/hooks/usePublicRoomDirectory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { RoomType } from "matrix-js-sdk/src/@types/event";
import { IRoomDirectoryOptions } from "matrix-js-sdk/src/@types/requests";
import { IProtocol, IPublicRoomsChunkRoom } from "matrix-js-sdk/src/client";
import { useCallback, useEffect, useState } from "react";
Expand All @@ -32,6 +33,7 @@ const LAST_INSTANCE_KEY = "mx_last_room_directory_instance";
export interface IPublicRoomsOpts {
limit: number;
query?: string;
roomTypes?: Set<RoomType | null>;
}

let thirdParty: Protocols;
Expand Down Expand Up @@ -72,6 +74,7 @@ export const usePublicRoomDirectory = () => {
const search = useCallback(async ({
limit = 20,
query,
roomTypes,
}: IPublicRoomsOpts): Promise<boolean> => {
const opts: IRoomDirectoryOptions = { limit };

Expand All @@ -85,9 +88,10 @@ export const usePublicRoomDirectory = () => {
opts.third_party_instance_id = config.instanceId;
}

if (query) {
if (query || roomTypes) {
opts.filter = {
generic_search_term: query,
"generic_search_term": query,
"org.matrix.msc3827.room_types": roomTypes ? Array.from<RoomType | null>(roomTypes) : null,
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@
"Can I use text chat alongside the video call?": "Can I use text chat alongside the video call?",
"Yes, the chat timeline is displayed alongside the video.": "Yes, the chat timeline is displayed alongside the video.",
"Thank you for trying the beta, please go into as much detail as you can so we can improve it.": "Thank you for trying the beta, please go into as much detail as you can so we can improve it.",
"Explore public spaces in the new search dialog": "Explore public spaces in the new search dialog",
"Let moderators hide messages pending moderation.": "Let moderators hide messages pending moderation.",
"Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators",
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
Expand Down Expand Up @@ -2803,6 +2804,9 @@
"Use \"%(query)s\" to search": "Use \"%(query)s\" to search",
"Search for": "Search for",
"Spaces you're in": "Spaces you're in",
"Show rooms": "Show rooms",
"Show spaces": "Show spaces",
"You cannot search for rooms that are neither a room nor a space": "You cannot search for rooms that are neither a room nor a space",
"Other rooms in %(spaceName)s": "Other rooms in %(spaceName)s",
"Join %(roomAddress)s": "Join %(roomAddress)s",
"Some results may be hidden for privacy": "Some results may be hidden for privacy",
Expand Down
5 changes: 5 additions & 0 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ export const SETTINGS: {[setting: string]: ISetting} = {
requiresRefresh: true,
},
},
"feature_exploring_public_spaces": {
displayName: _td("Explore public spaces in the new search dialog"),
supportedLevels: LEVELS_FEATURE,
default: false,
},
"feature_msc3531_hide_messages_pending_moderation": {
isFeature: true,
labsGroup: LabGroup.Moderation,
Expand Down

0 comments on commit 663bca5

Please sign in to comment.