From dd833a384d26f496979db9d19944b0a49e007071 Mon Sep 17 00:00:00 2001 From: 0x1eef <0x1eef@protonmail.com> Date: Thu, 13 Jul 2023 12:18:04 -0300 Subject: [PATCH] Additional changes for iOS Still not flawless. More work required. --- src/js/components/Stream.tsx | 33 ++------------------------------- src/js/components/Timer.tsx | 12 ++++++++---- src/js/pages/surah/stream.tsx | 33 +++++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/js/components/Stream.tsx b/src/js/components/Stream.tsx index c8a7f4d9f..6108a8530 100644 --- a/src/js/components/Stream.tsx +++ b/src/js/components/Stream.tsx @@ -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(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 (
  • @@ -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 ( ); } diff --git a/src/js/components/Timer.tsx b/src/js/components/Timer.tsx index 1c2c5069e..9d7dfc22c 100644 --- a/src/js/components/Timer.tsx +++ b/src/js/components/Timer.tsx @@ -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>(); + 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 (
    {formatNumber(ms / 1000, locale)} diff --git a/src/js/pages/surah/stream.tsx b/src/js/pages/surah/stream.tsx index e0a137641..3cc1159eb 100644 --- a/src/js/pages/surah/stream.tsx +++ b/src/js/pages/surah/stream.tsx @@ -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([]); const [isPaused, setIsPaused] = useState(paused); const [soundOn, setSoundOn] = useState(false); + const [isStalled, setIsStalled] = useState(false); const [theme, setTheme] = useState(getCookie('theme') || 'moon'); const [reciter] = useState(reciters[0]); const [surah] = useState(Quran.Surah.fromDOMNode(locale, node, getTimeSlots(reciter))); const readyToRender = stream.length > 0; + const audioRef = useRef(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 (
    @@ -91,15 +117,12 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) { )} {readyToRender && } @@ -120,10 +143,12 @@ function SurahStream({ node, reciters, locale, slice, paused, t }: Props) { locale={locale} isPaused={isPaused} soundOn={soundOn} + isStalled={isStalled} />} {readyToRender && endOfStream && setStream([])} />}
    +
    ); }