learngerman/patches/0201-show-audio-controls-an...

133 lines
4.6 KiB
Diff
Raw Permalink Normal View History

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 (
+ <div
+ style={{
+ display: playing ? 'block' : 'none',
+ width: '100%',
+ }}
+ >
+ <audio
+ onPlay={() => {setPlaying(true)}}
+ onEnded={() => {setPlaying(false)}}
+ controls
+ ref={ref}
+ >
+ {props.children}
+ </audio>
+ <input type="range" min="0.25" max="2" step="0.25" onChange={e => { set(e.target.value) }} />
+ </div>
+ );
+});
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) => (
<div className="exercise-audio-feedback">
- <audio
+ <Audio
className="exercise-audio-file feedback-audio initialized"
tabIndex="-1"
width="100%"
@@ -11,6 +12,6 @@
ref={ref}
>
<source src={src} type="audio/MP3" />
- </audio>
+ </Audio>
</div>
));
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 @@
>
<LessonExerciseQuestionAudioGlobalStyles />
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
- <audio
+ <Audio
className={`exercise-audio-file initialized${isPlaying ? ' playing-now' : ''}`}
tabIndex="0"
width="100%"
@@ -73,7 +74,7 @@
ref={audioRef}
>
<source src={audioUrl} type="audio/MP3" />
- </audio>
+ </Audio>
<div className="bubble-text-audio">{audioLabel}</div>
<div className="exercise-play-audio" />
</a>