Commit Graph
67 Commits
Author SHA1 Message Date
doodlewind bb1bbccd0f refactor(editor): rx state management in turbo renderer (#11200)
# Refactor Turbo Renderer State Management to Use RxJS

### TL;DR

Refactored the TurboRenderer state management to use RxJS observables instead of direct state mutations, improving state transitions and reactivity.

### What changed?

- Replaced the public `state` property with a private `state$` BehaviorSubject in `ViewportTurboRendererExtension`
- Added proper state transition logging using RxJS operators
- Combined multiple event subscriptions using `merge` operator for better organization
- Improved state transition logic in the `refresh()` method
- Updated the `zooming$` and `panning$` signals in the Viewport

### Why make this change?

This refactoring improves the codebase by:
1. Using a more consistent reactive programming model with RxJS
2. Making state transitions more explicit and traceable
3. Reducing potential bugs from manual state management
4. Improving code organization by combining related event streams
5. Ensuring proper cleanup of resources when components are disposed

The change maintains the same functionality while making the code more maintainable and the state management more robust.
2025-03-27 04:50:32 +00:00
doodlewind 80f62a995b perf(editor): improve resize frame rate (#10967)
This PR improves panel toggling FPS by minimizing DOM and canvas updates during resizing.

[Screen Recording 2025-03-18 at 11.57.45 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/lEGcysB4lFTEbCwZ8jMv/d36beeab-a2e4-4fd6-923a-705ce7fbcdf7.mov" />](https://app.graphite.dev/media/video/lEGcysB4lFTEbCwZ8jMv/d36beeab-a2e4-4fd6-923a-705ce7fbcdf7.mov)

### What changed?

- Added a debounced resize handling mechanism using RxJS's `debounceTime` operator
- Implemented a new resize strategy that preserves the top-left corner position during resizing
- Added state tracking for resize operations with `_isResizing` flag and `_initialTopLeft` coordinates
2025-03-19 04:42:23 +00:00
doodlewind 02d707feab fix(editor): adapt font size in turbo renderer (#10858) 2025-03-18 19:01:48 +00:00
doodlewind 81af7a0571 docs(editor): add guide for extension usage (#10911)
The guide is baed on #10847 to improve the code quality for migrating extensions using LLM.
2025-03-17 05:38:10 +00:00
doodlewind d8dfea6ccf fix(editor): type import in vite worker env (#10856)
The dependencies of `@blocksuite/affine-gfx-turbo-renderer` in work is now all type imports.
2025-03-14 10:22:58 +00:00
doodlewind d1c10f5401 chore(editor): hide tweakpane for turbo renderer (#10846) 2025-03-14 06:47:15 +00:00
doodlewind be9f44fc4f fix(editor): worker loading in webpack env (#10832)
### TL;DR

Created dedicated worker entry points to avoid dynamic imports.

### What changed?

- Painters are provided during worker initialization
- Removed `ParagraphPaintConfigExtension` and the associated configuration system
- Created dedicated worker entry points in both the integration test and frontend packages
- Modified `ViewportLayoutPainter` to accept painters in its constructor
- Updated the `TurboRendererConfig` interface to require a `painterWorkerEntry` function

### Why make this change?

Webpack support. Extension objects in main thread are not available to be passed into workers. Dynamic painter path import is hard to support in webpack environment. With the [webpack-ignore](https://webpack.js.org/api/module-methods/#webpackignore) rule, there are still build errors in webpack.
2025-03-14 05:26:57 +00:00
doodlewind 0f062b7157 refactor(editor): make turbo renderer a gfx extension (#10818)
This allows for easier debugging via `gfx.turboRenderer`
2025-03-13 07:45:05 +00:00
doodlewind c023b724d0 refactor(editor): generic layout type support for turbo renderer (#10766)
This PR refactored the turbo renderer architecture to support multiple block layout types.

- New base class `BlockLayoutPainter` and `BlockLayoutProvider` are introduced for writing extendable per-block layout querying and painting logic.
- Paragraph-specific lines are all moved into dedicated classes (`ParagraphLayoutProvider` and `ParagraphLayoutPainter`) under the `/variants/paragraph` dir.
- The `renderer-utils.ts` doesn't contain paragraph-specific logic now.
- The `text-utils.ts` is also now scoped for paragraph only.
- Worker messages are now strongly typed.

Upcoming PR should further implement the block registration system using extension API. The `variants` dir could still exist, since there will be similar rendering logic that can be reused among block types (i.e., between paragraph block and list block).
2025-03-13 05:18:12 +00:00
doodlewind ad36a9de35 refactor(editor): add gfx turbo renderer package (#10745)
The `ViewportTurboRendererExtension` is now extracted from `@blocksuite/affine-shared` to `@blocksuite/affine-gfx-turbo-renderer` with minimal dependencies, mirroring the gfx text package in #10378.
2025-03-11 03:21:52 +00:00
doodlewind d0bc1a0271 fix(editor): incorrect text position in turbo renderer (#10728)
Fixed incorrect text positioning regression across multiple lines (#10624)

Before:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/e1d7ba50-d331-41e3-8d31-dee2324e7439.png)

After:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/215ec925-65bf-4014-ba6c-db431cb56261.png)
2025-03-10 06:27:38 +00:00
doodlewind 334912e85b perf(editor): lazy DOM update with idle state in gfx viewport (#10624)
Currently, `GfxViewportElement` hides DOM blocks outside the viewport using `display: none` to optimize performance. However, this approach presents two issues:

1. Even when hidden, all top-level blocks still undergo frequent CSS transform updates during viewport panning and zooming.
2. Hidden blocks cannot access DOM layout information, preventing `TurboRenderer` from updating the complete canvas bitmap.

To address this, this PR introduces a refactoring that divides all top-level edgeless blocks into two states: `idle` and `active`. The improvements are as follows:

1. Blocks outside the viewport are set to the `idle` state, meaning they no longer update their DOM during viewport panning or zooming. Only `active` blocks within the viewport are updated frame by frame.
2. For `idle` blocks, the hiding method switches from `display: none` to `visibility: hidden`, ensuring their layout information remains accessible to `TurboRenderer`.

[Screen Recording 2025-03-07 at 3.23.56 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/lEGcysB4lFTEbCwZ8jMv/4bac640b-f5b6-4b0b-904d-5899f96cf375.mov" />](https://app.graphite.dev/media/video/lEGcysB4lFTEbCwZ8jMv/4bac640b-f5b6-4b0b-904d-5899f96cf375.mov)

While this minimizes DOM updates, it introduces a trade-off: `idle` blocks retain an outdated layout state. Since their positions are updated using a lazy update strategy, their layout state remains frozen at the moment they were last moved out of the viewport:

![idle-issue.jpg](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/9c8c2150-69d4-416b-b46e-8473a7fdf339.jpg)

To resolve this, the PR serializes and stores the viewport field of the block at that moment on the `idle` block itself. This allows the correct layout, positioned in the model coordinate system, to be restored from the stored data.
2025-03-08 01:38:02 +00:00
doodlewind c418e89fb9 chore(editor): add feature flag entry for testing turbo renderer (#10581)
The debug pane will be displayed once the `enable_turbo_renderer` feature flag is enabled.

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/c1ba558a-2d84-403c-aa81-864b0338c861.png)
2025-03-04 05:38:44 +00:00
doodlewind 86c449319b chore(editor): remove redundant fields in viewport (#10569) 2025-03-03 07:49:08 +00:00
doodlewind bd1b26a230 feat(editor): support zooming placeholder in turbo renderer (#10504)
[Screen Recording 2025-02-28 at 4.32.20 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/lEGcysB4lFTEbCwZ8jMv/6c08b827-8428-42f3-aa7a-a2366756bd16.mov" />](https://app.graphite.dev/media/video/lEGcysB4lFTEbCwZ8jMv/6c08b827-8428-42f3-aa7a-a2366756bd16.mov)

This prevents painting task backlog during zooming by adding a fast placeholder painter, with a `zooming` state in renderer state machine.
2025-03-03 02:07:46 +00:00
doodlewind 12acf7e4a0 fix(editor): range IndexSizeError on firefox (#10519)
This is a Firefox compat issue, I've manually confirmed this implementation works in latest Firefox build.
2025-02-28 11:50:56 +00:00
doodlewind 22191caa82 fix(editor): safari compat for lit host (#10514)
Fixed this white screen crash on mobile safari:

<img src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/00bffd51-8e06-4d37-88d4-6f5020cd503d.png" width="500">
2025-02-28 10:26:59 +00:00
doodlewind f1df774188 fix(editor): invalidate turbo renderer on selection update (#10499) 2025-02-28 08:08:28 +00:00
doodlewind 8cec22cc64 fix(editor): handle resize in turbo renderer (#10465) 2025-02-27 04:18:37 +00:00
doodlewind 3252dd7a31 feat(editor): automatically hide canvas optimized blocks (#10451)
Qualified DOM blocks can now be optimized away automatically.

<img alt="image.png" width="500" src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/102bf813-154a-4816-9eb0-2c9c0ce01fe7.png">

Since this is under development, verifying state correctness is more important than rendering details.

This won't affect current production version since the passive APIs added to `GfxViewportElement` are disabled by the `enableOptimization = false` config.
2025-02-27 02:10:49 +00:00
doodlewind 589622043c fix(editor): list toggle position offset (#10448)
Before:

![image](https://github.com/user-attachments/assets/fbddc396-1078-4c1e-8e2c-c26c6e4a6d61)

After:

<img width="579" alt="image" src="https://github.com/user-attachments/assets/7b049b53-269b-484e-ba76-fa6f46a2004c" />

This centering approach won't affect heading blocks:

<img width="267" alt="image" src="https://github.com/user-attachments/assets/3f3217e3-7e23-43fc-a7e5-33b6eadccc88" />
2025-02-26 12:09:00 +00:00
doodlewind 0f8c837fbe refactor(editor): simplify renderer state (#10441)
The redundant `monitoring` state has been removed. The new `ready` state is used for querying if DOM elements can be safely optimized away.
2025-02-26 08:39:58 +00:00
doodlewind e38e59d4e5 refactor(editor): request refresh after finding stale bitmap (#10438)
This ensures a bitmap will be eventually generated after tile got invalidated.
2025-02-26 06:49:09 +00:00
doodlewind 97cc814a22 fix(editor): remote cursor color inconsistency (#10437)
Fixed:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/c2db021e-6ee9-4022-913c-84b84953d36e.png)
2025-02-26 04:42:05 +00:00
doodlewind f3911b1b5e fix(editor): discard stale layout bitmap in turbo renderer (#10427)
Fixes this bug caused by stale bitmap:

[Screen Recording 2025-02-24 at 6.10.19 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/lEGcysB4lFTEbCwZ8jMv/3e24f4b7-6f95-4c7c-a79a-b8e4ffdb3b10.mov" />](https://app.graphite.dev/media/video/lEGcysB4lFTEbCwZ8jMv/3e24f4b7-6f95-4c7c-a79a-b8e4ffdb3b10.mov)
2025-02-25 10:51:55 +00:00
doodlewind 67889d9364 fix(editor): turbo renderer stale frame lag on zooming (#10376)
Before:

https://github.com/user-attachments/assets/593e91a3-042e-4619-93a0-dca21fa942aa

After:

https://github.com/user-attachments/assets/779d7582-f7b2-4135-a97a-d1f65c7cb467

This is only a bug fix that ensures correct baseline rendering result. There'll be more optimizations specific for zooming TBD.
2025-02-24 03:49:04 +00:00
doodlewind 542f759ffb refactor(editor): add panning/zooming field in viewport event (#10373) 2025-02-23 08:58:15 +00:00
doodlewind 22f9db63bc refactor(editor): invalidate support in turbo renderer (#10368)
refactor(editor): invalidate support in turbo renderer

- Added `invalidate()` method to clear cache and canvas
- Simplified debug pane controls to single invalidate button
- Replaced layout update with refresh debounce on block updates
- Improved cache handling and bitmap drawing flow

refactor: refresh after invalidate
2025-02-23 03:23:20 +00:00
doodlewind c362737441 perf(editor): reduce dom ops in viewport update (#10333) 2025-02-21 03:30:10 +00:00
doodlewind 64cc99354e refactor(editor): add zoom threshold for dom rendering fallback (#10322) 2025-02-20 11:45:19 +00:00
doodlewind 7b1dfb7ee8 refactor(editor): reduce dom query per refresh (#10319) 2025-02-20 10:01:13 +00:00
doodlewind b38abcb59c perf(editor): avoid recreation of Intl.Segmenter (#10295)
<img width="537" alt="image" src="https://github.com/user-attachments/assets/43e54d94-6228-4c26-b3d0-cf4725b251e4" />
2025-02-20 03:55:57 +00:00
doodlewind 676ccc9094 refactor(editor): allow force refresh in worker renderer (#10289) 2025-02-19 14:23:45 +00:00
doodlewind 1476ca922b refactor(editor): simplify worker renderer message and canvas transfer (#10199)
- Fixed frame delay on panning.
- Removed redundant worker message.
- Removed redundant offscreen bitmap transfer.
- Refactored logic using a clearer `refresh` method entry.
- Extracted plain utils.
2025-02-17 02:35:28 +00:00
doodlewind 0cd7868b3d refactor(editor): add mock notes creator (#10109)
Further features should be validated using multiple notes.

<img width="806" alt="image" src="https://github.com/user-attachments/assets/ad2bf934-bebe-479a-bec0-a0a28001b08d" />
2025-02-12 05:23:19 +00:00
doodlewind d021e4cddc refactor(editor): mount worker renderer in editor host (#10055)
This would allow for easier integration with current test runner, since the two column layout is removed.

The `ViewportTurboRender` canvas and its debug UI are only enabled if the extension is added, which won't affect the AFFiNE entry.

<img width="945" alt="image" src="https://github.com/user-attachments/assets/dc82daa4-cbed-4eb9-9660-28c3f7d35722" />
2025-02-11 14:12:41 +00:00
doodlewind 3062bd0771 refactor(editor): migrate viewport renderer to extension (#10094)
This removes `renderer.setHost(host)`
2025-02-11 11:37:31 +00:00
doodlewind 9bf1e38e94 chore(editor): simplify legacy playground build config (#10044)
This should allow for simpler migration of the `@blocksuite/playground` vite environment.
2025-02-10 23:38:40 +00:00
doodlewind 1d1eab8139 fix(editor): workaround empty text in insertText (#10049)
`sentry-5a32bef4f2724b5f8e6f31791cb20feb`
2025-02-10 07:24:26 +00:00
doodlewind 614ae024c2 fix(editor): workaround empty content in worker renderer (#10043) 2025-02-10 03:35:50 +00:00
doodlewind 56d604f685 perf(editor): use clipped section for worker bitmap cache (#9957)
Before (grey area as rendered canvas bitmap):

<img width="1114" alt="image" src="https://github.com/user-attachments/assets/9a209818-c388-4e55-af9b-116f24bd8027" />

After:

<img width="1103" alt="image" src="https://github.com/user-attachments/assets/1102264a-ec21-4c0c-b4b6-e82a64b1a844" />
2025-02-05 11:54:03 +00:00
doodlewind 872a578bf7 refactor(editor): move zod schema with model for non surface blocks (#9876) 2025-01-23 10:57:49 +00:00
doodlewind 22e424d7de test(editor): fix font style in preset tests (#9847) 2025-01-22 10:00:58 +00:00
doodlewind 14ca171a18 chore(web): bump theme (#9801) 2025-01-20 13:51:24 +00:00
doodlewind 509cdfd7bf fix(editor): playground font inconsistency (#9728) 2025-01-16 08:16:13 +00:00
doodlewind 890a962196 chore(editor): fix playground vscode tsc warning (#9603) 2025-01-09 07:49:16 +00:00
doodlewind e269cce141 refactor(editor): playground doc collection typing migration (#9593) 2025-01-09 03:07:43 +00:00
doodlewind cbc84ff672 fix(editor): blur in edgeless content zooming (#9496)
Fix [BS-2294](https://linear.app/affine-design/issue/BS-2294/edgeless-%E7%BC%A9%E6%94%BE%E5%AD%97%E5%8F%B7%E6%A8%A1%E7%B3%8A)
2025-01-03 02:36:57 +00:00
doodlewind 8227d68953 refactor(core): remove abort event error on init (#9465)
Following error always throw on Affine init, which is actually an `Event` from abort controller that can be handled in upstream.

![image](https://github.com/user-attachments/assets/50c25e5e-4a9c-45e0-b756-6b0f47390733)
2025-01-01 01:22:29 +00:00
doodlewind adf14d11d5 fix(editor): chat panel render warning (#9446)
Fixed the updated warning of both `chat-panel` and `chat-panel-messages`

![image](https://github.com/user-attachments/assets/73f30e45-119a-4899-bf05-84f8f64b944b)
2024-12-31 03:59:02 +00:00
doodlewind 2b47625deb refactor(editor): render presentation toolbar on demand (#9442) 2024-12-31 02:01:35 +00:00
doodlewind d4053a345e perf(editor): reduce per frame viewport dom ops (#9431)
Currently when panning / zooming on whiteboard, both position and transform of each block component are updated per frame. The positioning part lead to heavy layout costs, which can be reduced.

Before (~35fps):

![image](https://github.com/user-attachments/assets/3f6d8a76-26a5-4ed6-a64c-b519a453cbc0)

After (~50fps):

![image](https://github.com/user-attachments/assets/43bc4b0a-db01-4526-8400-2ec95c3bdd0b)

Tested environment: TibetTravel templet, Windows 11, i5-1130G7 1.1GHz
2024-12-30 10:50:33 +00:00
doodlewind 406460a3af chore(docs): update server start script (#9423)
Currently, directly running `yarn dev` in `packages/backend/server` (following `developing-server.md`) instead of `yarn affine server dev` would raise following error:

``` sh
server git:(canary) ✗ yarn dev
[nodemon] 3.1.9
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json
[nodemon] starting `node ./src/index.ts`
node:internal/modules/esm/get_format:160
  throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath);
        ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/ewind/code/AFFiNE/packages/backend/server/src/index.ts
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:141:22)
    at async ModuleLoader.load (node:internal/modules/esm/loader:409:7)
    at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:291:45)
    at async link (node:internal/modules/esm/module_job:76:21) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

Node.js v20.10.0
[nodemon] app crashed - waiting for file changes before starting...
```
2024-12-30 07:28:23 +00:00
doodlewind 5e1d936c2e fix(editor): sentry-b0cfc9953ff64c53b9994697171bb91a (#9396) 2024-12-27 14:02:00 +00:00
doodlewind fe957e3175 fix(editor): eslint useless escape (#9345) 2024-12-26 11:09:30 +00:00
doodlewind 9a29ac4a5c fix(editor): sentry-332848caa68e4679b403d56881e3c0e3 (#9343) 2024-12-26 10:26:31 +00:00
doodlewind 9b3a2fc0de fix(editor): sentry-624432d8f1e6420ca9c5023a051f4332 (#9342)
Close https://toeverything.sentry.io/issues/6091618868/?project=4506307500179456
2024-12-26 09:59:06 +00:00
doodlewind 71b5cddea1 fix(editor): use nullable inline editor root element (#9320)
Fixes `sentry-7906c03b79a54ede819c56cc15ad9889`
2024-12-26 07:55:15 +00:00
doodlewind 7b572bc89e fix(editor): sentry-17da76f65b91465b911fad44279d971a (#9315) 2024-12-26 02:54:07 +00:00
doodlewind a15009ce84 chore(editor): ignore debug zip snapshots (#9297)
Put snapshot zips in `blocksuite/playground/apps/starter/data/snapshots/`
2024-12-25 02:18:46 +00:00
doodlewind 20aca4d051 chore(tools): disable hmr by default (#9286) 2024-12-24 10:32:01 +00:00
doodlewind 98f88d2615 chore: base url for mobile debug (#9268)
Without this PR, the login requests on mobile devices will be sent to `localhost:8080`, which is incorrect.
2024-12-24 03:54:56 +00:00
doodlewind edd169720b chore(server): update env example and docs (#9153) 2024-12-13 11:04:08 +00:00
doodlewind 8545644bb6 chore: bump blocksuite (#9049) 2024-12-06 08:33:47 +00:00
doodlewind 6ac8cca440 fix(mobile): disable AI chat block peek on mobile (#8929) 2024-11-26 11:06:15 +00:00
doodlewind ba325a6040 chore: update env example (#8909)
This aligns better with the postgres config in [server development guide](https://github.com/toeverything/AFFiNE/blob/canary/docs/developing-server.md).
2024-11-26 10:17:16 +00:00
doodlewind 08ff619d47 chore(cli): enable accessing dev server by host name (#8912)
This PR is particularly useful for debugging mobile app (and any other personal devices for testing) via [Tailscale](https://tailscale.com/), since it allows accessing a stable hostname on phone, instead of typing in an unstable IP address.

Before:

![image](https://github.com/user-attachments/assets/6ca9edd5-11b1-449b-bf8d-0423cb8a53fe)

After:

![image](https://github.com/user-attachments/assets/9df7710f-f662-4a3c-83c4-cf5f28d7c64f)
2024-11-25 06:58:14 +00:00