v0.28.0 - #260
Conversation
… bugs with brush state and interactions at subtask opacity 0
There was a problem hiding this comment.
🟡 Changes recommended
Class selection, focus rendering, brush preservation, and raw-mask validation contain unresolved behavioral defects.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Releases ULabel v0.28.0 with memory-efficient bitmasks, class-focused workflows, expanded runtime APIs, and interaction fixes.
Changes:
- Adds windowed bitmask storage and scoped overlap handling.
- Adds active-class focus, mode enforcement, callbacks, batching, recoloring, and ClassCounter APIs.
- Improves annotation interaction, image swapping, UI positioning, demos, tests, and release packaging.
File summaries
| File | Description |
|---|---|
src/index.js |
Integrates the new APIs and interaction behavior. |
src/active_class.ts |
Implements class selection and focus state. |
src/annotation_operators.ts |
Applies per-class mode filtering. |
src/blobs.js |
Adjusts dialog stacking. |
src/configuration.ts |
Adds new configuration options. |
src/geometric_utils.ts |
Adds polyline proximity calculations. |
src/html_builder.ts |
Repositions confidence dialogs. |
src/initializer.ts |
Removes back canvases and refreshes boxes. |
src/listeners.ts |
Routes selection and focus interactions. |
src/mask_utils.ts |
Implements windowed bitmask storage. |
src/subtask.ts |
Adds class-focus state. |
src/toolbox.ts |
Extends ClassCounter and recoloring behavior. |
src/toolbox_items/annotation_list.ts |
Filters defocused annotations. |
src/toolbox_items/keybinds.ts |
Synchronizes shared class keybinds. |
src/version.js |
Bumps the library version. |
index.d.ts |
Declares the expanded public API. |
api_spec.md |
Documents new APIs and options. |
CHANGELOG.md |
Records the v0.28.0 release. |
package.json |
Bumps version and adds the prepare hook. |
package-lock.json |
Synchronizes package version metadata. |
scripts/prepare.js |
Builds missing distribution artifacts. |
.github/workflows/test.yml |
Stabilizes Playwright dependency installation. |
.github/tasks.md |
Tracks implementation and verification work. |
demo.js |
Lists the class-focus demo. |
demo/bitmask-example.html |
Demonstrates cross-subtask overlap. |
demo/class-focus.html |
Demonstrates class focus and mode restrictions. |
demo/single-class.html |
Exposes the instance for testing. |
tests/annotation.test.js |
Tests annotation swapping and canvas cleanup. |
tests/bitmask_overlap.test.js |
Tests overlap scoping. |
tests/brush_state.test.js |
Tests brush teardown during switching. |
tests/class_allowed_modes.test.js |
Tests class-specific mode enforcement. |
tests/class_counter.test.js |
Tests ClassCounter layouts and options. |
tests/class_focus.test.js |
Tests focus behavior and rendering. |
tests/class_keybinds.test.js |
Tests shared keybind synchronization. |
tests/host_callbacks.test.js |
Tests host callback semantics. |
tests/mask_utils.test.js |
Tests windowed mask behavior. |
tests/set_annotations_batch.test.js |
Tests batched annotation replacement. |
tests/set_class_color.test.js |
Tests class recoloring APIs. |
tests/set_subtask_opacity.test.js |
Tests runtime layer opacity. |
tests/subtask_hidden.test.js |
Tests hidden-subtask interaction gates. |
tests/swap_frame_image.test.js |
Tests image dimension validation. |
tests/teardown.test.js |
Updates teardown expectations. |
tests/e2e/basic-functionality.spec.js |
Tests confidence-card geometry. |
tests/e2e/bitmask.spec.js |
Tests cross-subtask overlap behavior. |
tests/e2e/read-only.spec.js |
Tests read-only button visibility. |
Review details
- Files reviewed: 43/45 changed files
- Comments generated: 4
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
One thing in here I think needs fixing before it goes in.
get_active_class_id_idx() can return -1, and the reclass paths use that as an index without checking. If you're in a delete mode with an annotation hovered, you end up writing confidence 0 to every class on it. Comments inline on the two spots.
The guard in listeners.ts that should have caught this is checking a field nothing ever assigns, so it never fires.
Worth fixing in get_active_class_id_idx() instead of at each call site. There's a third caller at index.js:7018 that isn't part of this diff but has the same problem.
Everything else is minor and inline: move_candidate not cleared on subtask switch, changelog mentions a console warning that isn't there, set_class_counter_options missing the is_destroyed guard, and is_subtask_hidden doing a DOM read on every mousemove.
v0.28.0
Description
New
set_active_class(class_id, subtask_key?, redraw?)andget_selected_class_id(subtask_key?)public API methodsNew per-subtask
focus_active_classoption. The selected class is the focused class, and other classes dim todefocused_opacityand drop out of hover, Tab navigation, the annotation list, and bulk delete. Toggleable viaset_focus_active_class()ortoggle_class_focus_keybind(defaultshift+f).Per-class
allowed_modesare enforced on reclassificationNew host callback config options
on_active_class_change,on_subtask_change, andon_focus_active_class_change: fired from any writer (API, toolbox, keybind), and only when the value actually changes.New
brush_overlap_across_subtasksconfig option (defaultfalse)set_annotations()andset_annotations_batch()gained an optionalshow_loaderparameter (defaulttrue)A subtask with its layer opacity slider at 0 is now non-interactive, matching vanish mode
Fix the Brush/Erase toolbox buttons staying lit after a subtask switch.
Fix class keybinds edited in the Keybinds toolbox item not applying to other subtasks sharing the class id until a reload; class-select keybinds now also work in read-only subtasks.
Fix stale containing boxes when
allow_annotations_outside_image = falseclamps loaded annotations at init.Removed unused per-subtask back canvas.
set_annotations()gained askip_toolbox_updateparameter for batching several per-subtask swaps, plus arefresh_toolbox()method to run the deferred filter-distance + toolbox update once at the end.ClassCountertoolbox item options viaclass_counter_toolbox_itemconfig:subtasks(string[] | "current") selects which subtasks to count,layout("current" | "grouped" | "flat") controls rendering (groupedadds a heading per subtask,flatmerges shared class ids into one summed list). Newset_class_counter_options()public API method changes them at runtime.New
set_class_color(class_id, color, redraw?)public API method: writescolor_infoand syncs the id-toolbox swatch and id-dialog color pies. Also fixes the front id-dialog pie not updating (and duplicating) on recolor via theRecolorActivetoolbox item.Fix the hover confidence card sitting on top of the hovered annotation: the card is now populated before it is measured and positioned, so it hugs the edit-button ring instead of drifting onto the anchor.
swap_frame_image()now rejects (and restores the old image) when the new image's dimensions don't match the ones the instance was initialized with, instead of silently misaligning annotations against the new frame. Changing image dimensions requires reinitializing the ULabel instance.Closes Three fixed subtasks trevor #259, three fixed subtasks: class focus, batched swaps, per-class modes #258, fix prepare for git installs #257, Cropped bitmasks #256
PR Checklist
package.jsonhas been bumped since last releasepackage.jsonandsrc/version.jsapi_spec.md)changelog.mdBreaking API Changes