diff --git a/patches/0009-show-audio-controls-and-speed.diff b/patches/0009-show-audio-controls-and-speed.diff new file mode 100644 index 0000000..c892969 --- /dev/null +++ b/patches/0009-show-audio-controls-and-speed.diff @@ -0,0 +1,132 @@ +diff -Naur orig.orig/components/commons/Audio.jsx orig/components/commons/Audio.jsx +--- orig.orig/components/commons/Audio.jsx 1969-12-31 21:00:00.000000000 -0300 ++++ orig/components/commons/Audio.jsx 2021-10-15 16:28:48.809523282 -0300 +@@ -0,0 +1,76 @@ ++import { forwardRef, useState, useEffect } from 'react'; ++ ++// https://formidable.com/blog/2021/stores-no-context-api/ ++const createEmitter = () => { ++ const subscriptions = new Map(); ++ return { ++ emit: (v) => subscriptions.forEach(fn => fn(v)), ++ subscribe: (fn) => { ++ const key = Symbol(); ++ subscriptions.set(key, fn); ++ return () => subscriptions.delete(key); ++ }, ++ } ++}; ++ ++const createStore = (init) => { ++ // create an emitter ++ const emitter = createEmitter(); ++ ++ let store = null; ++ const get = () => store; ++ const set = (op) => ( ++ store = op(store), ++ // notify all subscriptions when the store updates ++ emitter.emit(store) ++ ); ++ store = init(get, set); ++ ++ const useStore = () => { ++ // intitialize component with latest store ++ const [localStore, setLocalStore] = useState(get()); ++ ++ // update our local store when the global ++ // store updates. ++ // ++ // emitter.subscribe returns a cleanup ++ // function, so react will clean this ++ // up on unmount. ++ useEffect(() => emitter.subscribe(setLocalStore), []); ++ return localStore; ++ }; ++ return useStore; ++}; ++ ++const useSpeed = createStore((get, set) => ({ ++ value: 1, ++ set: value => set((state) => ({ ...state, value })), ++})); ++ ++export const Audio = forwardRef((props, ref) => { ++ const [playing, setPlaying] = useState(false); ++ const { value, set } = useSpeed(); ++ ++ useEffect(() => { ++ ref.current.playbackRate = value ++ }, [value]) ++ ++ return ( ++
++ ++ { set(e.target.value) }} /> ++
++ ); ++}); +diff -Naur orig.orig/components/Lesson/LessonExercise/LessonExerciseHiddenAudio/LessonExerciseHiddenAudio.jsx orig/components/Lesson/LessonExercise/LessonExerciseHiddenAudio/LessonExerciseHiddenAudio.jsx +--- orig.orig/components/Lesson/LessonExercise/LessonExerciseHiddenAudio/LessonExerciseHiddenAudio.jsx 2021-10-15 15:36:57.837243899 -0300 ++++ orig/components/Lesson/LessonExercise/LessonExerciseHiddenAudio/LessonExerciseHiddenAudio.jsx 2021-10-15 15:47:52.469350865 -0300 +@@ -1,9 +1,10 @@ + /* eslint-disable jsx-a11y/media-has-caption */ + import { forwardRef } from 'react'; ++import { Audio } from '../../../commons/Audio'; + + export const LessonExerciseHiddenAudio = forwardRef(({ src }, ref) => ( +
+- ++ +
+ )); +diff -Naur orig.orig/components/Lesson/LessonExercise/LessonExerciseQuestion/QuestionTypes/LessonExerciseQuestionAudio.jsx orig/components/Lesson/LessonExercise/LessonExerciseQuestion/QuestionTypes/LessonExerciseQuestionAudio.jsx +--- orig.orig/components/Lesson/LessonExercise/LessonExerciseQuestion/QuestionTypes/LessonExerciseQuestionAudio.jsx 2021-10-15 15:36:57.837243899 -0300 ++++ orig/components/Lesson/LessonExercise/LessonExerciseQuestion/QuestionTypes/LessonExerciseQuestionAudio.jsx 2021-10-15 15:45:48.129327782 -0300 +@@ -2,6 +2,7 @@ + import { useEffect, useRef, useState } from 'react'; + import { createGlobalStyle } from 'styled-components'; + import { useAudio } from '../../../../../hooks/useAudio'; ++import { Audio } from '../../../../commons/Audio'; + import { useTranslation } from '../../../../../hooks/useTranslation'; + import { useFrontendConfig } from '../../../../../hooks/useFrontendConfig'; + +@@ -62,7 +63,7 @@ + > + + {/* eslint-disable-next-line jsx-a11y/media-has-caption */} +- ++ +
{audioLabel}
+
+