From adf186f568037b18e0ae9302d639c1a39dbe0224 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 29 Jun 2020 23:02:10 +0100 Subject: [PATCH 01/11] Fix RoomTile2 Context Menu to match Figma Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_RoomTile2.scss | 8 ++++---- src/components/views/rooms/RoomTile2.tsx | 24 +++++++++++------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/res/css/views/rooms/_RoomTile2.scss b/res/css/views/rooms/_RoomTile2.scss index 2845068de39..f1516ee0e35 100644 --- a/res/css/views/rooms/_RoomTile2.scss +++ b/res/css/views/rooms/_RoomTile2.scss @@ -118,8 +118,7 @@ limitations under the License. } .mx_RoomTile2_menuButton::before { - top: 8px; - left: -1px; // this is off-center to align it with the badges + left: 1px; // this is off-center to align it with the badges mask-image: url('$(res)/img/feather-customised/more-horizontal.svg'); } @@ -133,9 +132,10 @@ limitations under the License. } .mx_RoomTile2_menuButton { - width: 18px; - height: 32px; + width: 16px; + height: 16px; visibility: visible; + margin: auto 0; } } } diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index 1284728855f..59741635f1c 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -64,8 +64,14 @@ interface IState { generalMenuDisplayed: boolean; } +export const contextMenuBelow = (elementRect) => { + const left = elementRect.left + window.pageXOffset - 6; + let top = elementRect.bottom + window.pageYOffset + 21; + const chevronFace = "none"; + return {left, top, chevronFace}; +}; + export default class RoomTile2 extends React.Component { - private roomTileRef: React.RefObject = createRef(); private generalMenuButtonRef: React.RefObject = createRef(); // TODO: a11y: https://github.com/vector-im/riot-web/issues/14180 @@ -159,18 +165,10 @@ export default class RoomTile2 extends React.Component { 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.roomTileRef.current.getBoundingClientRect(); + const elementRect = this.generalMenuButtonRef.current.getBoundingClientRect(); contextMenu = ( - -
+ +
  • @@ -280,7 +278,7 @@ export default class RoomTile2 extends React.Component { const avatarSize = 32; return ( - + {({onFocus, isActive, ref}) => Date: Tue, 30 Jun 2020 00:16:51 +0100 Subject: [PATCH 02/11] Add room notifications context menu and non-default indicator to RoomTile2 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_RoomTile2.scss | 37 ++++++---- src/components/views/rooms/RoomTile2.tsx | 87 +++++++++++++++++++++++- src/i18n/strings/en_EN.json | 4 +- 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/res/css/views/rooms/_RoomTile2.scss b/res/css/views/rooms/_RoomTile2.scss index f1516ee0e35..78a77328823 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 59741635f1c..52b3d444ac0 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 495300f3fec..0ef675c7c8e 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", From 6b2ba8caed50ac0c2a9b2871bf40d05d87d31bde Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 30 Jun 2020 00:27:32 +0100 Subject: [PATCH 03/11] Add svgs Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/img/feather-customised/bell-crossed.svg | 4 ++++ res/img/feather-customised/bell-notification.custom.svg | 5 +++++ res/img/feather-customised/bell.svg | 3 +++ 3 files changed, 12 insertions(+) create mode 100644 res/img/feather-customised/bell-crossed.svg create mode 100644 res/img/feather-customised/bell-notification.custom.svg create mode 100644 res/img/feather-customised/bell.svg diff --git a/res/img/feather-customised/bell-crossed.svg b/res/img/feather-customised/bell-crossed.svg new file mode 100644 index 00000000000..3ca24662b90 --- /dev/null +++ b/res/img/feather-customised/bell-crossed.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/feather-customised/bell-notification.custom.svg b/res/img/feather-customised/bell-notification.custom.svg new file mode 100644 index 00000000000..7bfd551f97a --- /dev/null +++ b/res/img/feather-customised/bell-notification.custom.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/img/feather-customised/bell.svg b/res/img/feather-customised/bell.svg new file mode 100644 index 00000000000..b6bc5ec5029 --- /dev/null +++ b/res/img/feather-customised/bell.svg @@ -0,0 +1,3 @@ + + + From 2a12fd1f6e85d0d201aa9d5e3f439f463930c5bc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 30 Jun 2020 21:58:54 +0100 Subject: [PATCH 04/11] Fix User context menu alignment to match Figma Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 8c06a068528..ef461bf1b45 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -204,7 +204,7 @@ export default class UserMenu extends React.Component { return ( From cbd2a9cd359717556237e8876e9238950e253760 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 30 Jun 2020 22:11:12 +0100 Subject: [PATCH 05/11] Redo Iconized Context Menu styling to match Figma and simplify future a11y work by flattening the DOM Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_common.scss | 115 +++++++++-------------- res/css/structures/_UserMenu.scss | 4 + src/components/structures/UserMenu.tsx | 78 ++++++--------- src/components/views/rooms/RoomTile2.tsx | 86 ++++++----------- 4 files changed, 107 insertions(+), 176 deletions(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index 560bd894c67..0d057d96abd 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -588,27 +588,16 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { // A context menu that largely fits the | [icon] [label] | format. .mx_IconizedContextMenu { - // Put 20px of padding around the whole menu. We do this instead of a - // simple `padding: 20px` rule so the horizontal rules added by the - // optionLists is rendered correctly (full width). - > * { - padding-left: 20px; - padding-right: 20px; - - &:first-child { - padding-top: 20px; - } + min-width: 146px; - &:last-child { - padding-bottom: 16px; + .mx_IconizedContextMenu_optionList { + & > * { + padding-left: 20px; + padding-right: 20px; } - } - .mx_IconizedContextMenu_optionList { // the notFirst class is for cases where the optionList might be under a header of sorts. &:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst { - margin-top: 12px; - // This is a bit of a hack when we could just use a simple border-top property, // however we have a (kinda) good reason for doing it this way: we need opacity. // To get the right color, we need an opacity modifier which means we have to work @@ -631,72 +620,54 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { } } - ul { - list-style: none; - margin: 0; - padding: 0; - - li { - margin: 0; - padding: 12px 0 0; - - .mx_AccessibleButton { - text-decoration: none; - color: $primary-fg-color; - font-size: $font-15px; - line-height: $font-24px; - - // Create a flexbox to more easily define the list items - display: flex; - align-items: center; - - img, .mx_IconizedContextMenu_icon { // icons - width: 16px; - min-width: 16px; - max-width: 16px; - } - - span:last-child { // labels - padding-left: 14px; - width: 100%; - flex: 1; - - // Ellipsize any text overflow - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - } - } + // round the top corners of the top button for the hover effect to be bounded + &:first-child .mx_AccessibleButton:first-child { + border-radius: 4px 4px 0 0; // radius matches .mx_ContextualMenu } - } - &.mx_IconizedContextMenu_compact { - > * { - padding-left: 11px; - padding-right: 16px; + // round the bottom corners of the bottom button for the hover effect to be bounded + &:last-child .mx_AccessibleButton:last-child { + border-radius: 0 0 4px 4px; // radius matches .mx_ContextualMenu + } - &:first-child { - padding-top: 13px; + .mx_AccessibleButton { + padding-top: 12px; + padding-bottom: 12px; + text-decoration: none; + color: $primary-fg-color; + font-size: $font-15px; + line-height: $font-24px; + + // Create a flexbox to more easily define the list items + display: flex; + align-items: center; + + &:hover { + background-color: $menu-selected-color; } - &:last-child { - padding-bottom: 13px; + img, .mx_IconizedContextMenu_icon { // icons + width: 16px; + min-width: 16px; + max-width: 16px; } - } - .mx_IconizedContextMenu_optionList { - &:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst { - margin-top: 10px; + span:last-child { // labels + padding-left: 14px; + width: 100%; + flex: 1; - li:first-child { - padding-top: 10px; - } + // Ellipsize any text overflow + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; } + } + } - li:first-child { - padding-top: 0; - } + &.mx_IconizedContextMenu_compact { + .mx_IconizedContextMenu_optionList > * { + padding: 8px 16px 8px 11px; } } } diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index bbb1e1cc7ba..c958b9eacda 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -86,6 +86,8 @@ limitations under the License. .mx_UserMenu_contextMenu_redRow { .mx_AccessibleButton { + padding-top: 16px; + padding-bottom: 16px; color: $warning-color !important; // !important to override styles from context menu } @@ -95,6 +97,8 @@ limitations under the License. } .mx_UserMenu_contextMenu_header { + padding: 20px; + // Create a flexbox to organize the header a bit easier display: flex; align-items: center; diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index ef461bf1b45..bd222c7f254 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -191,12 +191,10 @@ export default class UserMenu extends React.Component { let homeButton = null; if (this.hasHomePage) { homeButton = ( -
  • - - - {_t("Home")} - -
  • + + + {_t("Home")} + ); } @@ -232,49 +230,33 @@ export default class UserMenu extends React.Component {
{hostingLink}
-
    - {homeButton} -
  • - this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}> - - {_t("Notification settings")} - -
  • -
  • - this.onSettingsOpen(e, USER_SECURITY_TAB)}> - - {_t("Security & privacy")} - -
  • -
  • - this.onSettingsOpen(e, null)}> - - {_t("All settings")} - -
  • -
  • - - - {_t("Archived rooms")} - -
  • -
  • - - - {_t("Feedback")} - -
  • -
