A quick one-finger flick toward a free side of the active page, once that edge is on screen, highlights and pulses the plus button on that side for three seconds. It never adds a page by itself, so ordinary panning can't create pages; a tap on the highlighted plus does. Fling detection lives in ink/fling.ts with tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GaoZtJQZwLXkEgWs8twCia
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { flingDir, pushSample, type Sample } from './fling';
|
|
|
|
/** A straight drag from (0,0) by (dx,dy) over `ms`, sampled every 16 ms. */
|
|
function drag(dx: number, dy: number, ms: number): Sample[] {
|
|
const out: Sample[] = [];
|
|
for (let t = 0; t <= ms; t += 16) pushSample(out, { x: (dx * t) / ms, y: (dy * t) / ms, t });
|
|
return out;
|
|
}
|
|
|
|
describe('flingDir', () => {
|
|
it('maps a flick to the side it reveals', () => {
|
|
expect(flingDir(drag(-200, 0, 96))).toBe('right');
|
|
expect(flingDir(drag(200, 0, 96))).toBe('left');
|
|
expect(flingDir(drag(0, -200, 96))).toBe('down');
|
|
expect(flingDir(drag(0, 200, 96))).toBe('up');
|
|
});
|
|
|
|
it('ignores slow drags', () => {
|
|
expect(flingDir(drag(-200, 0, 800))).toBeNull();
|
|
});
|
|
|
|
it('ignores diagonal flicks', () => {
|
|
expect(flingDir(drag(-200, -150, 96))).toBeNull();
|
|
});
|
|
|
|
it('ignores a drag that stops before lifting', () => {
|
|
const s = drag(-300, 0, 96);
|
|
const end = s.at(-1)!;
|
|
for (let t = 16; t <= 160; t += 16) pushSample(s, { ...end, t: end.t + t });
|
|
expect(flingDir(s)).toBeNull();
|
|
});
|
|
|
|
it('needs at least two samples', () => {
|
|
expect(flingDir([])).toBeNull();
|
|
expect(flingDir([{ x: 0, y: 0, t: 0 }])).toBeNull();
|
|
});
|
|
|
|
it('keeps the trail short', () => {
|
|
const s = drag(-2000, 0, 2000);
|
|
expect(s.at(-1)!.t - s[0].t).toBeLessThanOrEqual(216);
|
|
});
|
|
});
|