Improve icon rendering in iconized context menu (#31458)
* Fix composer button visibility in contrast colour mode Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate 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> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve icon rendering in iconized context menu Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
committed by
GitHub
parent
4fda167c11
commit
efe59ff35f
@@ -10,6 +10,7 @@ import { EventType, RoomType, JoinRule, Preset, type Room, RoomEvent } from "mat
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import React, { type JSX, useCallback, useContext, useRef, useState } from "react";
|
||||
import { PlusIcon, RoomIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import createRoom, { type IOpts } from "../../createRoom";
|
||||
@@ -66,6 +67,7 @@ import MainSplit from "./MainSplit";
|
||||
import RightPanel from "./RightPanel";
|
||||
import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
|
||||
import { type RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||
import { Icon as HashVideoIcon } from "../../../res/img/element-icons/roomlist/hash-video.svg";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
@@ -117,7 +119,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewRoom"
|
||||
icon={<PlusIcon />}
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -132,7 +134,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
|
||||
icon={<HashVideoIcon />}
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -157,7 +159,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
||||
)}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconAddExistingRoom"
|
||||
icon={<RoomIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -168,7 +170,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
||||
{canCreateSpace && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("room_list|add_space_label")}
|
||||
iconClassName="mx_LegacyRoomList_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -8,6 +8,13 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { type JSX, createRef, type ReactNode } from "react";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
HomeSolidIcon,
|
||||
LockSolidIcon,
|
||||
QrCodeIcon,
|
||||
SettingsSolidIcon,
|
||||
LeaveIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
@@ -42,7 +49,9 @@ import PosthogTrackers from "../../PosthogTrackers";
|
||||
import { type ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
|
||||
import { SDKContext } from "../../contexts/SDKContext";
|
||||
import { shouldShowFeedback } from "../../utils/Feedback";
|
||||
import DarkLightModeSvg from "../../../res/img/element-icons/roomlist/dark-light-mode.svg";
|
||||
import { Icon as DarkLightModeSvg } from "../../../res/img/element-icons/roomlist/dark-light-mode.svg";
|
||||
import { Icon as NotificationsIcon } from "../../../res/img/element-icons/notifications.svg";
|
||||
import { Icon as FeedbackIcon } from "../../../res/img/element-icons/feedback.svg";
|
||||
|
||||
interface IProps {
|
||||
isPanelCollapsed: boolean;
|
||||
@@ -297,7 +306,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
if (this.hasHomePage) {
|
||||
homeButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconHome"
|
||||
icon={<HomeSolidIcon />}
|
||||
label={_t("common|home")}
|
||||
onClick={this.onHomeClick}
|
||||
/>
|
||||
@@ -308,7 +317,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
if (shouldShowFeedback()) {
|
||||
feedbackButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconMessage"
|
||||
icon={<FeedbackIcon />}
|
||||
label={_t("common|feedback")}
|
||||
onClick={this.onProvideFeedback}
|
||||
/>
|
||||
@@ -317,7 +326,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
|
||||
const linkNewDeviceButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconQr"
|
||||
icon={<QrCodeIcon />}
|
||||
label={_t("user_menu|link_new_device")}
|
||||
onClick={(e) => this.onSettingsOpen(e, UserTab.SessionManager, { showMsc4108QrCode: true })}
|
||||
/>
|
||||
@@ -328,24 +337,24 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
{homeButton}
|
||||
{linkNewDeviceButton}
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconBell"
|
||||
icon={<NotificationsIcon />}
|
||||
label={_t("notifications|enable_prompt_toast_title")}
|
||||
onClick={(e) => this.onSettingsOpen(e, UserTab.Notifications)}
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconLock"
|
||||
icon={<LockSolidIcon />}
|
||||
label={_t("room_settings|security|title")}
|
||||
onClick={(e) => this.onSettingsOpen(e, UserTab.Security)}
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconSettings"
|
||||
icon={<SettingsSolidIcon />}
|
||||
label={_t("user_menu|settings")}
|
||||
onClick={(e) => this.onSettingsOpen(e)}
|
||||
/>
|
||||
{feedbackButton}
|
||||
<IconizedContextMenuOption
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
iconClassName="mx_UserMenu_iconSignOut"
|
||||
icon={<LeaveIcon />}
|
||||
label={_t("action|sign_out")}
|
||||
onClick={this.onSignOutClick}
|
||||
/>
|
||||
@@ -357,7 +366,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
<IconizedContextMenuOptionList>
|
||||
{homeButton}
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_UserMenu_iconSettings"
|
||||
icon={<SettingsSolidIcon />}
|
||||
label={_t("common|settings")}
|
||||
onClick={(e) => this.onSettingsOpen(e)}
|
||||
/>
|
||||
@@ -398,7 +407,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||
: _t("user_menu|switch_theme_dark")
|
||||
}
|
||||
>
|
||||
<img src={DarkLightModeSvg} role="presentation" alt="" width={16} />
|
||||
<DarkLightModeSvg width="16px" height="16px" />
|
||||
</RovingAccessibleButton>
|
||||
</div>
|
||||
{topSection}
|
||||
|
||||
@@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { LabsIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import Modal from "../../../Modal";
|
||||
import DevtoolsDialog from "../dialogs/DevtoolsDialog";
|
||||
@@ -32,7 +33,7 @@ export const DeveloperToolsOption: React.FC<Props> = ({ onFinished, roomId }) =>
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("devtools|title")}
|
||||
iconClassName="mx_IconizedContextMenu_developerTools"
|
||||
icon={<LabsIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,14 +26,7 @@ interface IDeviceContextMenuDeviceProps {
|
||||
}
|
||||
|
||||
const DeviceContextMenuDevice: React.FC<IDeviceContextMenuDeviceProps> = ({ label, selected, onClick }) => {
|
||||
return (
|
||||
<IconizedContextMenuRadio
|
||||
iconClassName="mx_DeviceContextMenu_device_icon"
|
||||
label={label}
|
||||
active={selected}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
return <IconizedContextMenuRadio label={label} active={selected} onClick={onClick} />;
|
||||
};
|
||||
|
||||
interface IDeviceContextMenuSectionProps {
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { type JSX, type ReactNode } from "react";
|
||||
import classNames from "classnames";
|
||||
import { CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import ContextMenu, {
|
||||
ChevronFace,
|
||||
@@ -33,26 +34,19 @@ interface IOptionListProps {
|
||||
|
||||
interface IOptionProps extends React.ComponentProps<typeof MenuItem> {
|
||||
icon?: ReactNode;
|
||||
iconClassName?: string;
|
||||
isDestructive?: boolean;
|
||||
}
|
||||
|
||||
interface ICheckboxProps extends React.ComponentProps<typeof MenuItemCheckbox> {
|
||||
iconClassName: string;
|
||||
icon?: ReactNode;
|
||||
words?: boolean;
|
||||
}
|
||||
|
||||
interface IRadioProps extends React.ComponentProps<typeof MenuItemRadio> {
|
||||
iconClassName?: string;
|
||||
icon?: ReactNode;
|
||||
}
|
||||
|
||||
export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({
|
||||
label,
|
||||
iconClassName,
|
||||
active,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({ label, icon, active, className, ...props }) => {
|
||||
return (
|
||||
<MenuItemRadio
|
||||
{...props}
|
||||
@@ -63,35 +57,28 @@ export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({
|
||||
active={active}
|
||||
label={label}
|
||||
>
|
||||
{iconClassName && <span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />}
|
||||
{icon}
|
||||
<span className="mx_IconizedContextMenu_label">{label}</span>
|
||||
{active && <span className="mx_IconizedContextMenu_icon mx_IconizedContextMenu_checked" />}
|
||||
{active && <CheckIcon className="mx_IconizedContextMenu_checked" />}
|
||||
</MenuItemRadio>
|
||||
);
|
||||
};
|
||||
|
||||
export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
|
||||
label,
|
||||
iconClassName,
|
||||
icon,
|
||||
active,
|
||||
className,
|
||||
words,
|
||||
...props
|
||||
}) => {
|
||||
let marker: JSX.Element;
|
||||
let marker: JSX.Element | undefined;
|
||||
if (words) {
|
||||
marker = (
|
||||
<span className="mx_IconizedContextMenu_activeText">{active ? _t("common|on") : _t("common|off")}</span>
|
||||
);
|
||||
} else {
|
||||
marker = (
|
||||
<span
|
||||
className={classNames("mx_IconizedContextMenu_icon", {
|
||||
mx_IconizedContextMenu_checked: active,
|
||||
mx_IconizedContextMenu_unchecked: !active,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
} else if (active) {
|
||||
marker = <CheckIcon className="mx_IconizedContextMenu_checked" />;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -104,7 +91,7 @@ export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
|
||||
active={active}
|
||||
label={label}
|
||||
>
|
||||
<span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />
|
||||
{icon}
|
||||
<span className="mx_IconizedContextMenu_label">{label}</span>
|
||||
{marker}
|
||||
</MenuItemCheckbox>
|
||||
@@ -114,7 +101,6 @@ export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
|
||||
export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
|
||||
label,
|
||||
className,
|
||||
iconClassName,
|
||||
icon,
|
||||
children,
|
||||
isDestructive,
|
||||
@@ -130,7 +116,6 @@ export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
|
||||
})}
|
||||
label={label}
|
||||
>
|
||||
{iconClassName && <span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />}
|
||||
{icon}
|
||||
<span className="mx_IconizedContextMenu_label">{label}</span>
|
||||
{children}
|
||||
|
||||
@@ -20,6 +20,27 @@ import {
|
||||
Thread,
|
||||
M_POLL_START,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
CheckIcon,
|
||||
ChevronUpIcon,
|
||||
EditIcon,
|
||||
ErrorSolidIcon,
|
||||
InlineCodeIcon,
|
||||
LinkIcon,
|
||||
PinIcon,
|
||||
QuoteIcon,
|
||||
ReactionAddIcon,
|
||||
ReplyIcon,
|
||||
RestartIcon,
|
||||
ThreadsIcon,
|
||||
UnpinIcon,
|
||||
DeleteIcon,
|
||||
ForwardIcon,
|
||||
PopOutIcon,
|
||||
VisibilityOnIcon,
|
||||
ShareIcon,
|
||||
CopyIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
@@ -53,6 +74,8 @@ import { type ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadP
|
||||
import { CardContext } from "../right_panel/context";
|
||||
import PinningUtils from "../../../utils/PinningUtils";
|
||||
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||
import { Icon as ViewInRoomIcon } from "../../../../res/img/element-icons/view-in-room.svg";
|
||||
import { Icon as ChildRelationshipIcon } from "../../../../res/img/element-icons/child-relationship.svg";
|
||||
|
||||
interface IReplyInThreadButton {
|
||||
mxEvent: MatrixEvent;
|
||||
@@ -86,13 +109,7 @@ const ReplyInThreadButton: React.FC<IReplyInThreadButton> = ({ mxEvent, closeMen
|
||||
closeMenu();
|
||||
};
|
||||
|
||||
return (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconReplyInThread"
|
||||
label={_t("action|reply_in_thread")}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
return <IconizedContextMenuOption icon={<ThreadsIcon />} label={_t("action|reply_in_thread")} onClick={onClick} />;
|
||||
};
|
||||
|
||||
interface IProps extends MenuProps {
|
||||
@@ -413,7 +430,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (!mxEvent.isRedacted() && unsentReactionsCount !== 0) {
|
||||
resendReactionsButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconResend"
|
||||
icon={<RestartIcon />}
|
||||
label={_t("timeline|context_menu|resent_unsent_reactions", { unsentCount: unsentReactionsCount })}
|
||||
onClick={this.onResendReactionsClick}
|
||||
/>
|
||||
@@ -424,7 +441,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (isSent && this.state.canRedact) {
|
||||
redactButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconRedact"
|
||||
icon={<DeleteIcon />}
|
||||
label={_t("action|remove")}
|
||||
onClick={this.onRedactClick}
|
||||
/>
|
||||
@@ -437,7 +454,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
const mapSiteLink = createMapSiteLinkFromEvent(shareableLocationEvent);
|
||||
openInMapSiteButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconOpenInMapSite"
|
||||
icon={<PopOutIcon />}
|
||||
onClick={null}
|
||||
label={_t("timeline|context_menu|open_in_osm")}
|
||||
element="a"
|
||||
@@ -455,7 +472,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (contentActionable && forwardableEvent) {
|
||||
forwardButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconForward"
|
||||
icon={<ForwardIcon />}
|
||||
label={_t("action|forward")}
|
||||
onClick={this.onForwardClick(forwardableEvent)}
|
||||
/>
|
||||
@@ -465,7 +482,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
// This is specifically not behind the developerMode flag to give people insight into the Matrix
|
||||
const viewSourceButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconSource"
|
||||
icon={<InlineCodeIcon />}
|
||||
label={_t("timeline|context_menu|view_source")}
|
||||
onClick={this.onViewSourceClick}
|
||||
/>
|
||||
@@ -475,7 +492,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (eventTileOps?.isWidgetHidden()) {
|
||||
unhidePreviewButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconUnhidePreview"
|
||||
icon={<VisibilityOnIcon />}
|
||||
label={_t("timeline|context_menu|show_url_preview")}
|
||||
onClick={this.onUnhidePreviewClick}
|
||||
/>
|
||||
@@ -486,7 +503,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (permalink) {
|
||||
permalinkButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconPermalink"
|
||||
icon={<ShareIcon />}
|
||||
onClick={this.onShareClick}
|
||||
label={_t("action|share")}
|
||||
element="a"
|
||||
@@ -506,7 +523,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (this.canEndPoll(mxEvent)) {
|
||||
endPollButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconEndPoll"
|
||||
icon={<CheckIcon />}
|
||||
label={_t("poll|end_title")}
|
||||
onClick={this.onEndPollClick}
|
||||
/>
|
||||
@@ -521,7 +538,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
) {
|
||||
externalURLButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconLink"
|
||||
icon={<LinkIcon />}
|
||||
onClick={this.closeMenu}
|
||||
label={_t("timeline|context_menu|external_url")}
|
||||
element="a"
|
||||
@@ -541,7 +558,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (collapseReplyChain) {
|
||||
collapseReplyChainButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconCollapse"
|
||||
icon={<ChevronUpIcon />}
|
||||
label={_t("timeline|context_menu|collapse_reply_thread")}
|
||||
onClick={this.onCollapseReplyChainClick}
|
||||
/>
|
||||
@@ -553,7 +570,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (relatedEventId && SettingsStore.getValue("developerMode")) {
|
||||
jumpToRelatedEventButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_jumpToEvent"
|
||||
icon={<ChildRelationshipIcon />}
|
||||
label={_t("timeline|context_menu|view_related_event")}
|
||||
onClick={() => this.onJumpToRelatedEventClick(relatedEventId)}
|
||||
/>
|
||||
@@ -564,7 +581,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (mxEvent.getSender() !== me) {
|
||||
reportEventButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconReport"
|
||||
icon={<ErrorSolidIcon />}
|
||||
label={_t("timeline|context_menu|report")}
|
||||
onClick={this.onReportEventClick}
|
||||
/>
|
||||
@@ -575,7 +592,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (link) {
|
||||
copyLinkButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconCopy"
|
||||
icon={<CopyIcon />}
|
||||
onClick={this.onCopyLinkClick}
|
||||
label={_t("action|copy_link")}
|
||||
element="a"
|
||||
@@ -597,7 +614,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (rightClick && selectedText) {
|
||||
copyButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconCopy"
|
||||
icon={<CopyIcon />}
|
||||
label={_t("action|copy")}
|
||||
triggerOnMouseDown={true} // We use onMouseDown so that the selection isn't cleared when we click
|
||||
onClick={this.onCopyClick}
|
||||
@@ -609,7 +626,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (rightClick && selectedText && selectedText.trim().length > 0 && this.isSelectionWithinSingleTextBody()) {
|
||||
quoteButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconQuote"
|
||||
icon={<QuoteIcon />}
|
||||
label={_t("action|quote")}
|
||||
triggerOnMouseDown={true}
|
||||
onClick={this.onQuoteClick}
|
||||
@@ -620,11 +637,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
let editButton: JSX.Element | undefined;
|
||||
if (rightClick && canEditContent(cli, mxEvent)) {
|
||||
editButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconEdit"
|
||||
label={_t("action|edit")}
|
||||
onClick={this.onEditClick}
|
||||
/>
|
||||
<IconizedContextMenuOption icon={<EditIcon />} label={_t("action|edit")} onClick={this.onEditClick} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -632,7 +645,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (rightClick && contentActionable && canSendMessages) {
|
||||
replyButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconReply"
|
||||
icon={<ReplyIcon />}
|
||||
label={_t("action|reply")}
|
||||
onClick={this.onReplyClick}
|
||||
/>
|
||||
@@ -654,7 +667,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (rightClick && contentActionable && canReact) {
|
||||
reactButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconReact"
|
||||
icon={<ReactionAddIcon />}
|
||||
label={_t("action|react")}
|
||||
onClick={this.onReactClick}
|
||||
inputRef={this.reactButtonRef}
|
||||
@@ -667,7 +680,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
const isPinned = PinningUtils.isPinned(MatrixClientPeg.safeGet(), this.props.mxEvent);
|
||||
pinButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName={isPinned ? "mx_MessageContextMenu_iconUnpin" : "mx_MessageContextMenu_iconPin"}
|
||||
icon={isPinned ? <UnpinIcon /> : <PinIcon />}
|
||||
label={isPinned ? _t("action|unpin") : _t("action|pin")}
|
||||
onClick={() => this.onPinClick(isPinned)}
|
||||
/>
|
||||
@@ -678,7 +691,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||
if (isThreadRootEvent) {
|
||||
viewInRoomButton = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_MessageContextMenu_iconViewInRoom"
|
||||
icon={<ViewInRoomIcon />}
|
||||
label={_t("timeline|mab|view_in_room")}
|
||||
onClick={this.viewInRoom}
|
||||
/>
|
||||
|
||||
@@ -9,6 +9,15 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import React, { type JSX, useContext } from "react";
|
||||
import {
|
||||
FavouriteSolidIcon,
|
||||
LinkIcon,
|
||||
SettingsSolidIcon,
|
||||
ArrowDownIcon,
|
||||
MarkAsReadIcon,
|
||||
MarkAsUnreadIcon,
|
||||
LeaveIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||
import RoomListActions from "../../../actions/RoomListActions";
|
||||
@@ -34,6 +43,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import { DeveloperToolsOption } from "./DeveloperToolsOption";
|
||||
import { useSettingValue } from "../../../hooks/useSettings";
|
||||
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
|
||||
|
||||
export interface RoomGeneralContextMenuProps extends IContextMenuProps {
|
||||
room: Room;
|
||||
@@ -153,7 +163,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onClick={wrapHandler((ev) => onTagRoom(ev, DefaultTagID.Favourite), onPostFavoriteClick, true)}
|
||||
active={isFavorite}
|
||||
label={isFavorite ? _t("room|context_menu|unfavourite") : _t("room|context_menu|favourite")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconStar"
|
||||
icon={<FavouriteSolidIcon />}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -163,7 +173,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onClick={wrapHandler((ev) => onTagRoom(ev, DefaultTagID.LowPriority), onPostLowPriorityClick, true)}
|
||||
active={isLowPriority}
|
||||
label={_t("room|context_menu|low_priority")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconArrowDown"
|
||||
icon={<ArrowDownIcon />}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -180,7 +190,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onPostInviteClick,
|
||||
)}
|
||||
label={_t("action|invite")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconInvite"
|
||||
icon={<InviteIcon />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -198,7 +208,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onPostCopyLinkClick,
|
||||
)}
|
||||
label={_t("room|context_menu|copy_link")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconCopyLink"
|
||||
icon={<LinkIcon />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -214,7 +224,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onPostSettingsClick,
|
||||
)}
|
||||
label={_t("common|settings")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconSettings"
|
||||
icon={<SettingsSolidIcon />}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -222,7 +232,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
if (roomTags.includes(DefaultTagID.Archived)) {
|
||||
leaveOption = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconSignOut"
|
||||
icon={<LeaveIcon />}
|
||||
label={_t("room|context_menu|forget")}
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
onClick={wrapHandler(
|
||||
@@ -248,7 +258,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
)}
|
||||
label={_t("action|leave")}
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconSignOut"
|
||||
icon={<LeaveIcon />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -263,7 +273,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onFinished?.();
|
||||
}, onPostMarkAsReadClick)}
|
||||
label={_t("room|context_menu|mark_read")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconMarkAsRead"
|
||||
icon={<MarkAsReadIcon />}
|
||||
/>
|
||||
);
|
||||
} else if (!roomTags.includes(DefaultTagID.Archived)) {
|
||||
@@ -274,7 +284,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
|
||||
onFinished?.();
|
||||
}, onPostMarkAsUnreadClick)}
|
||||
label={_t("room|context_menu|mark_unread")}
|
||||
iconClassName="mx_RoomGeneralContextMenu_iconMarkAsUnread"
|
||||
icon={<MarkAsUnreadIcon />}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -20,6 +20,10 @@ import IconizedContextMenu, {
|
||||
IconizedContextMenuRadio,
|
||||
} from "../context_menus/IconizedContextMenu";
|
||||
import { type ButtonEvent } from "../elements/AccessibleButton";
|
||||
import { Icon as NotificationsIcon } from "../../../../res/img/element-icons/notifications.svg";
|
||||
import { Icon as NotificationsDefaultIcon } from "../../../../res/img/element-icons/roomlist/notifications-default.svg";
|
||||
import { Icon as NotificationsDmIcon } from "../../../../res/img/element-icons/roomlist/notifications-dm.svg";
|
||||
import { Icon as NotificationsOffIcon } from "../../../../res/img/element-icons/roomlist/notifications-off.svg";
|
||||
|
||||
interface IProps extends IContextMenuProps {
|
||||
room: Room;
|
||||
@@ -46,7 +50,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
|
||||
<IconizedContextMenuRadio
|
||||
label={_t("room|context_menu|notifications_default")}
|
||||
active={notificationState === RoomNotifState.AllMessages}
|
||||
iconClassName="mx_RoomNotificationContextMenu_iconBell"
|
||||
icon={<NotificationsIcon />}
|
||||
onClick={wrapHandler(() => setNotificationState(RoomNotifState.AllMessages))}
|
||||
/>
|
||||
);
|
||||
@@ -55,7 +59,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
|
||||
<IconizedContextMenuRadio
|
||||
label={_t("notifications|all_messages")}
|
||||
active={notificationState === RoomNotifState.AllMessagesLoud}
|
||||
iconClassName="mx_RoomNotificationContextMenu_iconBellDot"
|
||||
icon={<NotificationsDefaultIcon />}
|
||||
onClick={wrapHandler(() => setNotificationState(RoomNotifState.AllMessagesLoud))}
|
||||
/>
|
||||
);
|
||||
@@ -64,7 +68,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
|
||||
<IconizedContextMenuRadio
|
||||
label={_t("notifications|mentions_keywords")}
|
||||
active={notificationState === RoomNotifState.MentionsOnly}
|
||||
iconClassName="mx_RoomNotificationContextMenu_iconBellMentions"
|
||||
icon={<NotificationsDmIcon />}
|
||||
onClick={wrapHandler(() => setNotificationState(RoomNotifState.MentionsOnly))}
|
||||
/>
|
||||
);
|
||||
@@ -73,7 +77,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
|
||||
<IconizedContextMenuRadio
|
||||
label={_t("room|context_menu|notifications_mute")}
|
||||
active={notificationState === RoomNotifState.Mute}
|
||||
iconClassName="mx_RoomNotificationContextMenu_iconBellCrossed"
|
||||
icon={<NotificationsOffIcon />}
|
||||
onClick={wrapHandler(() => setNotificationState(RoomNotifState.Mute))}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,14 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { type JSX, useContext } from "react";
|
||||
import { type Room, EventType, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
HomeSolidIcon,
|
||||
PlusIcon,
|
||||
SettingsSolidIcon,
|
||||
LeaveIcon,
|
||||
SearchIcon,
|
||||
PreferencesIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { type IProps as IContextMenuProps } from "../../structures/ContextMenu";
|
||||
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
|
||||
@@ -32,6 +40,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import PosthogTrackers from "../../../PosthogTrackers";
|
||||
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
|
||||
|
||||
interface IProps extends IContextMenuProps {
|
||||
space?: Room;
|
||||
@@ -60,7 +69,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
<IconizedContextMenuOption
|
||||
data-testid="invite-option"
|
||||
className="mx_SpacePanel_contextMenu_inviteButton"
|
||||
iconClassName="mx_SpacePanel_iconInvite"
|
||||
icon={<InviteIcon />}
|
||||
label={_t("action|invite")}
|
||||
onClick={onInviteClick}
|
||||
/>
|
||||
@@ -81,7 +90,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
settingsOption = (
|
||||
<IconizedContextMenuOption
|
||||
data-testid="settings-option"
|
||||
iconClassName="mx_SpacePanel_iconSettings"
|
||||
icon={<SettingsSolidIcon />}
|
||||
label={_t("common|settings")}
|
||||
onClick={onSettingsClick}
|
||||
/>
|
||||
@@ -98,7 +107,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
leaveOption = (
|
||||
<IconizedContextMenuOption
|
||||
data-testid="leave-option"
|
||||
iconClassName="mx_SpacePanel_iconLeave"
|
||||
icon={<LeaveIcon />}
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
label={_t("space|leave_dialog_action")}
|
||||
onClick={onLeaveClick}
|
||||
@@ -123,7 +132,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
|
||||
devtoolsOption = (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconSettings"
|
||||
icon={<SettingsSolidIcon />}
|
||||
label={_t("space|context_menu|devtools_open_timeline")}
|
||||
onClick={onViewTimelineClick}
|
||||
/>
|
||||
@@ -170,7 +179,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
{canAddRooms && (
|
||||
<IconizedContextMenuOption
|
||||
data-testid="new-room-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
label={_t("common|room")}
|
||||
onClick={onNewRoomClick}
|
||||
/>
|
||||
@@ -178,7 +187,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
{canAddVideoRooms && (
|
||||
<IconizedContextMenuOption
|
||||
data-testid="new-video-room-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
label={_t("common|video_room")}
|
||||
onClick={onNewVideoRoomClick}
|
||||
>
|
||||
@@ -188,7 +197,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
{canAddSubSpaces && (
|
||||
<IconizedContextMenuOption
|
||||
data-testid="new-subspace-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
label={_t("common|space")}
|
||||
onClick={onNewSubspaceClick}
|
||||
>
|
||||
@@ -234,18 +243,18 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
||||
{!hideHeader && <div className="mx_SpacePanel_contextMenu_header">{space.name}</div>}
|
||||
<IconizedContextMenuOptionList first>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconHome"
|
||||
icon={<HomeSolidIcon />}
|
||||
label={_t("space|context_menu|home")}
|
||||
onClick={onHomeClick}
|
||||
/>
|
||||
{inviteOption}
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconExplore"
|
||||
icon={<SearchIcon />}
|
||||
label={canAddRooms ? _t("space|context_menu|manage_and_explore") : _t("space|context_menu|explore")}
|
||||
onClick={onExploreRoomsClick}
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconPreferences"
|
||||
icon={<PreferencesIcon />}
|
||||
label={_t("common|preferences")}
|
||||
onClick={onPreferencesClick}
|
||||
/>
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { LinkIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { type ButtonEvent } from "../elements/AccessibleButton";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
@@ -20,6 +21,7 @@ import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOpti
|
||||
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { Icon as ViewInRoomIcon } from "../../../../res/img/element-icons/view-in-room.svg";
|
||||
|
||||
export interface ThreadListContextMenuProps {
|
||||
mxEvent: MatrixEvent;
|
||||
@@ -102,7 +104,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
|
||||
<IconizedContextMenuOption
|
||||
onClick={(e) => viewInRoom(e)}
|
||||
label={_t("timeline|mab|view_in_room")}
|
||||
iconClassName="mx_ThreadPanel_viewInRoom"
|
||||
icon={<ViewInRoomIcon />}
|
||||
/>
|
||||
)}
|
||||
{permalinkCreator && (
|
||||
@@ -110,7 +112,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
|
||||
data-testid="copy-thread-link"
|
||||
onClick={(e) => copyLinkToThread(e)}
|
||||
label={_t("timeline|mab|copy_link_thread")}
|
||||
iconClassName="mx_ThreadPanel_copyLinkToThread"
|
||||
icon={<LinkIcon />}
|
||||
/>
|
||||
)}
|
||||
</IconizedContextMenuOptionList>
|
||||
|
||||
@@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import classNames from "classnames";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import React, { type JSX, Fragment, useState } from "react";
|
||||
import React, { type JSX, Fragment, useState, type ReactNode } from "react";
|
||||
import { OverflowHorizontalIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { ContextMenuTooltipButton } from "../../../../accessibility/context_menu/ContextMenuTooltipButton";
|
||||
import { useNotificationState } from "../../../../hooks/useRoomNotificationState";
|
||||
@@ -21,11 +21,25 @@ import { type ButtonEvent } from "../../elements/AccessibleButton";
|
||||
import { contextMenuBelow } from "../../rooms/RoomTile";
|
||||
import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../settings/UIFeature";
|
||||
import { Icon as NotificationsIcon } from "../../../../../res/img/element-icons/notifications.svg";
|
||||
import { Icon as NotificationsDefaultIcon } from "../../../../../res/img/element-icons/roomlist/notifications-default.svg";
|
||||
import { Icon as NotificationsDmIcon } from "../../../../../res/img/element-icons/roomlist/notifications-dm.svg";
|
||||
import { Icon as NotificationsOffIcon } from "../../../../../res/img/element-icons/roomlist/notifications-off.svg";
|
||||
|
||||
interface Props {
|
||||
room: Room;
|
||||
}
|
||||
|
||||
export function getNotificationIcon(state: RoomNotifState): ReactNode {
|
||||
const icons: Record<RoomNotifState, JSX.Element> = {
|
||||
[RoomNotifState.AllMessages]: <NotificationsIcon />,
|
||||
[RoomNotifState.AllMessagesLoud]: <NotificationsDefaultIcon />,
|
||||
[RoomNotifState.MentionsOnly]: <NotificationsDmIcon />,
|
||||
[RoomNotifState.Mute]: <NotificationsOffIcon />,
|
||||
};
|
||||
return icons[state];
|
||||
}
|
||||
|
||||
export function RoomResultContextMenus({ room }: Props): JSX.Element {
|
||||
const [notificationState] = useNotificationState(room);
|
||||
|
||||
@@ -64,14 +78,6 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
const notificationMenuClasses = classNames("mx_SpotlightDialog_option--notifications", {
|
||||
// Show bell icon for the default case too.
|
||||
mx_RoomNotificationContextMenu_iconBell: notificationState === RoomNotifState.AllMessages,
|
||||
mx_RoomNotificationContextMenu_iconBellDot: notificationState === RoomNotifState.AllMessagesLoud,
|
||||
mx_RoomNotificationContextMenu_iconBellMentions: notificationState === RoomNotifState.MentionsOnly,
|
||||
mx_RoomNotificationContextMenu_iconBellCrossed: notificationState === RoomNotifState.Mute,
|
||||
});
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{shouldShowComponent(UIComponent.RoomOptionsMenu) && (
|
||||
@@ -86,11 +92,13 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
|
||||
}}
|
||||
title={room.isSpaceRoom() ? _t("space|context_menu|options") : _t("room|context_menu|title")}
|
||||
isExpanded={generalMenuPosition !== null}
|
||||
/>
|
||||
>
|
||||
<OverflowHorizontalIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
)}
|
||||
{!room.isSpaceRoom() && (
|
||||
<ContextMenuTooltipButton
|
||||
className={notificationMenuClasses}
|
||||
className="mx_SpotlightDialog_option--notifications"
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
@@ -100,7 +108,9 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
|
||||
}}
|
||||
title={_t("room_list|notification_options")}
|
||||
isExpanded={notificationMenuPosition !== null}
|
||||
/>
|
||||
>
|
||||
{getNotificationIcon(notificationState!)}
|
||||
</ContextMenuTooltipButton>
|
||||
)}
|
||||
{generalMenu}
|
||||
{notificationMenu}
|
||||
|
||||
@@ -8,6 +8,13 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { EventType, type Room, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
import React, { type JSX, type ComponentType, createRef, type ReactComponentElement, type SyntheticEvent } from "react";
|
||||
import {
|
||||
PlusIcon,
|
||||
UserAddSolidIcon,
|
||||
RoomIcon,
|
||||
SearchIcon,
|
||||
ShareIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { type IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex.tsx";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext.tsx";
|
||||
@@ -67,6 +74,7 @@ import { getKeyBindingsManager } from "../../../KeyBindingsManager.ts";
|
||||
import AccessibleButton from "../elements/AccessibleButton.tsx";
|
||||
import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation.ts";
|
||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../LegacyCallHandler.tsx";
|
||||
import { Icon as HashVideoIcon } from "../../../../res/img/element-icons/roomlist/hash-video.svg";
|
||||
|
||||
interface IProps {
|
||||
onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void;
|
||||
@@ -142,7 +150,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
||||
{showCreateRooms && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|start_new_chat")}
|
||||
iconClassName="mx_LegacyRoomList_iconStartChat"
|
||||
icon={<UserAddSolidIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -158,7 +166,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
|
||||
{showInviteUsers && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|invite_to_space")}
|
||||
iconClassName="mx_LegacyRoomList_iconInvite"
|
||||
icon={<ShareIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -230,7 +238,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
<IconizedContextMenuOptionList first>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|explore_rooms")}
|
||||
iconClassName="mx_LegacyRoomList_iconExplore"
|
||||
icon={<SearchIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -247,7 +255,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewRoom"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -261,7 +269,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
|
||||
icon={<HashVideoIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -279,7 +287,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
)}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconAddExistingRoom"
|
||||
icon={<RoomIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -300,7 +308,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewRoom"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -312,7 +320,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
|
||||
icon={<HashVideoIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -333,7 +341,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
|
||||
{showExploreRooms ? (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|explore_public_rooms")}
|
||||
iconClassName="mx_LegacyRoomList_iconExplore"
|
||||
icon={<SearchIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { ClientEvent, EventType, type Room, RoomEvent, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
import React, { type JSX, useContext, useEffect, useState } from "react";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { PlusIcon, UserAddSolidIcon, SearchIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
@@ -51,6 +52,8 @@ import IconizedContextMenu, {
|
||||
import SpaceContextMenu from "../context_menus/SpaceContextMenu";
|
||||
import InlineSpinner from "../elements/InlineSpinner";
|
||||
import { HomeButtonContextMenu } from "../spaces/SpacePanel";
|
||||
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
|
||||
import { Icon as HashVideoIcon } from "../../../../res/img/element-icons/roomlist/hash-video.svg";
|
||||
|
||||
const contextMenuBelow = (elementRect: DOMRect): MenuProps => {
|
||||
// align the context menu's icons with the icon which opened the context menu
|
||||
@@ -178,7 +181,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
inviteOption = (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|invite")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconInvite"
|
||||
icon={<InviteIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -194,7 +197,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
newRoomOptions = (
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_LegacyRoomListHeader_iconNewRoom"
|
||||
icon={<PlusIcon />}
|
||||
label={_t("action|new_room")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@@ -206,7 +209,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
/>
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_LegacyRoomListHeader_iconNewVideoRoom"
|
||||
icon={<HashVideoIcon />}
|
||||
label={_t("action|new_video_room")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@@ -236,7 +239,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
{newRoomOptions}
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|explore_rooms")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconExplore"
|
||||
icon={<SearchIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -251,7 +254,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|add_existing_room")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -264,7 +267,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
{canCreateSpaces && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("room_list|add_space_label")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconPlus"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -289,7 +292,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
<>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|start_new_chat")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconStartChat"
|
||||
icon={<UserAddSolidIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -300,7 +303,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
/>
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_room")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconNewRoom"
|
||||
icon={<PlusIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -312,7 +315,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
{videoRoomsEnabled && (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("action|new_video_room")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconNewVideoRoom"
|
||||
icon={<HashVideoIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -333,7 +336,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
|
||||
joinRoomOpt = (
|
||||
<IconizedContextMenuOption
|
||||
label={_t("room_list|join_public_room_label")}
|
||||
iconClassName="mx_LegacyRoomListHeader_iconExplore"
|
||||
icon={<SearchIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -45,6 +45,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import { isKnockDenied } from "../../../utils/membership";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { getNotificationIcon } from "../dialogs/spotlight/RoomResultContextMenus.tsx";
|
||||
|
||||
interface Props {
|
||||
room: Room;
|
||||
@@ -293,12 +294,6 @@ class RoomTile extends React.PureComponent<Props, State> {
|
||||
const state = this.roomProps.notificationVolume;
|
||||
|
||||
const classes = classNames("mx_RoomTile_notificationsButton", {
|
||||
// Show bell icon for the default case too.
|
||||
mx_RoomNotificationContextMenu_iconBell: state === RoomNotifState.AllMessages,
|
||||
mx_RoomNotificationContextMenu_iconBellDot: state === RoomNotifState.AllMessagesLoud,
|
||||
mx_RoomNotificationContextMenu_iconBellMentions: state === RoomNotifState.MentionsOnly,
|
||||
mx_RoomNotificationContextMenu_iconBellCrossed: state === RoomNotifState.Mute,
|
||||
|
||||
// Only show the icon by default if the room is overridden to muted.
|
||||
// TODO: [FTUE Notifications] Probably need to detect global mute state
|
||||
mx_RoomTile_notificationsButton_show: state === RoomNotifState.Mute,
|
||||
@@ -312,7 +307,9 @@ class RoomTile extends React.PureComponent<Props, State> {
|
||||
title={_t("room_list|notification_options")}
|
||||
isExpanded={!!this.state.notificationsMenuPosition}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
/>
|
||||
>
|
||||
{getNotificationIcon(state!)}
|
||||
</ContextMenuTooltipButton>
|
||||
{this.state.notificationsMenuPosition && (
|
||||
<RoomNotificationContextMenu
|
||||
{...contextMenuBelow(this.state.notificationsMenuPosition)}
|
||||
|
||||
@@ -99,7 +99,6 @@ export const HomeButtonContextMenu: React.FC<ComponentProps<typeof SpaceContextM
|
||||
{!hideHeader && <div className="mx_SpacePanel_contextMenu_header">{_t("common|home")}</div>}
|
||||
<IconizedContextMenuOptionList first>
|
||||
<IconizedContextMenuCheckbox
|
||||
iconClassName="mx_SpacePanel_noIcon"
|
||||
label={_t("settings|sidebar|metaspaces_home_all_rooms")}
|
||||
active={allRoomsInHome}
|
||||
onClick={() => {
|
||||
|
||||
Reference in New Issue
Block a user