Skip to content

Commit

Permalink
Remember collapsed state in <SpacePanel />
Browse files Browse the repository at this point in the history
Stash the collapsed state in a setting, which is persisted in localStorage
between loads.

See element-hq/element-web#23172

Signed-off-by: Clark Fischer <[email protected]>
  • Loading branch information
clarkf committed Jan 11, 2023
1 parent bb99066 commit 6ce1244
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
14 changes: 9 additions & 5 deletions src/components/views/spaces/SpacePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2021 - 2022 The Matrix.org Foundation C.I.C.
Copyright 2021 - 2023 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.
Expand Down Expand Up @@ -60,7 +60,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import { SettingLevel } from "../../../settings/SettingLevel";
import UIStore from "../../../stores/UIStore";
import QuickSettingsButton from "./QuickSettingsButton";
import { useSettingValue } from "../../../hooks/useSettings";
import { useSetting, useSettingValue } from "../../../hooks/useSettings";
import UserMenu from "../../structures/UserMenu";
import IndicatorScrollbar from "../../structures/IndicatorScrollbar";
import { IS_MAC, Key } from "../../../Keyboard";
Expand Down Expand Up @@ -329,12 +329,15 @@ const InnerSpacePanel = React.memo<IInnerSpacePanelProps>(
);

const SpacePanel = () => {
const [isPanelCollapsed, setPanelCollapsed] = useState(true);
const ref = useRef<HTMLDivElement>();
const [isPanelCollapsed, setPanelCollapsed] = useSetting<boolean>("space_panel_collapsed");

const ref = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
if (!ref.current) return;

UIStore.instance.trackElementDimensions("SpacePanel", ref.current);
return () => UIStore.instance.stopTrackingElementDimensions("SpacePanel");
}, []);
}, [ ref ]);

useDispatcher(defaultDispatcher, (payload: ActionPayload) => {
if (payload.action === Action.ToggleSpacePanel) {
Expand All @@ -359,6 +362,7 @@ const SpacePanel = () => {
<UserMenu isPanelCollapsed={isPanelCollapsed}>
<AccessibleTooltipButton
className={classNames("mx_SpacePanel_toggleCollapse", { expanded: !isPanelCollapsed })}
data-testid="collapse-space-panel-button"
onClick={() => setPanelCollapsed(!isPanelCollapsed)}
title={isPanelCollapsed ? _t("Expand") : _t("Collapse")}
tooltip={
Expand Down
5 changes: 5 additions & 0 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,11 @@ export const SETTINGS: { [setting: string]: ISetting } = {
supportedLevels: [SettingLevel.ACCOUNT],
default: [], // list of room IDs, most recent first
},
"space_panel_collapsed": {
// not really a setting
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
default: true,
},
"room_directory_servers": {
supportedLevels: [SettingLevel.ACCOUNT],
default: [],
Expand Down
66 changes: 55 additions & 11 deletions test/components/views/spaces/SpacePanel-test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Copyright 2023 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.
Expand All @@ -15,17 +15,16 @@ limitations under the License.
*/

import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import { mocked } from "jest-mock";
import { MatrixClient } from "matrix-js-sdk/src/matrix";

import UnwrappedSpacePanel from "../../../../src/components/views/spaces/SpacePanel";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { SpaceKey } from "../../../../src/stores/spaces";
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
import { UIComponent } from "../../../../src/settings/UIFeature";
import { wrapInSdkContext } from "../../../test-utils";
import { stubClient, wrapInSdkContext } from "../../../test-utils";
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
import AbstractLocalStorageSettingsHandler from "../../../../src/settings/handlers/AbstractLocalStorageSettingsHandler";

jest.mock("../../../../src/stores/spaces/SpaceStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -45,16 +44,31 @@ jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
shouldShowComponent: jest.fn(),
}));

// function mockLocalStorage(): Storage {
// const storage = new Map<string, string>();

// return {
// length: 0,
// getItem: (key: string): string | null => {
// if (!storage.has(key)) {
// console.debug("Missing key: " + key);
// return null;
// }
// console.debug("Found key: " + key + "=" + storage.get(key)!);
// return storage.get(key)!;
// },
// setItem: (key, value) => {
// console.debug(`Setting key ${key}=${value}`);
// storage.set(key, value);
// },
// } as Storage;
// }

describe("<SpacePanel />", () => {
const mockClient = {
getUserId: jest.fn().mockReturnValue("@test:test"),
isGuest: jest.fn(),
getAccountData: jest.fn(),
} as unknown as MatrixClient;
const SpacePanel = wrapInSdkContext(UnwrappedSpacePanel, SdkContextClass.instance);

beforeAll(() => {
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
stubClient();
});

beforeEach(() => {
Expand All @@ -80,4 +94,34 @@ describe("<SpacePanel />", () => {
screen.getByTestId("create-space-button");
});
});

describe("collapsing", () => {
const clickCollapse = () => fireEvent.click(screen.getByTestId("collapse-space-panel-button"));

beforeEach(() => {
localStorage.clear();
AbstractLocalStorageSettingsHandler.clear();
});

it("should expand", () => {
const res = render(<SpacePanel />);
const panel = res.baseElement.querySelector(".mx_SpacePanel");
expect(panel).toHaveClass("collapsed");

clickCollapse();
expect(panel).not.toHaveClass("collapsed");
});

it("should remember its collapsed state", () => {
// Render a panel and expand it
render(<SpacePanel />);
clickCollapse();
cleanup();

// Re-render
const res = render(<SpacePanel />);
const newPanel = res.baseElement.querySelector(".mx_SpacePanel");
expect(newPanel).not.toHaveClass("collapsed");
});
});
});

0 comments on commit 6ce1244

Please sign in to comment.