+ {homeButton} + this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}> + + {_t("Notification settings")} + + this.onSettingsOpen(e, USER_SECURITY_TAB)}> + + {_t("Security & privacy")} + + this.onSettingsOpen(e, null)}> + + {_t("All settings")} + + + + {_t("Archived rooms")} + + + + {_t("Feedback")} +
-
-
    -
  • - - - {_t("Sign out")} - -
  • -
+
+ + + {_t("Sign out")} +
diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index 52b3d444ac0..f290edc5ddd 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -66,7 +66,7 @@ interface IState { generalMenuDisplayed: boolean; } -export const contextMenuBelow = (elementRect) => { +const contextMenuBelow = (elementRect) => { const left = elementRect.left + window.pageXOffset - 6; let top = elementRect.bottom + window.pageYOffset + 21; const chevronFace = "none"; @@ -185,32 +185,22 @@ export default class RoomTile2 extends React.Component {
-
    -
  • - - - {_t("All messages")} - -
  • -
  • - - - {_t("Default")} - -
  • -
  • - - - {_t("Mentions & Keywords")} - -
  • -
  • - - - {_t("None")} - -
  • -
+ + + {_t("All messages")} + + + + {_t("Default")} + + + + {_t("Mentions & Keywords")} + + + + {_t("None")} +
@@ -252,36 +242,20 @@ export default class RoomTile2 extends React.Component {
-
    -
  • - this.onTagRoom(e, DefaultTagID.Favourite)}> - - {_t("Favourite")} - -
  • -
  • - this.onTagRoom(e, DefaultTagID.LowPriority)}> - - {_t("Low Priority")} - -
  • -
  • - - - {_t("Settings")} - -
  • -
+ this.onTagRoom(e, DefaultTagID.Favourite)}> + + {_t("Favourite")} + + + + {_t("Settings")} +
-
-
    -
  • - - - {_t("Leave Room")} - -
  • -
+
+ + + {_t("Leave Room")} +
From 198958dcdd360baa20fe7459f5b0535edf7a3286 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 30 Jun 2020 22:32:59 +0100 Subject: [PATCH 06/11] Iterate to match figma Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_common.scss | 2 +- res/css/views/rooms/_RoomTile2.scss | 13 ++++ src/components/structures/UserMenu.tsx | 12 ++-- src/components/views/rooms/RoomTile2.tsx | 79 +++++++++++++++++------- src/i18n/strings/en_EN.json | 3 +- 5 files changed, 80 insertions(+), 29 deletions(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index 0d057d96abd..880b01a10e0 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -652,7 +652,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { max-width: 16px; } - span:last-child { // labels + span.mx_IconizedContextMenu_label { // labels padding-left: 14px; width: 100%; flex: 1; diff --git a/res/css/views/rooms/_RoomTile2.scss b/res/css/views/rooms/_RoomTile2.scss index 78a77328823..8933c73045d 100644 --- a/res/css/views/rooms/_RoomTile2.scss +++ b/res/css/views/rooms/_RoomTile2.scss @@ -166,6 +166,9 @@ limitations under the License. .mx_RoomTile2_iconBellCrossed::before { mask-image: url('$(res)/img/feather-customised/bell-crossed.svg'); } +.mx_RoomTile2_iconCheck::before { + mask-image: url('$(res)/img/feather-customised/check.svg'); +} .mx_RoomTile2_contextMenu { .mx_RoomTile2_contextMenu_redRow { @@ -178,6 +181,16 @@ limitations under the License. } } + .mx_RoomTile2_contextMenu_activeRow { + &.mx_AccessibleButton, .mx_AccessibleButton { + color: $accent-color !important; // !important to override styles from context menu + } + + .mx_IconizedContextMenu_icon::before { + background-color: $accent-color; + } + } + .mx_IconizedContextMenu_icon { position: relative; width: 16px; diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index bd222c7f254..4a451629023 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -233,29 +233,29 @@ export default class UserMenu extends React.Component { {homeButton} this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}> - {_t("Notification settings")} + {_t("Notification settings")} this.onSettingsOpen(e, USER_SECURITY_TAB)}> - {_t("Security & privacy")} + {_t("Security & privacy")} this.onSettingsOpen(e, null)}> - {_t("All settings")} + {_t("All settings")} - {_t("Archived rooms")} + {_t("Archived rooms")} - {_t("Feedback")} + {_t("Feedback")}
- {_t("Sign out")} + {_t("Sign out")}
diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index f290edc5ddd..4ed167d594c 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -32,7 +32,7 @@ import NotificationBadge, { TagSpecificNotificationState } from "./NotificationBadge"; import { _t } from "../../../languageHandler"; -import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu"; +import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/ContextMenu"; import { DefaultTagID, TagID } from "../../../stores/room-list/models"; import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore"; import RoomTileIcon from "./RoomTileIcon"; @@ -73,6 +73,34 @@ const contextMenuBelow = (elementRect) => { return {left, top, chevronFace}; }; +type State = ALL_MESSAGES_LOUD | ALL_MESSAGES | MENTIONS_ONLY | MUTE; + +interface INotifOptionProps { + active: boolean; + iconClassName: string; + label: string; + onClick(); +} + +const NotifOption: React.FC = ({active, onClick, iconClassName, label}) => { + const classes = classNames({ + mx_RoomTile2_contextMenu_activeRow: active, + }); + + let activeIcon; + if (active) { + activeIcon = ; + } + + return ( + + + { label } + { activeIcon } + + ); +}; + export default class RoomTile2 extends React.Component { private notificationsMenuButtonRef: React.RefObject = createRef(); private generalMenuButtonRef: React.RefObject = createRef(); @@ -178,6 +206,8 @@ export default class RoomTile2 extends React.Component { private renderNotificationsMenu(): React.ReactElement { if (this.props.isMinimized) return null; // no menu when minimized + const state = getRoomNotifsState(this.props.room.roomId); + let contextMenu = null; if (this.state.notificationsMenuDisplayed) { const elementRect = this.notificationsMenuButtonRef.current.getBoundingClientRect(); @@ -185,29 +215,36 @@ export default class RoomTile2 extends React.Component {
- - - {_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, @@ -244,17 +281,17 @@ export default class RoomTile2 extends React.Component {
this.onTagRoom(e, DefaultTagID.Favourite)}> - {_t("Favourite")} + {_t("Favourite")} - {_t("Settings")} + {_t("Settings")}
- {_t("Leave Room")} + {_t("Leave Room")}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e056576cb13..b23264a297a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1218,11 +1218,11 @@ "%(count)s unread messages.|one": "1 unread message.", "Unread mentions.": "Unread mentions.", "Unread messages.": "Unread messages.", + "Use default": "Use default", "All messages": "All messages", "Mentions & Keywords": "Mentions & Keywords", "Notification options": "Notification options", "Favourite": "Favourite", - "Low Priority": "Low Priority", "Leave Room": "Leave Room", "Room options": "Room options", "Add a topic": "Add a topic", @@ -1903,6 +1903,7 @@ "Mentions only": "Mentions only", "Leave": "Leave", "Forget": "Forget", + "Low Priority": "Low Priority", "Direct Chat": "Direct Chat", "Clear status": "Clear status", "Update status": "Update status", From 508dea1c8976eb8c4e05ad5cdcd7f5a547b160f2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 30 Jun 2020 22:53:30 +0100 Subject: [PATCH 07/11] Wire up Notifications context menu on room tile 2 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomTile2.tsx | 40 +++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index 4ed167d594c..aad9b00860e 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -37,6 +37,8 @@ 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"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { setRoomNotifsState } 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 @@ -73,13 +75,11 @@ const contextMenuBelow = (elementRect) => { return {left, top, chevronFace}; }; -type State = ALL_MESSAGES_LOUD | ALL_MESSAGES | MENTIONS_ONLY | MUTE; - interface INotifOptionProps { active: boolean; iconClassName: string; label: string; - onClick(); + onClick(ev: ButtonEvent); } const NotifOption: React.FC = ({active, onClick, iconClassName, label}) => { @@ -203,8 +203,32 @@ export default class RoomTile2 extends React.Component { this.setState({generalMenuDisplayed: false}); // hide the menu }; + private async saveNotifState(ev: ButtonEvent, newState: ALL_MESSAGES_LOUD | ALL_MESSAGES | MENTIONS_ONLY | MUTE) { + ev.preventDefault(); + ev.stopPropagation(); + if (MatrixClientPeg.get().isGuest()) return; + + try { + // TODO add local echo + await setRoomNotifsState(this.props.room.roomId, newState); + } catch (error) { + // TODO: some form of error notification to the user to inform them that their state change failed. + console.error(error); + } + + // Close the context menu + this.setState({ + notificationsMenuDisplayed: false, + }); + } + + private onClickAllNotifs = ev => this.saveNotifState(ev, ALL_MESSAGES); + private onClickAlertMe = ev => this.saveNotifState(ev, ALL_MESSAGES_LOUD); + private onClickMentions = ev => this.saveNotifState(ev, MENTIONS_ONLY); + private onClickMute = ev => this.saveNotifState(ev, MUTE); + private renderNotificationsMenu(): React.ReactElement { - if (this.props.isMinimized) return null; // no menu when minimized + if (this.props.isMinimized || MatrixClientPeg.get().isGuest()) return null; // no menu when minimized or guest const state = getRoomNotifsState(this.props.room.roomId); @@ -219,25 +243,25 @@ export default class RoomTile2 extends React.Component { label={_t("Use default")} active={state === ALL_MESSAGES} iconClassName="mx_RoomTile2_iconBell" - onClick={this._onClickAllNotifs} + onClick={this.onClickAllNotifs} /> From b5014282a4ed02ca8c186d95a0093f75bba07e11 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 1 Jul 2020 13:59:50 +0100 Subject: [PATCH 08/11] Iterate PR based on Figma design and feedback Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_common.scss | 1 + res/css/views/rooms/_RoomTile2.scss | 5 +++++ src/components/structures/UserMenu.tsx | 1 + src/components/views/rooms/RoomTile2.tsx | 7 ++++--- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index 880b01a10e0..6e706181421 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -631,6 +631,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { } .mx_AccessibleButton { + // pad the inside of the button so that the hover background is padded too padding-top: 12px; padding-bottom: 12px; text-decoration: none; diff --git a/res/css/views/rooms/_RoomTile2.scss b/res/css/views/rooms/_RoomTile2.scss index 8933c73045d..44c5b6ee175 100644 --- a/res/css/views/rooms/_RoomTile2.scss +++ b/res/css/views/rooms/_RoomTile2.scss @@ -92,6 +92,7 @@ limitations under the License. justify-content: center; } + // The context menu buttons are hidden by default .mx_RoomTile2_menuButton, .mx_RoomTile2_notificationsButton { width: 20px; @@ -114,6 +115,7 @@ limitations under the License. } } + // If the room has an overriden notification setting then we always show the notifications menu button .mx_RoomTile2_notificationsButton.mx_RoomTile2_notificationsButton_show { display: block; } @@ -166,6 +168,9 @@ limitations under the License. .mx_RoomTile2_iconBellCrossed::before { mask-image: url('$(res)/img/feather-customised/bell-crossed.svg'); } +.mx_RoomTile2_iconBellMentions::before { + mask-image: url('$(res)/img/feather-customised/bell-mentions.custom.svg'); +} .mx_RoomTile2_iconCheck::before { mask-image: url('$(res)/img/feather-customised/check.svg'); } diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 4a451629023..d6771f30119 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -202,6 +202,7 @@ export default class UserMenu extends React.Component { return ( { const left = elementRect.left + window.pageXOffset - 6; - let top = elementRect.bottom + window.pageYOffset + 21; + let top = elementRect.bottom + window.pageYOffset + 17; const chevronFace = "none"; return {left, top, chevronFace}; }; @@ -209,10 +209,11 @@ export default class RoomTile2 extends React.Component { if (MatrixClientPeg.get().isGuest()) return; try { - // TODO add local echo + // TODO add local echo - https://github.com/vector-im/riot-web/issues/14280 await setRoomNotifsState(this.props.room.roomId, newState); } catch (error) { // TODO: some form of error notification to the user to inform them that their state change failed. + // https://github.com/vector-im/riot-web/issues/14281 console.error(error); } @@ -254,7 +255,7 @@ export default class RoomTile2 extends React.Component { Date: Wed, 1 Jul 2020 14:05:33 +0100 Subject: [PATCH 09/11] align context menus even better Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomTile2.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index d518c74aa70..e12be8b30e1 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -69,7 +69,8 @@ interface IState { } const contextMenuBelow = (elementRect) => { - const left = elementRect.left + window.pageXOffset - 6; + // align the context menu's icons with the icon which opened the context menu + const left = elementRect.left + window.pageXOffset - 9; let top = elementRect.bottom + window.pageYOffset + 17; const chevronFace = "none"; return {left, top, chevronFace}; From 0cbc506ad615aaa5bd37e732edf9712021c9a175 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 1 Jul 2020 14:26:50 +0100 Subject: [PATCH 10/11] add missing svg Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/img/feather-customised/bell-mentions.custom.svg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 res/img/feather-customised/bell-mentions.custom.svg diff --git a/res/img/feather-customised/bell-mentions.custom.svg b/res/img/feather-customised/bell-mentions.custom.svg new file mode 100644 index 00000000000..fcc02f337f0 --- /dev/null +++ b/res/img/feather-customised/bell-mentions.custom.svg @@ -0,0 +1,3 @@ + + + From 9831698b1e004f7166e64c83a06583a1a162b9a8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 1 Jul 2020 14:28:00 +0100 Subject: [PATCH 11/11] Hide notifications menu from invite tiles Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomTile2.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile2.tsx b/src/components/views/rooms/RoomTile2.tsx index 882bd210847..c9a1f39982d 100644 --- a/src/components/views/rooms/RoomTile2.tsx +++ b/src/components/views/rooms/RoomTile2.tsx @@ -230,7 +230,10 @@ export default class RoomTile2 extends React.Component { private onClickMute = ev => this.saveNotifState(ev, MUTE); private renderNotificationsMenu(): React.ReactElement { - if (this.props.isMinimized || MatrixClientPeg.get().isGuest()) return null; // no menu when minimized or guest + if (this.props.isMinimized || MatrixClientPeg.get().isGuest() || this.props.tag === DefaultTagID.Invite) { + // the menu makes no sense in these cases so do not show one + return null; + } const state = getRoomNotifsState(this.props.room.roomId);