Enable 'strictNullChecks'
This commit is contained in:
parent
3a9d5ee022
commit
eedf2a9c8a
9 changed files with 56 additions and 38 deletions
|
@ -22,7 +22,7 @@ export function AudioControl({
|
||||||
onStatusChange = () => null,
|
onStatusChange = () => null,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [enabled, setEnabled] = useState<boolean>(false);
|
const [enabled, setEnabled] = useState<boolean>(false);
|
||||||
const [audioStatus, setAudioStatus] = useState<TAudioStatus>(null);
|
const [audioStatus, setAudioStatus] = useState<Maybe<TAudioStatus>>(null);
|
||||||
const play = (audio: HTMLAudioElement) => audio.play().catch(() => null);
|
const play = (audio: HTMLAudioElement) => audio.play().catch(() => null);
|
||||||
const pause = (audio: HTMLAudioElement) => audio.pause();
|
const pause = (audio: HTMLAudioElement) => audio.pause();
|
||||||
|
|
||||||
|
@ -69,22 +69,26 @@ export function AudioControl({
|
||||||
}, [enabled, ayah?.id]);
|
}, [enabled, ayah?.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onStatusChange(audioStatus, [
|
if (audioStatus) {
|
||||||
() => setEnabled(true),
|
onStatusChange(audioStatus, [
|
||||||
() => setEnabled(false),
|
() => setEnabled(true),
|
||||||
]);
|
() => setEnabled(false),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}, [audioStatus]);
|
}, [audioStatus]);
|
||||||
|
|
||||||
|
if (hidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!hidden && (
|
<>
|
||||||
<>
|
{enabled && (
|
||||||
{enabled && (
|
<SoundOnIcon onClick={() => [setEnabled(false), pause(audio)]} />
|
||||||
<SoundOnIcon onClick={() => [setEnabled(false), pause(audio)]} />
|
)}
|
||||||
)}
|
{!enabled && (
|
||||||
{!enabled && (
|
<SoundOffIcon onClick={() => [setEnabled(true), play(audio)]} />
|
||||||
<SoundOffIcon onClick={() => [setEnabled(true), play(audio)]} />
|
)}
|
||||||
)}
|
</>
|
||||||
</>
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export function LanguageSelect({ locale }: Props) {
|
||||||
new RegExp(`^/${locale}/`),
|
new RegExp(`^/${locale}/`),
|
||||||
`/${newLocale}/`,
|
`/${newLocale}/`,
|
||||||
);
|
);
|
||||||
content.classList.add("invisible");
|
content?.classList?.add("invisible");
|
||||||
location.replace(path);
|
location.replace(path);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
type Maybe<T> = T | null | undefined;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
value: string;
|
value: string;
|
||||||
children: JSX.Element[];
|
children: JSX.Element[];
|
||||||
|
@ -15,7 +17,7 @@ export function Select({
|
||||||
className,
|
className,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [open, setOpen] = useState<boolean>(false);
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
const [selected, setSelected] = useState<JSX.Element>(
|
const [selected, setSelected] = useState<Maybe<JSX.Element>>(
|
||||||
query(option, { within }),
|
query(option, { within }),
|
||||||
);
|
);
|
||||||
const close = () => setOpen(false);
|
const close = () => setOpen(false);
|
||||||
|
@ -31,7 +33,7 @@ export function Select({
|
||||||
className="selected"
|
className="selected"
|
||||||
onClick={e => [e.stopPropagation(), setOpen(true)]}
|
onClick={e => [e.stopPropagation(), setOpen(true)]}
|
||||||
>
|
>
|
||||||
{selected.props.children}
|
{selected?.props?.children}
|
||||||
</span>
|
</span>
|
||||||
<div className="br" />
|
<div className="br" />
|
||||||
<ul hidden={!open}>
|
<ul hidden={!open}>
|
||||||
|
@ -46,10 +48,12 @@ export function Select({
|
||||||
const target = e.target as HTMLLIElement;
|
const target = e.target as HTMLLIElement;
|
||||||
const value =
|
const value =
|
||||||
target.getAttribute("data-value") ||
|
target.getAttribute("data-value") ||
|
||||||
target.parentElement.getAttribute("data-value");
|
target.parentElement?.getAttribute("data-value");
|
||||||
const option: JSX.Element = query(value, { within });
|
const option: Maybe<JSX.Element> = query(value, { within });
|
||||||
onChange(option);
|
if (option) {
|
||||||
setSelected(option);
|
onChange(option);
|
||||||
|
setSelected(option);
|
||||||
|
}
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -63,9 +67,12 @@ export function Select({
|
||||||
}
|
}
|
||||||
|
|
||||||
function query(
|
function query(
|
||||||
option: string,
|
option: Maybe<string>,
|
||||||
options: { within: JSX.Element[] },
|
options: { within: JSX.Element[] },
|
||||||
): JSX.Element {
|
): Maybe<JSX.Element> {
|
||||||
|
if (!option) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const { within } = options;
|
const { within } = options;
|
||||||
return within.find(({ props: { value } }) => option === value);
|
return within.find(({ props: { value } }) => option === value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export function Stream({
|
||||||
t,
|
t,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const className = endOfStream || isPaused ? ["scroll-y"] : [];
|
const className = endOfStream || isPaused ? ["scroll-y"] : [];
|
||||||
const ref = useRef<HTMLUListElement>();
|
const ref = useRef<HTMLUListElement>(null);
|
||||||
const ul = useMemo<JSX.Element>(() => {
|
const ul = useMemo<JSX.Element>(() => {
|
||||||
const ltr = locale === "en";
|
const ltr = locale === "en";
|
||||||
const rtl = locale === "ar";
|
const rtl = locale === "ar";
|
||||||
|
|
|
@ -17,12 +17,12 @@ type Props = {
|
||||||
export function SurahIndex({ appVersion, locale, surahs, t }: Props) {
|
export function SurahIndex({ appVersion, locale, surahs, t }: Props) {
|
||||||
const [theme, setTheme] = useTheme();
|
const [theme, setTheme] = useTheme();
|
||||||
const [index, setIndex] = useState<Surah[]>(surahs);
|
const [index, setIndex] = useState<Surah[]>(surahs);
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const ltr = locale === "en";
|
const ltr = locale === "en";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const div = ref.current;
|
const div = ref.current;
|
||||||
if (ref.current) {
|
if (div) {
|
||||||
div.classList.remove("invisible");
|
div.classList.remove("invisible");
|
||||||
}
|
}
|
||||||
}, [ref.current, theme]);
|
}, [ref.current, theme]);
|
||||||
|
|
|
@ -25,11 +25,11 @@ type Props = {
|
||||||
export function SurahStream({ surah, locale, t }: Props) {
|
export function SurahStream({ surah, locale, t }: Props) {
|
||||||
const [stream, setStream] = useState<TAyat>([]);
|
const [stream, setStream] = useState<TAyat>([]);
|
||||||
const [isPaused, setIsPaused] = useState<boolean>(false);
|
const [isPaused, setIsPaused] = useState<boolean>(false);
|
||||||
const [audioStatus, setAudioStatus] = useState<TAudioStatus>(null);
|
const [audioStatus, setAudioStatus] = useState<Maybe<TAudioStatus>>(null);
|
||||||
const [endOfStream, setEndOfStream] = useState<boolean>(false);
|
const [endOfStream, setEndOfStream] = useState<boolean>(false);
|
||||||
const [theme, setTheme] = useTheme();
|
const [theme, setTheme] = useTheme();
|
||||||
const [ms, setMs] = useState<number | null>(null);
|
const [ms, setMs] = useState<number | null>(null);
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const audio = useMemo(() => new Audio(), []);
|
const audio = useMemo(() => new Audio(), []);
|
||||||
const readyToRender = stream.length > 0;
|
const readyToRender = stream.length > 0;
|
||||||
const ayah: Maybe<Ayah> = stream[stream.length - 1];
|
const ayah: Maybe<Ayah> = stream[stream.length - 1];
|
||||||
|
|
|
@ -32,7 +32,7 @@ export function Timer({
|
||||||
}, [ayah?.id]);
|
}, [ayah?.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ayah) {
|
if (!ayah || !ms) {
|
||||||
return;
|
return;
|
||||||
} else if (isStalled || isPaused) {
|
} else if (isStalled || isPaused) {
|
||||||
/* no-op */
|
/* no-op */
|
||||||
|
@ -44,13 +44,16 @@ export function Timer({
|
||||||
}
|
}
|
||||||
}, [isStalled, isPaused, ms]);
|
}, [isStalled, isPaused, ms]);
|
||||||
|
|
||||||
|
if (isStalled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!isStalled && (
|
<div className="timer text-base w-10 flex justify-end">
|
||||||
<div className="timer text-base w-10 flex justify-end">
|
{ms &&
|
||||||
{ms / 1000 <= 0
|
(ms / 1000 <= 0
|
||||||
? formatNumber(locale, 0)
|
? formatNumber(locale, 0)
|
||||||
: formatNumber(locale, ms / 1000)}
|
: formatNumber(locale, ms / 1000))}
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,11 @@ import { SurahIndex } from "~/components/SurahIndex";
|
||||||
(e: TSurah) => new Surah(e),
|
(e: TSurah) => new Surah(e),
|
||||||
);
|
);
|
||||||
ReactDOM.createRoot(root).render(
|
ReactDOM.createRoot(root).render(
|
||||||
<SurahIndex appVersion={appVersion} locale={locale} surahs={surahs} t={t} />,
|
<SurahIndex
|
||||||
|
appVersion={appVersion}
|
||||||
|
locale={locale}
|
||||||
|
surahs={surahs}
|
||||||
|
t={t}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"strictNullChecks": false,
|
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
|
|
Loading…
Reference in a new issue