From bcfdd4d98406ed26c3df7b3e10bd0de92ed2a6dd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 25 Jun 2020 19:38:11 -0600 Subject: [PATCH] Move all of the UserMenu into the UserMenu component --- res/css/structures/_LeftPanel2.scss | 28 +--------- res/css/structures/_UserMenu.scss | 60 ++++++++++++++++----- src/components/structures/LeftPanel2.tsx | 54 +------------------ src/components/structures/UserMenu.tsx | 67 ++++++++++++++++++------ 4 files changed, 100 insertions(+), 109 deletions(-) diff --git a/res/css/structures/_LeftPanel2.scss b/res/css/structures/_LeftPanel2.scss index 0765b628f6..837a1d1f0d 100644 --- a/res/css/structures/_LeftPanel2.scss +++ b/res/css/structures/_LeftPanel2.scss @@ -54,7 +54,7 @@ $tagPanelWidth: 70px; // only applies in this file, used for calculations display: flex; flex-direction: column; - // There's 2 rows when breadcrumbs are present: the top bit and the breadcrumbs + // This is basically just breadcrumbs. The row above that is handled by the UserMenu .mx_LeftPanel2_headerRow { // Create yet another flexbox, this time within the row, to ensure items stay // aligned correctly. This is also a row-based flexbox. @@ -62,32 +62,6 @@ $tagPanelWidth: 70px; // only applies in this file, used for calculations align-items: center; } - .mx_LeftPanel2_userAvatarContainer { - position: relative; // to make default avatars work - margin-right: 8px; - height: 32px; // to remove the unknown 4px gap the browser puts below it - - .mx_LeftPanel2_userAvatar { - border-radius: 32px; // should match avatar size - } - } - - .mx_LeftPanel2_userName { - font-weight: 600; - font-size: $font-15px; - line-height: $font-20px; - flex: 1; - - // Ellipsize any text overflow - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - - .mx_LeftPanel2_headerButtons { - // No special styles: the rest of the layout happens to make it work. - } - .mx_LeftPanel2_breadcrumbsContainer { width: 100%; overflow: hidden; diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index f1dffbd1f5..a15eeb6c81 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -14,6 +14,38 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_UserMenu { + // Create a row-based flexbox to ensure items stay aligned correctly. + display: flex; + align-items: center; + + .mx_UserMenu_userAvatarContainer { + position: relative; // to make default avatars work + margin-right: 8px; + height: 32px; // to remove the unknown 4px gap the browser puts below it + + .mx_UserMenu_userAvatar { + border-radius: 32px; // should match avatar size + } + } + + .mx_UserMenu_userName { + font-weight: 600; + font-size: $font-15px; + line-height: $font-20px; + flex: 1; + + // Ellipsize any text overflow + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .mx_UserMenu_headerButtons { + // No special styles: the rest of the layout happens to make it work. + } +} + .mx_UserMenuButton { > span { width: 16px; @@ -37,10 +69,10 @@ limitations under the License. } } -.mx_UserMenuButton_contextMenu { +.mx_UserMenu_contextMenu { width: 247px; - .mx_UserMenuButton_contextMenu_redRow { + .mx_UserMenu_contextMenu_redRow { .mx_AccessibleButton { color: $warning-color !important; // !important to override styles from context menu } @@ -50,12 +82,12 @@ limitations under the License. } } - .mx_UserMenuButton_contextMenu_header { + .mx_UserMenu_contextMenu_header { // Create a flexbox to organize the header a bit easier display: flex; align-items: center; - .mx_UserMenuButton_contextMenu_name { + .mx_UserMenu_contextMenu_name { // Create another flexbox of columns to handle large user IDs display: flex; flex-direction: column; @@ -72,19 +104,19 @@ limitations under the License. white-space: nowrap; } - .mx_UserMenuButton_contextMenu_displayName { + .mx_UserMenu_contextMenu_displayName { font-weight: bold; font-size: $font-15px; line-height: $font-20px; } - .mx_UserMenuButton_contextMenu_userId { + .mx_UserMenu_contextMenu_userId { font-size: $font-15px; line-height: $font-24px; } } - .mx_UserMenuButton_contextMenu_themeButton { + .mx_UserMenu_contextMenu_themeButton { min-width: 32px; max-width: 32px; width: 32px; @@ -118,31 +150,31 @@ limitations under the License. } } - .mx_UserMenuButton_iconHome::before { + .mx_UserMenu_iconHome::before { mask-image: url('$(res)/img/feather-customised/home.svg'); } - .mx_UserMenuButton_iconBell::before { + .mx_UserMenu_iconBell::before { mask-image: url('$(res)/img/feather-customised/notifications.svg'); } - .mx_UserMenuButton_iconLock::before { + .mx_UserMenu_iconLock::before { mask-image: url('$(res)/img/feather-customised/lock.svg'); } - .mx_UserMenuButton_iconSettings::before { + .mx_UserMenu_iconSettings::before { mask-image: url('$(res)/img/feather-customised/settings.svg'); } - .mx_UserMenuButton_iconArchive::before { + .mx_UserMenu_iconArchive::before { mask-image: url('$(res)/img/feather-customised/archive.svg'); } - .mx_UserMenuButton_iconMessage::before { + .mx_UserMenu_iconMessage::before { mask-image: url('$(res)/img/feather-customised/message-circle.svg'); } - .mx_UserMenuButton_iconSignOut::before { + .mx_UserMenu_iconSignOut::before { mask-image: url('$(res)/img/feather-customised/sign-out.svg'); } } diff --git a/src/components/structures/LeftPanel2.tsx b/src/components/structures/LeftPanel2.tsx index 4731dad1fc..32d6748f94 100644 --- a/src/components/structures/LeftPanel2.tsx +++ b/src/components/structures/LeftPanel2.tsx @@ -22,18 +22,13 @@ import dis from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import RoomList2 from "../views/rooms/RoomList2"; import { Action } from "../../dispatcher/actions"; -import { MatrixClientPeg } from "../../MatrixClientPeg"; -import BaseAvatar from '../views/avatars/BaseAvatar'; -import UserMenu from "./UserMenuButton"; +import UserMenu from "./UserMenu"; import RoomSearch from "./RoomSearch"; import AccessibleButton from "../views/elements/AccessibleButton"; import RoomBreadcrumbs2 from "../views/rooms/RoomBreadcrumbs2"; import { BreadcrumbsStore } from "../../stores/BreadcrumbsStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; import ResizeNotifier from "../../utils/ResizeNotifier"; -import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import { throttle } from 'lodash'; -import { OwnProfileStore } from "../../stores/OwnProfileStore"; /******************************************************************* * CAUTION * @@ -76,32 +71,13 @@ export default class LeftPanel2 extends React.Component { // We watch the middle panel because we don't actually get resized, the middle panel does. // We listen to the noisy channel to avoid choppy reaction times. this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); - - OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate); } public componentWillUnmount() { BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate); this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize); - OwnProfileStore.instance.off(UPDATE_EVENT, this.onProfileUpdate); } - // TSLint wants this to be a member, but we don't want that. - // tslint:disable-next-line - private onRoomStateUpdate = throttle((ev: MatrixEvent) => { - const myUserId = MatrixClientPeg.get().getUserId(); - if (ev.getType() === 'm.room.member' && ev.getSender() === myUserId && ev.getStateKey() === myUserId) { - // noinspection JSIgnoredPromiseFromCall - this.onProfileUpdate(); - } - }, 200, {trailing: true, leading: true}); - - private onProfileUpdate = async () => { - // the store triggered an update, so force a layout update. We don't - // have any state to store here for that to magically happen. - this.forceUpdate(); - }; - private onSearch = (term: string): void => { this.setState({searchFilter: term}); }; @@ -170,7 +146,6 @@ export default class LeftPanel2 extends React.Component { // TODO: Presence // TODO: Breadcrumbs toggle // TODO: Menu button - const avatarSize = 32; // should match border-radius of the avatar let breadcrumbs; if (this.state.showBreadcrumbs) { @@ -181,34 +156,9 @@ export default class LeftPanel2 extends React.Component { ); } - let name = {OwnProfileStore.instance.displayName}; - let buttons = ( - - - - ); - if (this.props.isMinimized) { - name = null; - buttons = null; - } - return (
-
- - - - {name} - {buttons} -
+ {breadcrumbs}
); diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index c927e5c7a7..89593aa702 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -35,8 +35,10 @@ import SdkConfig from "../../SdkConfig"; import {getHomePageUrl} from "../../utils/pages"; import { OwnProfileStore } from "../../stores/OwnProfileStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; +import BaseAvatar from '../views/avatars/BaseAvatar'; interface IProps { + isMinimized: boolean; } interface IState { @@ -158,14 +160,14 @@ export default class UserMenu extends React.Component { defaultDispatcher.dispatch({action: 'view_home_page'}); }; - public render() { + private renderMenuButton(): React.ReactNode { let contextMenu; if (this.state.menuDisplayed) { let hostingLink; const signupLink = getHostingLink("user-context-menu"); if (signupLink) { hostingLink = ( -
+
{_t( "Upgrade to your own domain", {}, { @@ -188,7 +190,7 @@ export default class UserMenu extends React.Component { homeButton = (
  • - + {_t("Home")}
  • @@ -203,18 +205,18 @@ export default class UserMenu extends React.Component { top={elementRect.top + elementRect.height} onFinished={this.onCloseMenu} > -
    -
    -
    - +
    +
    +
    + {OwnProfileStore.instance.displayName} - + {MatrixClientPeg.get().getUserId()}
    @@ -231,31 +233,31 @@ export default class UserMenu extends React.Component { {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")}
  • @@ -263,9 +265,9 @@ export default class UserMenu extends React.Component {
      -
    • +
    • - + {_t("Sign out")}
    • @@ -291,4 +293,37 @@ export default class UserMenu extends React.Component { ); } + + public render() { + const avatarSize = 32; // should match border-radius of the avatar + + let name = {OwnProfileStore.instance.displayName}; + let buttons = ( + + {this.renderMenuButton()} + + ); + if (this.props.isMinimized) { + name = null; + buttons = null; + } + + return ( +
      + + + + {name} + {buttons} +
      + ); + } }