1
0
mirror of https://github.com/mathuo/dockview synced 2025-03-11 00:12:07 +00:00

feat: touch support refactor and test

- add tests
- refactor methods to have a clear seperation between mouse and touch
  logic
This commit is contained in:
mathuo 2023-06-12 21:41:46 +01:00
parent 9e10814840
commit 01544a9953
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
2 changed files with 124 additions and 19 deletions
packages/dockview-core/src
__tests__/splitview
splitview

View File

@ -84,6 +84,8 @@ describe('splitview', () => {
beforeEach(() => {
container = document.createElement('div');
container.className = 'container';
jest.clearAllMocks();
});
test('vertical splitview', () => {
@ -610,6 +612,12 @@ describe('splitview', () => {
splitview.addView(view1);
splitview.addView(view2);
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
const removeEventListenerSpy = jest.spyOn(
document,
'removeEventListener'
);
const sashElement = container
.getElementsByClassName('sash')
.item(0) as HTMLElement;
@ -623,6 +631,8 @@ describe('splitview', () => {
// start the drag event
fireEvent.mouseDown(sashElement, { clientX: 50, clientY: 100 });
expect(addEventListenerSpy).toBeCalledTimes(5);
// during a sash drag the views should have pointer-events disabled
expect(view1.element.parentElement!.style.pointerEvents).toBe('none');
expect(view2.element.parentElement!.style.pointerEvents).toBe('none');
@ -638,6 +648,8 @@ describe('splitview', () => {
// end the drag event
fireEvent.mouseUp(document);
expect(removeEventListenerSpy).toBeCalledTimes(5);
// expect pointer-eventes on views to be restored
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
@ -645,5 +657,79 @@ describe('splitview', () => {
fireEvent.mouseMove(document, { clientX: 100, clientY: 100 });
// expect no additional resizes
expect([view1.size, view2.size]).toEqual([225, 175]);
// expect no additional document listeners
expect(addEventListenerSpy).toBeCalledTimes(5);
expect(removeEventListenerSpy).toBeCalledTimes(5);
});
test('dnd: touch events to move sash', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(400, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
const removeEventListenerSpy = jest.spyOn(
document,
'removeEventListener'
);
const sashElement = container
.getElementsByClassName('sash')
.item(0) as HTMLElement;
// validate the expected state before drag
expect([view1.size, view2.size]).toEqual([200, 200]);
expect(sashElement).toBeTruthy();
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
// start the drag event
fireEvent.touchStart(sashElement, {
touches: [{ clientX: 50, clientY: 100 }],
});
expect(addEventListenerSpy).toBeCalledTimes(5);
// during a sash drag the views should have pointer-events disabled
expect(view1.element.parentElement!.style.pointerEvents).toBe('none');
expect(view2.element.parentElement!.style.pointerEvents).toBe('none');
// expect a delta move of 70 - 50 = 20
fireEvent.touchMove(document, {
touches: [{ clientX: 70, clientY: 110 }],
});
expect([view1.size, view2.size]).toEqual([220, 180]);
// expect a delta move of 75 - 70 = 5
fireEvent.touchMove(document, {
touches: [{ clientX: 75, clientY: 110 }],
});
expect([view1.size, view2.size]).toEqual([225, 175]);
// end the drag event
fireEvent.touchEnd(document);
expect(removeEventListenerSpy).toBeCalledTimes(5);
// expect pointer-eventes on views to be restored
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
fireEvent.touchMove(document, {
touches: [{ clientX: 100, clientY: 100 }],
});
// expect no additional resizes
expect([view1.size, view2.size]).toEqual([225, 175]);
// expect no additional document listeners
expect(addEventListenerSpy).toBeCalledTimes(5);
expect(removeEventListenerSpy).toBeCalledTimes(5);
});
});

View File

@ -393,8 +393,17 @@ export class Splitview {
const sash = document.createElement('div');
sash.className = 'sash';
const onStart = (nativeEvent: MouseEvent | TouchEvent) => {
const event = nativeEvent instanceof TouchEvent ? nativeEvent.touches[0] : nativeEvent;
const onTouchStart = (event: TouchEvent) => {
event.preventDefault();
const touch = event.touches[0];
onStart(touch);
};
const onMouseDown = (event: MouseEvent) => {
onStart(event);
};
const onStart = (event: { clientX: number; clientY: number }) => {
for (const item of this.viewItems) {
item.enabled = false;
}
@ -487,14 +496,25 @@ export class Splitview {
size: snappedViewItem.size,
};
}
//
const mousemove = (nativeMoveEvent: MouseEvent | TouchEvent) => {
const moveEvent = nativeMoveEvent instanceof TouchEvent ? nativeMoveEvent.touches[0] : nativeMoveEvent;
const onMouseMove = (event: MouseEvent) => {
reposition(event);
};
const onTouchMove = (event: TouchEvent) => {
event.preventDefault();
const touch = event.touches[0];
reposition(touch);
};
const reposition = (event: {
clientX: number;
clientY: number;
}) => {
const current =
this._orientation === Orientation.HORIZONTAL
? moveEvent.clientX
: moveEvent.clientY;
? event.clientX
: event.clientY;
const delta = current - start;
this.resize(
@ -523,31 +543,30 @@ export class Splitview {
this.saveProportions();
document.removeEventListener('mousemove', mousemove);
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', end);
document.removeEventListener("touchmove", mousemove);
document.removeEventListener("touchend", end);
document.removeEventListener("touchcancel", end);
document.removeEventListener('touchmove', onTouchMove);
document.removeEventListener('touchend', end);
document.removeEventListener('touchcancel', end);
this._onDidSashEnd.fire(undefined);
return true // Consume, otherwise Monaco complains
};
document.addEventListener('mousemove', mousemove);
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', end);
document.addEventListener("touchmove", mousemove);
document.addEventListener("touchend", end);
document.addEventListener("touchcancel", end);
return true // consume pull to refresh gesture
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', end);
document.addEventListener('touchcancel', end);
};
sash.addEventListener('mousedown', onStart);
sash.addEventListener("touchstart", onStart);
sash.addEventListener('mousedown', onMouseDown);
sash.addEventListener('touchstart', onTouchStart);
const sashItem: ISashItem = {
container: sash,
disposable: () => {
sash.removeEventListener('mousedown', onStart);
sash.removeEventListener('touchstart', onTouchStart);
this.sashContainer.removeChild(sash);
},
};