Skip to content

Conversation

bencodeorg
Copy link
Contributor

@bencodeorg bencodeorg commented Oct 1, 2025

This PR adds support for resetting the canvas when a change to the current sources are observed (eg, when navigating between levels).

An earlier version of this PR used a more targeted approach of updating only specific bits of state on the existing Excalidraw canvas, vs. a full remount of the canvas (via a key prop). I was torn on which was preferable, but landed on a full remount (for now). There were a couple of problems with the more targeted approach:

  • There's a files property (ie, images) that we serialize and deserialize from S3. The Excalidraw API appears to offer mechanisms to addFiles and to getFiles, but no explicit "I want to set the files available to something else" (ie, setFiles)?
  • Relatedly, the helper that I tried to use to update a "scene" (updateScene) accepts the "elements" of your sketch (which I needed to deep clone to get to work, I am not sure why) and "app state", but not files.

Handily, thanks to the SourcesContainer component, this appears to also give support for updating the Excalidraw canvas when a teacher switches between students, not just when switching between levels as a single user.

Links

Testing story

I tested manually navigating between levels as an individual user, as well as navigating between students as a teacher.

@bencodeorg bencodeorg requested a review from a team October 2, 2025 18:16
};
}, []);

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this useEffect only fire on level change or does it fire every time sources change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It fires when sources change (which is debounced to max every 500ms), but only actually remounts when the level changes (or a teacher switches between students). I chatted with Sanchit and modeled it after something similar we're doing in DanceView:

useEffect(() => {
if (!workspace.current) {
return;
}
const blocks = Blockly.serialization.workspaces.save(workspace.current);
if (!isEqual(blocks, currentSources.source)) {
loadBlocksToWorkspace(
workspace.current,
JSON.stringify(currentSources.source)
);
}
}, [currentSources.source]);

Copy link
Contributor

Choose a reason for hiding this comment

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

Mind adding a comment explaining that it only remounts if the level changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep can do!

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.

2 participants