Implemented click detection all the way up to quadruple clicks. 🤯
It sort of works like this: each time the user clicks, we fire three events—we fire onPointerDown when they start clicking, then onPointerUp _and_ onClick when the they stop clicking.
We also keep track of a clicking state.
This starts in "idle" and can be either "idle", "pendingDoubleClick", "pendingTripleClick", "pendingQuadrupleClick", or "overflow".
When we a pointer down event, what we do next depends on our current state.
If our state is idle, then we change our state to "pendingDoubleClick". We also set a timer for ~450ms. When that time goes off, it will set the state back to "idle".
If we get another pointer event while we're still in "pendingDoubleClick", we've got a double click! We first fire a single click, then a double click, then clear the current timer and set a new one that, when it goes off, will advance us to "pendingTripleClick".
Repeat for triple click—fire a single click, fire a triple click, clear the timer, move to "pendingQuadrupleClick", and set a new timer.
Repeat for quadruple click—fire a click, fire a quadruple click, clear the timer, move to "overflow", and set a new timer.
The "overflow" state is special! The overflow state prevents us from firing additional events other than regular "click" until there's been at least our ~450ms between clicks. Each click in "overflow" resets the timer but returns us to overflow.
That's the pattern. I'll see if I can work out a nice isolated implementation, but in the meantime here are my tests: gist.github.com/steveruizok/00…
Also—moving the pointer more than a certain threshold (~5px) clears the timer. This prevents accidental double-clicks after finishing a drag.
So "down, move, up, down" should be a single click, even if it happens quickly.
Working on a new Undo / Redo manager that runs on mobx and JSON patches. Here's how it works! 🧵
First off, here's a CodeSandbox. Looks pretty simple but there's a lot going on. I've included my tests! codesandbox.io/s/mobx-undo-re…
In our system, we're tracking changes to a "document". Each time the document changes, we generate a "snapshot" and compare it with our previous snapshot in order to create a "patch" that describes how to get from the current snapshot back to the previous.
What do I mean by smarter? Let's say each of our blocks has a position in a grid, [x, y]. (It's actually a 3D grid, so [x, y, z], but we can ignore the z for now)
The positions map to the block's index in z/y/x arrays. This means that a block's position can only be an integer like 1 or 2, but never a float like 1.25 or 2.81.
So a position like [0, 0] is fine but [0.5, 0] is not.
I'm currently experiencing a "where do I put whitespace in my code" crisis.
I've usually placed empty lines between pretty much everything except maybe variable definitions, but this makes different methods hard to spot and sometimes makes methods themselves harder to read?
But saving empty lines for just separating methods / class fields can lead to some very dense code.