Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resize preference save sequence #233

Merged
merged 3 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/fair-laws-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"ember-headless-table": patch
---

Fixes column resize and preference save sequencing
to ensure that the functions always run in the correct order.
35 changes: 26 additions & 9 deletions ember-headless-table/src/plugins/column-resizing/handle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,41 @@ class ResizeHandle extends Modifier<{ Args: { Positional: [Column] } }> {
}
};

queueUpdate = () => {
cancelAnimationFrame(this.dragFrame);
/**
* queueUpdate takes an optional function argument that is called
* in the requestAnimationFrame callback _after_ the resize function.
*
* We can use this to ensure that preferences are only ever saved after
* we have completed column resizing.
*
* Because the requestAnimationFrame 'hides' these function calls from the
* the ember test waiter, we also ensure that we track them by also cancelling
* the waiter in the requestAnimationFrame callback.
*/
queueUpdate = (callback?: () => void) => {
joelamb marked this conversation as resolved.
Show resolved Hide resolved
if (this.dragFrame) {
cancelAnimationFrame(this.dragFrame);
}

this.dragFrame = requestAnimationFrame(() => {
this.meta.resize(this.pointerX - this.pointerStartX);
this.pointerStartX = this.pointerX;

if (callback) {
callback();
}

if (this.token) {
waiter.endAsync(this.token);
this.token = undefined;
}
});
};

dragEndHandler = () => {
this.meta.isResizing = false;
this.queueUpdate();

if (this.token) {
waiter.endAsync(this.token);
this.token = undefined;
}

this.meta.save();
this.queueUpdate(this.meta.save);

/**
* No need to listen if we aren't dragging
Expand Down
9 changes: 0 additions & 9 deletions ember-headless-table/src/test-support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,9 @@ export function createHelpers(selectors: Selectors) {

triggerEvent(element, 'mousedown', { clientX: startX, button: 0 });
triggerEvent(element, 'mousemove', { clientX: targetX, button: 0 });

await new Promise((resolve) => setTimeout(resolve, 50));

triggerEvent(element, 'mouseup', { clientX: targetX, button: 0 });

await settled();

/**
* This has been super finnicky... :(
*/
await new Promise((resolve) => setTimeout(resolve, 100));
await requestAnimationFrameSettled();
}

function horizontalScrollElement() {
Expand Down
33 changes: 18 additions & 15 deletions test-app/tests/plugins/column-resizing/rendering-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,7 @@ module('Plugins | resizing', function (hooks) {
}, 'All column preferences reset');
});

test('it resizes each column', async function (assert) {
// Columns are set to equal widths so each of the four columns
// will initially be 250px wide in the 1000px wide container
test('it resizes each column and persists the new widths in the preferences', async function (assert) {
ctx.setContainerWidth(1000);
await render(
<template>
Expand All @@ -314,30 +312,35 @@ module('Plugins | resizing', function (hooks) {
debugAssert(`columnC doesn't exist`, columnC);
debugAssert(`columnD doesn't exist`, columnD);

assert.equal(width(columnA), 300, 'col A has expected width before resize');
assert.equal(width(columnB), 250, 'col B has expected width before resize');
assert.equal(width(columnC), 250, 'col C has expected width before resize');
assert.equal(width(columnD), 200, 'col D has expected width before resize');

await requestAnimationFrameSettled();

await assertChanges(
() => dragRight(columnB, 50),
[
{ value: () => width(columnA), by: 50, msg: 'width of A increased by 50' },
{ value: () => width(columnB), by: -50, msg: 'width of B decreased by 50' },
{ value: () => width(columnC), by: 0, msg: 'width of C unchanged' },
{ value: () => width(columnD), by: 0, msg: 'width of D unchanged' },
]
);
// move the the resize handler between columns A & B 200px to the right
// increasing the width of column A and decreasing the width of columns
// to the right , while respecting the min width (128px)
await dragRight(columnB, 200);
joelamb marked this conversation as resolved.
Show resolved Hide resolved

assert.equal(width(columnA), 500, 'col A has expected width after resize');
assert.equal(width(columnB), 128, 'col B has expected width after resize');
joelamb marked this conversation as resolved.
Show resolved Hide resolved
assert.equal(width(columnC), 172, 'col C has expected width after resize');
assert.equal(width(columnD), 200, 'col D has expected width after resize');

assert.deepEqual(preferences, {
"plugins": {
"ColumnResizing": {
"columns": {
"A": {
"width": "350"
"width": "500"
},
"B": {
"width": "200"
"width": "128"
},
"C": {
"width": "250"
"width": "172"
},
"D": {
"width": "200"
Expand Down