Merge pull request #136 from ReflectsLight/audio_ios_2
Additional changes for iOS
This commit is contained in:
commit
5a4f0fd92e
3 changed files with 39 additions and 39 deletions
|
@ -1,31 +1,24 @@
|
|||
import * as Quran from 'lib/Quran';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { formatNumber, TFunction } from 'lib/i18n';
|
||||
import { Slice } from 'lib/Quran/Slice';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface Props {
|
||||
reciter: Quran.Reciter
|
||||
surah: Quran.Surah
|
||||
stream: Quran.Ayat
|
||||
locale: Quran.Locale
|
||||
slice: Slice
|
||||
endOfStream: boolean
|
||||
isPaused: boolean
|
||||
soundOn: boolean
|
||||
setSoundOn: (v: boolean) => void
|
||||
t: TFunction
|
||||
}
|
||||
|
||||
export function Stream({ reciter, surah, stream, locale, slice, endOfStream, isPaused, setSoundOn, soundOn, t }: Props) {
|
||||
export function Stream({ surah, stream, locale, slice, endOfStream, isPaused, t }: Props) {
|
||||
const className = classNames('body', 'stream');
|
||||
const style: React.CSSProperties = endOfStream || isPaused ?
|
||||
{ 'overflowY': 'auto' } :
|
||||
{ 'overflowY': 'hidden' };
|
||||
const audioRef = useRef<HTMLAudioElement>(null);
|
||||
const { url: baseUrl } = reciter;
|
||||
const ayah = stream[stream.length-1];
|
||||
const src = `${baseUrl}/${surah.id}/${ayah.id}.mp3`;
|
||||
const ayat = stream.map((ayah: Quran.Ayah) => {
|
||||
return (
|
||||
<li key={ayah.id} className="ayah fade">
|
||||
|
@ -51,31 +44,9 @@ export function Stream({ reciter, surah, stream, locale, slice, endOfStream, isP
|
|||
}
|
||||
}, [stream]);
|
||||
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
if (!audio) {
|
||||
return;
|
||||
} else if (isPaused || !soundOn) {
|
||||
audio.pause();
|
||||
} else if (soundOn) {
|
||||
audio.play()
|
||||
.catch(() => setSoundOn(false));
|
||||
}
|
||||
}, [stream, isPaused, soundOn]);
|
||||
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
if (audio) {
|
||||
audio.addEventListener('ended', () => {
|
||||
audio.setAttribute('src', src);
|
||||
});
|
||||
}
|
||||
}, [audioRef.current]);
|
||||
|
||||
return (
|
||||
<ul lang={locale} className={className} style={style}>
|
||||
{ayat}
|
||||
<audio src={src} ref={audioRef} />
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,28 +9,32 @@ interface Props {
|
|||
soundOn: boolean
|
||||
setStream: (stream: Quran.Ayat) => void
|
||||
isPaused: boolean
|
||||
isStalled: boolean
|
||||
}
|
||||
|
||||
export function Timer ({ surah, stream, soundOn, setStream, locale, isPaused }: Props) {
|
||||
export function Timer ({ surah, stream, isStalled, soundOn, setStream, locale, isPaused }: Props) {
|
||||
const ayah = stream[stream.length - 1];
|
||||
const [ms, setMs] = useState(ayah.readTimeMs);
|
||||
const [tid, setTid] = useState<ReturnType<typeof setTimeout>>();
|
||||
|
||||
useEffect(() => {
|
||||
if (tid) {
|
||||
clearTimeout(tid);
|
||||
setTid(undefined);
|
||||
}
|
||||
setMs(ayah.readTimeMs);
|
||||
}, [soundOn, ayah.id]);
|
||||
}, [ayah.id, soundOn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPaused) {
|
||||
if (isStalled || isPaused) {
|
||||
return;
|
||||
} else if (ms <= 0) {
|
||||
setStream([...stream, surah.ayat[ayah.id]]);
|
||||
} else {
|
||||
setTid(setTimeout(() => setMs(ms - 100), 100));
|
||||
}
|
||||
}, [ms, isPaused]);
|
||||
}, [isStalled, isPaused, soundOn, ms]);
|
||||
|
||||
return (
|
||||
<div className='timer'>
|
||||
{formatNumber(ms / 1000, locale)}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import classNames from 'classnames';
|
||||
import { get as getCookie } from 'es-cookie';
|
||||
|
@ -31,10 +31,15 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) {
|
|||
const [stream, setStream] = useState<Quran.Ayat>([]);
|
||||
const [isPaused, setIsPaused] = useState<boolean>(paused);
|
||||
const [soundOn, setSoundOn] = useState<boolean>(false);
|
||||
const [isStalled, setIsStalled] = useState<boolean>(false);
|
||||
const [theme, setTheme] = useState(getCookie('theme') || 'moon');
|
||||
const [reciter] = useState<Quran.Reciter>(reciters[0]);
|
||||
const [surah] = useState<Quran.Surah>(Quran.Surah.fromDOMNode(locale, node, getTimeSlots(reciter)));
|
||||
const readyToRender = stream.length > 0;
|
||||
const audioRef = useRef<HTMLAudioElement>(null);
|
||||
const { url: baseUrl } = reciter;
|
||||
const ayah = stream[stream.length-1];
|
||||
const src = `${baseUrl}/${surah.id}/${ayah?.id}.mp3`;
|
||||
const getAyahParam = (slice: Slice, stream: Quran.Ayat) => {
|
||||
if (slice.coversSubsetOfSurah) {
|
||||
return `${slice.begin}..${slice.end}`;
|
||||
|
@ -69,6 +74,27 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) {
|
|||
}
|
||||
}, [stream.length === 0]);
|
||||
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
if (!audio) {
|
||||
return;
|
||||
} else if (isPaused || !soundOn) {
|
||||
audio.pause();
|
||||
} else if (soundOn) {
|
||||
audio.play()
|
||||
.catch(() => setSoundOn(false));
|
||||
}
|
||||
}, [stream, isPaused, soundOn]);
|
||||
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
audio.addEventListener('ended', () => audio.setAttribute('src', src));
|
||||
audio.addEventListener('stalled', () => setIsStalled(true));
|
||||
audio.addEventListener('waiting', () => setIsStalled(true));
|
||||
audio.addEventListener('playing', () => setIsStalled(false));
|
||||
audio.addEventListener('play', () => setIsStalled(false));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={classNames('content', 'theme', theme, locale)}>
|
||||
<div className="header">
|
||||
|
@ -91,15 +117,12 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) {
|
|||
)}
|
||||
{readyToRender &&
|
||||
<Stream
|
||||
reciter={reciter}
|
||||
slice={slice}
|
||||
surah={surah}
|
||||
stream={stream}
|
||||
locale={locale}
|
||||
endOfStream={endOfStream}
|
||||
isPaused={isPaused}
|
||||
soundOn={soundOn}
|
||||
setSoundOn={setSoundOn}
|
||||
t={t}
|
||||
/>
|
||||
}
|
||||
|
@ -120,10 +143,12 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) {
|
|||
locale={locale}
|
||||
isPaused={isPaused}
|
||||
soundOn={soundOn}
|
||||
isStalled={isStalled}
|
||||
/>}
|
||||
{readyToRender && endOfStream &&
|
||||
<RefreshShape onClick={() => setStream([])} />}
|
||||
</div>
|
||||
<audio src={src} ref={audioRef} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue