Skip to content

[Image] Pause and play image gifs#3432

Open
catandthemachines wants to merge 45 commits intomainfrom
catjohnson/lems-3735
Open

[Image] Pause and play image gifs#3432
catandthemachines wants to merge 45 commits intomainfrom
catjohnson/lems-3735

Conversation

@catandthemachines
Copy link
Copy Markdown
Member

@catandthemachines catandthemachines commented Mar 31, 2026

Summary:

Functionality to pause and play image gifs. This includes:

  1. Loaded gifs start off paused, until the learner presses play.
  2. Pressing play button plays only one loop of the gif image, and then pauses.
  3. Pausing a gif will pause at the current frame, and resume from that frame until the loop is completed.

Before:

Screen.Recording.2026-03-18.at.4.40.45.PM.mov

After:

Screen.Recording.2026-03-31.at.3.21.47.PM.mov

Issue: LEMS-3735

Test plan:

Highly recommend checking these Storybook pages to confirm the implementation:

  • /?path=/story/widgets-image-widget-demo--gif-image
  • /?path=/story/editors-editorpage--with-all-flags

Here are some test gifs to use:

Also confirm that this experience is not visible when flags are off:

  • /?path=/story/editors-editorpage--demo

@catandthemachines catandthemachines marked this pull request as ready for review March 31, 2026 22:42
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@catandthemachines
Copy link
Copy Markdown
Member Author

@claude review once

Copy link
Copy Markdown
Member

@benchristel benchristel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good! Thanks for adding gifuct-js. I will come back and do a more thorough review later today — for now, I left some thoughts inline.

};
// Only re-run when src changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [src]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't list play, pause, and renderFrame as deps here — should we?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed those dependencies because we really should only run this useEffect (decode all the GIF frames) on changes to src, if I added those other dependencies it would run this useEffect more often then necessary, and decoding the frames is the more expensive aspect of this code.

I can add them back, but I recommend against it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like decoding should be done in a separate hook then; perhaps a usePromise hook similar to this one: https://www.npmjs.com/package/react-use-promise

const [frames, error] = usePromise(() => {
  return decodeGifFrames(src)
}, [src]);

React.useEffect(() => {
  if (frames != null) {
    play();
  }

  return pause;
}, [play, pause, frames])

(not suggesting we use that library; we could write our own)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it could cause a significant re-write. Might I suggest a separate ticket to circle back to that? I would like to avoid another re-write at least in this PR. Thoughts?

};
// Only re-run when src changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [src]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like decoding should be done in a separate hook then; perhaps a usePromise hook similar to this one: https://www.npmjs.com/package/react-use-promise

const [frames, error] = usePromise(() => {
  return decodeGifFrames(src)
}, [src]);

React.useEffect(() => {
  if (frames != null) {
    play();
  }

  return pause;
}, [play, pause, frames])

(not suggesting we use that library; we could write our own)

Copy link
Copy Markdown
Contributor

@nishasy nishasy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works really well!!

Just left one comment to make sure we have a story in the case where a gif is uploaded without a size, but that's not a blocker.

src: string;
alt: string;
width?: number;
height?: number;
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.

Could I request a new story for a GIF image that's saved with no size? The optional width and height here reminded me that's a possible case.

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.

4 participants