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

Commit

Permalink
Add room topic to right panel room info (#12503)
Browse files Browse the repository at this point in the history
* Add room topic to right panel room info

Signed-off-by: Michael Telatynski <[email protected]>

* Tweak styles

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshot

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshots

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

* Add snapshot tests

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshots

Signed-off-by: Michael Telatynski <[email protected]>

---------

Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy authored May 10, 2024
1 parent 3889392 commit eee0b2a
Show file tree
Hide file tree
Showing 18 changed files with 1,057 additions and 35 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions res/css/views/right_panel/_BaseCard.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ limitations under the License.
min-height: 0;
width: 100%;
height: 100%;
scrollbar-gutter: stable;
}

.mx_BaseCard_Group {
Expand Down
46 changes: 46 additions & 0 deletions res/css/views/right_panel/_RoomSummaryCard.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,52 @@ limitations under the License.
}
}

.mx_RoomSummaryCard_topic {
padding: 0 12px;

.mx_Box {
width: 100%;
}

.mx_RoomSummaryCard_topic_container {
display: flex;
}

.mx_RoomSummaryCard_topic_edit {
width: max-content;
}

p {
white-space: pre-wrap;
width: 100%;
min-width: 0;
margin: 0;
}

a {
cursor: pointer;
}

.mx_RoomSummaryCard_topic_chevron {
transition: transform 0.3s;
}

&.mx_RoomSummaryCard_topic_collapsed {
p {
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}

.mx_RoomSummaryCard_topic_chevron {
transform: rotate(-90deg);
}
}
}

.mx_RoomSummaryCard_appsGroup {
.mx_RoomSummaryCard_Button {
/* this button is special so we have to override some of the original styling */
Expand Down
10 changes: 7 additions & 3 deletions src/HtmlUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,13 @@ export function topicToHtml(
emojiBodyElements = formatEmojis(topic, false);
}

return isFormattedTopic ? (
<span ref={ref} dangerouslySetInnerHTML={{ __html: safeTopic }} dir="auto" />
) : (
if (isFormattedTopic) {
if (!safeTopic) return null;
return <span ref={ref} dangerouslySetInnerHTML={{ __html: safeTopic }} dir="auto" />;
}

if (!emojiBodyElements && !topic) return null;
return (
<span ref={ref} dir="auto">
{emojiBodyElements || topic}
</span>
Expand Down
20 changes: 12 additions & 8 deletions src/components/views/elements/RoomTopic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ interface IProps extends React.HTMLProps<HTMLDivElement> {
room: Room;
}

export function onRoomTopicLinkClick(e: React.MouseEvent): void {
const anchor = e.target as HTMLLinkElement;
const localHref = tryTransformPermalinkToLocalHref(anchor.href);

if (localHref !== anchor.href) {
// it could be converted to a localHref -> therefore handle locally
e.preventDefault();
window.location.hash = localHref;
}
}

export default function RoomTopic({ room, className, ...props }: IProps): JSX.Element {
const client = useContext(MatrixClientContext);
const ref = useRef<HTMLDivElement>(null);
Expand All @@ -54,14 +65,7 @@ export default function RoomTopic({ room, className, ...props }: IProps): JSX.El
return;
}

const anchor = e.target as HTMLLinkElement;
const localHref = tryTransformPermalinkToLocalHref(anchor.href);

if (localHref !== anchor.href) {
// it could be converted to a localHref -> therefore handle locally
e.preventDefault();
window.location.hash = localHref;
}
onRoomTopicLinkClick(e);
},
[props],
);
Expand Down
99 changes: 97 additions & 2 deletions src/components/views/right_panel/RoomSummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
import React, { SyntheticEvent, useCallback, useContext, useEffect, useMemo, useState } from "react";
import classNames from "classnames";
import { MenuItem, Tooltip, Separator, ToggleMenuItem, Text, Badge, Heading } from "@vector-im/compound-web";
import {
MenuItem,
Tooltip,
Separator,
ToggleMenuItem,
Text,
Badge,
Heading,
IconButton,
Link,
} from "@vector-im/compound-web";
import { Icon as SearchIcon } from "@vector-im/compound-design-tokens/icons/search.svg";
import { Icon as FavouriteIcon } from "@vector-im/compound-design-tokens/icons/favourite.svg";
import { Icon as UserAddIcon } from "@vector-im/compound-design-tokens/icons/user-add.svg";
Expand All @@ -32,6 +42,7 @@ import { Icon as LockIcon } from "@vector-im/compound-design-tokens/icons/lock-s
import { Icon as LockOffIcon } from "@vector-im/compound-design-tokens/icons/lock-off.svg";
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
import { Icon as ChevronDownIcon } from "@vector-im/compound-design-tokens/icons/chevron-down.svg";
import { EventType, JoinRule, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";

import MatrixClientContext from "../../../contexts/MatrixClientContext";
Expand Down Expand Up @@ -74,6 +85,10 @@ import { canInviteTo } from "../../../utils/room/canInviteTo";
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
import { useAccountData } from "../../../hooks/useAccountData";
import { useRoomState } from "../../../hooks/useRoomState";
import { useTopic } from "../../../hooks/room/useTopic";
import { Linkify, topicToHtml } from "../../../HtmlUtils";
import { Box } from "../../utils/Box";
import { onRoomTopicLinkClick } from "../elements/RoomTopic";

interface IProps {
room: Room;
Expand Down Expand Up @@ -271,6 +286,84 @@ const onRoomSettingsClick = (ev: Event): void => {
PosthogTrackers.trackInteraction("WebRightPanelRoomInfoSettingsButton", ev);
};

const RoomTopic: React.FC<Pick<IProps, "room">> = ({ room }): JSX.Element | null => {
const [expanded, setExpanded] = useState(false);

const topic = useTopic(room);
const body = topicToHtml(topic?.text, topic?.html);

const onEditClick = (e: SyntheticEvent): void => {
e.preventDefault();
e.stopPropagation();
defaultDispatcher.dispatch({ action: "open_room_settings" });
};

if (!body) {
return (
<Flex
as="section"
direction="column"
justify="center"
gap="var(--cpd-space-2x)"
className="mx_RoomSummaryCard_topic"
>
<Box flex="1">
<Link kind="primary" onClick={onEditClick}>
<Text size="sm" weight="regular">
{_t("right_panel|add_topic")}
</Text>
</Link>
</Box>
</Flex>
);
}

const content = expanded ? <Linkify>{body}</Linkify> : body;
return (
<Flex
as="section"
direction="column"
justify="center"
gap="var(--cpd-space-2x)"
className={classNames("mx_RoomSummaryCard_topic", {
mx_RoomSummaryCard_topic_collapsed: !expanded,
})}
>
<Box flex="1" className="mx_RoomSummaryCard_topic_container">
<Text
size="sm"
weight="regular"
onClick={(ev: React.MouseEvent): void => {
if (ev.target instanceof HTMLAnchorElement) {
onRoomTopicLinkClick(ev);
return;
}
setExpanded(!expanded);
}}
>
{content}
</Text>
<IconButton
className="mx_RoomSummaryCard_topic_chevron"
size="24px"
onClick={() => setExpanded(!expanded)}
>
<ChevronDownIcon />
</IconButton>
</Box>
{expanded && (
<Box flex="1" className="mx_RoomSummaryCard_topic_edit">
<Link kind="primary" onClick={onEditClick}>
<Text size="sm" weight="regular">
{_t("action|edit")}
</Text>
</Link>
</Box>
)}
</Flex>
);
};

const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, onSearchClick }) => {
const cli = useContext(MatrixClientContext);

Expand Down Expand Up @@ -382,6 +475,8 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, on
</Badge>
)}
</Flex>

<RoomTopic room={room} />
</header>
);

Expand Down
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,7 @@
},
"right_panel": {
"add_integrations": "Add widgets, bridges & bots",
"add_topic": "Add topic",
"edit_integrations": "Edit widgets, bridges & bots",
"export_chat_button": "Export chat",
"files_button": "Files",
Expand Down
24 changes: 4 additions & 20 deletions test/components/structures/__snapshots__/RoomView-test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
>
<span
dir="auto"
/>
</div>
/>
</div>
</header>
<div
Expand Down Expand Up @@ -129,11 +125,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
>
<span
dir="auto"
/>
</div>
/>
</div>
</header>
<main
Expand Down Expand Up @@ -296,11 +288,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
>
<span
dir="auto"
/>
</div>
/>
</div>
</header>
<main
Expand Down Expand Up @@ -547,11 +535,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
dir="auto"
tabindex="0"
>
<span
dir="auto"
/>
</div>
/>
</div>
</header>
<main
Expand Down
34 changes: 34 additions & 0 deletions test/components/views/right_panel/RoomSummaryCard-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,40 @@ describe("<RoomSummaryCard />", () => {
expect(container).toMatchSnapshot();
});

it("renders the room topic in the summary", () => {
room.currentState.setStateEvents([
new MatrixEvent({
type: "m.room.topic",
room_id: roomId,
sender: userId,
content: {
topic: "This is the room's topic.",
},
state_key: "",
}),
]);
const { container } = getComponent();
expect(container).toMatchSnapshot();
});

it("has button to edit topic when expanded", () => {
room.currentState.setStateEvents([
new MatrixEvent({
type: "m.room.topic",
room_id: roomId,
sender: userId,
content: {
topic: "This is the room's topic.",
},
state_key: "",
}),
]);
const { container, getByText } = getComponent();
fireEvent.click(screen.getByText("This is the room's topic."));
expect(getByText("Edit")).toBeInTheDocument();
expect(container).toMatchSnapshot();
});

it("opens the search", async () => {
const onSearchClick = jest.fn();
const { getByLabelText } = getComponent({
Expand Down
Loading

0 comments on commit eee0b2a

Please sign in to comment.