whoisryosuke / next-mdx-deck

Presentation decks using MDX, React, and Next.JS
https://next-mdx-deck.netlify.app/
MIT License
175 stars 45 forks source link

Speaker notes #1

Closed whoisryosuke closed 4 years ago

whoisryosuke commented 4 years ago

Adds speaker notes functionality to the app. This includes presentation mode, syncing slides between browser tabs, and syncing mode between page changes.

Process

Local Storage Sync

The basic process:

Currently the <SlidePage> component that renders the entire slideshow handles the state for the current slide. There's a context hook for total number of pages, but no context available for slides.

If I wanted to implement it currently, I'd have to code the storage changes into the state changes (where I currently handle changing the URL). Then in the same component, I'd also have to check for storage changes in a useEffect lifecycle and handle state changes there.

If I wanted to make things a bit more modular, I could extract the <SlidePage> state into a context object. Then it can be accessed inside any component using the context. MDX Deck uses this architecture to add things like a <Keyboard> component that handles keyboard detection independently thanks to context hooks (it can push changes directly to the context vs getting it passed down by a parent component).

If I wanted to make things fast, and not worry about the modularity of it all, I could just create a <Storage> component and pass the slide state and state update method (<Storage currentSlide={slide} updateSlide={updateSlide} />). This way the component can use it through the props, and when we figure out context (if we really need it), it can be swapped out fairly easily without structural changes.

When the slide changes, update the local storage.

Still use event listeners, checking if user focuses on/blurs off window. Update the slide from inside storage if window is not in focus and detects storage changes.

The Implementation

Went with transferring the slide state to context. This made it easier to create modular components that could act independently of the <SlidePage> component, which had plenty of logic packed in as it is (and now with context, can be refactored out in the future).

Created a hook to handle the local storage syncing process. It checks if the current browser is in focus and updates the local storage with the current slide and page data. Or if the browser isn't in focus, it updates the context with the local storage data. Then to make it more "modular" and avoid attaching it to my <SlidePage> lifecycle, I created a <Storage> component that runs the hook and doesn't return anything to the DOM.

Speaker Notes

The basic process

The implementation

Issues discovered: