Skip to content

[players] Migrate annotation stack to fabric.js 7#2044

Merged
frankrousseau merged 9 commits into
cgwire:mainfrom
frankrousseau:fabric-7
Jun 10, 2026
Merged

[players] Migrate annotation stack to fabric.js 7#2044
frankrousseau merged 9 commits into
cgwire:mainfrom
frankrousseau:fabric-7

Conversation

@frankrousseau

@frankrousseau frankrousseau commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Problems

  • Kitsu was pinned to fabric@6.9.1 while fabric 7 is the current major (canvas 3, node 20+, jsdom 26).
  • fabric 7 flips the default originX/originY to 'center': every Kitsu shape is created and serialised by its top-left corner, so new drawings and previously-saved annotations would render shifted by half a dimension.
  • fabricjs-psbrush was still pinned to a personal fork branch instead of the upstream cgwire repo.
  • Clicking an annotation marker landed on the previous frame about half the time (float floor vs the round used to draw the marker).
  • Shift-scrub did not drive the comparison player in the playlist view.
  • Drawing while navigating frames quickly could lose annotations: the canvas reloads asynchronously without cancellation, so a save could replace an annotation with a partially-loaded canvas, and legacy unrounded annotation times left duplicated same-frame entries of which only one ever displays.

Solutions

  • Bump fabric to 7.4.0 and repoint fabricjs-psbrush to cgwire/fabricjs-psbrush (peer range widened to ^6 || ^7 in [deps] Accept fabric 7 as a peer dependency fabricjs-psbrush#2, prerequisite).
  • Restore the v6 left/top default origin globally via FabricObject.ownDefaults at annotation module init, with a regression test.
  • Compute the clicked annotation frame with Math.round, matching the marker position; bar clicks keep floor.
  • Sync the comparison player from the shift-scrub handler, like every other navigation path.
  • Cancel in-flight annotation loads on canvas clear (load token), merge canvas objects by id instead of replacing the annotation drawing on save, and merge duplicated same-frame entries at load time (mergeAnnotationsByFrame). Server-side cleanup of the legacy entries: [previews] Add a command to normalize annotation times zou#1105.
  • Gates: full unit suite (909 tests) and prod build green; runtime checklist validated by hand (draw + reload of every tool, pre-v7 annotation data, eraser mask, fullscreen/resize, playlist comparison, right-click).

frankrousseau and others added 2 commits June 9, 2026 22:55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@frankrousseau

Copy link
Copy Markdown
Contributor Author

Follow-up (non-blocking): the cgwire/fabric.js v5-snapshot fork is no longer referenced by Kitsu since the v6 migration — it can be archived once we confirm nothing else depends on it.

frankrousseau and others added 3 commits June 10, 2026 00:07
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@frankrousseau

Copy link
Copy Markdown
Contributor Author

The annotation-loss fix in this branch has a server-side complement: cgwire/zou#1105 adds a zou normalize-annotation-times command that merges the legacy duplicated entries in base and snaps their times onto the player's frame grid. Until it is run, deleting a legacy-timed object can make it reappear on reload (the deletion targets the canonical time, not the stored legacy one).

frankrousseau and others added 4 commits June 10, 2026 10:48
Drive the whole widget through diff2html's own --d2h-* design tokens
instead of overriding it class-by-class, so light and dark are themed
from a single token set that follows Kitsu's variables. Keep code text
high-contrast neutral and carry add/delete through row tint plus
word-level highlights (the old green/red text on a green/red row was
unreadable, and the default light theme leaked white into dark mode).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
diff2html silently returns an empty render when the content is not a
valid unified diff (e.g. a pretty-printed summary with no ---/+++ or @@
headers and line numbers baked into each line), leaving the viewer
blank. Detect the empty render and show the raw content in a readable
monospace block instead of nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@frankrousseau frankrousseau merged commit 0c56a36 into cgwire:main Jun 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant