- Tag the Studio player's video with the media class the floating viewer
uses, so zoom, pan, exposure/channel tone and overlay guides apply to it
in A/B, side by side and grid like they do to the other slots.
- Stop the A/B divider above the player controls instead of drawing over
them.
- Keep B's aspect ratio when comparing images of different sizes in the
Studio viewer.
With the Studio player on A, put layer A on top and clip only its picture
at the divider (B shows underneath), instead of clipping B over A, which
hid the right half of the player controls.
- Floating viewer compare modes (A/B, side by side, grid) now build their
primary video/audio with the Studio player, like the simple mode. The
legacy video controls, their media bridge, styles and tests are removed;
only the sidebar's preview controls remain.
- The Studio viewer closes again when the empty area around the picture is
clicked (quick click only, so panning never dismisses it).
The Studio viewer now covers everything the classic overlay did, so the
classic runtime (toolbar, panzoom, A/B and side-by-side engine, scopes,
loupe, probe, grading and WebGL video processors, filmstrip, context menu,
keyboard handling), its styles and its tests are deleted.
- Every open request goes to the Studio viewer; requestViewerOpen no longer
falls back to a viewer singleton.
- Drop the classic-only settings (use classic viewer, pan without zoom,
disable WebGL) and their internal options and constants.
- Studio tells the grid which asset it ended on when it closes, and the
rating hotkeys yield to it while it is open.
- Remove dead helpers left behind (image processor, media player helpers,
3D helpers, metadata block, viewerbar controls variant) and unused CSS.
- Update the viewer tutorial, hotkeys doc and changelog.
A tool rail on the left of the stage adds channels, exposure and gamma,
zebra, histogram and waveform scopes, composition guides, aspect masks,
pixel probe, loupe, copy to clipboard and A/B compare (wipe, side by side,
difference, add, subtract, multiply, screen) with B selection, pin and
swap. Colour tools are SVG filters so they also apply to playing video;
video compare keeps a second player in sync.
3D models and the A/B / side-by-side open modes now use the Studio viewer,
audio files show a live spectrum, and the inspector's tag editor no longer
steals focus after navigating.
- Simple mode renders video and audio with the Studio player through
mountStudioPlayerHost, which honours the floating viewer's player-host
contract (togglePlay / stepFrames / destroy handle, inner media element
for mute/speed persistence) and releases media on teardown. Falls back
to the legacy player for images, 3D, compare modes, mount failures
and the "classic viewer" setting.
- StudioPlayer gains initial mute/speed, a compact width-aware variant
and an autoplay that retries muted when sound is blocked.
- CSS-only refresh of the floating window aligned with the Studio
viewer; popped-out / desktop-expanded windows stay square.
A simpler, review-first main viewer built in Vue, routed through the
existing OPEN_VIEWER event so every caller keeps working:
- Header with navigation, file summary and actions; zoom/pan image
stage (cursor-anchored wheel zoom, fit/1:1, transparency checker).
- New video/audio player: frame stepping and counter, A-B loop, loop,
speed, volume, fullscreen, save frame as PNG, auto-hiding controls;
media is released on change/close.
- Inspector reusing the asset sidebar's rating, tags, generation,
workflow and file components, hydrated with the viewer metadata
cache; filmstrip windowed for large lists; keyboard shortcuts.
- The classic viewer stays for A/B and side-by-side compare, 3D models
and its analysis tools, and as an opt-in setting.
- Use the typed ToastManager API (success/error/info/warning/loading)
instead of the deprecated add(); add() stays as a fallback for older
frontends.
- Accept a toast manager without add() so toasts keep working once
ComfyUI drops the deprecated methods.
- Tracked operations (DB restore/reset, vector backfill) show one
loading toast updated in place via its ToastId instead of stacking a
toast per step; dismiss them on extension teardown.
- Persistent toasts use the largest safe timer delay instead of
Infinity; history action links become native toast action buttons
(http(s) or same-origin paths only).
- Route genInfoOverridePicker and comfyAlert through the core toast API;
drop the app.ui.toast fallback, the no-op fallback dismisser and the
unused .mjr-toast CSS.
- Keep the Majoor message center as a read-only history; it no longer
pops open by itself on reset/backfill.
- Document the notification audit.
Root causes found by deep CSS + Vue audit:
1. Missing .mjr-show-details CSS rule (PRIMARY cause of reload impression)
- .mjr-card-info had no hide rule in the main grid
- applyGridSettingsClasses() toggles .mjr-show-details on the container
- estimateRowHeight() assumed metaHeight=0 when showDetails=false
- But .mjr-card-info was always rendered (~44px) -> virtualizer under-
estimated every row -> repositioned all rows on first measure -> visual
jump that looked like a full grid reload on each scroll
Fix: add .mjr-grid .mjr-card-info { display:none } default with
.mjr-grid.mjr-show-details .mjr-card-info { display:block } toggle
(same pattern already used by the bottom feed at line 9119)
2. estimateRowHeight metaHeight constant was 82px instead of ~52px
- Actual card-info height: padding 12 + filename 15 + margin 4 + row 13 = 44px
- 82px caused over-allocation when showDetails=true -> gap between rows
that the virtualizer would correct on measure -> same jump artifact
Fix: reduce to 52px (44px actual + 8px buffer for font variance)
3. scale(0.92) on .is-selected caused a visible blink on selection change
- The 8% shrink animated over 120ms transition; rapid selection change
(e.g. keyboard nav) caused all de-selected cards to snap back -> blink
Fix: reduce to scale(0.97) - still gives inset feel without the flash
4. Skeleton card min-height:146px conflicted with computed skeletonCardStyle
height -> skeleton cards taller than real cards -> layout jump on first
asset load
Fix: remove min-height from .mjr-grid-skeleton-card