This PR adds a computed cache for masked shape page bounds, which speeds
up visibility checks (a lot!).
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
Fixes [#3437](https://github.com/tldraw/tldraw/issues/3437)
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [x] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Create a shared document
2. Add a text note and start editing it
3. Double click document name. You should be now editing the document
name.
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Allow users to editing document name by double clicking even when
previously editing text.
Before we were running this on any change, even mouse position changes.
Now we only run it when shapes change.
Results wouldn't change in any case, so there's not a huge improvement.
Still, why run it if it is not necessary.
Before:
https://github.com/tldraw/tldraw/assets/2523721/b4111494-488a-42d0-9dfe-7fbc2ed88315
After:
https://github.com/tldraw/tldraw/assets/2523721/d96de329-235b-4dcb-93ea-fe297062985d
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
Hides the edit link option in the context menu for locked shapes.
Fixes [#3308](https://github.com/tldraw/tldraw/issues/3308)
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Add a link to a shape.
2. Lock it
3. Right click it to open the context menu.
4. You should not see the `Edit link` option
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Hide edit link context menu option for locked shapes.
This PR makes a small improvement to the way we measure distances.
(Often we measure distances multiple times per frame per shape on the
screen). In many cases, we compare a minimum distance. This makes those
checks faster by avoiding a square root.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
### Release Notes
- Improve performance of minimum distance checks.
After the panning hotfix got merged I created a branch from that, then
bumped the vscode version and created a new version of the extension so
that the extension also gets the hotfix.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [x] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
---------
Co-authored-by: SomeHats <huppy+SomeHats@tldraw.com>
Co-authored-by: ds300 <huppy+ds300@tldraw.com>
Co-authored-by: alex <alex@dytry.ch>
Co-authored-by: GitHub <noreply@github.com>
Co-authored-by: mimecuvalo <huppy+mimecuvalo@tldraw.com>
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
Co-authored-by: steveruizok <huppy+steveruizok@tldraw.com>
We also need to clear the timeout when panning.
https://github.com/tldraw/tldraw/assets/2523721/f32fd4d0-332c-4a80-bed0-9ce49a68e1abhttps://github.com/tldraw/tldraw/assets/2523721/e97f5fac-083f-4f77-ab72-40701790f039
Had an [alternative
approach](https://github.com/tldraw/tldraw/pull/3444) of setting
timeouts and clearing them in dispatch, but since the timeout is 500ms I
think this should work as well.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
This PR adds a micro benchmarking utility. We can use it in our jest
tests or in random scripts, though given the other requirements of our
library, benchmarking.
<img width="750" alt="Screenshot 2024-04-11 at 2 44 23 PM"
src="https://github.com/tldraw/tldraw/assets/23072548/6bba07eb-65fd-45a2-abd8-ddd0e206b9fa">
## What this isn't
This is not benchmarking. The speeds etc are based on your machine.
## What this is
This is a tool for measuring / comparing different implementations etc.
Some things run much faster than others.
### Change Type
- [x] `sdk`
- [x] `internal`
Next.js bans the use of react-dom/server APIs on the client. React's
docs recommend against using these too:
https://react.dev/reference/react-dom/server/renderToString#removing-rendertostring-from-the-client-code
In this diff, we switch from using `ReactDOMServer.renderToStaticMarkup`
to `ReactDOMClient.createRoot`, fixing SVG exports in next.js apps.
`getSvg` remains deprecated, but we've introduced a new `getSvgElement`
method with a similar API to `getSvgString` - it returns an `{svg,
width, height}` object.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix
This PR fixes flipped boolean logic for displaying the cursor chat
option on coarse pointer devices.
### Change Type
- [x] `dotcom` — Changes the tldraw.com web app
- [x] `bugfix` — Bug fix
Fixes font import link in quickstart guide
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [x] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Add a step-by-step description of how to test your PR here.
2.
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Fixes font import link in tldraw.dev quickstart guide
We reorded the dom a bit when we added the web gl rendered culled
shapes. We can now revert that.
Also noticed we weren't positioning the wrapper, so the z-index didn't
not apply.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [x] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR makes a small improvement to the hand tool to address a "long
press"-related issues.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix
Reworks our culling logic:
- No longer show the gray rectangles for culled shapes.
- Don't use `renderingBoundExpanded`, instead we now use
`viewportPageBounds`. I've removed `renderingBoundsExpanded`, but we
might want to deprecate it?
- There's now a incremental computation of non visible shapes, which are
shapes outside of `viewportPageBounds` and shapes that outside of their
parents' clipping bounds.
- There's also a new `getCulledShapes` function in `Editor`, which uses
the non visible shapes computation as a part of the culled shape
computation.
- Also moved some of the `getRenderingShapes` tests to newly created
`getCullingShapes` tests.
Feels much better on my old, 2017 ipad (first tab is this PR, second is
current prod, third is staging).
https://github.com/tldraw/tldraw/assets/2523721/327a7313-9273-4350-89a0-617a30fc01a2
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Regular culling shapes tests. Pan / zoom around. Use minimap. Change
pages.
- [x] Unit Tests
- [ ] End to end tests
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
We use text shadows to create "outlines" around text shapes. These
shadows are rendered on the GPU. In Chrome (and on computers with a
capable GPU) text shadows work pretty well, however on Safari—and in
particular on iOS—they cause massive frame drops.
https://github.com/tldraw/tldraw/assets/23072548/b65cbcaa-6cc3-46f3-b54d-1f9cc07fc499
This PR:
- adds an LOD to text shadows, removing them at < 35% zoom
- removes text shadows entirely on Safari
If we had a "high performance" or "low-end device" mode, then shadows /
text shadows would be the first to go.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
### Test Plan
1. Use text shapes on iOS.
2. Use text shapes on Safari.
3. Use text shapes on Chrome.
### Release Notes
- Improves performance of text shapes on iOS / Safari.
This PR fixes some jest test.
- We skip the culling shapes in test environments.
- We skip rendering patterns in test environments.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `tests` — Changes to any test code
This PR throttles the `updateHoveredId` call so that it happens ever
30ms.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
### Release Notes
- Improves canvas performance by throttling the update to the editor's
hovered id.
In this PR, we no longer buffer pointer down/ups. We now batch only
`pointer_move`, `wheel`, and `pinch` events.
Batched inputs were causing text not to work on iOS. On iOS, the
keyboard is only shown if we call `focus` during the same event loop as
a user input.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix
### Test Plan
1. Use text on iOS.
This PR uses an element that prevents hit tests on shapes while the
camera is moving.
https://github.com/tldraw/tldraw/assets/23072548/9905f3d4-ba64-4e4d-ae99-194f513eaac8
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
### Test Plan
1. Move the camera.
2. Interact with the canvas.
3. Zoom in and out.
### Release Notes
- Improves performance of canvas while the camera is moving.
This PR makes a small improvement to the speed of `getShapeAtPoint`. It
removes `Editor.getCurrentPageRenderingShapesSorted`.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
Can be useful for ad-hoc measure of performance. One is a method
decorator, which can be use on methods like so:
```typescript
@measureDuration
someLongRunningProccess() {
// ....
}
```
And the other offer more granular control. It also returns what the
callback returns, so it can be use in assignments / return statements.
```typescript
return measureCbDuration('sorting took', () => renderingShapes.sort(sortById))
```
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [x] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
This PR improves a bunch of places where we do "minimum distance
checks". Previously, we were using `Vec.Dist`, which uses `Math.hypot`
to find the actual distance, but we can just as well use the squared
distance. So this PR makes a small improvement to `Vec.Dist2` and then
switches to that method when checking minimum distances.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
### Test Plan
- [x] Unit Tests
### Release Notes
- Performance: small improvements to hit testing.
An immense contribution, I know.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ x ] `docs` — Changes to the documentation, examples, or templates.
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ x ] `chore` — Updating dependencies, other boring stuff
This PR extracts the #3344 changes to a smaller diff against main. It
does not include the changes to how / where culled shapes are
calculated, though I understand this could be much more efficiently
done!
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
---------
Co-authored-by: Mitja Bezenšek <mitja.bezensek@gmail.com>
This PR makes the `getCurrentPageId` method use a computed. Previously,
anything that referenced the current page id would pick up any change to
instance state. This will help a bunch of interactions like brushing
that would update the instance state on every frame.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features
Comparing different culling optimizations:
https://github.com/tldraw/tldraw/assets/2523721/0b3b8b42-ed70-45b7-bf83-41023c36a563
I think we should go with the `display: none` + showing the skeleteon.
The way it works is:
- We now add a sibling to the shape wrapper div which serves as the
skeleton for the culled shapes.
- Only one of the two divs (shape wrapper and skeleton div) is
displayed. The other one is using `display: none` to improve
performance.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
- Improve performance of culled shapes by using `display: none`.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR makes a small change to how useFileSystem reports errors, so
that legitimate errors may be caught.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `feature` — New feature
I think the keyboard shortcuts example already teaches the concept that
the actions overrides example does. I've updated the keyboard shortcuts
example and included an action override example in case we want that
too.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [x] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Add a step-by-step description of how to test your PR here.
2.
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Add action overrides example, update keyboard shortcuts example
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR adds a "long press" event that fires when pointing for more than
500ms. This event is used in the same way that dragging is used (e.g. to
transition to from pointing_selection to translating) but only on
desktop. On mobile, long presses are used to open the context menu.
![Kapture 2024-03-26 at 18 57
15](https://github.com/tldraw/tldraw/assets/23072548/34a7ee2b-bde6-443b-93e0-082453a1cb61)
## Background
This idea came out of @TodePond's #3208 PR. We use a "dead zone" to
avoid accidentally moving / rotating things when clicking on them, which
is especially common on mobile if a dead zone feature isn't implemented.
However, this makes it difficult to make "fine adjustments" because you
need to drag out of the dead zone (to start translating) and then drag
back to where you want to go.
![Kapture 2024-03-26 at 19 00
38](https://github.com/tldraw/tldraw/assets/23072548/9a15852d-03d0-4b88-b594-27dbd3b68780)
With this change, you can long press on desktop to get to that
translating state. It's a micro UX optimization but especially nice if
apps want to display different UI for "dragging" shapes before the user
leaves the dead zone.
![Kapture 2024-03-26 at 19 02
59](https://github.com/tldraw/tldraw/assets/23072548/f0ff337e-2cbd-4b73-9ef5-9b7deaf0ae91)
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [x] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Long press shapes, selections, resize handles, rotate handles, crop
handles.
2. You should enter the corresponding states, just as you would have
with a drag.
- [ ] Unit Tests TODO
### Release Notes
- Add support for long pressing on desktop.
This PR changes our input buffering to only buffer pointer events. We
were already moving in this direction with the complete / cancel
flushes, now it's just more explicit. If we want to add other events
into here, then we can.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix
This PR fixes a bug that was introduced by #3223. There was a code path
that normally used to never run (a blur event running when the shape was
no longer editing) but which was being run now that shapes aren't
immediately removed on pointer down.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix
### Test Plan
1. Create a sticky note
2. Begin editing the note
3. click on the canvas
4. You should be in pointing_canvas
Adds an example of a tool with child states. I'm going over the
annotations at the moment, just wanted to validate the idea in the
meantime.
Closes tld-2114
- [x] `documentation` — Changes to the documentation only[^2]
### Release Notes
- Add an example of a tool with child states
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
The refactor of the textfields in this PR
https://github.com/tldraw/tldraw/pull/3050 caused a regression in
resizing Text shapes. (as demonstrated in this PR's video:
https://github.com/tldraw/tldraw/pull/3327)
We reverted that PR and now this PR updates the CSS to fix the gap that
was introduced when it was refactored.
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
Fixes a bug with text resizing on text shapes, now the transform origin
is set depending on the alignment.
![2024-04-02 at 16 50 49 - Aqua
Snail](https://github.com/tldraw/tldraw/assets/98838967/86b59691-e950-4367-8632-03ae6dfef7f6)
![2024-04-02 at 16 49 37 - Teal
Tuna](https://github.com/tldraw/tldraw/assets/98838967/6b6c97a8-fc53-45a0-8282-6bd63e77507b)
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Make a text shape
2. resize it
3. It should stay within the bounds
### Release Notes
- Fixes an issue with text shapes overflowing their bounds when resized.
This PR buffs input events.
## The story so far
In the olde days, we throttled events from the canvas events hook so
that a pointer event would only be sent every 1/60th of a second. This
was fine but made drawing on the iPad / 120FPS displays a little sad.
Then we removed this throttle. It seemed fine! Drawing at 120FPS was
great. We improved some rendering speeds and tightened some loops so
that the engine could keep up with 2x the number of points in a line.
Then we started noticing that iPads and other screens could start
choking on events as it received new inputs and tried to process and
render inputs while still recovering from a previous dropped frame. Even
worse, on iPad the work of rendering at 120FPS was causing the browser
to throttle the app after some sustained drawing. Yikes!
### Batching
I did an experimental PR (#3180) to bring back batching but do it in the
editor instead. What we would do is: rather than immediately processing
an event when we get it, we would instead put the event into a buffer.
On the next 60FPS tick, we would flush the buffer and process all of the
events. We'd have them all in the same transaction so that the app would
only render once.
### Render batching?
We then tried batching the renders, so that the app would only ever
render once per (next) frame. This added a bunch of complexity around
events that needed to happen synchronously, such as writing text in a
text field. Some inputs could "lag" in a way familiar to anyone who's
tried to update an input's state asynchronously. So we backed out of
this.
### Coalescing?
Another idea from @ds300 was to "coalesce" the events. This would be
useful because, while some interactions like drawing would require the
in-between frames in order to avoid data loss, most interactions (like
resizing) didn't actually need the in-between frames, they could just
use the last input of a given type.
Coalescing turned out to be trickier than we thought, though. Often a
state node required information from elsewhere in the app when
processing an event (such as camera position or page point, which is
derived from the camera position), and so the coalesced events would
need to also include this information or else the handlers wouldn't work
the way they should when processing the "final" event during a tick.
So we backed out of the coalescing strategy for now. Here's the [PR that
removes](937469d69d)
it.
### Let's just buffer the fuckers
So this PR now should only include input buffering.
I think there are ways to achieve the same coalescing-like results
through the state nodes, which could gather information during the
`onPointerMove` handler and then actually make changes during the
`onTick` handler, so that the changes are only done as many time as
necessary. This should help with e.g. resizing lots of shapes at once.
But first let's land the buffering!
---
Mitja's original text:
This PR builds on top of Steve's [experiment
PR](https://github.com/tldraw/tldraw/pull/3180) here. It also adds event
coalescing for [`pointerMove`
events](https://github.com/tldraw/tldraw/blob/mitja/input-buffering/packages/editor/src/lib/editor/Editor.ts#L8364-L8368).
The API is [somewhat similar
](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/getCoalescedEvents)
to `getCoalescedEvent`. In `StateNodes` we register an `onPointerMove`
handler. When the event happens it gets called with the event `info`.
There's now an additional field on `TLMovePointerEvent` called
`coalescedInfo` which includes all the events. It's then on the user to
process all of these.
I decided on this API since it allows us to only expose one event
handler, but it still gives the users access to all events if they need
them.
We would otherwise either need to:
- Expose two events (coalesced and non-coalesced one and complicate the
api) so that state nodes like Resizing would not be triggered for each
pointer move.
- Offer some methods on the editor that would allow use to get the
coalesced information. Then the nodes that need that info could request
it. I [tried
this](9ad973da3a (diff-32f1de9a5a9ec72aa49a8d18a237fbfff301610f4689a4af6b37f47af435aafcR67)),
but it didn't feel good.
This also complicated the editor inputs. The events need to store
information about the event (like the mouse position when the event
happened for `onPointerMove`). But we cannot immediately update inputs
when the event happens. To make this work for `pointerMove` events I've
added `pagePoint`. It's
[calculated](https://github.com/tldraw/tldraw/pull/3223/files#diff-980beb0aa0ee9aa6d1cd386cef3dc05a500c030638ffb58d45fd11b79126103fR71)
when the event triggers and then consumers can get it straight from the
event (like
[Drawing](https://github.com/tldraw/tldraw/pull/3223/files#diff-32f1de9a5a9ec72aa49a8d18a237fbfff301610f4689a4af6b37f47af435aafcR104)).
### Change Type
<!-- ❗ Please select a 'Scope' label ❗️ -->
- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff
<!-- ❗ Please select a 'Type' label ❗️ -->
- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
### Test Plan
1. Add a step-by-step description of how to test your PR here.
4.
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Add a brief release note for your PR here.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
Recently (https://github.com/tldraw/tldraw/pull/3012), we started
aggregating data messages before sending them out. However, local
testing shows that we generate *many* redundant messages (see the test
file for an example of a real buffer captured during local testing with
just two users). This PR adds a function to squish those updates
together, reducing the amount of data we need to transfer and load on
the client that won't need to process those redundant messages.
The function is checked with [fast-check](https://fast-check.dev/), a JS
property test framework, to make sure that squished deltas result in
exactly the same state as the original ones.
### Change Type
- [x] `minor` — New feature
### Test Plan
1. Needs a group smoke test
- [x] End to end tests
This PR adds scripts that allow us to generate reports on our
dependencies.
### Change Type
- [x] `internal` — Any other changes that don't affect the published
package[^2]
This PR simplifies the debug count for debugging number of elements on
the page. It fixes a bug where note shapes and other shapes without
shapeid ids were not correctly counted.
### Change Type
- [x] `sdk` — Changes the tldraw SDK
- [x] `bugfix` — Bug fix