mirror of
https://github.com/tiennm99/claude-code-usage-bubble.git
synced 2026-10-23 14:14:47 +00:00
fix(ui): resize on Ctrl+wheel only after 100 px of gesture travel
A new gesture, including one started by a change of direction, used to send a full step at once, so a few px of reversed jitter in a touchpad pinch shrank and grew the bubble back and forth. A new gesture now starts from its own travel and steps only once that reaches 100 px.
This commit is contained in:
1 parent
a4f8011b26
commit
d583e173d2
2 files changed
+27
-14
No files matched your search
+20
-9
@@ -310,9 +310,10 @@ describe('wheelSteps', () => {
|
||||
assert.deepEqual(run([[-100, PIXEL, 0], [-100, PIXEL, 50], [-100, PIXEL, 100]]), [1, 1, 1]);
|
||||
});
|
||||
|
||||
it('gives one step for a single notch reported as few px', () => {
|
||||
assert.deepEqual(run([[-40, PIXEL, 0]]), [1]);
|
||||
assert.deepEqual(run([[-40, PIXEL, 0], [-40, PIXEL, 1000]]), [1, 1]);
|
||||
it('waits for 100 px of travel before a step', () => {
|
||||
assert.deepEqual(run([[-40, PIXEL, 0]]), [0]);
|
||||
assert.deepEqual(run([[-40, PIXEL, 0], [-40, PIXEL, 10], [-40, PIXEL, 20]]), [0, 0, 1]);
|
||||
assert.deepEqual(run([[-40, PIXEL, 0], [-40, PIXEL, 1000]]), [0, 0]);
|
||||
});
|
||||
|
||||
it('turns a stream of small touchpad deltas into one step per 100 px', () => {
|
||||
@@ -320,18 +321,28 @@ describe('wheelSteps', () => {
|
||||
Array.from({ length: 30 }, (_, i) => [-10, PIXEL, i * 10])
|
||||
);
|
||||
const steps = run(events);
|
||||
// The first event starts the gesture with a step; the other 290 px add two.
|
||||
assert.equal(steps.reduce((a, b) => a + b, 0), 3);
|
||||
assert.ok(steps.every((s) => s === 0 || s === 1));
|
||||
});
|
||||
|
||||
it('starts a new gesture after an idle pause', () => {
|
||||
assert.deepEqual(run([[-60, PIXEL, 0], [-60, PIXEL, WHEEL_IDLE_MS + 1]]), [1, 1]);
|
||||
assert.deepEqual(run([[-60, PIXEL, 0], [-60, PIXEL, WHEEL_IDLE_MS]]), [1, 0]);
|
||||
assert.deepEqual(run([[-60, PIXEL, 0], [-60, PIXEL, WHEEL_IDLE_MS + 1]]), [0, 0]);
|
||||
assert.deepEqual(run([[-60, PIXEL, 0], [-60, PIXEL, WHEEL_IDLE_MS]]), [0, 1]);
|
||||
});
|
||||
|
||||
it('starts a new gesture when the direction flips', () => {
|
||||
assert.deepEqual(run([[-150, PIXEL, 0], [10, PIXEL, 10]]), [1, -1]);
|
||||
assert.deepEqual(run([[-150, PIXEL, 0], [10, PIXEL, 10]]), [1, 0]);
|
||||
assert.deepEqual(run([[-150, PIXEL, 0], [60, PIXEL, 10], [60, PIXEL, 20]]), [1, 0, -1]);
|
||||
});
|
||||
|
||||
it('ignores a few px of reversed jitter inside a gesture', () => {
|
||||
assert.deepEqual(
|
||||
run([[-10, PIXEL, 0], [-10, PIXEL, 10], [2, PIXEL, 20], [-10, PIXEL, 30], [1, PIXEL, 40], [-10, PIXEL, 50]]),
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
);
|
||||
// After a whole notch leaves no travel, a reverse twitch and the next
|
||||
// forward delta still wait for 100 px.
|
||||
assert.deepEqual(run([[-100, PIXEL, 0], [2, PIXEL, 10], [-10, PIXEL, 20]]), [1, 0, 0]);
|
||||
});
|
||||
|
||||
it('sends several steps for one large delta', () => {
|
||||
@@ -339,9 +350,9 @@ describe('wheelSteps', () => {
|
||||
});
|
||||
|
||||
it('converts line and page deltas to px', () => {
|
||||
// Three lines are 48 px: the gesture's first step, then one per 100 px.
|
||||
// Three lines are 48 px, so the third event crosses 100 px.
|
||||
const lines = run([[-3, LINE, 0], [-3, LINE, 10], [-3, LINE, 20], [-3, LINE, 30]]);
|
||||
assert.deepEqual(lines, [1, 0, 0, 1]);
|
||||
assert.deepEqual(lines, [0, 0, 1, 0]);
|
||||
assert.deepEqual(run([[-1, PAGE, 0]]), [8]);
|
||||
});
|
||||
|
||||
|
||||
+7
-5
@@ -374,9 +374,10 @@ export const WHEEL_IDLE = Object.freeze({ acc: 0, lastMs: -Infinity });
|
||||
/**
|
||||
* Turn one Ctrl+wheel event into resize steps. Travel accumulates in px, so
|
||||
* a touchpad's stream of small deltas resizes gradually instead of one step
|
||||
* per event. The first event of a gesture always gives at least one step, so
|
||||
* a single mouse notch resizes however few px the platform reports for it.
|
||||
* A pause of `WHEEL_IDLE_MS` or a change of direction starts a new gesture.
|
||||
* per event: a step is sent each time the gesture's travel reaches
|
||||
* `WHEEL_STEP_PX`. A pause of `WHEEL_IDLE_MS` or a change of direction starts
|
||||
* a new gesture from zero, so a few px of reversed jitter inside a touchpad
|
||||
* stream never resizes the other way.
|
||||
* @param {WheelState} state State from the previous event, or `WHEEL_IDLE`.
|
||||
* @param {number} deltaY `WheelEvent.deltaY`; negative scrolls up and grows.
|
||||
* @param {number} deltaMode `WheelEvent.deltaMode`.
|
||||
@@ -389,7 +390,8 @@ export function wheelSteps(state, deltaY, deltaMode, nowMs) {
|
||||
return { state, steps: 0 };
|
||||
}
|
||||
const fresh = nowMs - state.lastMs > WHEEL_IDLE_MS || Math.sign(state.acc) === -Math.sign(px);
|
||||
const acc = fresh ? Math.sign(px) * Math.max(Math.abs(px), WHEEL_STEP_PX) : state.acc + px;
|
||||
const steps = Math.trunc(acc / WHEEL_STEP_PX);
|
||||
const acc = fresh ? px : state.acc + px;
|
||||
// `|| 0` turns the -0 of a small reverse delta into a plain 0.
|
||||
const steps = Math.trunc(acc / WHEEL_STEP_PX) || 0;
|
||||
return { state: { acc: acc - steps * WHEEL_STEP_PX, lastMs: nowMs }, steps };
|
||||
}
|
||||
Reference in new issue
Block a user