Skip to content

feat: improve sam segmentation, questionaire, recorder, sam-segmemnta…#184

Merged
Aiosa merged 3 commits into
masterfrom
release/v3
Jun 15, 2026
Merged

feat: improve sam segmentation, questionaire, recorder, sam-segmemnta…#184
Aiosa merged 3 commits into
masterfrom
release/v3

Conversation

@Aiosa

@Aiosa Aiosa commented Jun 15, 2026

Copy link
Copy Markdown
Member

…tion, menu-pages, profiler, remove web worker

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Developer Setup Playground for interactive session configuration authoring.
    • Introduced Summer School Demos showcasing explainability techniques (Occlusion Masks, GradCam, Activation Clusters).
    • Enabled per-viewer recording with named recordings instead of single timeline.
    • Added overlay support for recorded snapshots with text, images, and audio.
    • Introduced Tools menu subsystem in the app bar.
    • Implemented Segment Anything (SAM) for AI-assisted image segmentation.
  • Bug Fixes

    • Fixed viewer identification for multi-slot backgrounds.
    • Improved multi-viewer support across recorder and profiler.
  • Documentation

    • Updated recorder event documentation for viewer-scoped operations.
    • Expanded AdvancedMenuPages and custom pages configuration guides.

@Aiosa Aiosa merged commit e7ae07e into master Jun 15, 2026
1 of 3 checks passed
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 599c6edf-3223-485d-b776-8549a84d38cb

📥 Commits

Reviewing files that changed from the base of the PR and between aab0c0e and 447cb64.

⛔ Files ignored due to path filters (2)
  • modules/sam-segmentation-experimental/index.workspace.js.map is excluded by !**/*.map
  • src/libs/flex-renderer/flex-renderer.js.map is excluded by !**/*.map
📒 Files selected for processing (55)
  • AGENTS.md
  • README.md
  • docs/site/docs/dev-setup-playground.mdx
  • docs/site/docs/summer-school-demo.mdx
  • docs/site/sidebars.js
  • docs/site/src/components/DemoFrame/index.js
  • modules/annotations/annotations.js
  • modules/menu-pages/README.md
  • modules/menu-pages/menu.js
  • modules/recorder/EVENTS.md
  • modules/recorder/include.json
  • modules/recorder/recorder-module.ts
  • modules/recorder/recorder.d.ts
  • modules/sam-segmentation-experimental/include.json
  • modules/sam-segmentation-experimental/index.ts
  • modules/sam-segmentation-experimental/package.json
  • modules/sam-segmentation-experimental/samInference.js
  • modules/sam-segmentation-experimental/samInference.ts
  • modules/sam-segmentation-experimental/samState.js
  • modules/sam-segmentation-experimental/samState.ts
  • modules/web-worker-manager/README.md
  • modules/web-worker-manager/manager.ts
  • modules/web-worker-manager/package.json
  • modules/web-worker-manager/requestPool.ts
  • modules/web-worker-manager/requestType.ts
  • plugins/annotations/components/globalPluginWindow.mjs
  • plugins/custom-pages/README.md
  • plugins/custom-pages/include.json
  • plugins/custom-pages/pages.js
  • plugins/profiler/include.json
  • plugins/profiler/profile.js
  • plugins/questionaire-new/include.json
  • plugins/questionaire-new/index.ts
  • plugins/questionaire-new/plugin.ts
  • plugins/questionaire-new/schema.ts
  • plugins/questionaire-new/types.ts
  • plugins/questionaire-new/validation.ts
  • plugins/recorder/overlay-editor.ts
  • plugins/recorder/overlay-renderer.ts
  • plugins/recorder/overlay-types.ts
  • plugins/recorder/placement-anchor-grid.ts
  • plugins/recorder/recorder-plugin.ts
  • plugins/sam-segment-tool-experimental/include.json
  • plugins/sam-segment-tool-experimental/package.json
  • plugins/sam-segment-tool-experimental/samSegmentationGUI.js
  • plugins/sam-segment-tool-experimental/samSegmentationGUI.ts
  • plugins/sam-segment-tool-experimental/style.css
  • plugins/youtrack-feedback-form/include.json
  • src/libs/flex-renderer/flex-renderer.js
  • src/loader.ts
  • src/locales/en.json
  • src/types/globals.d.ts
  • src/types/loader.d.ts
  • src/user-interface.js
  • ui/services/appBar.mjs

