From e897e97fd6e15b39aec89080d0096d570dcdfd63 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 23 Apr 2020 22:52:28 +0300 Subject: [PATCH] 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 }
);