-
+
+
{ this._canUserModify() && addWidget }
);
}
}
+
+const PersistentVResizer = ({
+ id,
+ minHeight,
+ maxHeight,
+ className,
+ handleWrapperClass,
+ handleClass,
+ resizeNotifier,
+ children,
+}) => {
+ const [height, setHeight] = useLocalStorageState("pvr_" + id, 100);
+ const [resizing, setResizing] = useState(false);
+
+ return
{
+ if (!resizing) setResizing(true);
+ resizeNotifier.startResizing();
+ }}
+ onResize={() => {
+ resizeNotifier.notifyTimelineHeightChanged();
+ }}
+ onResizeStop={(e, dir, ref, d) => {
+ setHeight(height + d.height);
+ if (resizing) setResizing(false);
+ resizeNotifier.stopResizing();
+ }}
+ handleWrapperClass={handleWrapperClass}
+ handleClasses={{bottom: handleClass}}
+ className={classNames(className, {
+ mx_AppsDrawer_resizing: resizing,
+ })}
+ enable={{bottom: true}}
+ >
+ { children }
+ ;
+};
diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js
index fc31d66160..1f6f104487 100644
--- a/src/components/views/rooms/AuxPanel.js
+++ b/src/components/views/rooms/AuxPanel.js
@@ -204,6 +204,7 @@ export default class AuxPanel extends React.Component {
maxHeight={this.props.maxHeight}
showApps={this.props.showApps}
hide={this.props.hideAppsDrawer}
+ resizeNotifier={this.props.resizeNotifier}
/>;
let stateViews = null;
diff --git a/src/hooks/useLocalStorageState.ts b/src/hooks/useLocalStorageState.ts
new file mode 100644
index 0000000000..ce3b574f86
--- /dev/null
+++ b/src/hooks/useLocalStorageState.ts
@@ -0,0 +1,44 @@
+/*
+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.
+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];
+};
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/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();
}
}
}
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() {