Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it, vi, beforeEach } from 'vitest'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'
import { useReviewStore } from '@/stores/review-store'

const replace = vi.fn()
Expand Down Expand Up @@ -315,6 +315,48 @@ describe('CompareOverlay marker click', () => {
})
})

describe('CompareOverlay version-switch offset reset (#182)', () => {
it('switching the left version clears offA/offB (calibrated for the OLD pair)', () => {
// Pre-existing sync offsets from calibrating the v1/v3 pair.
searchParamsString = 'compare=v-1&offA=1.5&offB=-0.5'
render(
<CompareOverlay
asset={videoAsset}
versions={[makeVersion(1), makeVersion(2), makeVersion(3)]}
rightVersion={makeVersion(3)}
onClose={vi.fn()}
/>,
)

fireEvent.click(within(screen.getByTestId('compare-select-a')).getByRole('button'))
fireEvent.click(screen.getByRole('option', { name: /^v2$/ }))

const url = new URL(replace.mock.calls.at(-1)?.[0], 'http://x')
expect(url.searchParams.get('offA')).toBeNull()
expect(url.searchParams.get('offB')).toBeNull()
expect(url.searchParams.get('compare')).toBe('v-2')
})

it('switching the right version clears offA/offB too', () => {
searchParamsString = 'compare=v-1&offA=1.5&offB=-0.5'
render(
<CompareOverlay
asset={videoAsset}
versions={[makeVersion(1), makeVersion(2), makeVersion(3)]}
rightVersion={makeVersion(3)}
onClose={vi.fn()}
/>,
)

fireEvent.click(within(screen.getByTestId('compare-select-b')).getByRole('button'))
fireEvent.click(screen.getByRole('option', { name: /^v2$/ }))

const url = new URL(replace.mock.calls.at(-1)?.[0], 'http://x')
expect(url.searchParams.get('offA')).toBeNull()
expect(url.searchParams.get('offB')).toBeNull()
})
})

describe('CompareOverlay per-pane annotation display', () => {
const DRAWING = { objects: [], _canvasWidth: 640, _canvasHeight: 360 }

Expand Down
21 changes: 19 additions & 2 deletions apps/web/components/review/compare/compare-overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,23 @@ export function CompareOverlay({ asset, versions, rightVersion, onClose, canComm
[sideB],
)

// Version switch (either pane): offA/offB were calibrated for the OLD pair —
// they no longer describe the new one, so drop them rather than silently
// misapplying a stale sync offset to the new pair (#182).
const handleSwitchLeft = React.useCallback(
(v: AssetVersion) => {
writeParams((p) => { p.set('compare', v.id); p.delete('offA'); p.delete('offB') })
},
[writeParams],
)
const handleSwitchRight = React.useCallback(
(v: AssetVersion) => {
writeParams((p) => { p.delete('offA'); p.delete('offB') })
setCurrentVersion(v)
},
[writeParams, setCurrentVersion],
)

// Shared zoom/pan for image modes
const transform = useSharedTransform()

Expand Down Expand Up @@ -310,7 +327,7 @@ export function CompareOverlay({ asset, versions, rightVersion, onClose, canComm
value={left.id}
excludeId={right.id}
accentClass="text-sky-400"
onChange={(v) => writeParams((p) => p.set('compare', v.id))}
onChange={handleSwitchLeft}
/>
</div>
{/* Center: asset title (flex-1 min-w-0 truncates without pushing either
Expand Down Expand Up @@ -338,7 +355,7 @@ export function CompareOverlay({ asset, versions, rightVersion, onClose, canComm
value={right.id}
excludeId={left.id}
accentClass="text-emerald-400"
onChange={(v) => setCurrentVersion(v)}
onChange={handleSwitchRight}
/>
<button
type="button"
Expand Down