mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-09 14:16:22 +02:00
Add a class to orchestrate all the collapse behaviours
This commit is contained in:
parent
8348fe8eba
commit
bc2dc8c912
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import type { PanelImperativeHandle } from "@element-hq/web-shared-components";
|
||||
import { CollapseHandler } from "./CollapseHandler";
|
||||
import type { BaseCollapseBehaviour } from "./behaviours/BaseCollapseBehaviour";
|
||||
import { Behaviours } from "./behaviours/behaviours";
|
||||
|
||||
/**
|
||||
* This class orchestrates all the auto-collapse behaviours.
|
||||
*/
|
||||
export class AutoCollapse {
|
||||
private readonly behaviours: BaseCollapseBehaviour[] = [];
|
||||
private readonly collapseHandler: CollapseHandler;
|
||||
|
||||
public constructor(setCollapsed: (collapsed: boolean) => void) {
|
||||
this.collapseHandler = new CollapseHandler(setCollapsed);
|
||||
for (const Behaviour of Behaviours) {
|
||||
this.behaviours.push(new Behaviour(this.collapseHandler));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When this returns true, any left panel resized events should be ignored.
|
||||
*/
|
||||
public get shouldIgnoreResize(): boolean {
|
||||
return this.behaviours.some((b) => b.shouldIgnoreResize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the panel is currently auto-collapsed.
|
||||
*/
|
||||
public get isAutoCollapsed(): boolean {
|
||||
return this.collapseHandler.isAutoCollapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean indicating whether the left panel should be collapsed at app start.
|
||||
*/
|
||||
public static shouldStartCollapsed(): boolean {
|
||||
return Behaviours.some((B) => B.shouldStartCollapsed());
|
||||
}
|
||||
|
||||
public dispose = (): void => {
|
||||
for (const behaviour of this.behaviours) {
|
||||
behaviour.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the panel API from react-resizable-panels available to this class.
|
||||
* @param handle The panel handle to access react-resizable-panels API
|
||||
*/
|
||||
public setHandle = (handle: PanelImperativeHandle): void => {
|
||||
this.collapseHandler.setHandle(handle);
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called when the left panel is resized.
|
||||
*/
|
||||
public onLeftPanelResized = (): void => {
|
||||
for (const behaviour of this.behaviours) {
|
||||
behaviour.onLeftPanelResized();
|
||||
}
|
||||
this.collapseHandler.isAutoCollapsed = false;
|
||||
this.collapseHandler.updateRestoreWidth();
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import type { PanelImperativeHandle } from "@element-hq/web-shared-components";
|
||||
import { AutoCollapse } from "../../../../src/viewmodels/structures/auto-collapse/AutoCollapse";
|
||||
import { MockPanelHandle } from "./mocks";
|
||||
import type { CollapseHandler } from "../../../../src/viewmodels/structures/auto-collapse/CollapseHandler";
|
||||
import { BaseCollapseBehaviour } from "../../../../src/viewmodels/structures/auto-collapse/behaviours/BaseCollapseBehaviour";
|
||||
|
||||
let instances: BaseCollapseBehaviour[] = [];
|
||||
|
||||
class MockBehaviour extends BaseCollapseBehaviour {
|
||||
public constructor(collapseHandler: CollapseHandler) {
|
||||
super(collapseHandler);
|
||||
instances.push(this);
|
||||
}
|
||||
|
||||
public onLeftPanelResized = jest.fn();
|
||||
}
|
||||
|
||||
class MockBehaviourWithStartCollapsed extends MockBehaviour {
|
||||
public static shouldStartCollapsed(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class MockBehaviourWithIgnoreResize extends MockBehaviour {
|
||||
public get shouldIgnoreResize(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
jest.mock("../../../../src/viewmodels/structures/auto-collapse/behaviours/behaviours", () => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
get Behaviours() {
|
||||
return [MockBehaviour, MockBehaviour, MockBehaviourWithIgnoreResize, MockBehaviourWithStartCollapsed];
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe("AutoCollapse", () => {
|
||||
beforeEach(() => {
|
||||
instances = [];
|
||||
});
|
||||
|
||||
it("should call onLeftPanelResized of each behaviour", () => {
|
||||
const setCollapsed = jest.fn();
|
||||
const panelHandle = new MockPanelHandle();
|
||||
const autoCollapse = new AutoCollapse(setCollapsed);
|
||||
autoCollapse.setHandle(panelHandle as unknown as PanelImperativeHandle);
|
||||
autoCollapse.onLeftPanelResized();
|
||||
for (const behaviour of instances) {
|
||||
expect(behaviour.onLeftPanelResized).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
expect(autoCollapse.isAutoCollapsed).toBe(false);
|
||||
});
|
||||
|
||||
it("should calculate shouldStartCollapsed correctly", () => {
|
||||
expect(AutoCollapse.shouldStartCollapsed()).toBe(true);
|
||||
});
|
||||
|
||||
it("should calculate shouldIgnoreResize correctly", () => {
|
||||
const setCollapsed = jest.fn();
|
||||
const panelHandle = new MockPanelHandle();
|
||||
const autoCollapse = new AutoCollapse(setCollapsed);
|
||||
autoCollapse.setHandle(panelHandle as unknown as PanelImperativeHandle);
|
||||
expect(autoCollapse.shouldIgnoreResize).toBe(true);
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user