From 68852f30b55a669fc7f3a7cfce1bead63587fd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 15 Jun 2022 17:58:57 +0200 Subject: [PATCH 1/3] Properly handle `visibility` for spaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/spaces/SpaceCreateMenu.tsx | 11 +++++------ .../views/spaces/SpaceSettingsVisibilityTab.tsx | 6 +++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 3d0af8f6fc3..5b93d5e001b 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -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"; @@ -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, @@ -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, @@ -80,11 +84,6 @@ const SpaceCreateMenuType = ({ title, description, className, onClick }) => { ); }; -enum Visibility { - Public, - Private, -} - const spaceNameValidator = withValidation({ rules: [ { diff --git a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx index 690900c3b72..a59ad39f626 100644 --- a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx +++ b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx @@ -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; @@ -38,6 +39,9 @@ interface IProps { const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn }: IProps) => { const [error, setError] = useState(""); + const serverSupportsExploringSpaces = useAsyncMemo(async () => { + return cli.doesServerSupportUnstableFeature("org.matrix.msc3827"); + }, [cli], false); const userId = cli.getUserId(); @@ -103,7 +107,7 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn canSetCanonicalAlias={canSetCanonical} canSetAliases={true} canonicalAliasEvent={canonicalAliasEv} - hidePublishSetting={true} + hidePublishSetting={!serverSupportsExploringSpaces} /> ; } From 31a4986cb9c6f8310cbcd452703d82148e501bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 18 Jun 2022 13:31:44 +0200 Subject: [PATCH 2/3] Add UI for MSC3827 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/dialogs/_SpotlightDialog.scss | 5 ++ .../dialogs/spotlight/SpotlightDialog.tsx | 53 +++++++++++++++---- src/hooks/usePublicRoomDirectory.ts | 8 ++- src/i18n/strings/en_EN.json | 3 ++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/res/css/views/dialogs/_SpotlightDialog.scss b/res/css/views/dialogs/_SpotlightDialog.scss index 2b7674a2416..e8a2e22dce6 100644 --- a/res/css/views/dialogs/_SpotlightDialog.scss +++ b/res/css/views/dialogs/_SpotlightDialog.scss @@ -168,6 +168,11 @@ limitations under the License. justify-content: space-between; align-items: center; margin-bottom: 8px; + + .mx_SpotlightDialog_options { + display: flex; + gap: $spacing-4; + } } & + .mx_SpotlightDialog_section { diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 679f611696d..9af0e7182c0 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -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, { @@ -89,6 +89,7 @@ import { Option } from "./Option"; import { PublicRoomResultDetails } from "./PublicRoomResultDetails"; import { RoomResultDetails } from "./RoomResultDetails"; import { TooltipOption } from "./TooltipOption"; +import LabelledCheckbox from "../../elements/LabelledCheckbox"; const MAX_RECENT_SEARCHES = 10; const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons @@ -103,6 +104,18 @@ function refIsForRecentlyViewed(ref: RefObject): boolean { return ref.current?.id?.startsWith("mx_SpotlightDialog_button_recentlyViewed_") === true; } +function getRoomTypes(showRooms: boolean, showSpaces: boolean): Set | null { + const roomTypes = new Set(); + + // 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, @@ -279,12 +292,15 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n 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, @@ -624,15 +640,32 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n

{ _t("Suggestions") }

- -
-
- { results[Section.PublicRooms].slice(0, SECTION_LIMIT).map(resultMapper) } +
+ { cli.doesServerSupportUnstableFeature("org.matrix.msc3827") && <> + + + } + +
+
{ (showRooms || showSpaces) + ? results[Section.PublicRooms].slice(0, SECTION_LIMIT).map(resultMapper) + :
+ { _t("You cannot search for rooms that are neither a room nor a space") } +
+ }
); } diff --git a/src/hooks/usePublicRoomDirectory.ts b/src/hooks/usePublicRoomDirectory.ts index fd0b7643725..895c448834f 100644 --- a/src/hooks/usePublicRoomDirectory.ts +++ b/src/hooks/usePublicRoomDirectory.ts @@ -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"; @@ -32,6 +33,7 @@ const LAST_INSTANCE_KEY = "mx_last_room_directory_instance"; export interface IPublicRoomsOpts { limit: number; query?: string; + roomTypes?: Set; } let thirdParty: Protocols; @@ -72,6 +74,7 @@ export const usePublicRoomDirectory = () => { const search = useCallback(async ({ limit = 20, query, + roomTypes, }: IPublicRoomsOpts): Promise => { const opts: IRoomDirectoryOptions = { limit }; @@ -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(roomTypes) : null, }; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4e0042bbe36..5357b8f7280 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2803,6 +2803,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", From 6d73e3de1a1056e3d1a1dd1196d020e398420078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 18 Jun 2022 13:47:39 +0200 Subject: [PATCH 3/3] Hide MSC3827 behind a labs flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/dialogs/spotlight/SpotlightDialog.tsx | 2 +- .../settings/tabs/user/LabsUserSettingsTab.tsx | 15 +++++++++++++++ src/i18n/strings/en_EN.json | 1 + src/settings/Settings.tsx | 5 +++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 9af0e7182c0..31f1be68451 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -641,7 +641,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n

{ _t("Suggestions") }

- { cli.doesServerSupportUnstableFeature("org.matrix.msc3827") && <> + { SettingsStore.getValue("feature_exploring_public_spaces") && <> interface IState { showHiddenReadReceipts: boolean; showJumpToDate: boolean; + showExploringPublicSpaces: boolean; } export default class LabsUserSettingsTab extends React.Component<{}, IState> { @@ -63,9 +64,13 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { this.setState({ showJumpToDate }); }); + MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827"). + then((showExploringPublicSpaces) => this.setState({ showExploringPublicSpaces })); + this.state = { showHiddenReadReceipts: false, showJumpToDate: false, + showExploringPublicSpaces: false, }; } @@ -133,6 +138,16 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { ); } + if (this.state.showExploringPublicSpaces) { + groups.getOrCreate(LabGroup.Spaces, []).push( + , + ); + } + labsSections = <> { sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5357b8f7280..9982b505424 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -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", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 202a5037bdd..000b832cb08 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -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,