diff --git a/res/css/views/rooms/_RoomTile2.scss b/res/css/views/rooms/_RoomTile2.scss index f1516ee0e3..78a7732882 100644 --- a/res/css/views/rooms/_RoomTile2.scss +++ b/res/css/views/rooms/_RoomTile2.scss @@ -92,20 +92,17 @@ limitations under the License. justify-content: center; } - // The menu button is hidden by default - // TODO: [Notifications] Use mx_RoomTile2_notificationsButton, similar to the following approach: - // https://github.com/matrix-org/matrix-react-sdk/blob/2180a56074f3698fc0241c309a72ba6cad802d1c/res/css/views/rooms/_RoomSublist2.scss#L48-L76 - // You'll need to do the same down below on the &:hover selector for the tile. - // See https://github.com/vector-im/riot-web/issues/13961. - // ... also remove this 5 line TODO comment. .mx_RoomTile2_menuButton, .mx_RoomTile2_notificationsButton { - width: 0; - height: 0; - visibility: hidden; + width: 20px; + height: 20px; + margin: auto 0 auto 8px; position: relative; + display: none; &::before { + top: 2px; + left: 2px; content: ''; width: 16px; height: 16px; @@ -117,8 +114,11 @@ limitations under the License. } } + .mx_RoomTile2_notificationsButton.mx_RoomTile2_notificationsButton_show { + display: block; + } + .mx_RoomTile2_menuButton::before { - left: 1px; // this is off-center to align it with the badges mask-image: url('$(res)/img/feather-customised/more-horizontal.svg'); } @@ -131,11 +131,9 @@ limitations under the License. visibility: hidden; } + .mx_RoomTile2_notificationsButton, .mx_RoomTile2_menuButton { - width: 16px; - height: 16px; - visibility: visible; - margin: auto 0; + display: block; } } } @@ -158,6 +156,17 @@ limitations under the License. } } +// We use these both in context menus and the room tiles +.mx_RoomTile2_iconBell::before { + mask-image: url('$(res)/img/feather-customised/bell.svg'); +} +.mx_RoomTile2_iconBellDot::before { + mask-image: url('$(res)/img/feather-customised/bell-notification.custom.svg'); +} +.mx_RoomTile2_iconBellCrossed::before { + mask-image: url('$(res)/img/feather-customised/bell-crossed.svg'); +} + .mx_RoomTile2_contextMenu { .mx_RoomTile2_contextMenu_redRow { .mx_AccessibleButton { diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index 59741635f1..52b3d444ac 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -36,6 +36,7 @@ import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu"; import { DefaultTagID, TagID } from "../../../stores/room-list/models"; import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore"; import RoomTileIcon from "./RoomTileIcon"; +import { getRoomNotifsState, ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs"; // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231 // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231 @@ -61,6 +62,7 @@ interface IState { hover: boolean; notificationState: INotificationState; selected: boolean; + notificationsMenuDisplayed: boolean; generalMenuDisplayed: boolean; } @@ -72,6 +74,7 @@ export const contextMenuBelow = (elementRect) => { }; export default class RoomTile2 extends React.Component { + private notificationsMenuButtonRef: React.RefObject = createRef(); private generalMenuButtonRef: React.RefObject = createRef(); // TODO: a11y: https://github.com/vector-im/riot-web/issues/14180 @@ -83,6 +86,7 @@ export default class RoomTile2 extends React.Component { hover: false, notificationState: new TagSpecificNotificationState(this.props.room, this.props.tag), selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId, + notificationsMenuDisplayed: false, generalMenuDisplayed: false, }; @@ -117,6 +121,18 @@ export default class RoomTile2 extends React.Component { this.setState({selected: isActive}); }; + private onNotificationsMenuOpenClick = (ev: InputEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + this.setState({notificationsMenuDisplayed: true}); + }; + + private onCloseNotificationsMenu = (ev: InputEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + this.setState({notificationsMenuDisplayed: false}); + }; + private onGeneralMenuOpenClick = (ev: InputEvent) => { ev.preventDefault(); ev.stopPropagation(); @@ -159,12 +175,78 @@ export default class RoomTile2 extends React.Component { this.setState({generalMenuDisplayed: false}); // hide the menu }; + private renderNotificationsMenu(): React.ReactElement { + if (this.props.isMinimized) return null; // no menu when minimized + + let contextMenu = null; + if (this.state.notificationsMenuDisplayed) { + const elementRect = this.notificationsMenuButtonRef.current.getBoundingClientRect(); + contextMenu = ( + +
+
+
    +
  • + + + {_t("All messages")} + +
  • +
  • + + + {_t("Default")} + +
  • +
  • + + + {_t("Mentions & Keywords")} + +
  • +
  • + + + {_t("None")} + +
  • +
+
+
+
+ ); + } + + const state = getRoomNotifsState(this.props.room.roomId); + const classes = classNames("mx_RoomTile2_notificationsButton", { + // Show bell icon for the default case too. + mx_RoomTile2_iconBell: state === ALL_MESSAGES_LOUD || state === ALL_MESSAGES, + mx_RoomTile2_iconBellDot: state === MENTIONS_ONLY, + mx_RoomTile2_iconBellCrossed: state === MUTE, + // XXX: RoomNotifs assumes ALL_MESSAGES is default, this is wrong, + // but cannot be fixed until FTUE Notifications lands. + mx_RoomTile2_notificationsButton_show: state !== ALL_MESSAGES, + }); + + return ( + + + {contextMenu} + + ); + } + private renderGeneralMenu(): React.ReactElement { if (this.props.isMinimized) return null; // no menu when minimized let contextMenu = null; if (this.state.generalMenuDisplayed) { - // The context menu appears within the list, so use the room tile as a reference point const elementRect = this.generalMenuButtonRef.current.getBoundingClientRect(); contextMenu = ( @@ -227,7 +309,7 @@ export default class RoomTile2 extends React.Component { const classes = classNames({ 'mx_RoomTile2': true, 'mx_RoomTile2_selected': this.state.selected, - 'mx_RoomTile2_hasMenuOpen': this.state.generalMenuDisplayed, + 'mx_RoomTile2_hasMenuOpen': this.state.generalMenuDisplayed || this.state.notificationsMenuDisplayed, 'mx_RoomTile2_minimized': this.props.isMinimized, }); @@ -298,6 +380,7 @@ export default class RoomTile2 extends React.Component {
{badge}
+ {this.renderNotificationsMenu()} {this.renderGeneralMenu()} } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 495300f3fe..0ef675c7c8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1218,6 +1218,9 @@ "%(count)s unread messages.|one": "1 unread message.", "Unread mentions.": "Unread mentions.", "Unread messages.": "Unread messages.", + "All messages": "All messages", + "Mentions & Keywords": "Mentions & Keywords", + "Notification options": "Notification options", "Favourite": "Favourite", "Low Priority": "Low Priority", "Leave Room": "Leave Room", @@ -1894,7 +1897,6 @@ "Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s", "Notification settings": "Notification settings", "All messages (noisy)": "All messages (noisy)", - "All messages": "All messages", "Mentions only": "Mentions only", "Leave": "Leave", "Forget": "Forget",