📝 Walkthrough

Walkthrough

This PR refactors the recorder from a global timeline to a per-viewer/per-recording model with named recordings, adds an overlay system (types, renderer, editor) for per-step annotations, migrates SAM segmentation from JS to TypeScript, redesigns the questionnaire plugin with new element types and an IO pipeline, adds AppBar.Tools, refactors AdvancedMenuPages to owner-scoped viewer menus, rewrites the profiler for per-viewer tile measurement, fixes per-slot viewer UUIDs in the loader, removes the web-worker-manager module, and adds documentation pages.

Changes

Recorder: Per-viewer/per-recording overhaul with overlays

Layer / File(s) Summary
Recorder type contracts and event docs
modules/recorder/recorder.d.ts, modules/recorder/EVENTS.md, modules/recorder/include.json
RecorderState is replaced with a per-viewer viewers: Map<UniqueViewerId, RecorderViewerCollection> shape; overlay types, RecorderAsset, RecorderRecording, RecorderPlaybackState are added; RecorderModule gains recording lifecycle, asset, and createEmpty methods with optional viewerId; events gain viewer/recording scope and four new recording lifecycle events.
Recorder module: per-viewer state, CRUD resources, playback engine
modules/recorder/recorder-module.ts
Restructures internal state from a global steps array to viewer-scoped collections with named recordings; adds CRUD step/asset resources; rewrites recording lifecycle, create/createNavigation, history-wrapped helpers, session-based playback engine (_jumpAt, playStep), and bundle import/migration supporting v3 and legacy v2 formats.
Overlay types, anchor grid, renderer, and editor
plugins/recorder/overlay-types.ts, plugins/recorder/placement-anchor-grid.ts, plugins/recorder/overlay-renderer.ts, plugins/recorder/overlay-editor.ts
Adds ID generators, anchorToCss, ANCHOR_LIST, and defaults; a 3×3 anchor picker widget; a lifecycle-driven overlay DOM renderer with composite/text/image/audio mounting and chrome integration; and an EasyMDE-based modal editor with draft assets, live preview, and save/commit logic.
RecorderPlugin: lane-based UI, recordings modal, navigation sessions
plugins/recorder/recorder-plugin.ts
Refactors the plugin UI to per-viewer lane containers for step rendering; adds drag/drop scoped to lanes, a recordings management modal, multi-session navigation recording via navSessions, overlay editor wiring per step, and lane chrome for arm/current-viewer state.

SAM segmentation: JS→TypeScript migration

Layer / File(s) Summary
SAMInference TypeScript module
modules/sam-segmentation-experimental/samInference.ts, modules/sam-segmentation-experimental/samInference.js (removed), modules/sam-segmentation-experimental/include.json, modules/sam-segmentation-experimental/package.json, modules/sam-segmentation-experimental/index.ts
Rewrites samInference.js as typed TypeScript with hash-verified Transformers.js loading, client/server inference, mask-to-polygon tracing, viewport capture; pins Transformers.js to @3.8.1; removes predefined server endpoints; adds index.ts entry and package.json.
SegmentAnythingState TypeScript module and host plugin
modules/sam-segmentation-experimental/samState.ts, modules/sam-segmentation-experimental/samState.js (removed), plugins/sam-segment-tool-experimental/samSegmentationGUI.ts, plugins/sam-segment-tool-experimental/samSegmentationGUI.js (removed), plugins/sam-segment-tool-experimental/...
Rewrites samState.js as samState.ts with lazy init, mode-options panel, click→inference→polygon→annotation flow; replaces samSegmentationGUI.js with a thin TypeScript host plugin that registers the SAM_SEGMENTATION custom mode; removes spinner CSS.

Questionnaire plugin: new element types and designer redesign

Layer / File(s) Summary
Questionnaire type contracts and schema normalization
plugins/questionaire-new/types.ts, plugins/questionaire-new/schema.ts, plugins/questionaire-new/validation.ts, plugins/questionaire-new/include.json, plugins/questionaire-new/index.ts
Adds measurement, roi, and matrix kinds; extends QuestionnaireContentElement with variant/text; adds QuestionnaireMeasurementElement and QuestionnaireRoiElement; updates schema defaults/normalization with HTML-to-text migration; adds measurement validation; adds capabilities/io to include.json; renames plugin id to "questionaire".
QuestionnairePlugin designer refactor and IO pipeline
plugins/questionaire-new/plugin.ts
Replaces multi-panel inspector UI with a single-column designer gated by questionaire.edit capability; integrates IO bundle pipeline and crud:answer resource; adds undo/redo snapshot history with debounced commitInline/commitFormMeta; updates runtime rendering (checkbox-group multiselect, plain-text content, ROI capture UI).

UI infrastructure: AppBar Tools, menu-pages, profiler, custom-pages, annotations, loader

Layer / File(s) Summary
AppBar.Tools registry and localization
ui/services/appBar.mjs, src/locales/en.json
Adds AppBar.Tools with lazy "tools" tab creation, register/unregister/setLabel/setDisabled/has; wires Tools.init into AppBar.init; adds "Tools" locale string.
AdvancedMenuPages: owner-scoped IDs, Vega lifecycle, viewer menu
modules/menu-pages/menu.js, modules/menu-pages/README.md
Renames constructor arg to ownerId; replaces _buildMenu/builder-parent with per-page AppBar.Plugins.setMenu submenus; adds _pageToViewerItem and buildMetaDataViewerMenu; rewrites Vega init to queued MutationObserver model; strips type/children before forwarding options; updates docs.
custom-mode-added event and toolbar auto-registration
modules/annotations/annotations.js, plugins/annotations/components/globalPluginWindow.mjs
setCustomModeUsed now emits custom-mode-added; _initAnnotationsToolbar auto-adds toolbar buttons for custom modes on init and on the event.
custom-pages plugin: target-based placement routing
plugins/custom-pages/pages.js, plugins/custom-pages/include.json, plugins/custom-pages/README.md
Adds a target config field; pluginReady flattens page configs and routes into buildMetaDataMenu / buildMetaDataViewerMenu by per-page target; documents placement targets.
Profiler: per-viewer tile-load measurement via recorder
plugins/profiler/profile.js, plugins/profiler/include.json
Rewrites profiler to wrap viewer.imageLoader.addJob per-viewer, store durations in a Map, register Tools entries for recorder-driven and manual profiling modes, and render per-viewer boxplot results with per-viewer JSON export; bumps to v2 and switches module dependency to recorder.
Loader: per-slot explicit background UUID and flex drawer reset
src/loader.ts, src/types/globals.d.ts, src/types/loader.d.ts, src/user-interface.js
Adds explicitSlotBackgroundId + __uuidExplicit caching for distinct per-slot viewer UUIDs; updates teardown/reset to clear cache and suspend/resume flex drawers; adds can/onCapabilityChange to IXOpatElement; fixes loading text call.
flex-renderer undefined channel fix, web-worker-manager removal, and docs
src/libs/flex-renderer/flex-renderer.js, modules/web-worker-manager/*, docs/site/..., AGENTS.md, README.md, plugins/youtrack-feedback-form/include.json
Adds channel = def guard for undefined channel in flex-renderer; removes entire web-worker-manager module (manager, requestPool, requestType); adds Summer School Demos and Developer Setup Playground doc pages with enhanced DemoFrame; minor metadata and doc updates.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant RecorderPlugin
  participant RecorderModule
  participant OverlayRenderer
  participant OSDViewer

  rect rgba(70, 130, 180, 0.5)
    Note over User,OSDViewer: Playback with overlays
    User->>RecorderPlugin: click Play
    RecorderPlugin->>RecorderModule: play(viewerId?)
    RecorderModule->>RecorderModule: fan-out to all viewers' active recordings
    loop per viewer session
      RecorderModule->>RecorderModule: _jumpAt(session, index)
      RecorderModule->>OSDViewer: apply visualization / navigation state
      RecorderModule->>RecorderPlugin: emit enter {viewerId, recordingId, index, step}
      RecorderPlugin->>OverlayRenderer: _onEnter(step, viewerId)
      OverlayRenderer->>OSDViewer: mount overlay DOM elements
    end
  end

  rect rgba(180, 100, 50, 0.5)
    Note over User,OSDViewer: Overlay editing
    User->>RecorderPlugin: click overlay edit button on step
    RecorderPlugin->>OverlayEditor: open()
    OverlayEditor->>OverlayRenderer: previewSet(step, draftOverlays, draftAssets)
    OverlayRenderer->>OSDViewer: mount preview overlay elements
    User->>OverlayEditor: edit markdown / image / anchor
    OverlayEditor->>OverlayRenderer: previewSet(step, updatedOverlays, draftAssets)
    User->>OverlayEditor: Save
    OverlayEditor->>RecorderModule: updateStep(id, mutate)
    OverlayEditor->>RecorderModule: putAsset(asset) per new draft asset
    OverlayEditor->>OverlayRenderer: previewClear()
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 Hop, hop, the timeline's grown wide,
Each viewer now holds its own glide,
Overlays sparkle on every frame,
SAM speaks TypeScript — now that's the game!
The questionnaire sprouts ROI and measure,
And Tools in the bar bring reviewer pleasure! 🌟

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v3

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces significant enhancements across several modules and plugins, notably refactoring the Recorder module to support parallel multi-viewport playback and named recordings, updating the Questionnaire plugin with a capability-gated designer and ROI region capture, and migrating the Segment Anything (SAM) experimental module to TypeScript. It also adds a generic 'Tools' category to the app-bar and resolves various multi-viewport rendering and reset issues. Feedback on the changes highlights critical runtime issues in the Questionnaire plugin, including focus loss on numeric inputs due to the use of the 'input' event instead of 'change', and TypeErrors caused by calling the non-existent 'this.showInfo' method instead of 'Dialogs.show'. Additionally, a minor typo in the README was identified.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

unitSel.disabled = readOnly;
units.forEach((u) => { const o = document.createElement("option"); o.value = u; o.textContent = u; o.selected = (cur.unit ?? units[0]) === u; unitSel.append(o); });
const push = () => setValue({ value: num.value === "" ? null : Number(num.value), unit: unitSel.value } as unknown as QuestionnaireValue);
num.addEventListener("input", push);

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.

high

Using the "input" event listener on the numeric input causes "setValue" to be called on every keystroke. This triggers "setAnswer", which calls "renderRuntime()" and completely destroys and recreates the DOM elements of the runtime view. As a result, the user loses focus and cursor position after typing a single character, making the field virtually unusable. Changing the event listener to "change" ensures the value is committed only when the input is blurred or the user presses Enter, preserving focus during typing.

Suggested change
num.addEventListener("input", push);
num.addEventListener("change", push);

const actions = el("div", "flex flex-wrap gap-2");
if (!readOnly) actions.append(button("Capture selected region", "btn btn-primary btn-sm", () => {
const captured = captureSelectedRegion(Array.from(this._viewerMap.values()));
if (!captured) { this.showInfo("Select a single annotation in the viewer first."); return; }

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.

high

"this.showInfo" is not a valid method on "XOpatPlugin" or "XOpatElement" and will cause a runtime "TypeError" when triggered. Please use the standard "Dialogs.show" method to display warning/info messages to the user.

Suggested change
if (!captured) { this.showInfo("Select a single annotation in the viewer first."); return; }
if (!captured) { Dialogs.show("Select a single annotation in the viewer first.", 3000, Dialogs.MSG_WARN); return; }

setValue(captured as unknown as QuestionnaireValue);
}));
actions.append(button("Show region", "btn btn-outline btn-sm", () => {
if (!region) { this.showInfo("No region captured yet."); return; }

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.

high

"this.showInfo" is not a valid method on "XOpatPlugin" or "XOpatElement" and will cause a runtime "TypeError" when triggered. Please use the standard "Dialogs.show" method to display warning/info messages to the user.

Suggested change
if (!region) { this.showInfo("No region captured yet."); return; }
if (!region) { Dialogs.show("No region captured yet.", 3000, Dialogs.MSG_WARN); return; }

Comment thread README.md
> ⚠️ **This is xOpat v3 — an alpha release.** The older but
> stable **v2** line lives on the [`archive/v2`](https://github.com/RationAI/xopat/tree/archive/v2)
> branch.
> branch. If you experience anny issues, please, let us know.

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.

medium

There is a typo in this line: "anny" should be "any". Also, the comma after "please" is unnecessary.

Suggested change
> branch. If you experience anny issues, please, let us know.
> branch. If you experience any issues, please let us know.

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