From 2e7bd2e3f03da46f171846d9d81466fb414f65d9 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 20 Apr 2020 23:05:50 +0300 Subject: [PATCH 01/13] Use flexboxes in AppTile/AppDrawer CSS for automatic resizing Using flexboxes removes the need for pixel constants, and the app content now resizes to fill the tiles. Signed-off-by: Pauli Virtanen --- res/css/views/rooms/_AppsDrawer.scss | 55 ++++++++++++++++-------- src/components/views/elements/AppTile.js | 12 +++--- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 1b1bab67bc..61da3a360b 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -16,17 +16,14 @@ limitations under the License. */ /* -the tile title bar is 5 (top border) + 12 (title, buttons) + 5 (bottom padding) px = 22px -the body is assumed to be 300px (assumed by at least the sticker pickerm, perhaps elsewhere), -so the body height would be 300px - 22px (room for title bar) = 278px -BUT! the sticker picker also assumes it's a little less high than that because the iframe -for the sticker picker doesn't have any padding or margin on it's bottom. -so subtracking another 5px, which brings us at 273px. + Minimum size for usual AppTiles and fixed size for mini-tiles. */ -$AppsDrawerBodyHeight: 273px; +$AppTileMinHeight: 300px; +$MiniAppTileHeight: 114px; .mx_AppsDrawer { margin: 5px; + display: block; } .mx_AppsDrawer_hidden { @@ -36,7 +33,7 @@ $AppsDrawerBodyHeight: 273px; .mx_AppsContainer { display: flex; flex-direction: row; - align-items: center; + align-items: stretch; justify-content: center; } @@ -44,7 +41,7 @@ $AppsDrawerBodyHeight: 273px; order: 2; cursor: pointer; padding: 0; - margin: 5px auto 5px auto; + margin: 5px auto 5px 0px; color: $accent-color; font-size: $font-12px; } @@ -68,6 +65,9 @@ $AppsDrawerBodyHeight: 273px; margin-right: 5px; border: 5px solid $widget-menu-bar-bg-color; border-radius: 4px; + display: flex; + flex-direction: column; + min-height: $AppTileMinHeight; } .mx_AppTile:last-child { @@ -77,27 +77,40 @@ $AppsDrawerBodyHeight: 273px; .mx_AppTileFullWidth { max-width: 960px; width: 100%; - height: 100%; margin: 0; padding: 0; border: 5px solid $widget-menu-bar-bg-color; border-radius: 4px; + display: flex; + flex-direction: column; + min-height: $AppTileMinHeight; } .mx_AppTile_mini { max-width: 960px; width: 100%; - height: 100%; margin: 0; padding: 0; + display: flex; + flex-direction: column; + height: $MiniAppTileHeight; } -.mx_AppTile_persistedWrapper { - height: $AppsDrawerBodyHeight; +.mx_AppTile.mx_AppTile_minimised, +.mx_AppTileFullWidth.mx_AppTile_minimised, +.mx_AppTile_mini.mx_AppTile_minimised { + min-height: inherit; } +.mx_AppTile .mx_AppTile_persistedWrapper, +.mx_AppTileFullWidth .mx_AppTile_persistedWrapper, .mx_AppTile_mini .mx_AppTile_persistedWrapper { - height: 114px; + flex: 1; +} + +.mx_AppTile_persistedWrapper div { + width: 100%; + height: 100%; } .mx_AppTileMenuBar { @@ -109,6 +122,7 @@ $AppsDrawerBodyHeight: 273px; align-items: center; justify-content: space-between; cursor: pointer; + width: 100%; } .mx_AppTileMenuBar_expanded { @@ -171,7 +185,7 @@ $AppsDrawerBodyHeight: 273px; } .mx_AppTileBody { - height: $AppsDrawerBodyHeight; + height: 100%; width: 100%; overflow: hidden; } @@ -182,6 +196,13 @@ $AppsDrawerBodyHeight: 273px; overflow: hidden; } +.mx_AppTile .mx_AppTileBody, +.mx_AppTileFullWidth .mx_AppTileBody, +.mx_AppTile_mini .mx_AppTileBody_mini { + height: inherit; + flex: 1; +} + .mx_AppTileBody_mini iframe { border: none; width: 100%; @@ -190,7 +211,7 @@ $AppsDrawerBodyHeight: 273px; .mx_AppTileBody iframe { width: 100%; - height: $AppsDrawerBodyHeight; + height: 100%; overflow: hidden; border: none; padding: 0; @@ -330,7 +351,7 @@ form.mx_Custom_Widget_Form div { align-items: center; font-weight: bold; position: relative; - height: $AppsDrawerBodyHeight; + height: 100%; } .mx_AppLoading .mx_Spinner { diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 6a5dfc97e0..61d36723d3 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -775,14 +775,16 @@ export default class AppTile extends React.Component { const showMinimiseButton = this.props.showMinimise && this.props.show; const showMaximiseButton = this.props.showMinimise && !this.props.show; - let appTileClass; + let appTileClasses; if (this.props.miniMode) { - appTileClass = 'mx_AppTile_mini'; + appTileClasses = {mx_AppTile_mini: true}; } else if (this.props.fullWidth) { - appTileClass = 'mx_AppTileFullWidth'; + appTileClasses = {mx_AppTileFullWidth: true}; } else { - appTileClass = 'mx_AppTile'; + appTileClasses = {mx_AppTile: true}; } + appTileClasses.mx_AppTile_minimised = !this.props.show; + appTileClasses = classNames(appTileClasses); const menuBarClasses = classNames({ mx_AppTileMenuBar: true, @@ -814,7 +816,7 @@ export default class AppTile extends React.Component { } return -
+
{ this.props.showMenubar &&
From 11438aeee61cf3faabe170da49150003cd35ae52 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Tue, 21 Apr 2020 00:41:58 +0300 Subject: [PATCH 02/13] Fix resizer/sizer.js mouse event offset calculation The event coordinates are document coordinates, so the offset they are compared to should also be the document one. Signed-off-by: Pauli Virtanen --- src/resizer/sizer.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/resizer/sizer.js b/src/resizer/sizer.js index 50861d34d5..4ce9232457 100644 --- a/src/resizer/sizer.js +++ b/src/resizer/sizer.js @@ -56,6 +56,18 @@ export default class Sizer { return this.vertical ? this.container.offsetTop : this.container.offsetLeft; } + /** @return {number} container offset to document */ + _getPageOffset() { + let element = this.container; + let offset = 0; + while (element) { + const pos = this.vertical ? element.offsetTop : element.offsetLeft; + offset = offset + pos; + element = element.offsetParent; + } + return offset; + } + setItemSize(item, size) { if (this.vertical) { item.style.height = `${Math.round(size)}px`; @@ -80,9 +92,9 @@ export default class Sizer { offsetFromEvent(event) { const pos = this.vertical ? event.pageY : event.pageX; if (this.reverse) { - return (this._getOffset() + this.getTotalSize()) - pos; + return (this._getPageOffset() + this.getTotalSize()) - pos; } else { - return pos - this._getOffset(); + return pos - this._getPageOffset(); } } } From e897e97fd6e15b39aec89080d0096d570dcdfd63 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 23 Apr 2020 22:52:28 +0300 Subject: [PATCH 03/13] Make AppsDrawer resizable by dragging its bottom border Signed-off-by: Pauli Virtanen --- res/css/views/rooms/_AppsDrawer.scss | 38 ++++++++++++++++-- src/components/views/rooms/AppsDrawer.js | 51 +++++++++++++++++++++++- 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 61da3a360b..3a33b73ec9 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -16,9 +16,10 @@ limitations under the License. */ /* - Minimum size for usual AppTiles and fixed size for mini-tiles. + Size settings */ -$AppTileMinHeight: 300px; +$AppsDrawerMinHeight: 50px; +$AppsDrawerDefaultHeight: 300px; $MiniAppTileHeight: 114px; .mx_AppsDrawer { @@ -35,6 +36,13 @@ $MiniAppTileHeight: 114px; flex-direction: row; align-items: stretch; justify-content: center; + min-height: $AppsDrawerMinHeight; + height: $AppsDrawerDefaultHeight; +} + +.mx_AppsDrawer_minimised .mx_AppsContainer { + min-height: inherit; + height: inherit; } .mx_AddWidget_button { @@ -67,7 +75,6 @@ $MiniAppTileHeight: 114px; border-radius: 4px; display: flex; flex-direction: column; - min-height: $AppTileMinHeight; } .mx_AppTile:last-child { @@ -83,7 +90,6 @@ $MiniAppTileHeight: 114px; border-radius: 4px; display: flex; flex-direction: column; - min-height: $AppTileMinHeight; } .mx_AppTile_mini { @@ -378,3 +384,27 @@ form.mx_Custom_Widget_Form div { .mx_AppLoading iframe { display: none; } + +/* Hidden resize handle (Apptile bottom serves as indicator) */ +.mx_AppsDrawer .mx_ResizeHandle > div { + background: inherit; +} + +.mx_AppsDrawer_fullWidth .mx_ResizeHandle { + max-width: 960px; + margin-left: auto; + margin-right: auto; +} + +.mx_AppsDrawer_minimised .mx_ResizeHandle { + display: none; +} + +/* Avoid apptile iframes capturing mouse event focus when resizing */ +.mx_AppsDrawer_resizing iframe { + pointer-events: none; +} + +.mx_AppsDrawer_resizing .mx_AppTile_persistedWrapper { + z-index: 1; +} diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index b64eb33435..842b93170f 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -30,6 +30,9 @@ import WidgetEchoStore from "../../../stores/WidgetEchoStore"; import AccessibleButton from '../elements/AccessibleButton'; import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; import SettingsStore from "../../../settings/SettingsStore"; +import classNames from 'classnames'; +import ResizeHandle from '../elements/ResizeHandle'; +import {Resizer, FixedDistributor} from '../../../resizer'; // The maximum number of widgets that can be added in a room const MAX_WIDGETS = 2; @@ -60,6 +63,7 @@ export default createReactClass({ MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents); WidgetEchoStore.on('update', this._updateApps); this.dispatcherRef = dis.register(this.onAction); + this._createResizer(); }, componentWillUnmount: function() { @@ -69,6 +73,10 @@ export default createReactClass({ } WidgetEchoStore.removeListener('update', this._updateApps); if (this.dispatcherRef) dis.unregister(this.dispatcherRef); + if (this.resizer) { + this.resizer.detach(); + this.resizer = null; + } }, // TODO: [REACT-WARNING] Replace with appropriate lifecycle event @@ -154,6 +162,30 @@ export default createReactClass({ this._launchManageIntegrations(); }, + _createResizer: function() { + if (!this.resizeContainer) { + return; + } + + const classNames = { + handle: "mx_ResizeHandle", + vertical: "mx_ResizeHandle_vertical", + resizing: "mx_AppsDrawer_resizing", + }; + const resizer = new Resizer( + this.resizeContainer, + FixedDistributor, + {}, + ); + resizer.setClassNames(classNames); + resizer.attach(); + this.resizer = resizer; + }, + + _setResizeContainerRef: function(div) { + this.resizeContainer = div; + }, + render: function() { const apps = this.state.apps.map((app, index, arr) => { const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, this.props.room.roomId); @@ -191,6 +223,13 @@ export default createReactClass({ ; } + const containerStyle = { + maxHeight: Math.max(this.props.maxHeight - 50, 300), + }; + if (!this.props.showApps && this.resizer) { + this.resizer.forHandleAt(0).item.clearSize(); + } + let spinner; if ( apps.length === 0 && WidgetEchoStore.roomHasPendingWidgets( @@ -202,12 +241,20 @@ export default createReactClass({ spinner = ; } + const classes = classNames({ + "mx_AppsDrawer": true, + "mx_AppsDrawer_hidden": this.props.hide, + "mx_AppsDrawer_fullWidth": apps.length < 2, + "mx_AppsDrawer_minimised": !this.props.showApps, + }); + return ( -
-
+
+
{ apps } { spinner }
+ { this._canUserModify() && addWidget }
); From 735826015daa75a7cd385a6f206dff283f4cbc0b Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 30 Apr 2020 20:29:08 +0300 Subject: [PATCH 04/13] Make AppsDrawer resize handle easier to grab --- res/css/views/rooms/_AppsDrawer.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 3a33b73ec9..d6fb055bc0 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -386,6 +386,11 @@ form.mx_Custom_Widget_Form div { } /* Hidden resize handle (Apptile bottom serves as indicator) */ +.mx_AppsDrawer .mx_ResizeHandle { + position: relative; + z-index: 1; +} + .mx_AppsDrawer .mx_ResizeHandle > div { background: inherit; } From cca5ccd79d1e6ce6cdedf1d7f8ce49e2a59de87a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 21 Aug 2020 16:29:07 +0100 Subject: [PATCH 05/13] Switch widget resizing to re-resizable and add persistence --- res/css/views/rooms/_AppsDrawer.scss | 61 +++++++++----- res/css/views/voip/_CallContainer.scss | 4 + src/components/structures/RoomView.js | 4 +- .../views/elements/PersistedElement.js | 8 +- src/components/views/rooms/AppsDrawer.js | 79 ++++++++----------- src/hooks/useLocalStorage.ts | 37 +++++++++ 6 files changed, 124 insertions(+), 69 deletions(-) create mode 100644 src/hooks/useLocalStorage.ts diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index aae255f81a..348fb853d4 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -15,16 +15,43 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* - Size settings -*/ -$AppsDrawerMinHeight: 50px; -$AppsDrawerDefaultHeight: 300px; $MiniAppTileHeight: 114px; .mx_AppsDrawer { - margin: 5px; - display: block; + margin: 5px 5px 5px 18px; + position: relative; + display: flex; + flex-direction: column; + overflow: hidden; + + .mx_RoomSublist_resizerHandles { + flex: 0 0 4px; + } + + .mx_RoomSublist_resizerHandle { + cursor: ns-resize; + border-radius: 3px; + + // Override styles from library + width: unset !important; + height: 4px !important; + + // This is positioned directly below frame + position: absolute; + bottom: -8px !important; // override from library + + // Together, these make the bar 64px wide + // These are also overridden from the library + left: calc(50% - 32px) !important; + right: calc(50% - 32px) !important; + } + + &:hover { + .mx_RoomSublist_resizerHandle { + opacity: 0.8; + background: $primary-fg-color; + } + } } .mx_AppsDrawer_hidden { @@ -36,13 +63,13 @@ $MiniAppTileHeight: 114px; flex-direction: row; align-items: stretch; justify-content: center; - min-height: $AppsDrawerMinHeight; - height: $AppsDrawerDefaultHeight; + height: 100%; } .mx_AppsDrawer_minimised .mx_AppsContainer { - min-height: inherit; - height: inherit; + // override the re-resizable inline styles + height: inherit !important; + min-height: inherit !important; } .mx_AddWidget_button { @@ -70,15 +97,14 @@ $MiniAppTileHeight: 114px; .mx_AppTile { max-width: 960px; width: 50%; - margin-right: 5px; border: 5px solid $widget-menu-bar-bg-color; border-radius: 4px; display: flex; flex-direction: column; -} -.mx_AppTile:last-child { - margin-right: 1px; + & + .mx_AppTile { + margin-left: 5px; + } } .mx_AppTileFullWidth { @@ -105,7 +131,7 @@ $MiniAppTileHeight: 114px; .mx_AppTile.mx_AppTile_minimised, .mx_AppTileFullWidth.mx_AppTile_minimised, .mx_AppTile_mini.mx_AppTile_minimised { - min-height: inherit; + height: 14px; } .mx_AppTile .mx_AppTile_persistedWrapper, @@ -117,7 +143,6 @@ $MiniAppTileHeight: 114px; .mx_AppTile_persistedWrapper div { width: 100%; height: 100%; - min-width: 300px; } .mx_AppTileMenuBar { @@ -402,7 +427,7 @@ form.mx_Custom_Widget_Form div { margin-right: auto; } -.mx_AppsDrawer_minimised .mx_ResizeHandle { +.mx_AppsDrawer_minimised .mx_RoomSublist_resizerHandle { display: none; } diff --git a/res/css/views/voip/_CallContainer.scss b/res/css/views/voip/_CallContainer.scss index 8d1b68dd99..4d26d8a312 100644 --- a/res/css/views/voip/_CallContainer.scss +++ b/res/css/views/voip/_CallContainer.scss @@ -36,6 +36,10 @@ limitations under the License. } } + .mx_AppTile_persistedWrapper div { + min-width: 300px; + } + .mx_IncomingCallBox { min-width: 250px; background-color: $primary-bg-color; diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a79e5b0aa8..7605bdbfc0 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1547,9 +1547,9 @@ export default createReactClass({ // header + footer + status + give us at least 120px of scrollback at all times. let auxPanelMaxHeight = window.innerHeight - - (83 + // height of RoomHeader + (54 + // height of RoomHeader 36 + // height of the status area - 72 + // minimum height of the message compmoser + 51 + // minimum height of the message compmoser 120); // amount of desired scrollback // XXX: this is a bit of a hack and might possibly cause the video to push out the page anyway diff --git a/src/components/views/elements/PersistedElement.js b/src/components/views/elements/PersistedElement.js index 7f9bfdebf4..9a64b7c7c4 100644 --- a/src/components/views/elements/PersistedElement.js +++ b/src/components/views/elements/PersistedElement.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; - +import {throttle} from "lodash"; import ResizeObserver from 'resize-observer-polyfill'; import dis from '../../../dispatcher/dispatcher'; @@ -156,7 +156,7 @@ export default class PersistedElement extends React.Component { child.style.display = visible ? 'block' : 'none'; } - updateChildPosition(child, parent) { + updateChildPosition = throttle((child, parent) => { if (!child || !parent) return; const parentRect = parent.getBoundingClientRect(); @@ -167,9 +167,9 @@ export default class PersistedElement extends React.Component { width: parentRect.width + 'px', height: parentRect.height + 'px', }); - } + }, 100, {trailing: true, leading: true}); render() { - return
; + return
; } } diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index f173d76f24..502cbdc692 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -31,8 +31,8 @@ import AccessibleButton from '../elements/AccessibleButton'; import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; import SettingsStore from "../../../settings/SettingsStore"; import classNames from 'classnames'; -import ResizeHandle from '../elements/ResizeHandle'; -import {Resizer, FixedDistributor} from '../../../resizer'; +import {Resizable} from "re-resizable"; +import {useLocalStorageState} from "../../../hooks/useLocalStorage"; // The maximum number of widgets that can be added in a room const MAX_WIDGETS = 2; @@ -63,7 +63,6 @@ export default createReactClass({ MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents); WidgetEchoStore.on('update', this._updateApps); this.dispatcherRef = dis.register(this.onAction); - this._createResizer(); }, componentWillUnmount: function() { @@ -73,10 +72,6 @@ export default createReactClass({ } WidgetEchoStore.removeListener('update', this._updateApps); if (this.dispatcherRef) dis.unregister(this.dispatcherRef); - if (this.resizer) { - this.resizer.detach(); - this.resizer = null; - } }, // TODO: [REACT-WARNING] Replace with appropriate lifecycle event @@ -162,30 +157,6 @@ export default createReactClass({ this._launchManageIntegrations(); }, - _createResizer: function() { - if (!this.resizeContainer) { - return; - } - - const classNames = { - handle: "mx_ResizeHandle", - vertical: "mx_ResizeHandle_vertical", - resizing: "mx_AppsDrawer_resizing", - }; - const resizer = new Resizer( - this.resizeContainer, - FixedDistributor, - {}, - ); - resizer.setClassNames(classNames); - resizer.attach(); - this.resizer = resizer; - }, - - _setResizeContainerRef: function(div) { - this.resizeContainer = div; - }, - render: function() { const apps = this.state.apps.map((app, index, arr) => { const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, this.props.room.roomId); @@ -193,7 +164,7 @@ export default createReactClass({ return (); }); - if (apps.length == 0) { - return
; + if (apps.length === 0) { + return
; } let addWidget; @@ -223,13 +194,6 @@ export default createReactClass({ ; } - const containerStyle = { - maxHeight: Math.max(this.props.maxHeight - 50, 300), - }; - if (!this.props.showApps && this.resizer) { - this.resizer.forHandleAt(0).item.clearSize(); - } - let spinner; if ( apps.length === 0 && WidgetEchoStore.roomHasPendingWidgets( @@ -249,14 +213,39 @@ export default createReactClass({ }); return ( -
-
+
+ { apps } { spinner } -
- + { this._canUserModify() && addWidget }
); }, }); + +const PersistentVResizer = ({id, minHeight, maxHeight, className, handleWrapperClass, handleClass, children}) => { + const [height, setHeight] = useLocalStorageState("pvr_" + id, 100); + + return { + setHeight(height + d.height); + }} + handleWrapperClass={handleWrapperClass} + handleClasses={{bottom: handleClass}} + className={className} + enable={{bottom: true}} + > + { children } + ; +}; diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts new file mode 100644 index 0000000000..2f110c58f2 --- /dev/null +++ b/src/hooks/useLocalStorage.ts @@ -0,0 +1,37 @@ +/* +Copyright 2019 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 {useEffect, useRef, useState} from "react"; + +// Hook behaving like useState but persisting the value to localStorage. Returns same as useState +export const useLocalStorageState = (key: string, initialValue: boolean) => { + const lsKey = useRef("useLocalStorageState_" + key).current; + + const [value, setValue] = useState(() => { + try { + const item = window.localStorage.getItem(lsKey); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + return initialValue; + } + }); + + useEffect(() => { + window.localStorage.setItem(lsKey, JSON.stringify(value)); + }, [lsKey, value]); + + return [value, setValue]; +}; From 35cc1fb06d51290db8da256b773d4be77b101fb7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 21 Aug 2020 16:38:28 +0100 Subject: [PATCH 06/13] small tweaks --- res/css/views/rooms/_AppsDrawer.scss | 8 ++++---- src/components/views/rooms/AppsDrawer.js | 15 +++++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 348fb853d4..1d62e0a9b4 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -24,11 +24,11 @@ $MiniAppTileHeight: 114px; flex-direction: column; overflow: hidden; - .mx_RoomSublist_resizerHandles { + .mx_AppsContainer_resizerHandles { flex: 0 0 4px; } - .mx_RoomSublist_resizerHandle { + .mx_AppsContainer_resizerHandle { cursor: ns-resize; border-radius: 3px; @@ -47,7 +47,7 @@ $MiniAppTileHeight: 114px; } &:hover { - .mx_RoomSublist_resizerHandle { + .mx_AppsContainer_resizerHandle { opacity: 0.8; background: $primary-fg-color; } @@ -427,7 +427,7 @@ form.mx_Custom_Widget_Form div { margin-right: auto; } -.mx_AppsDrawer_minimised .mx_RoomSublist_resizerHandle { +.mx_AppsDrawer_minimised .mx_AppsContainer_resizerHandle { display: none; } diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 502cbdc692..3a60f21f9c 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React, {useState} from 'react'; import PropTypes from 'prop-types'; import createReactClass from 'create-react-class'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; @@ -218,8 +218,8 @@ export default createReactClass({ id={"apps-drawer_" + this.props.room.roomId} minHeight={100} maxHeight={this.props.maxHeight - 50} - handleWrapperClass="mx_RoomSublist_resizerHandles" - handleClass="mx_RoomSublist_resizerHandle" + handleWrapperClass="mx_AppsContainer_resizerHandles" + handleClass="mx_AppsContainer_resizerHandle" className="mx_AppsContainer" > { apps } @@ -233,17 +233,24 @@ export default createReactClass({ const PersistentVResizer = ({id, minHeight, maxHeight, className, handleWrapperClass, handleClass, children}) => { const [height, setHeight] = useLocalStorageState("pvr_" + id, 100); + const [resizing, setResizing] = useState(false); return { + setResizing(true); + }} onResizeStop={(e, dir, ref, d) => { setHeight(height + d.height); + setResizing(false); }} handleWrapperClass={handleWrapperClass} handleClasses={{bottom: handleClass}} - className={className} + className={classNames(className, { + mx_AppsDrawer_resizing: resizing, + })} enable={{bottom: true}} > { children } From 97d8cec94e29e315b1e725f1d87b74d5edfacaef Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 21 Aug 2020 16:40:05 +0100 Subject: [PATCH 07/13] dedup --- src/components/views/rooms/AppsDrawer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 3a60f21f9c..9b37dd3f4f 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -240,11 +240,11 @@ const PersistentVResizer = ({id, minHeight, maxHeight, className, handleWrapperC minHeight={minHeight} maxHeight={maxHeight} onResizeStart={() => { - setResizing(true); + if (!resizing) setResizing(true); }} onResizeStop={(e, dir, ref, d) => { setHeight(height + d.height); - setResizing(false); + if (resizing) setResizing(false); }} handleWrapperClass={handleWrapperClass} handleClasses={{bottom: handleClass}} From dc08fee635641b1fa2eda45e08e221e8ff543d0a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 24 Aug 2020 14:38:58 +0100 Subject: [PATCH 08/13] Fix the resize handle being unreachable when you don't have permission to add widgets --- res/css/views/rooms/_AppsDrawer.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 1d62e0a9b4..13130fc6f6 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -64,6 +64,7 @@ $MiniAppTileHeight: 114px; align-items: stretch; justify-content: center; height: 100%; + margin-bottom: 8px; } .mx_AppsDrawer_minimised .mx_AppsContainer { @@ -76,7 +77,7 @@ $MiniAppTileHeight: 114px; order: 2; cursor: pointer; padding: 0; - margin: 5px auto 5px 0; + margin: -3px auto 5px 0; color: $accent-color; font-size: $font-12px; } From 89ec90cf043d753baa4a15821dae0d758cabd3be Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 27 Aug 2020 10:27:27 +0100 Subject: [PATCH 09/13] Rewrite useLocalStorageState hook --- src/components/views/rooms/AppsDrawer.js | 2 +- src/hooks/useLocalStorage.ts | 37 -------------------- src/hooks/useLocalStorageState.ts | 44 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 38 deletions(-) delete mode 100644 src/hooks/useLocalStorage.ts create mode 100644 src/hooks/useLocalStorageState.ts diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 9b37dd3f4f..f58e0cc8e3 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -32,7 +32,7 @@ import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; import SettingsStore from "../../../settings/SettingsStore"; import classNames from 'classnames'; import {Resizable} from "re-resizable"; -import {useLocalStorageState} from "../../../hooks/useLocalStorage"; +import {useLocalStorageState} from "../../../hooks/useLocalStorageState"; // The maximum number of widgets that can be added in a room const MAX_WIDGETS = 2; diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts deleted file mode 100644 index 2f110c58f2..0000000000 --- a/src/hooks/useLocalStorage.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2019 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 {useEffect, useRef, useState} from "react"; - -// Hook behaving like useState but persisting the value to localStorage. Returns same as useState -export const useLocalStorageState = (key: string, initialValue: boolean) => { - const lsKey = useRef("useLocalStorageState_" + key).current; - - const [value, setValue] = useState(() => { - try { - const item = window.localStorage.getItem(lsKey); - return item ? JSON.parse(item) : initialValue; - } catch (error) { - return initialValue; - } - }); - - useEffect(() => { - window.localStorage.setItem(lsKey, JSON.stringify(value)); - }, [lsKey, value]); - - return [value, setValue]; -}; diff --git a/src/hooks/useLocalStorageState.ts b/src/hooks/useLocalStorageState.ts new file mode 100644 index 0000000000..a75ab55402 --- /dev/null +++ b/src/hooks/useLocalStorageState.ts @@ -0,0 +1,44 @@ +/* +Copyright 2019 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 {Dispatch, SetStateAction, useCallback, useEffect, useState} from "react"; + +const getValue = (key: string, initialValue: T): T => { + try { + const item = window.localStorage.getItem(key); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + return initialValue; + } +}; + +// Hook behaving like useState but persisting the value to localStorage. Returns same as useState +export const useLocalStorageState = (key: string, initialValue: T) => { + const lsKey = "mx_" + key; + + const [value, setValue] = useState(getValue(lsKey, initialValue)); + + useEffect(() => { + setValue(getValue(lsKey, initialValue)); + }, [lsKey, initialValue]); + + const _setValue: Dispatch> = useCallback((v: T) => { + window.localStorage.setItem(lsKey, JSON.stringify(v)); + setValue(v); + }, [lsKey]); + + return [value, _setValue]; +}; From bf3c49b8dfe6bdeeb4558579a489f63f3d534d7a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 27 Aug 2020 10:46:29 +0100 Subject: [PATCH 10/13] Remove redundant CSS rules --- res/css/views/rooms/_AppsDrawer.scss | 20 -------------------- src/components/views/rooms/AppsDrawer.js | 1 - 2 files changed, 21 deletions(-) diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss index 13130fc6f6..fee3d61153 100644 --- a/res/css/views/rooms/_AppsDrawer.scss +++ b/res/css/views/rooms/_AppsDrawer.scss @@ -24,10 +24,6 @@ $MiniAppTileHeight: 114px; flex-direction: column; overflow: hidden; - .mx_AppsContainer_resizerHandles { - flex: 0 0 4px; - } - .mx_AppsContainer_resizerHandle { cursor: ns-resize; border-radius: 3px; @@ -412,22 +408,6 @@ form.mx_Custom_Widget_Form div { display: none; } -/* Hidden resize handle (Apptile bottom serves as indicator) */ -.mx_AppsDrawer .mx_ResizeHandle { - position: relative; - z-index: 1; -} - -.mx_AppsDrawer .mx_ResizeHandle > div { - background: inherit; -} - -.mx_AppsDrawer_fullWidth .mx_ResizeHandle { - max-width: 960px; - margin-left: auto; - margin-right: auto; -} - .mx_AppsDrawer_minimised .mx_AppsContainer_resizerHandle { display: none; } diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index f58e0cc8e3..1446cd505c 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -218,7 +218,6 @@ export default createReactClass({ id={"apps-drawer_" + this.props.room.roomId} minHeight={100} maxHeight={this.props.maxHeight - 50} - handleWrapperClass="mx_AppsContainer_resizerHandles" handleClass="mx_AppsContainer_resizerHandle" className="mx_AppsContainer" > From ccd08aa0bd042311604ce40d962a05adf2ca5348 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 27 Aug 2020 10:56:04 +0100 Subject: [PATCH 11/13] Update src/hooks/useLocalStorageState.ts Co-authored-by: J. Ryan Stinnett --- src/hooks/useLocalStorageState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useLocalStorageState.ts b/src/hooks/useLocalStorageState.ts index a75ab55402..ce3b574f86 100644 --- a/src/hooks/useLocalStorageState.ts +++ b/src/hooks/useLocalStorageState.ts @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +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. From 6178b3c0e200fb66613135e71481cda2b15f6c89 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 2 Sep 2020 11:13:00 +0100 Subject: [PATCH 12/13] Wire up resizeNotifier --- src/components/structures/RoomView.js | 22 +++++++++++++--------- src/components/structures/ScrollPanel.js | 2 +- src/components/views/rooms/AppsDrawer.js | 20 ++++++++++++++++++-- src/components/views/rooms/AuxPanel.js | 1 + 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 7605bdbfc0..33df9b4961 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1886,15 +1886,19 @@ export default createReactClass({ } const auxPanel = ( - + { aux } ); diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 51113f4f56..5c3067c6eb 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -210,6 +210,7 @@ export default createReactClass({ }, onResize: function() { + debuglog("onResize"); this.checkScroll(); // update preventShrinkingState if present if (this.preventShrinkingState) { @@ -239,7 +240,6 @@ export default createReactClass({ // when scrolled all the way down. E.g. Chrome 72 on debian. // so check difference <= 1; return Math.abs(sn.scrollHeight - (sn.scrollTop + sn.clientHeight)) <= 1; - }, // returns the vertical height in the given direction that can be removed from diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 1446cd505c..7124d908de 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -33,6 +33,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import classNames from 'classnames'; import {Resizable} from "re-resizable"; import {useLocalStorageState} from "../../../hooks/useLocalStorageState"; +import ResizeNotifier from "../../../utils/ResizeNotifier"; // The maximum number of widgets that can be added in a room const MAX_WIDGETS = 2; @@ -43,6 +44,7 @@ export default createReactClass({ propTypes: { userId: PropTypes.string.isRequired, room: PropTypes.object.isRequired, + resizeNotifier: PropTypes.instanceOf(ResizeNotifier).isRequired, showApps: PropTypes.bool, // Should apps be rendered hide: PropTypes.bool, // If rendered, should apps drawer be visible }, @@ -217,9 +219,10 @@ export default createReactClass({ { apps } { spinner } @@ -230,7 +233,16 @@ export default createReactClass({ }, }); -const PersistentVResizer = ({id, minHeight, maxHeight, className, handleWrapperClass, handleClass, children}) => { +const PersistentVResizer = ({ + id, + minHeight, + maxHeight, + className, + handleWrapperClass, + handleClass, + resizeNotifier, + children, +}) => { const [height, setHeight] = useLocalStorageState("pvr_" + id, 100); const [resizing, setResizing] = useState(false); @@ -241,9 +253,13 @@ const PersistentVResizer = ({id, minHeight, maxHeight, className, handleWrapperC onResizeStart={() => { if (!resizing) setResizing(true); }} + onResize={() => { + resizeNotifier.notifyTimelineHeightChanged(); + }} onResizeStop={(e, dir, ref, d) => { setHeight(height + d.height); if (resizing) setResizing(false); + resizeNotifier.notifyTimelineHeightChanged(); }} handleWrapperClass={handleWrapperClass} handleClasses={{bottom: handleClass}} diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index 521aeec406..b51e3fefa8 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -203,6 +203,7 @@ export default createReactClass({ maxHeight={this.props.maxHeight} showApps={this.props.showApps} hide={this.props.hideAppsDrawer} + resizeNotifier={this.props.resizeNotifier} />; let stateViews = null; From cffe90250464895e07cb067cb9b48eafbbd33d5b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 2 Sep 2020 12:00:35 +0100 Subject: [PATCH 13/13] Add feature to ResizeNotifier to maintain isResizing state and use it to skip onScroll handling --- src/components/structures/GroupView.js | 2 +- src/components/structures/LoggedInView.tsx | 9 ++++++++- src/components/structures/MainSplit.js | 17 ++++++++++++++--- src/components/structures/RoomView.js | 5 +---- src/components/structures/ScrollPanel.js | 5 +++-- src/components/structures/UserView.js | 4 +++- src/components/views/rooms/AppsDrawer.js | 3 ++- src/resizer/resizer.js | 6 ++++++ src/utils/ResizeNotifier.js | 13 +++++++++++++ 9 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index 2e2fa25169..c6703b1b9a 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -1335,7 +1335,7 @@ export default createReactClass({
- + { this._getMembershipSection() } { this._getGroupSection() } diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index e427eb92cb..33e7c4a238 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -257,6 +257,12 @@ class LoggedInView extends React.Component { window.localStorage.setItem("mx_lhs_size", '' + size); this.props.resizeNotifier.notifyLeftHandleResized(); }, + onResizeStart: () => { + this.props.resizeNotifier.startResizing(); + }, + onResizeStop: () => { + this.props.resizeNotifier.stopResizing(); + }, }; const resizer = new Resizer( this._resizeContainer.current, @@ -650,12 +656,13 @@ class LoggedInView extends React.Component { break; case PageTypes.UserView: - pageElement = ; + pageElement = ; break; case PageTypes.GroupView: pageElement = ; break; } diff --git a/src/components/structures/MainSplit.js b/src/components/structures/MainSplit.js index 800ed76bb9..47dfe83ad6 100644 --- a/src/components/structures/MainSplit.js +++ b/src/components/structures/MainSplit.js @@ -19,9 +19,18 @@ import React from 'react'; import { Resizable } from 're-resizable'; export default class MainSplit extends React.Component { - _onResized = (event, direction, refToElement, delta) => { + _onResizeStart = () => { + this.props.resizeNotifier.startResizing(); + }; + + _onResize = () => { + this.props.resizeNotifier.notifyRightHandleResized(); + }; + + _onResizeStop = (event, direction, refToElement, delta) => { + this.props.resizeNotifier.stopResizing(); window.localStorage.setItem("mx_rhs_size", this._loadSidePanelSize().width + delta.width); - } + }; _loadSidePanelSize() { let rhsSize = parseInt(window.localStorage.getItem("mx_rhs_size"), 10); @@ -58,7 +67,9 @@ export default class MainSplit extends React.Component { bottomLeft: false, topLeft: false, }} - onResizeStop={this._onResized} + onResizeStart={this._onResizeStart} + onResize={this._onResize} + onResizeStop={this._onResizeStop} className="mx_RightPanel_ResizeWrapper" handleClasses={{left: "mx_RightPanel_ResizeHandle"}} > diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 33df9b4961..2e06be7b4c 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -2096,10 +2096,7 @@ export default createReactClass({ onLeaveClick={(myMembership === "join") ? this.onLeaveClick : null} e2eStatus={this.state.e2eStatus} /> - +
{auxPanel}
diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 5c3067c6eb..1e34e7e2ff 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -166,7 +166,7 @@ export default createReactClass({ this._pendingFillRequests = {b: null, f: null}; if (this.props.resizeNotifier) { - this.props.resizeNotifier.on("middlePanelResized", this.onResize); + this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); } this.resetScrollState(); @@ -196,11 +196,12 @@ export default createReactClass({ this.unmounted = true; if (this.props.resizeNotifier) { - this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize); + this.props.resizeNotifier.removeListener("middlePanelResizedNoisy", this.onResize); } }, onScroll: function(ev) { + if (this.props.resizeNotifier.isResizing) return; // skip scroll events caused by resizing debuglog("onScroll", this._getScrollNode().scrollTop); this._scrollTimeout.restart(); this._saveScrollState(); diff --git a/src/components/structures/UserView.js b/src/components/structures/UserView.js index 694592af88..8e21771bb9 100644 --- a/src/components/structures/UserView.js +++ b/src/components/structures/UserView.js @@ -80,7 +80,9 @@ export default class UserView extends React.Component { const RightPanel = sdk.getComponent('structures.RightPanel'); const MainSplit = sdk.getComponent('structures.MainSplit'); const panel = ; - return (); + return ( + + ); } else { return (
); } diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 7124d908de..feda2e8db1 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -252,6 +252,7 @@ const PersistentVResizer = ({ maxHeight={maxHeight} onResizeStart={() => { if (!resizing) setResizing(true); + resizeNotifier.startResizing(); }} onResize={() => { resizeNotifier.notifyTimelineHeightChanged(); @@ -259,7 +260,7 @@ const PersistentVResizer = ({ onResizeStop={(e, dir, ref, d) => { setHeight(height + d.height); if (resizing) setResizing(false); - resizeNotifier.notifyTimelineHeightChanged(); + resizeNotifier.stopResizing(); }} handleWrapperClass={handleWrapperClass} handleClasses={{bottom: handleClass}} diff --git a/src/resizer/resizer.js b/src/resizer/resizer.js index 2234fc5bdf..1e75bf3bdf 100644 --- a/src/resizer/resizer.js +++ b/src/resizer/resizer.js @@ -105,6 +105,9 @@ export default class Resizer { if (this.classNames.resizing) { this.container.classList.add(this.classNames.resizing); } + if (this.config.onResizeStart) { + this.config.onResizeStart(); + } const {sizer, distributor} = this._createSizerAndDistributor(resizeHandle); distributor.start(); @@ -119,6 +122,9 @@ export default class Resizer { if (this.classNames.resizing) { this.container.classList.remove(this.classNames.resizing); } + if (this.config.onResizeStop) { + this.config.onResizeStop(); + } distributor.finish(); body.removeEventListener("mouseup", finishResize, false); document.removeEventListener("mouseleave", finishResize, false); diff --git a/src/utils/ResizeNotifier.js b/src/utils/ResizeNotifier.js index 5467716576..512946828b 100644 --- a/src/utils/ResizeNotifier.js +++ b/src/utils/ResizeNotifier.js @@ -31,6 +31,19 @@ export default class ResizeNotifier extends EventEmitter { // with default options, will call fn once at first call, and then every x ms // if there was another call in that timespan this._throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200); + this._isResizing = false; + } + + get isResizing() { + return this._isResizing; + } + + startResizing() { + this._isResizing = true; + } + + stopResizing() { + this._isResizing = false; } _noisyMiddlePanel() {