Use the separator as border between roomlist and main panel (#33598)
* Remove border from roomlist container The separator will act as the border so we no longer need the roomlist border. * Use pointer events to detect click event Otherwise the onClick handler would run when you resize the panel. * Support showing the border in separator * Update tests * Disable double click behaviour on separator * Fix screenshot tests failing
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
@@ -8,5 +8,4 @@
|
||||
.mx_RoomListPanel {
|
||||
background-color: var(--cpd-color-bg-canvas-default);
|
||||
height: 100%;
|
||||
border-right: 1px solid var(--cpd-color-bg-subtle-primary);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,15 @@ export class ResizerViewModel
|
||||
*/
|
||||
private panelHandle?: PanelImperativeHandle;
|
||||
|
||||
/**
|
||||
* Needed to distinguish between a drag and a click on the separator.
|
||||
*/
|
||||
private readonly mouseClickHandler: MouseClickHandler;
|
||||
|
||||
public constructor() {
|
||||
super(undefined, getInitialState());
|
||||
// Run onSeparatorClick when the separator is clicked.
|
||||
this.mouseClickHandler = new MouseClickHandler(this.onSeparatorClick);
|
||||
}
|
||||
|
||||
public onLeftPanelResize = debounce((panelSize: PanelSize): void => {
|
||||
@@ -79,13 +86,25 @@ export class ResizerViewModel
|
||||
this.panelHandle = handle;
|
||||
};
|
||||
|
||||
public onSeparatorClick = (): void => {
|
||||
private onSeparatorClick = (): void => {
|
||||
if (this.panelHandle?.isCollapsed()) {
|
||||
const lastSize = SettingsStore.getValue("RoomList.panelSize");
|
||||
this.panelHandle.resize(`${lastSize ?? 100}%`);
|
||||
}
|
||||
};
|
||||
|
||||
public onPointerUp = (): void => {
|
||||
this.mouseClickHandler.onPointerUp();
|
||||
};
|
||||
|
||||
public onPointerMove = (): void => {
|
||||
this.mouseClickHandler.onPointerMove();
|
||||
};
|
||||
|
||||
public onPointerDown = (): void => {
|
||||
this.mouseClickHandler.onPointerDown();
|
||||
};
|
||||
|
||||
public onFocus = (): void => {
|
||||
/**
|
||||
* The intention here is to make the separator visible when it is focused by keyboard
|
||||
@@ -108,3 +127,26 @@ export class ResizerViewModel
|
||||
this.snapshot.merge({ isFocusedViaKeyboard: false });
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Dragging the separator will emit a click event.
|
||||
* This class uses pointer event handlers to distinguish between a drag and a click
|
||||
* on the separator.
|
||||
*/
|
||||
class MouseClickHandler {
|
||||
public constructor(private readonly onClick: () => void) {}
|
||||
|
||||
private isResize = false;
|
||||
|
||||
public onPointerUp = (): void => {
|
||||
if (!this.isResize) this.onClick();
|
||||
};
|
||||
|
||||
public onPointerDown = (): void => {
|
||||
this.isResize = false;
|
||||
};
|
||||
|
||||
public onPointerMove = (): void => {
|
||||
this.isResize = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,12 +63,33 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should noop on onSeparatorClick() when handle is not yet set", () => {
|
||||
it("should noop on click when handle is not yet set", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
expect(() => vm.onSeparatorClick()).not.toThrow();
|
||||
expect(() => {
|
||||
// Click
|
||||
vm.onPointerDown();
|
||||
vm.onPointerUp();
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
describe("should expand panel on onSeparatorClick()", () => {
|
||||
it("should noop on mouse drag", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
|
||||
const mockHandle = {
|
||||
resize: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
// Simulate drag
|
||||
vm.onPointerDown();
|
||||
vm.onPointerMove();
|
||||
vm.onPointerUp();
|
||||
|
||||
expect(mockHandle.resize).not.toHaveBeenCalledWith("34%");
|
||||
});
|
||||
|
||||
describe("should expand panel on click()", () => {
|
||||
it("to last non-zero width that the user set", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
|
||||
@@ -78,7 +99,9 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
vm.onSeparatorClick();
|
||||
// Simulate click
|
||||
vm.onPointerDown();
|
||||
vm.onPointerUp();
|
||||
|
||||
expect(mockHandle.resize).toHaveBeenCalledWith("34%");
|
||||
});
|
||||
@@ -91,7 +114,9 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
vm.onSeparatorClick();
|
||||
// Simulate click
|
||||
vm.onPointerDown();
|
||||
vm.onPointerUp();
|
||||
|
||||
expect(mockHandle.resize).toHaveBeenCalledWith("100%");
|
||||
});
|
||||
|
||||