From ed634a2bde594bd67212b43b26a013115f1e0528 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 16:35:40 +0100 Subject: [PATCH 01/14] Add StyledRadioGroup to simplify use of StyledRadioButton and use in Appearance Tab Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../views/elements/StyledRadioGroup.tsx | 61 +++++++++++++++++++ .../tabs/user/AppearanceUserSettingsTab.tsx | 29 +++++---- 2 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/components/views/elements/StyledRadioGroup.tsx diff --git a/src/components/views/elements/StyledRadioGroup.tsx b/src/components/views/elements/StyledRadioGroup.tsx new file mode 100644 index 0000000000..050a8b7adb --- /dev/null +++ b/src/components/views/elements/StyledRadioGroup.tsx @@ -0,0 +1,61 @@ +/* +Copyright 2020 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. +*/ + +import React from "react"; +import classNames from "classnames"; + +import StyledRadioButton from "./StyledRadioButton"; + +interface IDefinition { + value: T; + className?: string; + disabled?: boolean; + label: React.ReactChild; + description?: React.ReactChild; +} + +interface IProps { + name: string; + className?: string; + definitions: IDefinition[]; + value?: T; // if not provided no options will be selected + onChange(newValue: T); +} + +function StyledRadioGroup({name, definitions, value, className, onChange}: IProps) { + const _onChange = e => { + onChange(e.target.value); + }; + + return + {definitions.map(d => + + {d.label} + + {d.description} + )} + ; +} + +export default StyledRadioGroup; diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index e935663bbe..42f8cb01de 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -33,6 +33,7 @@ import StyledCheckbox from '../../../elements/StyledCheckbox'; import SettingsFlag from '../../../elements/SettingsFlag'; import Field from '../../../elements/Field'; import EventTilePreview from '../../../elements/EventTilePreview'; +import StyledRadioGroup from "../../../elements/StyledRadioGroup"; interface IProps { } @@ -116,8 +117,7 @@ export default class AppearanceUserSettingsTab extends React.Component): void => { - const newTheme = e.target.value; + private onThemeChange = (newTheme: string): void => { if (this.state.theme === newTheme) return; // doing getValue in the .catch will still return the value we failed to set, @@ -277,19 +277,18 @@ export default class AppearanceUserSettingsTab extends React.Component {_t("Theme")} {systemThemeSection} -
- {orderedThemes.map(theme => { - return - {theme.name} - ; - })} +
+ ({ + value: t.id, + label: t.name, + disabled: this.state.useSystemTheme, + className: "mx_ThemeSelector_" + t.id, + }))} + onChange={this.onThemeChange} + value={this.state.useSystemTheme ? undefined : this.state.theme} + />
{customThemeForm} From c920cf784e155f545264be990d5e2d1f3742efb5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 23 Jun 2020 08:08:48 -0600 Subject: [PATCH 02/14] Create a StaticNotificationState for representative purposes --- src/components/views/rooms/NotificationBadge.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx index 523b5a55cc..6929341845 100644 --- a/src/components/views/rooms/NotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge.tsx @@ -141,6 +141,20 @@ export default class NotificationBadge extends React.PureComponent Date: Thu, 25 Jun 2020 16:45:01 +0100 Subject: [PATCH 03/14] Add account and room-account data hooks Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/hooks/useAccountData.ts | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/hooks/useAccountData.ts diff --git a/src/hooks/useAccountData.ts b/src/hooks/useAccountData.ts new file mode 100644 index 0000000000..b9b89d1350 --- /dev/null +++ b/src/hooks/useAccountData.ts @@ -0,0 +1,50 @@ +/* +Copyright 2020 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. +*/ + +import {useCallback, useState} from "react"; +import {MatrixClient} from "matrix-js-sdk/src/client"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import {Room} from "matrix-js-sdk/src/models/room"; + +import {useEventEmitter} from "./useEventEmitter"; + +const tryGetContent = (ev?: MatrixEvent) => ev ? ev.getContent() : undefined; + +// Hook to simplify listening to Matrix account data +export const useAccountData = (cli: MatrixClient, eventType: string) => { + const [value, setValue] = useState(() => tryGetContent(cli.getAccountData(eventType))); + + const handler = useCallback((event) => { + if (event.getType() !== eventType) return; + setValue(event.getContent()); + }, [cli, eventType]); + useEventEmitter(cli, "accountData", handler); + + return value || {}; +}; + +// Hook to simplify listening to Matrix room account data +export const useRoomAccountData = (room: Room, eventType: string) => { + const [value, setValue] = useState(() => tryGetContent(room.getAccountData(eventType))); + + const handler = useCallback((event) => { + if (event.getType() !== eventType) return; + setValue(event.getContent()); + }, [room, eventType]); + useEventEmitter(room, "Room.accountData", handler); + + return value || {}; +}; From 4885615a40770ed7823e697e9bc79d9a4aacb790 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 16:55:38 +0100 Subject: [PATCH 04/14] improve typing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/hooks/useAccountData.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useAccountData.ts b/src/hooks/useAccountData.ts index b9b89d1350..dd0d53f0d3 100644 --- a/src/hooks/useAccountData.ts +++ b/src/hooks/useAccountData.ts @@ -33,7 +33,7 @@ export const useAccountData = (cli: MatrixClient, eventType: strin }, [cli, eventType]); useEventEmitter(cli, "accountData", handler); - return value || {}; + return value || {} as T; }; // Hook to simplify listening to Matrix room account data @@ -46,5 +46,5 @@ export const useRoomAccountData = (room: Room, eventType: string) }, [room, eventType]); useEventEmitter(room, "Room.accountData", handler); - return value || {}; + return value || {} as T; }; From 3524d678f7f5dd1a842a9a409f3bee0b97b2bd64 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 21:24:24 +0100 Subject: [PATCH 05/14] Fix Welcome.html URLs Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/BasePlatform.ts | 15 ++++++++++----- src/components/views/auth/Welcome.js | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index d54dc7dd23..aed063ca32 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -227,6 +227,15 @@ export default abstract class BasePlatform { return url; } + // persist hs url and is url for when the user is returned to the app with the login token + // MUST be called before using URLs from getSSOCallbackUrl, internally called by startSingleSignOn + persistSSODetails(mxClient: MatrixClient) { + localStorage.setItem(HOMESERVER_URL_KEY, mxClient.getHomeserverUrl()); + if (mxClient.getIdentityServerUrl()) { + localStorage.setItem(ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl()); + } + } + /** * Begin Single Sign On flows. * @param {MatrixClient} mxClient the matrix client using which we should start the flow @@ -234,11 +243,7 @@ export default abstract class BasePlatform { * @param {string} fragmentAfterLogin the hash to pass to the app during sso callback. */ startSingleSignOn(mxClient: MatrixClient, loginType: "sso" | "cas", fragmentAfterLogin: string) { - // persist hs url and is url for when the user is returned to the app with the login token - localStorage.setItem(HOMESERVER_URL_KEY, mxClient.getHomeserverUrl()); - if (mxClient.getIdentityServerUrl()) { - localStorage.setItem(ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl()); - } + this.persistSSODetails(mxClient); const callbackUrl = this.getSSOCallbackUrl(fragmentAfterLogin); window.location.href = mxClient.getSsoLoginUrl(callbackUrl.toString(), loginType); // redirect to SSO } diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js index 91ba368f70..c01b846739 100644 --- a/src/components/views/auth/Welcome.js +++ b/src/components/views/auth/Welcome.js @@ -45,8 +45,8 @@ export default class Welcome extends React.PureComponent { idBaseUrl: isUrl, }); const plaf = PlatformPeg.get(); - const callbackUrl = plaf.getSSOCallbackUrl(tmpClient.getHomeserverUrl(), tmpClient.getIdentityServerUrl(), - this.props.fragmentAfterLogin); + plaf.persistSSODetails(tmpClient); + const callbackUrl = plaf.getSSOCallbackUrl(this.props.fragmentAfterLogin); return ( From 1c00ae8dd35857bc052b21ee882e863e205e9e2b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 21:59:46 +0100 Subject: [PATCH 06/14] Move to mx_sso_hs_url and co for sso persistance to not conflict with guest creds Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/BasePlatform.ts | 21 ++++++++------------ src/Lifecycle.js | 9 ++++++--- src/components/structures/auth/SoftLogout.js | 6 +++--- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index aed063ca32..1d11495e61 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -25,8 +25,8 @@ import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload"; import {Action} from "./dispatcher/actions"; import {hideToast as hideUpdateToast} from "./toasts/UpdateToast"; -export const HOMESERVER_URL_KEY = "mx_hs_url"; -export const ID_SERVER_URL_KEY = "mx_is_url"; +export const SSO_HOMESERVER_URL_KEY = "mx_sso_hs_url"; +export const SSO_ID_SERVER_URL_KEY = "mx_sso_is_url"; export enum UpdateCheckStatus { Checking = "CHECKING", @@ -221,21 +221,12 @@ export default abstract class BasePlatform { setLanguage(preferredLangs: string[]) {} - getSSOCallbackUrl(fragmentAfterLogin: string): URL { + protected getSSOCallbackUrl(fragmentAfterLogin: string): URL { const url = new URL(window.location.href); url.hash = fragmentAfterLogin || ""; return url; } - // persist hs url and is url for when the user is returned to the app with the login token - // MUST be called before using URLs from getSSOCallbackUrl, internally called by startSingleSignOn - persistSSODetails(mxClient: MatrixClient) { - localStorage.setItem(HOMESERVER_URL_KEY, mxClient.getHomeserverUrl()); - if (mxClient.getIdentityServerUrl()) { - localStorage.setItem(ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl()); - } - } - /** * Begin Single Sign On flows. * @param {MatrixClient} mxClient the matrix client using which we should start the flow @@ -243,7 +234,11 @@ export default abstract class BasePlatform { * @param {string} fragmentAfterLogin the hash to pass to the app during sso callback. */ startSingleSignOn(mxClient: MatrixClient, loginType: "sso" | "cas", fragmentAfterLogin: string) { - this.persistSSODetails(mxClient); + // persist hs url and is url for when the user is returned to the app with the login token + localStorage.setItem(SSO_HOMESERVER_URL_KEY, mxClient.getHomeserverUrl()); + if (mxClient.getIdentityServerUrl()) { + localStorage.setItem(SSO_ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl()); + } const callbackUrl = this.getSSOCallbackUrl(fragmentAfterLogin); window.location.href = mxClient.getSsoLoginUrl(callbackUrl.toString(), loginType); // redirect to SSO } diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 96cefaf593..facde3011c 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -41,7 +41,10 @@ import {IntegrationManagers} from "./integrations/IntegrationManagers"; import {Mjolnir} from "./mjolnir/Mjolnir"; import DeviceListener from "./DeviceListener"; import {Jitsi} from "./widgets/Jitsi"; -import {HOMESERVER_URL_KEY, ID_SERVER_URL_KEY} from "./BasePlatform"; +import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform"; + +export const HOMESERVER_URL_KEY = "mx_hs_url"; +export const ID_SERVER_URL_KEY = "mx_is_url"; /** * Called at startup, to attempt to build a logged-in Matrix session. It tries @@ -164,8 +167,8 @@ export function attemptTokenLogin(queryParams, defaultDeviceDisplayName) { return Promise.resolve(false); } - const homeserver = localStorage.getItem(HOMESERVER_URL_KEY); - const identityServer = localStorage.getItem(ID_SERVER_URL_KEY); + const homeserver = localStorage.getItem(SSO_HOMESERVER_URL_KEY); + const identityServer = localStorage.getItem(SSO_ID_SERVER_URL_KEY); if (!homeserver) { console.warn("Cannot log in with token: can't determine HS URL to use"); return Promise.resolve(false); diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js index a2824b63a3..6577386fae 100644 --- a/src/components/structures/auth/SoftLogout.js +++ b/src/components/structures/auth/SoftLogout.js @@ -25,7 +25,7 @@ import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {sendLoginRequest} from "../../../Login"; import AuthPage from "../../views/auth/AuthPage"; import SSOButton from "../../views/elements/SSOButton"; -import {HOMESERVER_URL_KEY, ID_SERVER_URL_KEY} from "../../../BasePlatform"; +import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "../../../BasePlatform"; const LOGIN_VIEW = { LOADING: 1, @@ -158,8 +158,8 @@ export default class SoftLogout extends React.Component { async trySsoLogin() { this.setState({busy: true}); - const hsUrl = localStorage.getItem(HOMESERVER_URL_KEY); - const isUrl = localStorage.getItem(ID_SERVER_URL_KEY) || MatrixClientPeg.get().getIdentityServerUrl(); + const hsUrl = localStorage.getItem(SSO_HOMESERVER_URL_KEY); + const isUrl = localStorage.getItem(SSO_ID_SERVER_URL_KEY) || MatrixClientPeg.get().getIdentityServerUrl(); const loginType = "m.login.token"; const loginParams = { token: this.props.realQueryParams['loginToken'], From c65ccbcacf1ab3096c405434da6ec91349aebf75 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 22:00:22 +0100 Subject: [PATCH 07/14] Instead of passing sso and cas urls to Welcome, route via start_sso and start_cas Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 26 ++++++++++++++++++++---- src/components/views/auth/Welcome.js | 15 ++------------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index d5f73fa3df..a48b1e62a9 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -18,6 +18,7 @@ limitations under the License. */ import React, { createRef } from 'react'; +import { createClient } from "matrix-js-sdk"; import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; @@ -1612,6 +1613,19 @@ export default class MatrixChat extends React.PureComponent { }); } else if (screen === 'directory') { dis.fire(Action.ViewRoomDirectory); + } else if (screen === "start_sso" || screen === "start_cas") { + // TODO if logged in, skip SSO + let cli = MatrixClientPeg.get(); + if (!cli) { + const {hsUrl, isUrl} = this.props.serverConfig; + cli = createClient({ + baseUrl: hsUrl, + idBaseUrl: isUrl, + }); + } + + const type = screen === "start_sso" ? "sso" : "cas"; + PlatformPeg.get().startSingleSignOn(cli, type, this.getFragmentAfterLogin()); } else if (screen === 'groups') { dis.dispatch({ action: 'view_my_groups', @@ -1922,9 +1936,7 @@ export default class MatrixChat extends React.PureComponent { this.onLoggedIn(); }; - render() { - // console.log(`Rendering MatrixChat with view ${this.state.view}`); - + getFragmentAfterLogin() { let fragmentAfterLogin = ""; if (this.props.initialScreenAfterLogin && // XXX: workaround for https://github.com/vector-im/riot-web/issues/11643 causing a login-loop @@ -1932,7 +1944,13 @@ export default class MatrixChat extends React.PureComponent { ) { fragmentAfterLogin = `/${this.props.initialScreenAfterLogin.screen}`; } + return fragmentAfterLogin; + } + render() { + // console.log(`Rendering MatrixChat with view ${this.state.view}`); + + const fragmentAfterLogin = this.getFragmentAfterLogin(); let view; if (this.state.view === Views.LOADING) { @@ -2011,7 +2029,7 @@ export default class MatrixChat extends React.PureComponent { } } else if (this.state.view === Views.WELCOME) { const Welcome = sdk.getComponent('auth.Welcome'); - view = ; + view = ; } else if (this.state.view === Views.REGISTER) { const Registration = sdk.getComponent('structures.auth.Registration'); view = ( diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js index c01b846739..5a30a02490 100644 --- a/src/components/views/auth/Welcome.js +++ b/src/components/views/auth/Welcome.js @@ -18,9 +18,7 @@ import React from 'react'; import * as sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import AuthPage from "./AuthPage"; -import * as Matrix from "matrix-js-sdk"; import {_td} from "../../../languageHandler"; -import PlatformPeg from "../../../PlatformPeg"; // translatable strings for Welcome pages _td("Sign in with SSO"); @@ -39,15 +37,6 @@ export default class Welcome extends React.PureComponent { pageUrl = 'welcome.html'; } - const {hsUrl, isUrl} = this.props.serverConfig; - const tmpClient = Matrix.createClient({ - baseUrl: hsUrl, - idBaseUrl: isUrl, - }); - const plaf = PlatformPeg.get(); - plaf.persistSSODetails(tmpClient); - const callbackUrl = plaf.getSSOCallbackUrl(this.props.fragmentAfterLogin); - return (
@@ -55,8 +44,8 @@ export default class Welcome extends React.PureComponent { className="mx_WelcomePage" url={pageUrl} replaceMap={{ - "$riot:ssoUrl": tmpClient.getSsoLoginUrl(callbackUrl.toString(), "sso"), - "$riot:casUrl": tmpClient.getSsoLoginUrl(callbackUrl.toString(), "cas"), + "$riot:ssoUrl": "#/start_sso", + "$riot:casUrl": "#/start_cas", }} /> From f02c52b758439022b1746d0006d2e54dd1163ec0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 22:01:41 +0100 Subject: [PATCH 08/14] unexport things which need not exporting Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/Lifecycle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index facde3011c..9ae4ae7e03 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -43,8 +43,8 @@ import DeviceListener from "./DeviceListener"; import {Jitsi} from "./widgets/Jitsi"; import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform"; -export const HOMESERVER_URL_KEY = "mx_hs_url"; -export const ID_SERVER_URL_KEY = "mx_is_url"; +const HOMESERVER_URL_KEY = "mx_hs_url"; +const ID_SERVER_URL_KEY = "mx_is_url"; /** * Called at startup, to attempt to build a logged-in Matrix session. It tries From 29b0505bdbbfe21162d4a0c978a06238dc5f0991 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 22:02:39 +0100 Subject: [PATCH 09/14] Welcome no longer needs any props Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index a48b1e62a9..26621fb439 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -2029,7 +2029,7 @@ export default class MatrixChat extends React.PureComponent { } } else if (this.state.view === Views.WELCOME) { const Welcome = sdk.getComponent('auth.Welcome'); - view = ; + view = ; } else if (this.state.view === Views.REGISTER) { const Registration = sdk.getComponent('structures.auth.Registration'); view = ( From 555078a9935ade0ed3b0181a012a0a6a59cf2ef5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 25 Jun 2020 16:03:56 -0600 Subject: [PATCH 10/14] Iterate on the new room list resize handle Only show shadow when resizing, increase the hit area, and make the handle show up when the list itself is hovered. --- res/css/views/rooms/_RoomSublist2.scss | 21 ++++++++++----------- src/components/views/rooms/RoomSublist2.tsx | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/res/css/views/rooms/_RoomSublist2.scss b/res/css/views/rooms/_RoomSublist2.scss index 5f2e9e093b..cbe471e4da 100644 --- a/res/css/views/rooms/_RoomSublist2.scss +++ b/res/css/views/rooms/_RoomSublist2.scss @@ -245,24 +245,23 @@ limitations under the License. cursor: ns-resize; border-radius: 3px; - // Update the render() function for RoomSublist2 if this changes - height: 3px; + // Update RESIZE_HANDLE_HEIGHT if this changes + height: 4px; // This is positioned directly below the 'show more' button. position: absolute; bottom: 0; - // Together, these make the bar 48px wide - left: calc(50% - 24px); - right: calc(50% - 24px); + // Together, these make the bar 64px wide + left: calc(50% - 32px); + right: calc(50% - 32px); } - // TODO: Use less sketchy selector by replacing the resize component entirely - // This causes flickering. - .mx_RoomSublist2_showNButton:hover + .react-resizable-handle, - .react-resizable-handle:hover { - opacity: 0.8; - background-color: $primary-fg-color; + &:hover, &.mx_RoomSublist2_hasMenuOpen { + .react-resizable-handle { + opacity: 0.8; + background-color: $primary-fg-color; + } } } diff --git a/src/components/views/rooms/RoomSublist2.tsx b/src/components/views/rooms/RoomSublist2.tsx index 015ad5b646..7273e80c61 100644 --- a/src/components/views/rooms/RoomSublist2.tsx +++ b/src/components/views/rooms/RoomSublist2.tsx @@ -43,7 +43,7 @@ import { TagID } from "../../../stores/room-list/models"; *******************************************************************/ const SHOW_N_BUTTON_HEIGHT = 32; // As defined by CSS -const RESIZE_HANDLE_HEIGHT = 3; // As defined by CSS +const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS const MAX_PADDING_HEIGHT = SHOW_N_BUTTON_HEIGHT + RESIZE_HANDLE_HEIGHT; @@ -70,6 +70,7 @@ interface IProps { interface IState { notificationState: ListNotificationState; menuDisplayed: boolean; + isResizing: boolean; } export default class RoomSublist2 extends React.Component { @@ -82,6 +83,7 @@ export default class RoomSublist2 extends React.Component { this.state = { notificationState: new ListNotificationState(this.props.isInvite, this.props.tagId), menuDisplayed: false, + isResizing: false, }; this.state.notificationState.setRooms(this.props.rooms); } @@ -111,6 +113,14 @@ export default class RoomSublist2 extends React.Component { this.forceUpdate(); // because the layout doesn't trigger a re-render }; + private onResizeStart = () => { + this.setState({isResizing: true}); + }; + + private onResizeStop = () => { + this.setState({isResizing: false}); + }; + private onShowAllClick = () => { this.props.layout.visibleTiles = this.props.layout.tilesWithPadding(this.numTiles, MAX_PADDING_HEIGHT); this.forceUpdate(); // because the layout doesn't trigger a re-render @@ -359,7 +369,7 @@ export default class RoomSublist2 extends React.Component { const maxTilesFactored = layout.tilesWithResizerBoxFactor(tiles.length); const showMoreBtnClasses = classNames({ 'mx_RoomSublist2_showNButton': true, - 'mx_RoomSublist2_isCutting': layout.visibleTiles < maxTilesFactored, + 'mx_RoomSublist2_isCutting': this.state.isResizing && layout.visibleTiles < maxTilesFactored, }); // If we're hiding rooms, show a 'show more' button to the user. This button @@ -438,6 +448,8 @@ export default class RoomSublist2 extends React.Component { resizeHandles={handles} onResize={this.onResize} className="mx_RoomSublist2_resizeBox" + onResizeStart={this.onResizeStart} + onResizeStop={this.onResizeStop} > {visibleTiles} {showNButton} From 6116cfc2b96d753dbbe32b88c0ae8f715ad9a2de Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 Jun 2020 23:52:32 +0100 Subject: [PATCH 11/14] js-sdk imports suck Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 26621fb439..7f838f1e9e 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -18,7 +18,7 @@ limitations under the License. */ import React, { createRef } from 'react'; -import { createClient } from "matrix-js-sdk"; +import { createClient } from "matrix-js-sdk/src"; import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; @@ -1948,8 +1948,6 @@ export default class MatrixChat extends React.PureComponent { } render() { - // console.log(`Rendering MatrixChat with view ${this.state.view}`); - const fragmentAfterLogin = this.getFragmentAfterLogin(); let view; From 9391d151f363289b9860014c33a5508104a8edfb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 26 Jun 2020 09:15:02 +0100 Subject: [PATCH 12/14] ts-ignore because something is made of fail Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 7f838f1e9e..a205a4fb26 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1620,6 +1620,7 @@ export default class MatrixChat extends React.PureComponent { const {hsUrl, isUrl} = this.props.serverConfig; cli = createClient({ baseUrl: hsUrl, + // @ts-ignore - XXX: remove me when it doesn't break tests idBaseUrl: isUrl, }); } From 274e6f3825cdd0ffcaf67d34bff44f10c2730e15 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 26 Jun 2020 09:35:29 +0100 Subject: [PATCH 13/14] make js-sdk import happy? Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index a205a4fb26..9ee8a50c50 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -18,7 +18,7 @@ limitations under the License. */ import React, { createRef } from 'react'; -import { createClient } from "matrix-js-sdk/src"; +import * as Matrix from "matrix-js-sdk"; import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; @@ -1618,9 +1618,8 @@ export default class MatrixChat extends React.PureComponent { let cli = MatrixClientPeg.get(); if (!cli) { const {hsUrl, isUrl} = this.props.serverConfig; - cli = createClient({ + cli = Matrix.createClient({ baseUrl: hsUrl, - // @ts-ignore - XXX: remove me when it doesn't break tests idBaseUrl: isUrl, }); } From a905028d3a12c241004cb290d569a044feb1e52b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 26 Jun 2020 09:37:55 +0100 Subject: [PATCH 14/14] bandaid Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 9ee8a50c50..7da565739e 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -18,6 +18,7 @@ limitations under the License. */ import React, { createRef } from 'react'; +// @ts-ignore - XXX: no idea why this import fails import * as Matrix from "matrix-js-sdk"; import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";