Make AppsDrawer resizable by dragging its bottom border
Signed-off-by: Pauli Virtanen <pav@iki.fi>pull/21833/head
parent
11438aeee6
commit
e897e97fd6
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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({
|
|||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
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 = <Loader />;
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className={'mx_AppsDrawer' + (this.props.hide ? ' mx_AppsDrawer_hidden' : '')}>
|
||||
<div id='apps' className='mx_AppsContainer'>
|
||||
<div className={classes} ref={this._setResizeContainerRef}>
|
||||
<div id='apps' className='mx_AppsContainer' style={containerStyle}>
|
||||
{ apps }
|
||||
{ spinner }
|
||||
</div>
|
||||
<ResizeHandle vertical={true} />
|
||||
{ this._canUserModify() && addWidget }
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue