Bug
In the single-asset review view (video or image), clicking a comment that has a drawn annotation sets activeAnnotation in the review store, which AnnotationOverlay renders on top of the media. Switching versions via the version switcher does not clear activeAnnotation (or focusedCommentId), so the previous version's drawing keeps rendering on top of the newly selected version's media.
Steps to reproduce
- Open a video or image asset that has 2+ versions in the review view.
- Click a comment on the current version that includes a drawn annotation — the annotation overlay renders (driven by
activeAnnotation in the review store).
- Open the version switcher (top bar) and select a different version.
- Observe: the new version's media loads, but the old version's annotation drawing is still rendered on top of it.
Root cause
setCurrentVersion in the review store only updates currentVersion — it never resets activeAnnotation / focusedCommentId:
// apps/web/stores/review-store.ts:58-60
setCurrentVersion: (version: AssetVersion) => {
set({ currentVersion: version })
},
VersionSwitcher calls this directly with no other cleanup:
// apps/web/components/review/version-switcher.tsx
onSelect={() => setCurrentVersion(version)}
The single-view media viewers render the overlay straight off the store:
// apps/web/app/(dashboard)/projects/[id]/assets/[assetId]/page.tsx:299 (video) and :327 (image)
<AnnotationOverlay key={focusedCommentId ?? 'none'} />
// apps/web/components/review/annotation-overlay.tsx
const storeActiveAnnotation = useReviewStore((s) => s.activeAnnotation)
const active = annotation !== undefined ? annotation : storeActiveAnnotation
Since no annotation prop is passed in single view, AnnotationOverlay always reflects the store's activeAnnotation, which nothing clears on a version change. The key={focusedCommentId ?? 'none'} doesn't help either, since it's scoped to comment focus, not version. The only place that clears this state today is ImageViewer's click-off-media handler (setFocusedCommentId(null); setActiveAnnotation(null) in handleImageClick) — not a version-change path — and there's no equivalent for video at all.
Suggested fix
Clear activeAnnotation / focusedCommentId in setCurrentVersion when the version actually changes, guarding the initial null -> version set and re-selecting the same version so a URL-driven deep-link annotation isn't wiped on load:
setCurrentVersion: (version: AssetVersion) => {
set((state) =>
state.currentVersion != null && state.currentVersion.id !== version.id
? { currentVersion: version, activeAnnotation: null, focusedCommentId: null }
: { currentVersion: version },
)
},
(Not applicable to the version-compare view, which manages annotation state per-pane via props rather than through the shared store.)
Bug
In the single-asset review view (video or image), clicking a comment that has a drawn annotation sets
activeAnnotationin the review store, whichAnnotationOverlayrenders on top of the media. Switching versions via the version switcher does not clearactiveAnnotation(orfocusedCommentId), so the previous version's drawing keeps rendering on top of the newly selected version's media.Steps to reproduce
activeAnnotationin the review store).Root cause
setCurrentVersionin the review store only updatescurrentVersion— it never resetsactiveAnnotation/focusedCommentId:VersionSwitchercalls this directly with no other cleanup:The single-view media viewers render the overlay straight off the store:
Since no
annotationprop is passed in single view,AnnotationOverlayalways reflects the store'sactiveAnnotation, which nothing clears on a version change. Thekey={focusedCommentId ?? 'none'}doesn't help either, since it's scoped to comment focus, not version. The only place that clears this state today isImageViewer's click-off-media handler (setFocusedCommentId(null); setActiveAnnotation(null)inhandleImageClick) — not a version-change path — and there's no equivalent for video at all.Suggested fix
Clear
activeAnnotation/focusedCommentIdinsetCurrentVersionwhen the version actually changes, guarding the initialnull -> versionset and re-selecting the same version so a URL-driven deep-link annotation isn't wiped on load:(Not applicable to the version-compare view, which manages annotation state per-pane via props rather than through the shared store.)