Clean up SpaceHierarchy

This commit is contained in:
Michael Telatynski 2021-07-30 11:01:49 +01:00
parent d459dbe700
commit 259627fba2
5 changed files with 43 additions and 128 deletions

View file

@ -27,8 +27,8 @@
@import "./structures/_RoomView.scss"; @import "./structures/_RoomView.scss";
@import "./structures/_ScrollPanel.scss"; @import "./structures/_ScrollPanel.scss";
@import "./structures/_SearchBox.scss"; @import "./structures/_SearchBox.scss";
@import "./structures/_SpaceHierarchy.scss";
@import "./structures/_SpacePanel.scss"; @import "./structures/_SpacePanel.scss";
@import "./structures/_SpaceRoomDirectory.scss";
@import "./structures/_SpaceRoomView.scss"; @import "./structures/_SpaceRoomView.scss";
@import "./structures/_TabbedView.scss"; @import "./structures/_TabbedView.scss";
@import "./structures/_ToastContainer.scss"; @import "./structures/_ToastContainer.scss";

View file

@ -14,21 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
.mx_SpaceRoomDirectory_dialogWrapper > .mx_Dialog {
max-width: 960px;
height: 100%;
}
.mx_SpaceRoomDirectory {
height: 100%;
margin-bottom: 12px;
color: $primary-fg-color;
word-break: break-word;
display: flex;
flex-direction: column;
}
.mx_SpaceRoomDirectory,
.mx_SpaceRoomView_landing { .mx_SpaceRoomView_landing {
.mx_Dialog_title { .mx_Dialog_title {
display: flex; display: flex;
@ -67,7 +52,7 @@ limitations under the License.
margin: 24px 0 16px; margin: 24px 0 16px;
} }
.mx_SpaceRoomDirectory_noResults { .mx_SpaceHierarchy_noResults {
text-align: center; text-align: center;
> div { > div {
@ -77,7 +62,7 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_listHeader { .mx_SpaceHierarchy_listHeader {
display: flex; display: flex;
min-height: 32px; min-height: 32px;
align-items: center; align-items: center;
@ -104,7 +89,7 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_error { .mx_SpaceHierarchy_error {
position: relative; position: relative;
font-weight: $font-semi-bold; font-weight: $font-semi-bold;
color: $notice-primary-color; color: $notice-primary-color;
@ -123,13 +108,8 @@ limitations under the License.
background-image: url("$(res)/img/element-icons/warning-badge.svg"); background-image: url("$(res)/img/element-icons/warning-badge.svg");
} }
} }
}
.mx_SpaceRoomDirectory_list { .mx_SpaceHierarchy_roomCount {
margin-top: 16px;
padding-bottom: 40px;
.mx_SpaceRoomDirectory_roomCount {
> h3 { > h3 {
display: inline; display: inline;
font-weight: $font-semi-bold; font-weight: $font-semi-bold;
@ -146,13 +126,13 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_subspace { .mx_SpaceHierarchy_subspace {
.mx_BaseAvatar_image { .mx_BaseAvatar_image {
border-radius: 8px; border-radius: 8px;
} }
} }
.mx_SpaceRoomDirectory_subspace_toggle { .mx_SpaceHierarchy_subspace_toggle {
position: absolute; position: absolute;
left: -1px; left: -1px;
top: 10px; top: 10px;
@ -176,17 +156,17 @@ limitations under the License.
mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
} }
&.mx_SpaceRoomDirectory_subspace_toggle_shown::before { &.mx_SpaceHierarchy_subspace_toggle_shown::before {
transform: rotate(0deg); transform: rotate(0deg);
} }
} }
.mx_SpaceRoomDirectory_subspace_children { .mx_SpaceHierarchy_subspace_children {
position: relative; position: relative;
padding-left: 12px; padding-left: 12px;
} }
.mx_SpaceRoomDirectory_roomTile { .mx_SpaceHierarchy_roomTile {
position: relative; position: relative;
padding: 8px 16px; padding: 8px 16px;
border-radius: 8px; border-radius: 8px;
@ -203,7 +183,7 @@ limitations under the License.
grid-column: 1; grid-column: 1;
} }
.mx_SpaceRoomDirectory_roomTile_name { .mx_SpaceHierarchy_roomTile_name {
font-weight: $font-semi-bold; font-weight: $font-semi-bold;
font-size: $font-15px; font-size: $font-15px;
line-height: $font-18px; line-height: $font-18px;
@ -231,7 +211,7 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_roomTile_info { .mx_SpaceHierarchy_roomTile_info {
font-size: $font-14px; font-size: $font-14px;
line-height: $font-18px; line-height: $font-18px;
color: $secondary-fg-color; color: $secondary-fg-color;
@ -243,7 +223,7 @@ limitations under the License.
overflow: hidden; overflow: hidden;
} }
.mx_SpaceRoomDirectory_actions { .mx_SpaceHierarchy_actions {
text-align: right; text-align: right;
margin-left: 20px; margin-left: 20px;
grid-column: 3; grid-column: 3;
@ -277,8 +257,8 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_roomTile, .mx_SpaceHierarchy_roomTile,
.mx_SpaceRoomDirectory_subspace_children { .mx_SpaceHierarchy_subspace_children {
&::before { &::before {
content: ""; content: "";
position: absolute; position: absolute;
@ -290,8 +270,8 @@ limitations under the License.
} }
} }
.mx_SpaceRoomDirectory_actions { .mx_SpaceHierarchy_actions {
.mx_SpaceRoomDirectory_actionsText { .mx_SpaceHierarchy_actionsText {
font-weight: normal; font-weight: normal;
font-size: $font-12px; font-size: $font-12px;
line-height: $font-15px; line-height: $font-15px;
@ -306,7 +286,7 @@ limitations under the License.
margin: 20px 0; margin: 20px 0;
} }
.mx_SpaceRoomDirectory_createRoom { .mx_SpaceHierarchy_createRoom {
display: block; display: block;
margin: 16px auto 0; margin: 16px auto 0;
width: max-content; width: max-content;

View file

@ -354,11 +354,6 @@ $SpaceRoomViewInnerWidth: 428px;
display: none; display: none;
} }
} }
.mx_SpaceRoomDirectory_list {
// we don't want this container to get forced into the flexbox layout
display: contents;
}
} }
.mx_SpaceRoomView_privateScope { .mx_SpaceRoomView_privateScope {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy";
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event"; import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
@ -27,13 +27,10 @@ import dis from "../../dispatcher/dispatcher";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
import BaseDialog from "../views/dialogs/BaseDialog";
import Spinner from "../views/elements/Spinner"; import Spinner from "../views/elements/Spinner";
import SearchBox from "./SearchBox"; import SearchBox from "./SearchBox";
import RoomAvatar from "../views/avatars/RoomAvatar"; import RoomAvatar from "../views/avatars/RoomAvatar";
import RoomName from "../views/elements/RoomName";
import StyledCheckbox from "../views/elements/StyledCheckbox"; import StyledCheckbox from "../views/elements/StyledCheckbox";
import AutoHideScrollbar from "./AutoHideScrollbar";
import BaseAvatar from "../views/avatars/BaseAvatar"; import BaseAvatar from "../views/avatars/BaseAvatar";
import { mediaFromMxc } from "../../customisations/Media"; import { mediaFromMxc } from "../../customisations/Media";
import InfoTooltip from "../views/elements/InfoTooltip"; import InfoTooltip from "../views/elements/InfoTooltip";
@ -46,7 +43,7 @@ import { useDispatcher } from "../../hooks/useDispatcher";
import { Action } from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import { getDisplayAliasForRoom } from "./RoomDirectory"; import { getDisplayAliasForRoom } from "./RoomDirectory";
interface IHierarchyProps { interface IProps {
space: Room; space: Room;
initialText?: string; initialText?: string;
additionalButtons?: ReactNode; additionalButtons?: ReactNode;
@ -148,13 +145,13 @@ const Tile: React.FC<ITileProps> = ({
const content = <React.Fragment> const content = <React.Fragment>
{ avatar } { avatar }
<div className="mx_SpaceRoomDirectory_roomTile_name"> <div className="mx_SpaceHierarchy_roomTile_name">
{ name } { name }
{ suggestedSection } { suggestedSection }
</div> </div>
<div <div
className="mx_SpaceRoomDirectory_roomTile_info" className="mx_SpaceHierarchy_roomTile_info"
ref={e => e && linkifyElement(e)} ref={e => e && linkifyElement(e)}
onClick={ev => { onClick={ev => {
// prevent clicks on links from bubbling up to the room tile // prevent clicks on links from bubbling up to the room tile
@ -165,7 +162,7 @@ const Tile: React.FC<ITileProps> = ({
> >
{ description } { description }
</div> </div>
<div className="mx_SpaceRoomDirectory_actions"> <div className="mx_SpaceHierarchy_actions">
{ button } { button }
{ checkbox } { checkbox }
</div> </div>
@ -176,8 +173,8 @@ const Tile: React.FC<ITileProps> = ({
if (children) { if (children) {
// the chevron is purposefully a div rather than a button as it should be ignored for a11y // the chevron is purposefully a div rather than a button as it should be ignored for a11y
childToggle = <div childToggle = <div
className={classNames("mx_SpaceRoomDirectory_subspace_toggle", { className={classNames("mx_SpaceHierarchy_subspace_toggle", {
mx_SpaceRoomDirectory_subspace_toggle_shown: showChildren, mx_SpaceHierarchy_subspace_toggle_shown: showChildren,
})} })}
onClick={ev => { onClick={ev => {
ev.stopPropagation(); ev.stopPropagation();
@ -185,7 +182,7 @@ const Tile: React.FC<ITileProps> = ({
}} }}
/>; />;
if (showChildren) { if (showChildren) {
childSection = <div className="mx_SpaceRoomDirectory_subspace_children"> childSection = <div className="mx_SpaceHierarchy_subspace_children">
{ children } { children }
</div>; </div>;
} }
@ -193,8 +190,8 @@ const Tile: React.FC<ITileProps> = ({
return <> return <>
<AccessibleButton <AccessibleButton
className={classNames("mx_SpaceRoomDirectory_roomTile", { className={classNames("mx_SpaceHierarchy_roomTile", {
mx_SpaceRoomDirectory_subspace: room.room_type === RoomType.Space, mx_SpaceHierarchy_subspace: room.room_type === RoomType.Space,
})} })}
onClick={(hasPermissions && onToggleClick) ? onToggleClick : onPreviewClick} onClick={(hasPermissions && onToggleClick) ? onToggleClick : onPreviewClick}
> >
@ -319,6 +316,8 @@ export const HierarchyLevel = ({
</React.Fragment>; </React.Fragment>;
}; };
const INITIAL_PAGE_SIZE = 20;
export const useSpaceSummary = (space: Room): { export const useSpaceSummary = (space: Room): {
loading: boolean; loading: boolean;
rooms: IHierarchyRoom[]; rooms: IHierarchyRoom[];
@ -327,8 +326,6 @@ export const useSpaceSummary = (space: Room): {
} => { } => {
const [rooms, setRooms] = useState<IHierarchyRoom[]>([]); const [rooms, setRooms] = useState<IHierarchyRoom[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const INITIAL_PAGE_SIZE = 20;
const [hierarchy, setHierarchy] = useState<RoomHierarchy>(); const [hierarchy, setHierarchy] = useState<RoomHierarchy>();
const resetHierarchy = useCallback(() => { const resetHierarchy = useCallback(() => {
@ -368,13 +365,12 @@ export const useSpaceSummary = (space: Room): {
return { loading, rooms, hierarchy, loadMore }; return { loading, rooms, hierarchy, loadMore };
}; };
export const SpaceHierarchy: React.FC<IHierarchyProps> = ({ const SpaceHierarchy = ({
space, space,
initialText = "", initialText = "",
showRoom, showRoom,
additionalButtons, additionalButtons,
children, }: IProps) => {
}) => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const userId = cli.getUserId(); const userId = cli.getUserId();
const [query, setQuery] = useState(initialText); const [query, setQuery] = useState(initialText);
@ -416,7 +412,8 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
return <p>{ _t("Your server does not support showing space hierarchies.") }</p>; return <p>{ _t("Your server does not support showing space hierarchies.") }</p>;
} }
let content; let content: JSX.Element;
let loader: JSX.Element;
if (loading) { if (loading) {
content = <Spinner />; content = <Spinner />;
} else { } else {
@ -513,7 +510,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
</>; </>;
} }
let results; let results: JSX.Element;
if (filteredRoomSet.size) { if (filteredRoomSet.size) {
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
@ -544,34 +541,31 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
showRoom(hierarchy, roomId, autoJoin); showRoom(hierarchy, roomId, autoJoin);
}} }}
/> />
{ children && <hr /> }
</>; </>;
} else { } else {
results = <div className="mx_SpaceRoomDirectory_noResults"> results = <div className="mx_SpaceHierarchy_noResults">
<h3>{ _t("No results found") }</h3> <h3>{ _t("No results found") }</h3>
<div>{ _t("You may want to try a different search or check for typos.") }</div> <div>{ _t("You may want to try a different search or check for typos.") }</div>
</div>; </div>;
} }
content = <> content = <>
<div className="mx_SpaceRoomDirectory_listHeader"> <div className="mx_SpaceHierarchy_listHeader">
{ countsStr } { countsStr }
<span> <span>
{ additionalButtons } { additionalButtons }
{ manageButtons } { manageButtons }
</span> </span>
</div> </div>
{ error && <div className="mx_SpaceRoomDirectory_error"> { error && <div className="mx_SpaceHierarchy_error">
{ error } { error }
</div> } </div> }
<AutoHideScrollbar className="mx_SpaceRoomDirectory_list">
{ results } { results }
{ children } { loader }
</AutoHideScrollbar>
</>; </>;
} }
// TODO loading state/error state
return <> return <>
<SearchBox <SearchBox
className="mx_textinput_icon mx_textinput_search" className="mx_textinput_icon mx_textinput_search"
@ -585,58 +579,4 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
</>; </>;
}; };
interface IProps { export default SpaceHierarchy;
space: Room;
initialText?: string;
onFinished(): void;
}
const SpaceRoomDirectory: React.FC<IProps> = ({ space, onFinished, initialText }) => {
const onCreateRoomClick = () => {
dis.dispatch({
action: 'view_create_room',
public: true,
});
onFinished();
};
const title = <React.Fragment>
<RoomAvatar room={space} height={32} width={32} />
<div>
<h1>{ _t("Explore rooms") }</h1>
<div><RoomName room={space} /></div>
</div>
</React.Fragment>;
return (
<BaseDialog className="mx_SpaceRoomDirectory" hasCancel={true} onFinished={onFinished} title={title}>
<div className="mx_Dialog_content">
{ _t("If you can't find the room you're looking for, ask for an invite or <a>create a new room</a>.",
null,
{ a: sub => {
return <AccessibleButton kind="link" onClick={onCreateRoomClick}>{ sub }</AccessibleButton>;
} },
) }
<SpaceHierarchy
space={space}
showRoom={(hierarchy: RoomHierarchy, roomId: string, autoJoin = false) => {
showRoom(hierarchy, roomId, autoJoin);
onFinished();
}}
initialText={initialText}
>
<AccessibleButton
onClick={onCreateRoomClick}
kind="primary"
className="mx_SpaceRoomDirectory_createRoom"
>
{ _t("Create room") }
</AccessibleButton>
</SpaceHierarchy>
</div>
</BaseDialog>
);
};
export default SpaceRoomDirectory;

View file

@ -54,7 +54,7 @@ import {
showCreateNewSubspace, showCreateNewSubspace,
showSpaceSettings, showSpaceSettings,
} from "../../utils/space"; } from "../../utils/space";
import { showRoom, SpaceHierarchy } from "./SpaceRoomDirectory"; import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
import MemberAvatar from "../views/avatars/MemberAvatar"; import MemberAvatar from "../views/avatars/MemberAvatar";
import SpaceStore from "../../stores/SpaceStore"; import SpaceStore from "../../stores/SpaceStore";
import FacePile from "../views/elements/FacePile"; import FacePile from "../views/elements/FacePile";