2020-09-24 11:28:49 +03:00
|
|
|
/*
|
|
|
|
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 React, {useContext, useEffect, useMemo} from "react";
|
|
|
|
import {Resizable} from "re-resizable";
|
|
|
|
import classNames from "classnames";
|
|
|
|
|
|
|
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
|
|
|
import {useRovingTabIndex} from "../../accessibility/RovingTabIndex";
|
|
|
|
import {Key} from "../../Keyboard";
|
|
|
|
import {useLocalStorageState} from "../../hooks/useLocalStorageState";
|
|
|
|
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
2020-10-19 23:13:31 +03:00
|
|
|
import WidgetUtils, {IWidgetEvent} from "../../utils/WidgetUtils";
|
2020-09-24 11:28:49 +03:00
|
|
|
import {useAccountData} from "../../hooks/useAccountData";
|
|
|
|
import AppTile from "../views/elements/AppTile";
|
|
|
|
import {useSettingValue} from "../../hooks/useSettings";
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
onResize(): void;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MIN_HEIGHT = 100;
|
2020-09-24 11:34:19 +03:00
|
|
|
const MAX_HEIGHT = 500; // or 50% of the window height
|
2020-09-24 11:28:49 +03:00
|
|
|
const INITIAL_HEIGHT = 280;
|
|
|
|
|
|
|
|
const LeftPanelWidget: React.FC<IProps> = ({ onResize }) => {
|
|
|
|
const cli = useContext(MatrixClientContext);
|
|
|
|
|
2020-10-19 23:13:31 +03:00
|
|
|
const mWidgetsEvent = useAccountData<Record<string, IWidgetEvent>>(cli, "m.widgets");
|
2020-09-24 11:28:49 +03:00
|
|
|
const leftPanelWidgetId = useSettingValue("Widgets.leftPanel");
|
|
|
|
const app = useMemo(() => {
|
|
|
|
if (!mWidgetsEvent || !leftPanelWidgetId) return null;
|
|
|
|
const widgetConfig = Object.values(mWidgetsEvent).find(w => w.id === leftPanelWidgetId);
|
|
|
|
if (!widgetConfig) return null;
|
|
|
|
|
|
|
|
return WidgetUtils.makeAppConfig(
|
|
|
|
widgetConfig.state_key,
|
|
|
|
widgetConfig.content,
|
|
|
|
widgetConfig.sender,
|
|
|
|
null,
|
|
|
|
widgetConfig.id);
|
2020-09-24 11:49:30 +03:00
|
|
|
}, [mWidgetsEvent, leftPanelWidgetId]);
|
2020-09-24 11:28:49 +03:00
|
|
|
|
|
|
|
const [height, setHeight] = useLocalStorageState("left-panel-widget-height", INITIAL_HEIGHT);
|
|
|
|
const [expanded, setExpanded] = useLocalStorageState("left-panel-widget-expanded", true);
|
2021-01-20 16:49:15 +03:00
|
|
|
useEffect(onResize, [expanded, onResize]);
|
2020-09-24 11:28:49 +03:00
|
|
|
|
|
|
|
const [onFocus, isActive, ref] = useRovingTabIndex();
|
|
|
|
const tabIndex = isActive ? 0 : -1;
|
|
|
|
|
|
|
|
if (!app) return null;
|
|
|
|
|
|
|
|
let content;
|
|
|
|
if (expanded) {
|
|
|
|
content = <Resizable
|
|
|
|
size={{height} as any}
|
|
|
|
minHeight={MIN_HEIGHT}
|
2020-09-24 11:34:19 +03:00
|
|
|
maxHeight={Math.min(window.innerHeight / 2, MAX_HEIGHT)}
|
2020-09-24 11:28:49 +03:00
|
|
|
onResize={onResize}
|
|
|
|
onResizeStop={(e, dir, ref, d) => {
|
|
|
|
setHeight(height + d.height);
|
|
|
|
}}
|
|
|
|
handleWrapperClass="mx_LeftPanelWidget_resizerHandles"
|
|
|
|
handleClasses={{top: "mx_LeftPanelWidget_resizerHandle"}}
|
|
|
|
className="mx_LeftPanelWidget_resizeBox"
|
|
|
|
enable={{ top: true }}
|
|
|
|
>
|
|
|
|
<AppTile
|
|
|
|
app={app}
|
|
|
|
fullWidth
|
|
|
|
show
|
|
|
|
showMenubar={false}
|
|
|
|
userWidget
|
|
|
|
userId={cli.getUserId()}
|
|
|
|
creatorUserId={app.creatorUserId}
|
|
|
|
widgetPageTitle={WidgetUtils.getWidgetDataTitle(app)}
|
|
|
|
waitForIframeLoad={app.waitForIframeLoad}
|
|
|
|
/>
|
|
|
|
</Resizable>;
|
|
|
|
}
|
|
|
|
|
|
|
|
return <div className="mx_LeftPanelWidget">
|
|
|
|
<div
|
|
|
|
onFocus={onFocus}
|
2020-09-24 11:49:30 +03:00
|
|
|
className="mx_LeftPanelWidget_headerContainer"
|
2020-09-24 11:28:49 +03:00
|
|
|
onKeyDown={(ev: React.KeyboardEvent) => {
|
|
|
|
switch (ev.key) {
|
|
|
|
case Key.ARROW_LEFT:
|
|
|
|
ev.stopPropagation();
|
|
|
|
setExpanded(false);
|
|
|
|
break;
|
|
|
|
case Key.ARROW_RIGHT: {
|
|
|
|
ev.stopPropagation();
|
|
|
|
setExpanded(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<div className="mx_LeftPanelWidget_stickable">
|
|
|
|
<AccessibleButton
|
|
|
|
onFocus={onFocus}
|
|
|
|
inputRef={ref}
|
|
|
|
tabIndex={tabIndex}
|
|
|
|
className="mx_LeftPanelWidget_headerText"
|
|
|
|
role="treeitem"
|
|
|
|
aria-expanded={expanded}
|
|
|
|
aria-level={1}
|
|
|
|
onClick={() => {
|
|
|
|
setExpanded(e => !e);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<span className={classNames({
|
|
|
|
"mx_LeftPanelWidget_collapseBtn": true,
|
|
|
|
"mx_LeftPanelWidget_collapseBtn_collapsed": !expanded,
|
|
|
|
})} />
|
|
|
|
<span>{ WidgetUtils.getWidgetName(app) }</span>
|
|
|
|
</AccessibleButton>
|
2020-09-24 11:49:30 +03:00
|
|
|
|
|
|
|
{/* Code for the maximise button for once we have full screen widgets */}
|
|
|
|
{/*<AccessibleTooltipButton
|
|
|
|
tabIndex={tabIndex}
|
|
|
|
onClick={() => {
|
|
|
|
}}
|
|
|
|
className="mx_LeftPanelWidget_maximizeButton"
|
|
|
|
tooltipClassName="mx_LeftPanelWidget_maximizeButtonTooltip"
|
|
|
|
title={_t("Maximize")}
|
|
|
|
/>*/}
|
2020-09-24 11:28:49 +03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{ content }
|
|
|
|
</div>;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default LeftPanelWidget;
|