diff --git a/res/css/_components.scss b/res/css/_components.scss index 45ed6b33002..27ec1088c34 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -155,9 +155,12 @@ @import "./views/messages/_UnknownBody.scss"; @import "./views/messages/_ViewSourceEvent.scss"; @import "./views/messages/_common_CryptoEvent.scss"; +@import "./views/right_panel/_BaseCard.scss"; @import "./views/right_panel/_EncryptionInfo.scss"; +@import "./views/right_panel/_RoomSummaryCard.scss"; @import "./views/right_panel/_UserInfo.scss"; @import "./views/right_panel/_VerificationPanel.scss"; +@import "./views/right_panel/_WidgetCard.scss"; @import "./views/room_settings/_AliasSettings.scss"; @import "./views/rooms/_AppsDrawer.scss"; @import "./views/rooms/_Autocomplete.scss"; diff --git a/res/css/views/right_panel/_BaseCard.scss b/res/css/views/right_panel/_BaseCard.scss new file mode 100644 index 00000000000..c66b7261e30 --- /dev/null +++ b/res/css/views/right_panel/_BaseCard.scss @@ -0,0 +1,164 @@ +/* +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. +*/ + +.mx_BaseCard { + padding: 0 8px; + overflow: hidden; + display: flex; + flex-direction: column; + flex: 1; + + .mx_BaseCard_header { + margin: 8px 0; + + h2 { + margin: 0 44px; + font-size: $font-18px; + font-weight: $font-semi-bold; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .mx_BaseCard_back, .mx_BaseCard_close { + position: absolute; + background-color: rgba(141, 151, 165, 0.2); // TODO + height: 20px; + width: 20px; + margin: 12px; + top: 0; + + &::before { + content: ""; + position: absolute; + height: 16px; + width: 16px; + top: 2px; + left: 2px; + mask-repeat: no-repeat; + mask-position: center; + background-color: $rightpanel-button-color; + } + } + + .mx_BaseCard_back { + border-radius: 4px; + left: 0; + + &::before { + transform: rotate(90deg); + mask-size: 20px; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); // TODO + } + } + + .mx_BaseCard_close { + border-radius: 10px; + right: 0; + + &::before { + mask-image: url('$(res)/img/icons-close.svg'); // TODO + } + } + } + + .mx_AutoHideScrollbar { + // collapse the margin into a padding to move the scrollbar into the right gutter + margin-right: -8px; + padding-right: 8px; + min-height: 0; + width: 100%; + height: 100%; + } + + .mx_BaseCard_Group { + margin: 20px 0 16px; + + & > * { + margin-left: 10px; + margin-right: 10px; + } + + h1 { + color: $tertiary-fg-color; + font-size: $font-12px; + font-weight: 500; + } + + .mx_BaseCard_Button { + padding: 10px 38px 10px 12px; + margin: 0; + position: relative; + font-size: $font-13px; + height: 20px; + line-height: 20px; + border-radius: 8px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + &:hover { + background-color: rgba(141, 151, 165, 0.1); + } + + &::after { + content: ''; + position: absolute; + top: 10px; + right: 6px; + height: 20px; + width: 20px; + mask-repeat: no-repeat; + mask-position: center; + background-color: $icon-button-color; + transform: rotate(270deg); + mask-size: 20px; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); // TODO + } + } + } + + .mx_BaseCard_footer { + padding-top: 4px; + text-align: center; + + .mx_AccessibleButton_kind_secondary { + color: $secondary-fg-color; + background-color: rgba(141, 151, 165, 0.2); // TODO + font-weight: $font-semi-bold; + font-size: $font-14px; + min-width: 70px; + + & + .mx_AccessibleButton_kind_secondary { + margin-left: 16px; + } + } + } +} + +.mx_FilePanel, +.mx_UserInfo, +.mx_NotificationPanel, +.mx_MemberList { + &.mx_BaseCard { + padding: 32px 0 0; + + .mx_AutoHideScrollbar { + margin-right: unset; + padding-right: unset; + } + } +} diff --git a/res/css/views/right_panel/_RoomSummaryCard.scss b/res/css/views/right_panel/_RoomSummaryCard.scss new file mode 100644 index 00000000000..3c46727348b --- /dev/null +++ b/res/css/views/right_panel/_RoomSummaryCard.scss @@ -0,0 +1,157 @@ +/* +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. +*/ + +.mx_RoomSummaryCard { + // shrink left gutter by 12 and instead add it as margin to all things except the buttons + // as their hover effect should go into the gutter + & > * { // TODO consolidate this as the standard effect + margin-left: 10px; + margin-right: 10px; + } + .mx_AutoHideScrollbar { + margin-left: 0; + } + + .mx_BaseCard_header { + text-align: center; + margin-top: 20px; + + h2 { + font-weight: $font-semi-bold; + font-size: $font-18px; + margin: 12px 0 4px; + } + + .mx_RoomSummaryCard_alias { + font-size: $font-13px; + color: $secondary-fg-color; + } + + h2, .mx_RoomSummaryCard_alias { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + } + + .mx_RoomSummaryCard_avatar { + display: inline-flex; + + .mx_RoomSummaryCard_e2ee { + display: inline-block; + position: relative; + width: 54px; + height: 54px; + border-radius: 50%; + background-color: #737D8C; + margin-top: -3px; // alignment + margin-left: -10px; // overlap + border: 3px solid $dark-panel-bg-color; + + &::before { + content: ''; + position: absolute; + top: 13px; + left: 13px; + height: 28px; + width: 28px; + mask-size: cover; + mask-repeat: no-repeat; + mask-position: center; + mask-image: url('$(res)/img/e2e/disabled.svg'); + background-color: #ffffff; + } + } + + .mx_RoomSummaryCard_e2ee_secure{ + background-color: #5ABFF2; + &::before { + mask-image: url('$(res)/img/e2e/normal.svg'); + } + } + } + } + + .mx_RoomSummaryCard_aboutGroup { + .mx_RoomSummaryCard_Button { + padding-left: 48px; + + &::before { + content: ''; + position: absolute; + top: 8px; + left: 8px; + height: 24px; + width: 24px; + mask-repeat: no-repeat; + mask-position: center; + background-color: $icon-button-color; + } + } + } + + .mx_RoomSummaryCard_appsGroup { + .mx_RoomSummaryCard_Button { + padding-left: 10px; + color: $tertiary-fg-color; + + span { + color: $primary-fg-color; + } + + img { + vertical-align: top; + margin-right: 18px; + border-radius: 4px; + } + + &::before { + content: unset; + } + } + + .mx_RoomSummaryCard_icon_app_pinned::after { + mask-image: url('$(res)/img/element-icons/room/pin2.svg'); + background-color: $accent-color; + transform: unset; + } + } + + .mx_AccessibleButton_kind_link { + padding: 0; + margin-top: 12px; + margin-bottom: 12px; + font-size: $font-13px; + font-weight: $font-semi-bold; + } +} + +.mx_RoomSummaryCard_icon_people::before { + mask-image: url("$(res)/img/element-icons/room/members.svg"); +} + +.mx_RoomSummaryCard_icon_files::before { + mask-image: url('$(res)/img/element-icons/room/files.svg'); +} + +.mx_RoomSummaryCard_icon_share::before { + mask-image: url('$(res)/img/element-icons/room/share.svg'); +} + +.mx_RoomSummaryCard_icon_settings::before { + mask-image: url('$(res)/img/element-icons/settings.svg'); +} diff --git a/res/css/views/right_panel/_WidgetCard.scss b/res/css/views/right_panel/_WidgetCard.scss new file mode 100644 index 00000000000..b863c53c331 --- /dev/null +++ b/res/css/views/right_panel/_WidgetCard.scss @@ -0,0 +1,25 @@ +/* +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. +*/ + +.mx_WidgetCard { + height: 100%; + display: contents; + + .mx_AppTileFullWidth { + height: 100%; + border: 0; + } +} diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index a880a7bee2c..d240877507b 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -236,10 +236,6 @@ limitations under the License. } } -.mx_RoomHeader_settingsButton::before { - mask-image: url('$(res)/img/element-icons/settings.svg'); -} - .mx_RoomHeader_forgetButton::before { mask-image: url('$(res)/img/element-icons/leave.svg'); width: 26px; @@ -249,14 +245,6 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/search-inset.svg'); } -.mx_RoomHeader_shareButton::before { - mask-image: url('$(res)/img/element-icons/room/share.svg'); -} - -.mx_RoomHeader_manageIntegsButton::before { - mask-image: url('$(res)/img/element-icons/room/integrations.svg'); -} - .mx_RoomHeader_showPanel { height: 16px; } diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index b2b1ceae00d..57c0f46fadd 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -32,6 +32,9 @@ import {RightPanelPhases, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPa import RightPanelStore from "../../stores/RightPanelStore"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import {Action} from "../../dispatcher/actions"; +import RoomSummaryCard from "../views/right_panel/RoomSummaryCard"; +import WidgetCard from "../views/right_panel/WidgetCard"; +import defaultDispatcher from "../../dispatcher/dispatcher"; export default class RightPanel extends React.Component { static get propTypes() { @@ -182,6 +185,7 @@ export default class RightPanel extends React.Component { event: payload.event, verificationRequest: payload.verificationRequest, verificationRequestPromise: payload.verificationRequestPromise, + widgetId: payload.widgetId, }); } } @@ -209,6 +213,14 @@ export default class RightPanel extends React.Component { } }; + onClose = () => { + // the RightPanelStore has no way of knowing which mode room/group it is in, so we handle closing here + defaultDispatcher.dispatch({ + action: Action.ToggleRightPanel, + type: this.props.groupId ? "group" : "room", + }); + }; + render() { const MemberList = sdk.getComponent('rooms.MemberList'); const UserInfo = sdk.getComponent('right_panel.UserInfo'); @@ -225,17 +237,24 @@ export default class RightPanel extends React.Component { switch (this.state.phase) { case RightPanelPhases.RoomMemberList: if (this.props.room.roomId) { - panel = ; + panel = ; } break; + case RightPanelPhases.GroupMemberList: if (this.props.groupId) { panel = ; } break; + case RightPanelPhases.GroupRoomList: panel = ; break; + case RightPanelPhases.RoomMemberInfo: case RightPanelPhases.EncryptionPanel: panel = ; break; + case RightPanelPhases.Room3pidMemberInfo: panel = ; break; + case RightPanelPhases.GroupMemberInfo: panel = ; break; + case RightPanelPhases.GroupRoomInfo: panel = ; break; + case RightPanelPhases.NotificationPanel: - panel = ; + panel = ; break; + case RightPanelPhases.FilePanel: - panel = ; + panel = ; + break; + + case RightPanelPhases.RoomSummary: + panel = ; + break; + + case RightPanelPhases.Widget: + panel = ; break; } diff --git a/src/components/views/right_panel/BaseCard.tsx b/src/components/views/right_panel/BaseCard.tsx new file mode 100644 index 00000000000..3e95da1bc15 --- /dev/null +++ b/src/components/views/right_panel/BaseCard.tsx @@ -0,0 +1,93 @@ +/* +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, {ReactNode} from 'react'; +import classNames from 'classnames'; + +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; +import {_t} from "../../../languageHandler"; +import AccessibleButton from "../elements/AccessibleButton"; +import defaultDispatcher from "../../../dispatcher/dispatcher"; +import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; +import {Action} from "../../../dispatcher/actions"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; + +interface IProps { + header?: ReactNode; + footer?: ReactNode; + className?: string; + withoutScrollContainer?: boolean; + previousPhase?: RightPanelPhases; + onClose?(): void; +} + +interface IGroupProps { + className?: string; + title: string; +} + +export const Group: React.FC = ({ className, title, children }) => { + return
+

{title}

+ {children} +
; +}; + +const BaseCard: React.FC = ({ + onClose, + className, + header, + footer, + withoutScrollContainer, + previousPhase, + children, +}) => { + let backButton; + if (previousPhase) { + const onBackClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: previousPhase, + }); + }; + backButton = ; + } + + let closeButton; + if (onClose) { + closeButton = ; + } + + if (!withoutScrollContainer) { + children = + { children } + ; + } + + return ( +
+
+ { backButton } + { closeButton } + { header } +
+ { children } + { footer &&
{ footer }
} +
+ ); +}; + +export default BaseCard; diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx index e922959bbb8..543c7c067fb 100644 --- a/src/components/views/right_panel/HeaderButtons.tsx +++ b/src/components/views/right_panel/HeaderButtons.tsx @@ -96,8 +96,7 @@ export default abstract class HeaderButtons extends React.Component + return
{this.renderButtons()}
; } diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index 7d732b8ae32..e19a440005f 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -26,7 +26,10 @@ import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; import {ActionPayload} from "../../../dispatcher/payloads"; -const MEMBER_PHASES = [ +const ROOM_INFO_PHASES = [ + RightPanelPhases.RoomSummary, + RightPanelPhases.Widget, + RightPanelPhases.FilePanel, RightPanelPhases.RoomMemberList, RightPanelPhases.RoomMemberInfo, RightPanelPhases.EncryptionPanel, @@ -54,20 +57,10 @@ export default class RoomHeaderButtons extends HeaderButtons { } } - private onMembersClicked = () => { - if (this.state.phase === RightPanelPhases.RoomMemberInfo) { - // send the active phase to trigger a toggle - // XXX: we should pass refireParams here but then it won't collapse as we desire it to - this.setPhase(RightPanelPhases.RoomMemberInfo); - } else { - // This toggles for us, if needed - this.setPhase(RightPanelPhases.RoomMemberList); - } - }; - - private onFilesClicked = () => { + // TODO make it restore whatever widget they were on last + private onRoomSummaryClicked = () => { // This toggles for us, if needed - this.setPhase(RightPanelPhases.FilePanel); + this.setPhase(RightPanelPhases.RoomSummary); }; private onNotificationsClicked = () => { @@ -77,19 +70,17 @@ export default class RoomHeaderButtons extends HeaderButtons { public renderButtons() { return [ - , - , - = ({ children, className, onClick }) => { + return + { children } + ; +}; + +export const useWidgets = (room: Room) => { + const [apps, setApps] = useState(WidgetStore.instance.getApps(room)); + + const updateApps = useCallback(() => { + // Copy the array so that we always trigger a re-render, as some updates mutate the array of apps/settings + setApps([...WidgetStore.instance.getApps(room)]); + }, [room]); + + useEffect(updateApps, [room]); + useEventEmitter(WidgetEchoStore, "update", updateApps); + useEventEmitter(WidgetStore.instance, room.roomId, updateApps); + + return apps; +}; + +const AppsSection: React.FC = ({ room }) => { + const cli = useContext(MatrixClientContext); + const apps = useWidgets(room); + + const onManageIntegrations = () => { + const managers = IntegrationManagers.sharedInstance(); + if (!managers.hasManager()) { + managers.openNoManagerDialog(); + } else { + if (SettingsStore.getValue("feature_many_integration_managers")) { + managers.openAll(room); + } else { + managers.getPrimaryManager().open(room); + } + } + }; + + return + { apps.map(app => { + const name = WidgetUtils.getWidgetName(app); + const dataTitle = WidgetUtils.getWidgetDataTitle(app); + const subtitle = dataTitle && " - " + dataTitle; + + let iconUrls = [require("../../../../res/img/element-icons/room/default_app.svg")]; + // heuristics for some better icons until Widgets support their own icons + if (app.type.includes("meeting") || app.type.includes("calendar")) { + iconUrls = [require("../../../../res/img/element-icons/room/default_cal.svg")]; + } else if (app.type.includes("pad") || app.type.includes("doc") || app.type.includes("calc")) { + iconUrls = [require("../../../../res/img/element-icons/room/default_doc.svg")]; + } else if (app.type.includes("clock")) { + iconUrls = [require("../../../../res/img/element-icons/room/default_clock.svg")]; + } + + if (app.avatar_url) { // MSC2765 + iconUrls.unshift(getHttpUriForMxc(cli.getHomeserverUrl(), app.avatar_url, 20, 20, "crop")); + } + + const isPinned = WidgetStore.instance.isPinned(app.id); + const classes = classNames("mx_RoomSummaryCard_icon_app", { + mx_RoomSummaryCard_icon_app_pinned: isPinned, + }); + + if (isPinned) { + const onClick = () => { + WidgetStore.instance.unpinWidget(app.id); + }; + + return + + {name} + { subtitle } + + } + + const onOpenWidgetClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.Widget, + refireParams: { + widgetId: app.id, + }, + }); + }; + + return ; + }) } + + + { apps.length > 0 ? _t("Edit apps") : _t("Add applications") } + + ; +}; + +const onRoomMembersClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.RoomMemberList, + }); +}; + +const onRoomFilesClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.FilePanel, + }); +}; + +const onRoomSettingsClick = () => { + defaultDispatcher.dispatch({ action: "open_room_settings" }); +}; + +const RoomSummaryCard: React.FC = ({ room, onClose }) => { + const cli = useContext(MatrixClientContext); + + const onShareRoomClick = () => { + Modal.createTrackedDialog('share room dialog', '', ShareDialog, { + target: room, + }); + }; + + const isRoomEncrypted = useIsEncrypted(cli, room); + + const alias = room.getCanonicalAlias() || room.getAltAliases()[0] || ""; + const header = +
+ + +
+ +

{ room.name }

+
+ { alias } +
+
; + + return + + + + + + + + + ; +}; + +export default RoomSummaryCard; diff --git a/src/components/views/right_panel/WidgetCard.tsx b/src/components/views/right_panel/WidgetCard.tsx new file mode 100644 index 00000000000..c447bb29524 --- /dev/null +++ b/src/components/views/right_panel/WidgetCard.tsx @@ -0,0 +1,107 @@ +/* +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} from "react"; +import {Room} from "matrix-js-sdk/src/models/room"; + +import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import BaseCard from "./BaseCard"; +import WidgetUtils from "../../../utils/WidgetUtils"; +import AccessibleButton from "../elements/AccessibleButton"; +import AppTile from "../elements/AppTile"; +import {_t} from "../../../languageHandler"; +import {useWidgets} from "./RoomSummaryCard"; +import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; +import defaultDispatcher from "../../../dispatcher/dispatcher"; +import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; +import {Action} from "../../../dispatcher/actions"; +import {WidgetStore} from "../../../stores/WidgetStore"; + +interface IProps { + room: Room; + widgetId: string; + onClose(): void; +} + +const onFinished = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.RoomSummary, + }); +} + +const WidgetCard: React.FC = ({ room, widgetId, onClose }) => { + const cli = useContext(MatrixClientContext); + + const apps = useWidgets(room); + const app = apps.find(a => a.id === widgetId); + const isPinned = app && WidgetStore.instance.isPinned(app.id); + + useEffect(() => { + if (!app || isPinned) { + // TODO maybe we should do this in the ActiveWidgetStore instead + onFinished(); + } + }, [app, isPinned]); + + // Don't render anything as we are about to transition + if (!app || isPinned) return null; + + const header = +

{ WidgetUtils.getWidgetName(app) }

+
; + + const onPinClick = () => { + WidgetStore.instance.pinWidget(app.id); + }; + + const onEditClick = () => { + WidgetUtils.editWidget(room, app); + }; + + const footer = + + { _t("Pin to room") } + + + { _t("Edit") } + + ; + + return + + ; +}; + +export default WidgetCard; diff --git a/src/dispatcher/payloads/SetRightPanelPhasePayload.ts b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts index 75dea9f3df0..4126e8a6695 100644 --- a/src/dispatcher/payloads/SetRightPanelPhasePayload.ts +++ b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts @@ -34,4 +34,5 @@ export interface SetRightPanelPhaseRefireParams { groupRoomId?: string; // XXX: The type for event should 'view_3pid_invite' action's payload event?: any; + widgetId?: string; } diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 95861e11dff..43bb989d1fd 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -607,4 +607,8 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: _td("Enable experimental, compact IRC style layout"), default: false, }, + "Widgets.pinned": { + supportedLevels: LEVELS_ROOM_OR_ACCOUNT, + default: [], + }, }; diff --git a/src/stores/RightPanelStorePhases.ts b/src/stores/RightPanelStorePhases.ts index 9045b171932..11b51dfc2dd 100644 --- a/src/stores/RightPanelStorePhases.ts +++ b/src/stores/RightPanelStorePhases.ts @@ -22,6 +22,8 @@ export enum RightPanelPhases { NotificationPanel = 'NotificationPanel', RoomMemberInfo = 'RoomMemberInfo', EncryptionPanel = 'EncryptionPanel', + RoomSummary = 'RoomSummary', + Widget = 'Widget', Room3pidMemberInfo = 'Room3pidMemberInfo', // Group stuff @@ -34,6 +36,7 @@ export enum RightPanelPhases { // These are the phases that are safe to persist (the ones that don't require additional // arguments). export const RIGHT_PANEL_PHASES_NO_ARGS = [ + RightPanelPhases.RoomSummary, RightPanelPhases.NotificationPanel, RightPanelPhases.FilePanel, RightPanelPhases.RoomMemberList,