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

Implement MSC3827: Filtering of /publicRooms by room type #8866

Merged
merged 6 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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