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:
Use event listeners to check for local storage changes and update app with new slide
Sync storage with latest slide changes
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
User should be able to press ALT/OPTION + P and change from a slideshow mode to presenter mode.
Presenter mode displays the current slide, speaker notes (picked up from the MDX), and the next slide
The implementation
Issues discovered:
Sync mode with localstorage between frames or state gets lost between pages.
Fixed by syncing using URL query parameters, since localStorage would sync between all tabs. Required a bit f
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: