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:
parent
38893928cb
commit
eee0b2a9c3
18 changed files with 1055 additions and 33 deletions
|
@ -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>
|
||||
|
|
|
@ -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],
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue