Skip to content

v0.28.0 - #260

Merged
TrevorBurgoyne merged 29 commits into
mainfrom
three-fixed-subtasks-trevor
Sep 10, 2026
Merged

v0.28.0#260
TrevorBurgoyne merged 29 commits into
mainfrom
three-fixed-subtasks-trevor

Conversation

@TrevorBurgoyne

@TrevorBurgoyne TrevorBurgoyne commented Sep 10, 2026

Copy link
Copy Markdown
Member

v0.28.0

Description

  • New set_active_class(class_id, subtask_key?, redraw?) and get_selected_class_id(subtask_key?) public API methods

  • New per-subtask focus_active_class option. The selected class is the focused class, and other classes dim to defocused_opacity and drop out of hover, Tab navigation, the annotation list, and bulk delete. Toggleable via set_focus_active_class() or toggle_class_focus_keybind (default shift+f).

  • Per-class allowed_modes are enforced on reclassification

  • New host callback config options on_active_class_change, on_subtask_change, and on_focus_active_class_change: fired from any writer (API, toolbox, keybind), and only when the value actually changes.

  • New brush_overlap_across_subtasks config option (default false)

  • set_annotations() and set_annotations_batch() gained an optional show_loader parameter (default true)

  • 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 = false clamps loaded annotations at init.

  • Removed unused per-subtask back canvas.

  • set_annotations() gained a skip_toolbox_update parameter for batching several per-subtask swaps, plus a refresh_toolbox() method to run the deferred filter-distance + toolbox update once at the end.

  • ClassCounter toolbox item options via class_counter_toolbox_item config: subtasks (string[] | "current") selects which subtasks to count, layout ("current" | "grouped" | "flat") controls rendering (grouped adds a heading per subtask, flat merges shared class ids into one summed list). New set_class_counter_options() public API method changes them at runtime.

  • New set_class_color(class_id, color, redraw?) public API method: writes color_info and syncs the id-toolbox swatch and id-dialog color pies. Also fixes the front id-dialog pie not updating (and duplicating) on recolor via the RecolorActive toolbox 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

  • Merged latest main
  • Version number in package.json has been bumped since last release
  • Version numbers match between package package.json and src/version.js
  • Updated documentation if necessary (currently just in api_spec.md)
  • Added changes to changelog.md

Breaking API Changes

  • brush overlap resolution now stays within the active subtask; reaching masks in other subtasks (including read-only barriers) is opt-in.
  • removed unused per-subtask back canvas.

@TrevorBurgoyne TrevorBurgoyne added enhancement New feature or request bug Something isn't working labels Sep 10, 2026
@TrevorBurgoyne
TrevorBurgoyne requested a balanced review from Copilot September 10, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Comment thread src/index.js
Comment thread src/index.js
Comment thread src/index.js Outdated
Comment thread src/mask_utils.ts

@elliott-imhoff elliott-imhoff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/active_class.ts
Comment thread src/index.js
Comment thread src/listeners.ts Outdated
Comment thread src/index.js
Comment thread CHANGELOG.md
Comment thread src/index.js
Comment thread src/index.js
@TrevorBurgoyne
TrevorBurgoyne merged commit aa3d3f7 into main Sep 10, 2026
8 checks passed
@TrevorBurgoyne
TrevorBurgoyne deleted the three-fixed-subtasks-trevor branch September 10, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants