mirror of https://github.com/vector-im/riot-web
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;
|
$MiniAppTileHeight: 114px;
|
||||||
|
|
||||||
.mx_AppsDrawer {
|
.mx_AppsDrawer {
|
||||||
|
@ -35,6 +36,13 @@ $MiniAppTileHeight: 114px;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
min-height: $AppsDrawerMinHeight;
|
||||||
|
height: $AppsDrawerDefaultHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AppsDrawer_minimised .mx_AppsContainer {
|
||||||
|
min-height: inherit;
|
||||||
|
height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AddWidget_button {
|
.mx_AddWidget_button {
|
||||||
|
@ -67,7 +75,6 @@ $MiniAppTileHeight: 114px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: $AppTileMinHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AppTile:last-child {
|
.mx_AppTile:last-child {
|
||||||
|
@ -83,7 +90,6 @@ $MiniAppTileHeight: 114px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: $AppTileMinHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AppTile_mini {
|
.mx_AppTile_mini {
|
||||||
|
@ -378,3 +384,27 @@ form.mx_Custom_Widget_Form div {
|
||||||
.mx_AppLoading iframe {
|
.mx_AppLoading iframe {
|
||||||
display: none;
|
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 AccessibleButton from '../elements/AccessibleButton';
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
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
|
// The maximum number of widgets that can be added in a room
|
||||||
const MAX_WIDGETS = 2;
|
const MAX_WIDGETS = 2;
|
||||||
|
@ -60,6 +63,7 @@ export default createReactClass({
|
||||||
MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents);
|
MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents);
|
||||||
WidgetEchoStore.on('update', this._updateApps);
|
WidgetEchoStore.on('update', this._updateApps);
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
this._createResizer();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -69,6 +73,10 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
WidgetEchoStore.removeListener('update', this._updateApps);
|
WidgetEchoStore.removeListener('update', this._updateApps);
|
||||||
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
|
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
|
||||||
|
if (this.resizer) {
|
||||||
|
this.resizer.detach();
|
||||||
|
this.resizer = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
||||||
|
@ -154,6 +162,30 @@ export default createReactClass({
|
||||||
this._launchManageIntegrations();
|
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() {
|
render: function() {
|
||||||
const apps = this.state.apps.map((app, index, arr) => {
|
const apps = this.state.apps.map((app, index, arr) => {
|
||||||
const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, this.props.room.roomId);
|
const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, this.props.room.roomId);
|
||||||
|
@ -191,6 +223,13 @@ export default createReactClass({
|
||||||
</AccessibleButton>;
|
</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;
|
let spinner;
|
||||||
if (
|
if (
|
||||||
apps.length === 0 && WidgetEchoStore.roomHasPendingWidgets(
|
apps.length === 0 && WidgetEchoStore.roomHasPendingWidgets(
|
||||||
|
@ -202,12 +241,20 @@ export default createReactClass({
|
||||||
spinner = <Loader />;
|
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 (
|
return (
|
||||||
<div className={'mx_AppsDrawer' + (this.props.hide ? ' mx_AppsDrawer_hidden' : '')}>
|
<div className={classes} ref={this._setResizeContainerRef}>
|
||||||
<div id='apps' className='mx_AppsContainer'>
|
<div id='apps' className='mx_AppsContainer' style={containerStyle}>
|
||||||
{ apps }
|
{ apps }
|
||||||
{ spinner }
|
{ spinner }
|
||||||
</div>
|
</div>
|
||||||
|
<ResizeHandle vertical={true} />
|
||||||
{ this._canUserModify() && addWidget }
|
{ this._canUserModify() && addWidget }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue