Additional changes for iOS

Still not flawless. More work required.
This commit is contained in:
0x1eef 2023-07-13 12:18:04 -03:00
parent 465e3bf224
commit dd833a384d
3 changed files with 39 additions and 39 deletions

View file

@ -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>
);
}

View file

@ -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)}

View file

@ -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>
);
}