From 4cebc2aef42403422dc6c5250b191ca1066458f5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 2 Nov 2021 11:14:36 +0000 Subject: [PATCH 01/11] Tweak room summary card --- res/css/views/right_panel/_BaseCard.scss | 8 +++++++- src/components/views/right_panel/RoomSummaryCard.tsx | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/res/css/views/right_panel/_BaseCard.scss b/res/css/views/right_panel/_BaseCard.scss index 8c1a55fe053..8198e32def5 100644 --- a/res/css/views/right_panel/_BaseCard.scss +++ b/res/css/views/right_panel/_BaseCard.scss @@ -99,7 +99,7 @@ limitations under the License. } .mx_BaseCard_Button { - padding: 10px 38px 10px 12px; + padding: 10px 32px 10px 12px; margin: 0; position: relative; font-size: $font-13px; @@ -109,6 +109,12 @@ limitations under the License. overflow: hidden; white-space: nowrap; text-overflow: ellipsis; + display: flex; + + .mx_BaseCard_Button_sublabel { + color: $tertiary-content; + margin-left: auto; + } &:hover { background-color: rgba(141, 151, 165, 0.1); diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index f17a7236214..39951d4d646 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -276,10 +276,13 @@ const RoomSummaryCard: React.FC = ({ room, onClose }) => { return } diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx index bdc419a01a1..fd95eb0bd9c 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019 - 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,6 +24,11 @@ import { SettingLevel } from "../../../../../settings/SettingLevel"; import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { logger } from "matrix-js-sdk/src/logger"; +import { RoomEchoChamber } from "../../../../../stores/local-echo/RoomEchoChamber"; +import { EchoChamber } from '../../../../../stores/local-echo/EchoChamber'; +import MatrixClientContext from "../../../../../contexts/MatrixClientContext"; +import StyledRadioGroup from "../../../elements/StyledRadioGroup"; +import { RoomNotifState } from '../../../../../RoomNotifs'; interface IProps { roomId: string; @@ -36,10 +41,16 @@ interface IState { @replaceableComponent("views.settings.tabs.room.NotificationsSettingsTab") export default class NotificationsSettingsTab extends React.Component { + private readonly roomProps: RoomEchoChamber; private soundUpload = createRef(); - constructor(props: IProps) { - super(props); + static contextType = MatrixClientContext; + public context!: React.ContextType; + + constructor(props: IProps, context: React.ContextType) { + super(props, context); + + this.roomProps = EchoChamber.forRoom(context.getRoom(this.props.roomId)); this.state = { currentSound: "default", @@ -144,6 +155,11 @@ export default class NotificationsSettingsTab extends React.Component { + this.roomProps.notificationVolume = value; + this.forceUpdate(); + }; + public render(): JSX.Element { let currentUploadedFile = null; if (this.state.uploadedFile) { @@ -157,6 +173,30 @@ export default class NotificationsSettingsTab extends React.Component
{ _t("Notifications") }
+ +
+ +
+
{ _t("Sounds") }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index db3eb8e58df..8440265a93b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1455,6 +1455,8 @@ "URL Previews": "URL Previews", "Room Addresses": "Room Addresses", "Uploaded sound": "Uploaded sound", + "All messages": "All messages", + "@mentions & keywords": "@mentions & keywords", "Sounds": "Sounds", "Notification sound": "Notification sound", "Set a new custom sound": "Set a new custom sound", @@ -1743,18 +1745,6 @@ "Show %(count)s more|other": "Show %(count)s more", "Show %(count)s more|one": "Show %(count)s more", "Show less": "Show less", - "Use default": "Use default", - "All messages": "All messages", - "Mentions & Keywords": "Mentions & Keywords", - "Notification options": "Notification options", - "Forget Room": "Forget Room", - "Favourited": "Favourited", - "Favourite": "Favourite", - "Low Priority": "Low Priority", - "Invite People": "Invite People", - "Copy Room Link": "Copy Room Link", - "Settings": "Settings", - "Leave Room": "Leave Room", "Room options": "Room options", "%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.", "%(count)s unread messages including mentions.|one": "1 unread mention.", @@ -1856,9 +1846,7 @@ "Add widgets, bridges & bots": "Add widgets, bridges & bots", "Not encrypted": "Not encrypted", "About": "About", - "%(count)s people|other": "%(count)s people", - "%(count)s people|one": "%(count)s person", - "Show files": "Show files", + "Files": "Files", "Export chat": "Export chat", "Show threads": "Show threads", "Share room": "Share room", @@ -2445,6 +2433,7 @@ "Incoming Verification Request": "Incoming Verification Request", "Integrations are disabled": "Integrations are disabled", "Enable 'Manage Integrations' in Settings to do this.": "Enable 'Manage Integrations' in Settings to do this.", + "Settings": "Settings", "Integrations not allowed": "Integrations not allowed", "Your %(brand)s doesn't allow you to use an integration manager to do this. Please contact an admin.": "Your %(brand)s doesn't allow you to use an integration manager to do this. Please contact an admin.", "To continue, use Single Sign On to prove your identity.": "To continue, use Single Sign On to prove your identity.", @@ -2714,6 +2703,12 @@ "Collapse reply thread": "Collapse reply thread", "Report": "Report", "View in room": "View in room", + "Forget": "Forget", + "Leave": "Leave", + "Favourited": "Favourited", + "Favourite": "Favourite", + "Mentions only": "Mentions only", + "Copy link": "Copy link", "See room timeline (devtools)": "See room timeline (devtools)", "Add space": "Add space", "Manage & explore rooms": "Manage & explore rooms", @@ -2818,7 +2813,6 @@ "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.": "You are an administrator of this community. You will not be able to rejoin without an invite from another administrator.", "Leave Community": "Leave Community", "Leave %(groupName)s?": "Leave %(groupName)s?", - "Leave": "Leave", "Unable to leave community": "Unable to leave community", "Community Settings": "Community Settings", "Want more than a community? Get your own server": "Want more than a community? Get your own server", diff --git a/test/components/views/rooms/RoomHeader-test.tsx b/test/components/views/rooms/RoomHeader-test.tsx index 859107416e1..c827becca4e 100644 --- a/test/components/views/rooms/RoomHeader-test.tsx +++ b/test/components/views/rooms/RoomHeader-test.tsx @@ -159,7 +159,6 @@ function render(room: Room): HTMLDivElement { {}} onSearchClick={() => {}} onForgetClick={() => {}} onCallPlaced={(_type: PlaceCallType) => {}} From 0c279c8f9b8b651db6bb5b5b048e1af1aa5af013 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 2 Nov 2021 13:09:10 +0000 Subject: [PATCH 03/11] add missing chevron --- res/css/views/rooms/_RoomHeader.scss | 13 ++++++++++--- src/stores/local-echo/RoomEchoChamber.ts | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index e6224d698ba..4729636f153 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -122,7 +122,14 @@ limitations under the License. } .mx_RoomHeader_chevron { - + align-self: center; + width: 16px; + height: 16px; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); + background-color: $tertiary-content; } } @@ -145,8 +152,8 @@ limitations under the License. color: $roomtopic-color; font-weight: 400; font-size: $font-13px; - margin: 0 7px; - margin-top: 4px; // to align baseline of topic with room name + // to align baseline of topic with room name + margin: 4px 7px 0; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid transparent; diff --git a/src/stores/local-echo/RoomEchoChamber.ts b/src/stores/local-echo/RoomEchoChamber.ts index fb40e23a85b..a9a0a60976a 100644 --- a/src/stores/local-echo/RoomEchoChamber.ts +++ b/src/stores/local-echo/RoomEchoChamber.ts @@ -19,6 +19,7 @@ import { getRoomNotifsState, RoomNotifState, setRoomNotifsState } from "../../Ro import { RoomEchoContext } from "./RoomEchoContext"; import { _t } from "../../languageHandler"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { EventType } from "matrix-js-sdk/src/@types/event"; export enum CachedRoomKey { NotificationVolume, @@ -46,7 +47,7 @@ export class RoomEchoChamber extends GenericEchoChamber { - if (event.getType() === "m.push_rules") { + if (event.getType() === EventType.PushRules) { const currentVolume = this.properties.get(CachedRoomKey.NotificationVolume) as RoomNotifState; const newVolume = getRoomNotifsState(this.context.room.roomId) as RoomNotifState; if (currentVolume !== newVolume) { From 72429f994affca764f0d2f47c66337877f5db3a8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 5 Nov 2021 12:56:22 +0000 Subject: [PATCH 04/11] Update mx_RoomHeader_name colour to match design --- res/css/views/rooms/_RoomHeader.scss | 8 ++++---- res/themes/dark/css/_dark.scss | 1 - res/themes/legacy-dark/css/_legacy-dark.scss | 1 - res/themes/legacy-light/css/_legacy-light.scss | 1 - res/themes/light-custom/css/_custom.scss | 1 - res/themes/light/css/_light.scss | 1 - 6 files changed, 4 insertions(+), 9 deletions(-) diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 4729636f153..2b600dba9cb 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -85,9 +85,9 @@ limitations under the License. .mx_RoomHeader_simpleHeader { line-height: $font-52px; - color: $roomheader-color; + color: $primary-content; font-size: $font-18px; - font-weight: 600; + font-weight: $font-semi-bold; overflow: hidden; margin-left: 63px; text-overflow: ellipsis; @@ -107,8 +107,8 @@ limitations under the License. .mx_RoomHeader_name { flex: 0 1 auto; overflow: hidden; - color: $roomheader-color; - font-weight: 600; + color: $primary-content; + font-weight: $font-semi-bold; font-size: $font-18px; margin: 0 7px; border-bottom: 1px solid transparent; diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 865eb4de433..2235d3a303b 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -104,7 +104,6 @@ $settings-profile-button-fg-color: $settings-profile-overlay-placeholder-fg-colo $settings-subsection-fg-color: $text-secondary-color; $topleftmenu-color: $primary-content; -$roomheader-color: $primary-content; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.3); $roomheader-addroom-fg-color: $primary-content; $groupFilterPanel-button-color: $header-panel-text-primary-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 5fa0e903ba2..f34abecb6d7 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -97,7 +97,6 @@ $settings-profile-button-fg-color: $settings-profile-overlay-placeholder-fg-colo $settings-subsection-fg-color: $text-secondary-color; $topleftmenu-color: $text-primary-color; -$roomheader-color: $text-primary-color; $roomheader-addroom-bg-color: #3c4556; // $search-placeholder-color at 0.5 opacity $roomheader-addroom-fg-color: $text-primary-color; $groupFilterPanel-button-color: $header-panel-text-primary-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 7fe56497875..98e7d786241 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -153,7 +153,6 @@ $rte-room-pill-color: #aaa; $rte-group-pill-color: #aaa; $topleftmenu-color: #212121; -$roomheader-color: #45474a; $roomheader-bg-color: $primary-bg-color; $roomheader-addroom-bg-color: #91a1c0; $roomheader-addroom-fg-color: $accent-fg-color; diff --git a/res/themes/light-custom/css/_custom.scss b/res/themes/light-custom/css/_custom.scss index 2fbb91c5236..99b3fed132d 100644 --- a/res/themes/light-custom/css/_custom.scss +++ b/res/themes/light-custom/css/_custom.scss @@ -98,7 +98,6 @@ $dialog-title-fg-color: var(--timeline-text-color); $tab-label-fg-color: var(--timeline-text-color); // was #4e5054 $authpage-lang-color: var(--timeline-text-color); -$roomheader-color: var(--timeline-text-color); // was #232f32 $authpage-primary-color: var(--timeline-text-color); // --roomlist-text-secondary-color diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index ef4ab0115d4..78f6e5ff134 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -164,7 +164,6 @@ $rte-room-pill-color: #aaa; $rte-group-pill-color: #aaa; $topleftmenu-color: #212121; -$roomheader-color: #45474a; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.2); $roomheader-addroom-fg-color: #5c6470; $groupFilterPanel-button-color: #91A1C0; From 874eeac26bd7b8ff693a8bcb67086bafd292bfdc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 5 Nov 2021 13:02:44 +0000 Subject: [PATCH 05/11] Vary room context menu icons depending on notification setting --- res/css/views/rooms/_RoomTile.scss | 14 +++++++++++++- .../views/context_menus/RoomContextMenu.tsx | 7 ++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index ae15076f66c..1b2d24d1f81 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -164,10 +164,22 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/roomlist/low-priority.svg'); } - .mx_RoomTile_iconNotifications::before { + .mx_RoomTile_iconNotificationsDefault::before { mask-image: url('$(res)/img/element-icons/notifications.svg'); } + .mx_RoomTile_iconNotificationsAllMessages::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg'); + } + + .mx_RoomTile_iconNotificationsMentionsKeywords::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-dm.svg'); + } + + .mx_RoomTile_iconNotificationsNone::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg'); + } + .mx_RoomTile_iconPeople::before { mask-image: url('$(res)/img/element-icons/room/members.svg'); } diff --git a/src/components/views/context_menus/RoomContextMenu.tsx b/src/components/views/context_menus/RoomContextMenu.tsx index ce50994081c..f0aa5ab1333 100644 --- a/src/components/views/context_menus/RoomContextMenu.tsx +++ b/src/components/views/context_menus/RoomContextMenu.tsx @@ -133,18 +133,23 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { const echoChamber = EchoChamber.forRoom(room); let notificationLabel: string; + let iconClassName: string; switch (echoChamber.notificationVolume) { case RoomNotifState.AllMessages: notificationLabel = _t("Default"); + iconClassName = "mx_RoomTile_iconNotificationsDefault"; break; case RoomNotifState.AllMessagesLoud: notificationLabel = _t("All messages"); + iconClassName = "mx_RoomTile_iconNotificationsAllMessages"; break; case RoomNotifState.MentionsOnly: notificationLabel = _t("Mentions only"); + iconClassName = "mx_RoomTile_iconNotificationsMentionsKeywords"; break; case RoomNotifState.Mute: notificationLabel = _t("Mute"); + iconClassName = "mx_RoomTile_iconNotificationsNone"; break; } @@ -161,7 +166,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { onFinished(); }} label={_t("Notifications")} - iconClassName="mx_RoomTile_iconNotifications" + iconClassName={iconClassName} > { notificationLabel } From b6229e19e27cb21887278a15af0f111dbc4662b4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 5 Nov 2021 13:25:34 +0000 Subject: [PATCH 06/11] Update room header styling to match Figma --- res/css/views/rooms/_RoomHeader.scss | 15 +++++++++++---- src/components/views/rooms/RoomHeader.tsx | 11 ++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 2b600dba9cb..135c2c8ff96 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -33,12 +33,13 @@ limitations under the License. } .mx_RoomHeader_wrapper { - margin: auto; - height: 50px; + height: 44px; display: flex; align-items: center; min-width: 0; - padding: 0 10px 0 18px; + margin: 0 20px 0 16px; + padding-top: 8px; + border-bottom: 1px solid $system; .mx_InviteOnlyIcon_large { margin: 0; @@ -110,11 +111,16 @@ limitations under the License. color: $primary-content; font-weight: $font-semi-bold; font-size: $font-18px; + border-radius: 6px; margin: 0 7px; - border-bottom: 1px solid transparent; + padding: 1px 4px; display: flex; user-select: none; + &:hover { + background-color: $quinary-content; + } + .mx_RoomHeader_nametext { white-space: nowrap; text-overflow: ellipsis; @@ -233,6 +239,7 @@ limitations under the License. @media only screen and (max-width: 480px) { .mx_RoomHeader_wrapper { padding: 0; + margin: 0; } .mx_RoomHeader { overflow: hidden; diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index 28273f4d93a..dfd389c48f1 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -36,7 +36,7 @@ import { MatrixEvent, Room, RoomState } from 'matrix-js-sdk/src'; import { E2EStatus } from '../../../utils/ShieldUtils'; import { IOOBData } from '../../../stores/ThreepidInviteStore'; import { SearchScope } from './SearchBar'; -import { ContextMenuButton } from '../../structures/ContextMenu'; +import { ContextMenuTooltipButton } from '../../structures/ContextMenu'; import RoomContextMenu from "../context_menus/RoomContextMenu"; import { contextMenuBelow } from './RoomTile'; @@ -164,10 +164,11 @@ export default class RoomHeader extends React.Component { const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint }); const name = ( - { (name) => { @@ -176,9 +177,8 @@ export default class RoomHeader extends React.Component { } } { this.props.room &&
} - { searchStatus } { contextMenu } - + ); const topicElement = @@ -191,7 +191,7 @@ export default class RoomHeader extends React.Component { if (this.props.room) { roomAvatar = ; @@ -261,6 +261,7 @@ export default class RoomHeader extends React.Component {
{ roomAvatar }
{ e2eIcon }
{ name } + { searchStatus } { topicElement } { rightRow } From 310fceb6dc901b346d0e00f25fa15198143d4b5a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 5 Nov 2021 13:27:10 +0000 Subject: [PATCH 07/11] tidy --- res/css/views/rooms/_RoomHeader.scss | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 135c2c8ff96..593b38509a0 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -93,16 +93,16 @@ limitations under the License. margin-left: 63px; text-overflow: ellipsis; width: 100%; -} -.mx_RoomHeader_simpleHeader .mx_RoomHeader_cancelButton { - float: right; -} + .mx_RoomHeader_cancelButton { + float: right; + } -.mx_RoomHeader_simpleHeader .mx_RoomHeader_icon { - margin-left: 14px; - margin-right: 24px; - vertical-align: -4px; + .mx_RoomHeader_icon { + margin-left: 14px; + margin-right: 24px; + vertical-align: -4px; + } } .mx_RoomHeader_name { From 3677306da5ea0392e2b6bfe6e3cfc14f4817918a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 5 Nov 2021 14:15:08 +0000 Subject: [PATCH 08/11] Iterate room notification settings tab --- res/css/_components.scss | 1 + .../tabs/room/_NotificationSettingsTab.scss | 77 +++++++++++++++++++ .../context_menu/ContextMenuTooltipButton.tsx | 1 + .../views/dialogs/RoomSettingsDialog.tsx | 2 +- .../tabs/room/NotificationSettingsTab.tsx | 55 +++++++++++-- src/i18n/strings/en_EN.json | 6 +- 6 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 res/css/views/settings/tabs/room/_NotificationSettingsTab.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index 116189d64cc..f1d79ef6af6 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -265,6 +265,7 @@ @import "./views/settings/_UpdateCheckButton.scss"; @import "./views/settings/tabs/_SettingsTab.scss"; @import "./views/settings/tabs/room/_GeneralRoomSettingsTab.scss"; +@import "./views/settings/tabs/room/_NotificationSettingsTab.scss"; @import "./views/settings/tabs/room/_RolesRoomSettingsTab.scss"; @import "./views/settings/tabs/room/_SecurityRoomSettingsTab.scss"; @import "./views/settings/tabs/user/_AppearanceUserSettingsTab.scss"; diff --git a/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss b/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss new file mode 100644 index 00000000000..46d89bc75a9 --- /dev/null +++ b/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss @@ -0,0 +1,77 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_NotificationSettingsTab_notificationsSection { + width: 360px; + + .mx_StyledRadioButton { + flex-direction: row-reverse; + color: $primary-content; + font-size: $font-15px; + line-height: $font-18px; + font-weight: $font-semi-bold; + margin-top: 16px; + position: relative; + padding-left: 8px; + align-items: center; + + &::before { + content: ""; + position: absolute; + height: 24px; + width: 24px; + left: 0; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + background-color: $secondary-content; + } + + input + div { + margin-top: 8px; + } + + .mx_NotificationSettingsTab_microCopy { + color: $secondary-content; + font-weight: normal; + font-size: $font-12px; + line-height: $font-15px; + margin-right: 32px; + + .mx_AccessibleButton_kind_link { + padding: 0; + font-size: inherit; + } + } + } + + .mx_NotificationSettingsTab_defaultEntry::before { + mask-image: url('$(res)/img/element-icons/notifications.svg'); + } + + .mx_NotificationSettingsTab_allMessagesEntry::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg'); + + } + + .mx_NotificationSettingsTab_mentionsKeywordsEntry::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-dm.svg'); + } + + .mx_NotificationSettingsTab_noneEntry::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg'); + } +} diff --git a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx index 49f57ca7b6f..74a45a57eea 100644 --- a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx +++ b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx @@ -40,6 +40,7 @@ export const ContextMenuTooltipButton: React.FC = ({ onContextMenu={onContextMenu || onClick} aria-haspopup={true} aria-expanded={isExpanded} + forceHide={isExpanded} > { children } diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx index b0c6fc40500..be4d935477d 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.tsx +++ b/src/components/views/dialogs/RoomSettingsDialog.tsx @@ -113,7 +113,7 @@ export default class RoomSettingsDialog extends React.Component ROOM_NOTIFICATIONS_TAB, _td("Notifications"), "mx_RoomSettingsDialog_notificationsIcon", - , + this.props.onFinished(true)} />, )); if (SettingsStore.getValue("feature_bridge_state")) { diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx index fd95eb0bd9c..6f1d8301b0b 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx @@ -29,9 +29,13 @@ import { EchoChamber } from '../../../../../stores/local-echo/EchoChamber'; import MatrixClientContext from "../../../../../contexts/MatrixClientContext"; import StyledRadioGroup from "../../../elements/StyledRadioGroup"; import { RoomNotifState } from '../../../../../RoomNotifs'; +import defaultDispatcher from "../../../../../dispatcher/dispatcher"; +import { Action } from "../../../../../dispatcher/actions"; +import { UserTab } from "../../../dialogs/UserSettingsDialog"; interface IProps { roomId: string; + closeSettingsFn(): void; } interface IState { @@ -160,6 +164,14 @@ export default class NotificationsSettingsTab extends React.Component { + this.props.closeSettingsFn(); + defaultDispatcher.dispatch({ + action: Action.ViewUserSettings, + initialTabId: UserTab.Notifications, + }); + }; + public render(): JSX.Element { let currentUploadedFile = null; if (this.state.uploadedFile) { @@ -174,22 +186,55 @@ export default class NotificationsSettingsTab extends React.Component
{ _t("Notifications") }
-
+
+ { _t("Default") } +
+ { _t("Get notifications as set up in your settings", {}, { + a: sub => + { sub } + , + }) } +
+ , }, { value: RoomNotifState.AllMessagesLoud, - label: _t("All messages"), + className: "mx_NotificationSettingsTab_allMessagesEntry", + label: <> + { _t("All messages") } +
+ { _t("Get notified for every message") } +
+ , }, { value: RoomNotifState.MentionsOnly, - label: _t("@mentions & keywords"), + className: "mx_NotificationSettingsTab_mentionsKeywordsEntry", + label: <> + { _t("@mentions & keywords") } +
+ { _t("Get notified only with mentions and keywords " + + "as set up in your settings", {}, { + a: sub => + { sub } + , + }) } +
+ , }, { value: RoomNotifState.Mute, - label: _t("Off"), + className: "mx_NotificationSettingsTab_noneEntry", + label: <> + { _t("Off") } +
+ { _t("You won't get any notifications") } +
+ , }, ]} onChange={this.onRoomNotificationChange} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 914e1512813..fcdd5b29758 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1456,8 +1456,12 @@ "URL Previews": "URL Previews", "Room Addresses": "Room Addresses", "Uploaded sound": "Uploaded sound", + "Get notifications as set up in your settings": "Get notifications as set up in your settings", "All messages": "All messages", + "Get notified for every message": "Get notified for every message", "@mentions & keywords": "@mentions & keywords", + "Get notified only with mentions and keywords as set up in your settings": "Get notified only with mentions and keywords as set up in your settings", + "You won't get any notifications": "You won't get any notifications", "Sounds": "Sounds", "Notification sound": "Notification sound", "Set a new custom sound": "Set a new custom sound", @@ -1667,6 +1671,7 @@ "(~%(count)s results)|other": "(~%(count)s results)", "(~%(count)s results)|one": "(~%(count)s result)", "Join Room": "Join Room", + "Room options": "Room options", "Forget room": "Forget room", "Hide Widgets": "Hide Widgets", "Show Widgets": "Show Widgets", @@ -1749,7 +1754,6 @@ "Show %(count)s more|other": "Show %(count)s more", "Show %(count)s more|one": "Show %(count)s more", "Show less": "Show less", - "Room options": "Room options", "%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.", "%(count)s unread messages including mentions.|one": "1 unread mention.", "%(count)s unread messages.|other": "%(count)s unread messages.", From 117f043eea407695e83be8a24b9671ac8ff6821c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 8 Nov 2021 17:49:07 +0000 Subject: [PATCH 09/11] fix lint & props --- res/css/views/rooms/_RoomTile.scss | 5 +---- .../views/settings/tabs/room/_NotificationSettingsTab.scss | 1 - src/components/views/rooms/RoomHeader.tsx | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 1b2d24d1f81..9ca6a24148c 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -120,13 +120,10 @@ limitations under the License. mask-size: contain; mask-repeat: no-repeat; background: $primary-content; + mask-image: url('$(res)/img/element-icons/context-menu.svg'); } } - .mx_RoomTile_menuButton::before { - mask-image: url('$(res)/img/element-icons/context-menu.svg'); - } - &:not(.mx_RoomTile_minimized) { &:hover, &:focus-within, diff --git a/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss b/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss index 46d89bc75a9..97b807863f9 100644 --- a/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss +++ b/res/css/views/settings/tabs/room/_NotificationSettingsTab.scss @@ -64,7 +64,6 @@ limitations under the License. .mx_NotificationSettingsTab_allMessagesEntry::before { mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg'); - } .mx_NotificationSettingsTab_mentionsKeywordsEntry::before { diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index dfd389c48f1..26b101d3e34 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -50,7 +50,6 @@ interface IProps { room: Room; oobData?: IOOBData; inRoom: boolean; - onSettingsClick: () => void; onSearchClick: () => void; onForgetClick: () => void; onCallPlaced: (type: PlaceCallType) => void; From 2a9565c7ddcafa699fd121d70f370737c221dd3f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 9 Nov 2021 16:09:41 +0000 Subject: [PATCH 10/11] Match threads lab style by flipping the chevron whilst active --- res/css/views/rooms/_RoomHeader.scss | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 593b38509a0..f72618b58e5 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -137,6 +137,14 @@ limitations under the License. mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); background-color: $tertiary-content; } + + &[aria-expanded=true] { + background-color: $quinary-content; + + .mx_RoomHeader_chevron { + transform: rotate(180deg); + } + } } .mx_RoomHeader_settingsHint { From 332a35abffbe091c3c5b48a19a7cf6fa111475b5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 Nov 2021 14:30:06 +0000 Subject: [PATCH 11/11] revert changes to RoomTile --- res/css/views/rooms/_RoomTile.scss | 34 ++- src/components/views/rooms/RoomTile.tsx | 320 ++++++++++++++++++++++-- src/i18n/strings/en_EN.json | 14 +- 3 files changed, 339 insertions(+), 29 deletions(-) diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 9ca6a24148c..e11bde1f52e 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -79,6 +79,10 @@ limitations under the License. } } + .mx_RoomTile_notificationsButton { + margin-left: 4px; // spacing between buttons + } + .mx_RoomTile_badgeContainer { height: 16px; // don't set width so that it takes no space when there is no badge to show @@ -99,8 +103,9 @@ limitations under the License. } } - // The context menu button is hidden by default - .mx_RoomTile_menuButton { + // The context menu buttons are hidden by default + .mx_RoomTile_menuButton, + .mx_RoomTile_notificationsButton { width: 20px; min-width: 20px; // yay flex height: 20px; @@ -120,10 +125,18 @@ limitations under the License. mask-size: contain; mask-repeat: no-repeat; background: $primary-content; - mask-image: url('$(res)/img/element-icons/context-menu.svg'); } } + // If the room has an overriden notification setting then we always show the notifications menu button + .mx_RoomTile_notificationsButton.mx_RoomTile_notificationsButton_show { + display: block; + } + + .mx_RoomTile_menuButton::before { + mask-image: url('$(res)/img/element-icons/context-menu.svg'); + } + &:not(.mx_RoomTile_minimized) { &:hover, &:focus-within, @@ -135,6 +148,7 @@ limitations under the License. display: none; } + .mx_RoomTile_notificationsButton, .mx_RoomTile_menuButton { display: block; } @@ -152,6 +166,20 @@ limitations under the License. } } +// We use these both in context menus and the room tiles +.mx_RoomTile_iconBell::before { + mask-image: url('$(res)/img/element-icons/notifications.svg'); +} +.mx_RoomTile_iconBellDot::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-default.svg'); +} +.mx_RoomTile_iconBellCrossed::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg'); +} +.mx_RoomTile_iconBellMentions::before { + mask-image: url('$(res)/img/element-icons/roomlist/notifications-dm.svg'); +} + .mx_RoomTile_contextMenu { .mx_RoomTile_iconStar::before { mask-image: url('$(res)/img/element-icons/roomlist/favorite.svg'); diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 0548edb2631..c6c815b0dcf 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -19,7 +19,7 @@ import React, { createRef } from "react"; import { Room } from "matrix-js-sdk/src/models/room"; import classNames from "classnames"; import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex"; -import AccessibleButton from "../../views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton"; import dis from '../../../dispatcher/dispatcher'; import defaultDispatcher from '../../../dispatcher/dispatcher'; import { Key } from "../../../Keyboard"; @@ -29,14 +29,28 @@ import { ChevronFace, ContextMenuTooltipButton } from "../../structures/ContextM import { DefaultTagID, TagID } from "../../../stores/room-list/models"; import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore"; import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; +import { RoomNotifState } from "../../../RoomNotifs"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import NotificationBadge from "./NotificationBadge"; +import RoomListStore from "../../../stores/room-list/RoomListStore"; +import RoomListActions from "../../../actions/RoomListActions"; import { ActionPayload } from "../../../dispatcher/payloads"; import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; import { NOTIFICATION_STATE_UPDATE, NotificationState } from "../../../stores/notifications/NotificationState"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import { EchoChamber } from "../../../stores/local-echo/EchoChamber"; +import { CachedRoomKey, RoomEchoChamber } from "../../../stores/local-echo/RoomEchoChamber"; +import { PROPERTY_UPDATED } from "../../../stores/local-echo/GenericEchoChamber"; +import IconizedContextMenu, { + IconizedContextMenuCheckbox, + IconizedContextMenuOption, + IconizedContextMenuOptionList, + IconizedContextMenuRadio, +} from "../context_menus/IconizedContextMenu"; import { CommunityPrototypeStore, IRoomProfile } from "../../../stores/CommunityPrototypeStore"; import { replaceableComponent } from "../../../utils/replaceableComponent"; -import RoomContextMenu from "../context_menus/RoomContextMenu"; + +import { logger } from "matrix-js-sdk/src/logger"; interface IProps { room: Room; @@ -49,7 +63,8 @@ type PartialDOMRect = Pick; interface IState { selected: boolean; - contextMenuPosition: PartialDOMRect; + notificationsMenuPosition: PartialDOMRect; + generalMenuPosition: PartialDOMRect; messagePreview?: string; } @@ -68,13 +83,15 @@ export default class RoomTile extends React.PureComponent { private dispatcherRef: string; private roomTileRef = createRef(); private notificationState: NotificationState; + private roomProps: RoomEchoChamber; constructor(props: IProps) { super(props); this.state = { selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId, - contextMenuPosition: null, + notificationsMenuPosition: null, + generalMenuPosition: null, // generatePreview() will return nothing if the user has previews disabled messagePreview: "", @@ -82,6 +99,7 @@ export default class RoomTile extends React.PureComponent { this.generatePreview(); this.notificationState = RoomNotificationStateStore.instance.getRoomState(this.props.room); + this.roomProps = EchoChamber.forRoom(this.props.room); } private onRoomNameUpdate = (room: Room) => { @@ -92,6 +110,11 @@ export default class RoomTile extends React.PureComponent { this.forceUpdate(); // notification state changed - update }; + private onRoomPropertyUpdate = (property: CachedRoomKey) => { + if (property === CachedRoomKey.NotificationVolume) this.onNotificationUpdate(); + // else ignore - not important for this tile + }; + private get showContextMenu(): boolean { return this.props.tag !== DefaultTagID.Invite; } @@ -141,6 +164,7 @@ export default class RoomTile extends React.PureComponent { this.onRoomPreviewChanged, ); this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate); + this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate); this.props.room?.on("Room.name", this.onRoomNameUpdate); CommunityPrototypeStore.instance.on( CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId), @@ -164,6 +188,7 @@ export default class RoomTile extends React.PureComponent { ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate); defaultDispatcher.unregister(this.dispatcherRef); this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate); + this.roomProps.off(PROPERTY_UPDATED, this.onRoomPropertyUpdate); CommunityPrototypeStore.instance.off( CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId), this.onCommunityUpdate, @@ -221,11 +246,22 @@ export default class RoomTile extends React.PureComponent { this.setState({ selected: isActive }); }; - private onContextMenuOpenClick = (ev: React.MouseEvent) => { + private onNotificationsMenuOpenClick = (ev: React.MouseEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + const target = ev.target as HTMLButtonElement; + this.setState({ notificationsMenuPosition: target.getBoundingClientRect() }); + }; + + private onCloseNotificationsMenu = () => { + this.setState({ notificationsMenuPosition: null }); + }; + + private onGeneralMenuOpenClick = (ev: React.MouseEvent) => { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; - this.setState({ contextMenuPosition: target.getBoundingClientRect() }); + this.setState({ generalMenuPosition: target.getBoundingClientRect() }); }; private onContextMenu = (ev: React.MouseEvent) => { @@ -235,38 +271,275 @@ export default class RoomTile extends React.PureComponent { ev.preventDefault(); ev.stopPropagation(); this.setState({ - contextMenuPosition: { + generalMenuPosition: { left: ev.clientX, bottom: ev.clientY, }, }); }; - private onCloseContextMenu = () => { - this.setState({ contextMenuPosition: null }); + private onCloseGeneralMenu = () => { + this.setState({ generalMenuPosition: null }); }; - private renderContextMenu(): React.ReactElement { - if (!this.showContextMenu) return null; // no menu to show + private onTagRoom = (ev: ButtonEvent, tagId: TagID) => { + ev.preventDefault(); + ev.stopPropagation(); + + if (tagId === DefaultTagID.Favourite || tagId === DefaultTagID.LowPriority) { + const inverseTag = tagId === DefaultTagID.Favourite ? DefaultTagID.LowPriority : DefaultTagID.Favourite; + const isApplied = RoomListStore.instance.getTagsForRoom(this.props.room).includes(tagId); + const removeTag = isApplied ? tagId : inverseTag; + const addTag = isApplied ? null : tagId; + dis.dispatch(RoomListActions.tagRoom( + MatrixClientPeg.get(), + this.props.room, + removeTag, + addTag, + undefined, + 0, + )); + } else { + logger.warn(`Unexpected tag ${tagId} applied to ${this.props.room.roomId}`); + } + + if ((ev as React.KeyboardEvent).key === Key.ENTER) { + // Implements https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-12 + this.setState({ generalMenuPosition: null }); // hide the menu + } + }; + + private onLeaveRoomClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + + dis.dispatch({ + action: 'leave_room', + room_id: this.props.room.roomId, + }); + this.setState({ generalMenuPosition: null }); // hide the menu + }; + + private onForgetRoomClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + + dis.dispatch({ + action: 'forget_room', + room_id: this.props.room.roomId, + }); + this.setState({ generalMenuPosition: null }); // hide the menu + }; + + private onOpenRoomSettings = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + + dis.dispatch({ + action: 'open_room_settings', + room_id: this.props.room.roomId, + }); + this.setState({ generalMenuPosition: null }); // hide the menu + }; + + private onCopyRoomClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + + dis.dispatch({ + action: 'copy_room', + room_id: this.props.room.roomId, + }); + this.setState({ generalMenuPosition: null }); // hide the menu + }; + + private onInviteClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + + dis.dispatch({ + action: 'view_invite', + roomId: this.props.room.roomId, + }); + this.setState({ generalMenuPosition: null }); // hide the menu + }; + + private async saveNotifState(ev: ButtonEvent, newState: RoomNotifState) { + ev.preventDefault(); + ev.stopPropagation(); + if (MatrixClientPeg.get().isGuest()) return; + + this.roomProps.notificationVolume = newState; + + const key = (ev as React.KeyboardEvent).key; + if (key === Key.ENTER) { + // Implements https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-12 + this.setState({ notificationsMenuPosition: null }); // hide the menu + } + } + + private onClickAllNotifs = ev => this.saveNotifState(ev, RoomNotifState.AllMessages); + private onClickAlertMe = ev => this.saveNotifState(ev, RoomNotifState.AllMessagesLoud); + private onClickMentions = ev => this.saveNotifState(ev, RoomNotifState.MentionsOnly); + private onClickMute = ev => this.saveNotifState(ev, RoomNotifState.Mute); + + private renderNotificationsMenu(isActive: boolean): React.ReactElement { + if (MatrixClientPeg.get().isGuest() || this.props.tag === DefaultTagID.Archived || + !this.showContextMenu || this.props.isMinimized + ) { + // the menu makes no sense in these cases so do not show one + return null; + } + + const state = this.roomProps.notificationVolume; let contextMenu = null; - if (this.state.contextMenuPosition) { - contextMenu = ( - + + + + + + + ; + } + + const classes = classNames("mx_RoomTile_notificationsButton", { + // Show bell icon for the default case too. + mx_RoomTile_iconBell: state === RoomNotifState.AllMessages, + mx_RoomTile_iconBellDot: state === RoomNotifState.AllMessagesLoud, + mx_RoomTile_iconBellMentions: state === RoomNotifState.MentionsOnly, + mx_RoomTile_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, + }); + + return ( + + - ); + { contextMenu } + + ); + } + + private renderGeneralMenu(): React.ReactElement { + if (!this.showContextMenu) return null; // no menu to show + + let contextMenu = null; + if (this.state.generalMenuPosition && this.props.tag === DefaultTagID.Archived) { + contextMenu = + + + + ; + } else if (this.state.generalMenuPosition) { + const roomTags = RoomListStore.instance.getTagsForRoom(this.props.room); + + const isFavorite = roomTags.includes(DefaultTagID.Favourite); + const favouriteLabel = isFavorite ? _t("Favourited") : _t("Favourite"); + + const isLowPriority = roomTags.includes(DefaultTagID.LowPriority); + const lowPriorityLabel = _t("Low Priority"); + + const userId = MatrixClientPeg.get().getUserId(); + const canInvite = this.props.room.canInvite(userId); + contextMenu = + + this.onTagRoom(e, DefaultTagID.Favourite)} + active={isFavorite} + label={favouriteLabel} + iconClassName="mx_RoomTile_iconStar" + /> + this.onTagRoom(e, DefaultTagID.LowPriority)} + active={isLowPriority} + label={lowPriorityLabel} + iconClassName="mx_RoomTile_iconArrowDown" + /> + { canInvite ? ( + + ) : null } + + + + + + + ; } return ( { contextMenu } @@ -277,7 +550,7 @@ export default class RoomTile extends React.PureComponent { const classes = classNames({ 'mx_RoomTile': true, 'mx_RoomTile_selected': this.state.selected, - 'mx_RoomTile_hasMenuOpen': this.state.contextMenuPosition, + 'mx_RoomTile_hasMenuOpen': !!(this.state.generalMenuPosition || this.state.notificationsMenuPosition), 'mx_RoomTile_minimized': this.props.isMinimized, }); @@ -367,7 +640,7 @@ export default class RoomTile extends React.PureComponent { Button = AccessibleTooltipButton; props.title = name; // force the tooltip to hide whilst we are showing the context menu - props.forceHide = !!this.state.contextMenuPosition; + props.forceHide = !!this.state.generalMenuPosition; } return ( @@ -390,7 +663,8 @@ export default class RoomTile extends React.PureComponent { { roomAvatar } { nameContainer } { badge } - { this.renderContextMenu() } + { this.renderGeneralMenu() } + { this.renderNotificationsMenu(isActive) } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5770855f05a..078f4a9a534 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1766,6 +1766,17 @@ "Show %(count)s more|other": "Show %(count)s more", "Show %(count)s more|one": "Show %(count)s more", "Show less": "Show less", + "Use default": "Use default", + "Mentions & Keywords": "Mentions & Keywords", + "Notification options": "Notification options", + "Forget Room": "Forget Room", + "Favourited": "Favourited", + "Favourite": "Favourite", + "Low Priority": "Low Priority", + "Invite People": "Invite People", + "Copy Room Link": "Copy Room Link", + "Settings": "Settings", + "Leave Room": "Leave Room", "%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.", "%(count)s unread messages including mentions.|one": "1 unread mention.", "%(count)s unread messages.|other": "%(count)s unread messages.", @@ -2460,7 +2471,6 @@ "Incoming Verification Request": "Incoming Verification Request", "Integrations are disabled": "Integrations are disabled", "Enable 'Manage Integrations' in Settings to do this.": "Enable 'Manage Integrations' in Settings to do this.", - "Settings": "Settings", "Integrations not allowed": "Integrations not allowed", "Your %(brand)s doesn't allow you to use an integration manager to do this. Please contact an admin.": "Your %(brand)s doesn't allow you to use an integration manager to do this. Please contact an admin.", "To continue, use Single Sign On to prove your identity.": "To continue, use Single Sign On to prove your identity.", @@ -2732,8 +2742,6 @@ "View in room": "View in room", "Forget": "Forget", "Leave": "Leave", - "Favourited": "Favourited", - "Favourite": "Favourite", "Mentions only": "Mentions only", "Copy link": "Copy link", "See room timeline (devtools)": "See room timeline (devtools)",