Enable 'strictNullChecks'

This commit is contained in:
0x1eef 2024-05-01 12:35:56 -03:00
parent 3a9d5ee022
commit eedf2a9c8a
9 changed files with 56 additions and 38 deletions

View file

@ -22,7 +22,7 @@ export function AudioControl({
onStatusChange = () => null,
}: Props) {
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 pause = (audio: HTMLAudioElement) => audio.pause();
@ -69,22 +69,26 @@ export function AudioControl({
}, [enabled, ayah?.id]);
useEffect(() => {
onStatusChange(audioStatus, [
() => setEnabled(true),
() => setEnabled(false),
]);
if (audioStatus) {
onStatusChange(audioStatus, [
() => setEnabled(true),
() => setEnabled(false),
]);
}
}, [audioStatus]);
if (hidden) {
return null;
}
return (
!hidden && (
<>
{enabled && (
<SoundOnIcon onClick={() => [setEnabled(false), pause(audio)]} />
)}
{!enabled && (
<SoundOffIcon onClick={() => [setEnabled(true), play(audio)]} />
)}
</>
)
<>
{enabled && (
<SoundOnIcon onClick={() => [setEnabled(false), pause(audio)]} />
)}
{!enabled && (
<SoundOffIcon onClick={() => [setEnabled(true), play(audio)]} />
)}
</>
);
}

View file

@ -17,7 +17,7 @@ export function LanguageSelect({ locale }: Props) {
new RegExp(`^/${locale}/`),
`/${newLocale}/`,
);
content.classList.add("invisible");
content?.classList?.add("invisible");
location.replace(path);
}}
>

View file

@ -1,6 +1,8 @@
import React, { useState, useEffect } from "react";
import classNames from "classnames";
type Maybe<T> = T | null | undefined;
type Props = {
value: string;
children: JSX.Element[];
@ -15,7 +17,7 @@ export function Select({
className,
}: Props) {
const [open, setOpen] = useState<boolean>(false);
const [selected, setSelected] = useState<JSX.Element>(
const [selected, setSelected] = useState<Maybe<JSX.Element>>(
query(option, { within }),
);
const close = () => setOpen(false);
@ -31,7 +33,7 @@ export function Select({
className="selected"
onClick={e => [e.stopPropagation(), setOpen(true)]}
>
{selected.props.children}
{selected?.props?.children}
</span>
<div className="br" />
<ul hidden={!open}>
@ -46,10 +48,12 @@ export function Select({
const target = e.target as HTMLLIElement;
const value =
target.getAttribute("data-value") ||
target.parentElement.getAttribute("data-value");
const option: JSX.Element = query(value, { within });
onChange(option);
setSelected(option);
target.parentElement?.getAttribute("data-value");
const option: Maybe<JSX.Element> = query(value, { within });
if (option) {
onChange(option);
setSelected(option);
}
setOpen(false);
}}
>
@ -63,9 +67,12 @@ export function Select({
}
function query(
option: string,
option: Maybe<string>,
options: { within: JSX.Element[] },
): JSX.Element {
): Maybe<JSX.Element> {
if (!option) {
return null;
}
const { within } = options;
return within.find(({ props: { value } }) => option === value);
}

View file

@ -22,7 +22,7 @@ export function Stream({
t,
}: Props) {
const className = endOfStream || isPaused ? ["scroll-y"] : [];
const ref = useRef<HTMLUListElement>();
const ref = useRef<HTMLUListElement>(null);
const ul = useMemo<JSX.Element>(() => {
const ltr = locale === "en";
const rtl = locale === "ar";

View file

@ -17,12 +17,12 @@ type Props = {
export function SurahIndex({ appVersion, locale, surahs, t }: Props) {
const [theme, setTheme] = useTheme();
const [index, setIndex] = useState<Surah[]>(surahs);
const ref = useRef<HTMLDivElement>();
const ref = useRef<HTMLDivElement>(null);
const ltr = locale === "en";
useEffect(() => {
const div = ref.current;
if (ref.current) {
if (div) {
div.classList.remove("invisible");
}
}, [ref.current, theme]);

View file

@ -25,11 +25,11 @@ type Props = {
export function SurahStream({ surah, locale, t }: Props) {
const [stream, setStream] = useState<TAyat>([]);
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 [theme, setTheme] = useTheme();
const [ms, setMs] = useState<number | null>(null);
const ref = useRef<HTMLDivElement>();
const ref = useRef<HTMLDivElement>(null);
const audio = useMemo(() => new Audio(), []);
const readyToRender = stream.length > 0;
const ayah: Maybe<Ayah> = stream[stream.length - 1];

View file

@ -32,7 +32,7 @@ export function Timer({
}, [ayah?.id]);
useEffect(() => {
if (!ayah) {
if (!ayah || !ms) {
return;
} else if (isStalled || isPaused) {
/* no-op */
@ -44,13 +44,16 @@ export function Timer({
}
}, [isStalled, isPaused, ms]);
if (isStalled) {
return null;
}
return (
!isStalled && (
<div className="timer text-base w-10 flex justify-end">
{ms / 1000 <= 0
<div className="timer text-base w-10 flex justify-end">
{ms &&
(ms / 1000 <= 0
? formatNumber(locale, 0)
: formatNumber(locale, ms / 1000)}
</div>
)
: formatNumber(locale, ms / 1000))}
</div>
);
}

View file

@ -13,6 +13,11 @@ import { SurahIndex } from "~/components/SurahIndex";
(e: TSurah) => new Surah(e),
);
ReactDOM.createRoot(root).render(
<SurahIndex appVersion={appVersion} locale={locale} surahs={surahs} t={t} />,
<SurahIndex
appVersion={appVersion}
locale={locale}
surahs={surahs}
t={t}
/>,
);
})();

View file

@ -1,7 +1,6 @@
{
"compilerOptions": {
"strict": true,
"strictNullChecks": false,
"module": "commonjs",
"target": "ES2020",
"noImplicitAny": true,