Skip to content

Commit

Permalink
Use local state for Flipbook Viewer's frame to avoid MST re-renders (#…
Browse files Browse the repository at this point in the history
…5952)

* use local state for FlipbookViewer's frame
  • Loading branch information
goplayoutside3 authored Mar 5, 2024
1 parent d601d3f commit e18ee83
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import FlipbookControls from './components'
const DEFAULT_HANDLER = () => true

const FlipbookViewer = ({
defaultFrame = 0,
enableInteractionLayer = false,
frame = 0,
enableRotation = DEFAULT_HANDLER,
flipbookAutoplay = false,
invert = false,
Expand All @@ -25,17 +25,17 @@ const FlipbookViewer = ({
onReady = DEFAULT_HANDLER,
playIterations,
rotation,
setFrame = DEFAULT_HANDLER,
setOnPan = DEFAULT_HANDLER,
setOnZoom = DEFAULT_HANDLER,
subject
}) => {
const [currentFrame, setCurrentFrame] = useState(defaultFrame)
const [playing, setPlaying] = useState(false)
const [dragMove, setDragMove] = useState()
/** This initializes an image element from the subject's defaultFrame src url.
* We do this so the SVGPanZoom has dimensions of the subject image.
* We're assuming all frames in one subject have the same dimensions. */
const defaultFrameLocation = subject ? subject.locations[frame] : null
const defaultFrameLocation = subject ? subject.locations[defaultFrame] : null
const { img, error, loading, subjectImage } = useSubjectImage({
src: defaultFrameLocation.url,
onReady,
Expand All @@ -46,7 +46,7 @@ const FlipbookViewer = ({
naturalWidth = 800
} = img

const viewerLocation = subject?.locations ? subject.locations[frame] : ''
const viewerLocation = subject?.locations ? subject.locations[currentFrame] : ''

useEffect(() => {
enableRotation()
Expand Down Expand Up @@ -97,7 +97,7 @@ const FlipbookViewer = ({
>
<SingleImageViewer
enableInteractionLayer={enableInteractionLayer}
frame={frame}
frame={currentFrame}
height={naturalHeight}
limitSubjectHeight={limitSubjectHeight}
onKeyDown={handleSpaceBar}
Expand All @@ -119,9 +119,9 @@ const FlipbookViewer = ({
</SingleImageViewer>
</SVGPanZoom>
<FlipbookControls
currentFrame={frame}
currentFrame={currentFrame}
locations={subject.locations}
onFrameChange={setFrame}
onFrameChange={setCurrentFrame}
onPlayPause={onPlayPause}
playing={playing}
playIterations={playIterations}
Expand All @@ -131,12 +131,12 @@ const FlipbookViewer = ({
}

FlipbookViewer.propTypes = {
/** Fetched from metadata.default_frame or initialized to zero */
defaultFrame: PropTypes.number,
/** Passed from Subject Viewer Store */
enableInteractionLayer: PropTypes.bool,
/** Function passed from Subject Viewer Store */
enableRotation: PropTypes.func,
/** Index of currently viewed Frame or initialized to zero */
frame: PropTypes.number,
/** Fetched from workflow configuration. Determines whether to autoplay the loop on viewer load */
flipbookAutoplay: PropTypes.bool,
/** Passed from Subject Viewer Store */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,18 @@ describe('Component > FlipbookViewer', function () {
expect(newButtonStyle.border).to.equal('2px solid #f0b200')
})

// NOTE: these tests are run sequentially and the frame state of the below test is inherited from the above test
it('should handle using arrow keys on the tablist', async function () {
const user = userEvent.setup({ delay: null })

const { getAllByRole } = render(<DefaultStory />)
const thumbnailButtons = getAllByRole('tab')
expect(thumbnailButtons[1].tabIndex).to.equal(0)
expect(thumbnailButtons[0].tabIndex).to.equal(0)

thumbnailButtons[1].focus()
thumbnailButtons[0].focus()
await user.keyboard('{ArrowRight}')

expect(thumbnailButtons[1].tabIndex).to.equal(-1)
expect(thumbnailButtons[2].tabIndex).to.equal(0)
expect(thumbnailButtons[0].tabIndex).to.equal(-1)
expect(thumbnailButtons[1].tabIndex).to.equal(0)
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,23 @@ import SeparateFramesViewer from '../SeparateFramesViewer/SeparateFramesViewer'
function storeMapper(store) {
const {
enableRotation,
frame,
frame: defaultFrame,
invert,
move,
rotation,
separateFramesView,
setFrame,
setOnPan,
setOnZoom
} = store.subjectViewer

const {
flipbook_autoplay: flipbookAutoplay,
limit_subject_height: limitSubjectHeight,
playIterations
} = store.workflows?.active?.configuration

return {
frame,
defaultFrame,
enableRotation,
flipbookAutoplay,
invert,
Expand All @@ -37,7 +36,6 @@ function storeMapper(store) {
playIterations,
rotation,
separateFramesView,
setFrame,
setOnPan,
setOnZoom
}
Expand All @@ -53,7 +51,7 @@ function FlipbookViewerContainer({
subject
}) {
const {
frame,
defaultFrame,
enableRotation,
flipbookAutoplay,
invert,
Expand All @@ -62,7 +60,6 @@ function FlipbookViewerContainer({
playIterations,
rotation,
separateFramesView,
setFrame,
setOnPan,
setOnZoom
} = useStores(storeMapper)
Expand Down Expand Up @@ -97,8 +94,8 @@ function FlipbookViewerContainer({
/>
) : (
<FlipbookViewer
defaultFrame={defaultFrame}
enableInteractionLayer={enableInteractionLayer}
frame={frame}
enableRotation={enableRotation}
flipbookAutoplay={flipbookAutoplay}
invert={invert}
Expand All @@ -109,7 +106,6 @@ function FlipbookViewerContainer({
onReady={onReady}
playIterations={playIterations}
rotation={rotation}
setFrame={setFrame}
setOnPan={setOnPan}
setOnZoom={setOnZoom}
subject={subject}
Expand Down

0 comments on commit e18ee83

Please sign in to comment.