diff --git a/res/css/views/right_panel/_RoomSummaryCard.scss b/res/css/views/right_panel/_RoomSummaryCard.scss index 59b3588283..14e5dc654f 100644 --- a/res/css/views/right_panel/_RoomSummaryCard.scss +++ b/res/css/views/right_panel/_RoomSummaryCard.scss @@ -251,6 +251,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/files.svg'); } +.mx_RoomSummaryCard_icon_pins::before { + mask-image: url('$(res)/img/element-icons/room/pin-upright.svg'); +} + .mx_RoomSummaryCard_icon_threads::before { mask-image: url('$(res)/img/element-icons/message/thread.svg'); } diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index e11bde1f52..9253a25e32 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -213,6 +213,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/files.svg'); } + .mx_RoomTile_iconPins::before { + mask-image: url('$(res)/img/element-icons/room/pin-upright.svg'); + } + .mx_RoomTile_iconWidgets::before { mask-image: url('$(res)/img/element-icons/room/apps.svg'); } diff --git a/src/components/views/context_menus/RoomContextMenu.tsx b/src/components/views/context_menus/RoomContextMenu.tsx index 290b53c1d8..cc7a567f59 100644 --- a/src/components/views/context_menus/RoomContextMenu.tsx +++ b/src/components/views/context_menus/RoomContextMenu.tsx @@ -36,6 +36,8 @@ import { EchoChamber } from "../../../stores/local-echo/EchoChamber"; import { RoomNotifState } from "../../../RoomNotifs"; import Modal from "../../../Modal"; import ExportDialog from "../dialogs/ExportDialog"; +import { useSettingValue } from "../../../hooks/useSettings"; +import { usePinnedEvents } from "../right_panel/PinnedMessagesCard"; import RoomViewStore from "../../../stores/RoomViewStore"; import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases'; import { ROOM_NOTIFICATIONS_TAB } from "../dialogs/RoomSettingsDialog"; @@ -228,6 +230,29 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { />; } + const pinningEnabled = useSettingValue("feature_pinning"); + const pinCount = usePinnedEvents(pinningEnabled && room)?.length; + + let pinsOption: JSX.Element; + if (pinningEnabled) { + pinsOption = { + ev.preventDefault(); + ev.stopPropagation(); + + ensureViewingRoom(ev); + RightPanelStore.instance.pushCard({ phase: RightPanelPhases.PinnedMessages }, false); + onFinished(); + }} + label={_t("Pinned")} + iconClassName="mx_RoomTile_iconPins" + > + { pinCount > 0 && + { pinCount } + } + ; + } + const onTagRoom = (ev: ButtonEvent, tagId: TagID) => { ev.preventDefault(); ev.stopPropagation(); @@ -278,6 +303,8 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { iconClassName="mx_RoomTile_iconFiles" /> + { pinsOption } + { ev.preventDefault(); diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index acca6f935c..aa2a8ffd63 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -82,7 +82,7 @@ const PinnedMessagesHeaderButton = ({ room, isHighlighted, onClick }: IHeaderBut const pinningEnabled = useSettingValue("feature_pinning"); const pinnedEvents = usePinnedEvents(pinningEnabled && room); const readPinnedEvents = useReadPinnedEvents(pinningEnabled && room); - if (!pinningEnabled) return null; + if (!pinnedEvents?.length) return null; let unreadIndicator; if (pinnedEvents.some(id => !readPinnedEvents.has(id))) { diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index e3a4f3740f..5942d73bd6 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -42,6 +42,8 @@ import { UIFeature } from "../../../settings/UIFeature"; import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu"; import WidgetContextMenu from "../context_menus/WidgetContextMenu"; import { useRoomMemberCount } from "../../../hooks/useRoomMembers"; +import { useSettingValue } from "../../../hooks/useSettings"; +import { usePinnedEvents } from "./PinnedMessagesCard"; import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import RoomName from "../elements/RoomName"; import UIStore from "../../../stores/UIStore"; @@ -239,6 +241,10 @@ const onRoomFilesClick = () => { RightPanelStore.instance.pushCard({ phase: RightPanelPhases.FilePanel }, true); }; +const onRoomPinsClick = () => { + RightPanelStore.instance.pushCard({ phase: RightPanelPhases.PinnedMessages }, true); +}; + const onRoomSettingsClick = (ev: ButtonEvent) => { defaultDispatcher.dispatch({ action: "open_room_settings" }); PosthogTrackers.trackInteraction("WebRightPanelRoomInfoSettingsButton", ev); @@ -290,6 +296,8 @@ const RoomSummaryCard: React.FC = ({ room, onClose }) => { ; const memberCount = useRoomMemberCount(room); + const pinningEnabled = useSettingValue("feature_pinning"); + const pinCount = usePinnedEvents(pinningEnabled && room)?.length; return @@ -302,6 +310,12 @@ const RoomSummaryCard: React.FC = ({ room, onClose }) => { + { pinningEnabled && } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e70c96d984..7b8dfad5a7 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1961,6 +1961,7 @@ "Not encrypted": "Not encrypted", "About": "About", "Files": "Files", + "Pinned": "Pinned", "Export chat": "Export chat", "Share room": "Share room", "Room settings": "Room settings",