Add room topic to right panel room info (#12503)

* Add room topic to right panel room info

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tweak styles

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add snapshot tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2024-05-10 11:00:43 +01:00 committed by GitHub
parent 38893928cb
commit eee0b2a9c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1055 additions and 33 deletions

View file

@ -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>

View file

@ -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);
@ -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],
);

View file

@ -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";
@ -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";
@ -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;
@ -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);
@ -382,6 +475,8 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, on
</Badge>
)}
</Flex>
<RoomTopic room={room} />
</header>
);

View file

@ -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",