Fix widget resizing
There was a line of CSS that set pointer-events: none on widget iframes whilst they were being resized to stop iframes swallowing the mousemove/up events while dragging the resize handle, but a) all widgets are now in a persisted element wrapper and therefore not in the right place in the DOM to get that CSS and b) that only got set when resizing the whole aps drawer vertically, not dragging the handle between apps to change the width distribution. Add a pointer events prop to AppTile to allow the pointer-events style to be set by the parent, and set it when dragging either resize handle. Fixes https://github.com/vector-im/element-web/issues/16473
This commit is contained in:
parent
06ad9f0fb8
commit
e5b03488d8
3 changed files with 23 additions and 10 deletions
|
@ -370,11 +370,6 @@ $MinWidth: 240px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoid apptile iframes capturing mouse event focus when resizing */
|
|
||||||
.mx_AppsDrawer_resizing iframe {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AppsDrawer_resizing .mx_AppTile_persistedWrapper {
|
.mx_AppsDrawer_resizing .mx_AppTile_persistedWrapper {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,6 +328,10 @@ export default class AppTile extends React.Component {
|
||||||
const iframeFeatures = "microphone; camera; encrypted-media; autoplay; display-capture;";
|
const iframeFeatures = "microphone; camera; encrypted-media; autoplay; display-capture;";
|
||||||
|
|
||||||
const appTileBodyClass = 'mx_AppTileBody' + (this.props.miniMode ? '_mini ' : ' ');
|
const appTileBodyClass = 'mx_AppTileBody' + (this.props.miniMode ? '_mini ' : ' ');
|
||||||
|
const appTileBodyStyles = {};
|
||||||
|
if (this.props.pointerEvents) {
|
||||||
|
appTileBodyStyles['pointer-events'] = this.props.pointerEvents;
|
||||||
|
}
|
||||||
|
|
||||||
const loadingElement = (
|
const loadingElement = (
|
||||||
<div className="mx_AppLoading_spinner_fadeIn">
|
<div className="mx_AppLoading_spinner_fadeIn">
|
||||||
|
@ -338,7 +342,7 @@ export default class AppTile extends React.Component {
|
||||||
// only possible for room widgets, can assert this.props.room here
|
// only possible for room widgets, can assert this.props.room here
|
||||||
const isEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
|
const isEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
|
||||||
appTileBody = (
|
appTileBody = (
|
||||||
<div className={appTileBodyClass}>
|
<div className={appTileBodyClass} style={appTileBodyStyles}>
|
||||||
<AppPermission
|
<AppPermission
|
||||||
roomId={this.props.room.roomId}
|
roomId={this.props.room.roomId}
|
||||||
creatorUserId={this.props.creatorUserId}
|
creatorUserId={this.props.creatorUserId}
|
||||||
|
@ -350,20 +354,20 @@ export default class AppTile extends React.Component {
|
||||||
);
|
);
|
||||||
} else if (this.state.initialising) {
|
} else if (this.state.initialising) {
|
||||||
appTileBody = (
|
appTileBody = (
|
||||||
<div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')}>
|
<div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')} style={appTileBodyStyles}>
|
||||||
{ loadingElement }
|
{ loadingElement }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (this.isMixedContent()) {
|
if (this.isMixedContent()) {
|
||||||
appTileBody = (
|
appTileBody = (
|
||||||
<div className={appTileBodyClass}>
|
<div className={appTileBodyClass} style={appTileBodyStyles}>
|
||||||
<AppWarning errorMsg="Error - Mixed content" />
|
<AppWarning errorMsg="Error - Mixed content" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
appTileBody = (
|
appTileBody = (
|
||||||
<div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')}>
|
<div className={appTileBodyClass + (this.state.loading ? 'mx_AppLoading' : '')} style={appTileBodyStyles}>
|
||||||
{ this.state.loading && loadingElement }
|
{ this.state.loading && loadingElement }
|
||||||
<iframe
|
<iframe
|
||||||
allow={iframeFeatures}
|
allow={iframeFeatures}
|
||||||
|
@ -477,6 +481,8 @@ AppTile.propTypes = {
|
||||||
showPopout: PropTypes.bool,
|
showPopout: PropTypes.bool,
|
||||||
// Is this an instance of a user widget
|
// Is this an instance of a user widget
|
||||||
userWidget: PropTypes.bool,
|
userWidget: PropTypes.bool,
|
||||||
|
// sets the pointer-events property on the iframe
|
||||||
|
pointerEvents: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
AppTile.defaultProps = {
|
AppTile.defaultProps = {
|
||||||
|
|
|
@ -53,6 +53,8 @@ export default class AppsDrawer extends React.Component {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
apps: this._getApps(),
|
apps: this._getApps(),
|
||||||
|
resizingVertical: false, // true when changing the height of the apps drawer
|
||||||
|
resizingHorizontal: false, // true when chagning the distribution of the width between widgets
|
||||||
};
|
};
|
||||||
|
|
||||||
this._resizeContainer = null;
|
this._resizeContainer = null;
|
||||||
|
@ -85,13 +87,16 @@ export default class AppsDrawer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onIsResizing = (resizing) => {
|
onIsResizing = (resizing) => {
|
||||||
this.setState({ resizing });
|
// This one is the vertical, ie. change height of apps drawer
|
||||||
|
this.setState({ resizingVertical: resizing });
|
||||||
if (!resizing) {
|
if (!resizing) {
|
||||||
this._relaxResizer();
|
this._relaxResizer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_createResizer() {
|
_createResizer() {
|
||||||
|
// This is the horizontal one, changing the distribution of the width between the app tiles
|
||||||
|
// (ie. a vertical resize handle because, the handle itself is vertical...)
|
||||||
const classNames = {
|
const classNames = {
|
||||||
handle: "mx_ResizeHandle",
|
handle: "mx_ResizeHandle",
|
||||||
vertical: "mx_ResizeHandle_vertical",
|
vertical: "mx_ResizeHandle_vertical",
|
||||||
|
@ -100,6 +105,7 @@ export default class AppsDrawer extends React.Component {
|
||||||
const collapseConfig = {
|
const collapseConfig = {
|
||||||
onResizeStart: () => {
|
onResizeStart: () => {
|
||||||
this._resizeContainer.classList.add("mx_AppsDrawer_resizing");
|
this._resizeContainer.classList.add("mx_AppsDrawer_resizing");
|
||||||
|
this.setState({ resizingHorizontal: true });
|
||||||
},
|
},
|
||||||
onResizeStop: () => {
|
onResizeStop: () => {
|
||||||
this._resizeContainer.classList.remove("mx_AppsDrawer_resizing");
|
this._resizeContainer.classList.remove("mx_AppsDrawer_resizing");
|
||||||
|
@ -107,6 +113,7 @@ export default class AppsDrawer extends React.Component {
|
||||||
this.props.room, Container.Top,
|
this.props.room, Container.Top,
|
||||||
this.state.apps.slice(1).map((_, i) => this.resizer.forHandleAt(i).size),
|
this.state.apps.slice(1).map((_, i) => this.resizer.forHandleAt(i).size),
|
||||||
);
|
);
|
||||||
|
this.setState({ resizingHorizontal: false });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// pass a truthy container for now, we won't call attach until we update it
|
// pass a truthy container for now, we won't call attach until we update it
|
||||||
|
@ -162,6 +169,10 @@ export default class AppsDrawer extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isResizing() {
|
||||||
|
return this.state.resizingVertical || this.state.resizingHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
onAction = (action) => {
|
onAction = (action) => {
|
||||||
const hideWidgetKey = this.props.room.roomId + '_hide_widget_drawer';
|
const hideWidgetKey = this.props.room.roomId + '_hide_widget_drawer';
|
||||||
switch (action.action) {
|
switch (action.action) {
|
||||||
|
@ -209,6 +220,7 @@ export default class AppsDrawer extends React.Component {
|
||||||
creatorUserId={app.creatorUserId}
|
creatorUserId={app.creatorUserId}
|
||||||
widgetPageTitle={WidgetUtils.getWidgetDataTitle(app)}
|
widgetPageTitle={WidgetUtils.getWidgetDataTitle(app)}
|
||||||
waitForIframeLoad={app.waitForIframeLoad}
|
waitForIframeLoad={app.waitForIframeLoad}
|
||||||
|
pointerEvents={this.isResizing() ? 'none' : undefined}
|
||||||
/>);
|
/>);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue