securityos/components/apps/Webamp/index.tsx

116 lines
3.6 KiB
TypeScript

import {
cleanBufferOnSkinLoad,
focusWindow,
parseTrack,
tracksFromPlaylist,
unFocus,
} from "components/apps/Webamp/functions";
import StyledWebamp from "components/apps/Webamp/StyledWebamp";
import useWebamp from "components/apps/Webamp/useWebamp";
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
import useFocusable from "components/system/Window/useFocusable";
import useWindowTransitions from "components/system/Window/useWindowTransitions";
import { useFileSystem } from "contexts/fileSystem";
import { useProcesses } from "contexts/process";
import { basename, extname } from "path";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AUDIO_PLAYLIST_EXTENSIONS } from "utils/constants";
import { bufferToUrl, loadFiles } from "utils/functions";
import type { Options } from "webamp";
const Webamp: FC<ComponentProcessProps> = ({ id }) => {
const containerRef = useRef<HTMLDivElement | null>(null);
const { readFile } = useFileSystem();
const {
processes: { [id]: { libs = [], minimized = false, url = "" } = {} } = {},
url: setUrl,
} = useProcesses();
const [loadedUrl, setLoadedUrl] = useState(url);
const { initWebamp, webampCI } = useWebamp(id);
const windowTransitions = useWindowTransitions(id, true);
const focusEvents = useMemo(
() => ({
onBlurCapture: () => webampCI && unFocus(webampCI),
onFocusCapture: () => webampCI && focusWindow(webampCI, "main"),
}),
[webampCI]
);
const { zIndex, ...focusableProps } = useFocusable(id, focusEvents);
const getUrlOptions = useCallback(async (): Promise<Options> => {
if (url) {
const extension = extname(url).toLowerCase();
if (AUDIO_PLAYLIST_EXTENSIONS.has(extension)) {
const initialTracks = await tracksFromPlaylist(
(await readFile(url)).toString(),
extension,
basename(url, extname(url))
);
return initialTracks.length > 0 ? { initialTracks } : {};
}
if (extension === ".mp3") {
return {
initialTracks: [await parseTrack(await readFile(url), basename(url))],
};
}
if (extension === ".wsz") {
return { initialSkin: { url: bufferToUrl(await readFile(url)) } };
}
}
return {};
}, [readFile, url]);
const loadWebampUrl = useCallback(async () => {
if (webampCI) {
const { initialTracks, initialSkin } = await getUrlOptions();
if (initialTracks) webampCI.setTracksToPlay(initialTracks);
else if (initialSkin) {
cleanBufferOnSkinLoad(webampCI, initialSkin.url);
webampCI.setSkinFromUrl(initialSkin.url);
}
}
}, [getUrlOptions, webampCI]);
const loadingWebamp = useRef(false);
useEffect(() => {
if (containerRef.current && !webampCI) {
loadFiles(libs).then(async () => {
if (window.Webamp && !loadingWebamp.current) {
loadingWebamp.current = true;
initWebamp(
containerRef.current as HTMLDivElement,
await getUrlOptions()
);
}
});
}
}, [getUrlOptions, initWebamp, libs, webampCI]);
useEffect(() => {
if (url !== loadedUrl) {
loadWebampUrl();
setLoadedUrl(url);
} else if (url) {
setUrl(id, "");
setLoadedUrl("");
}
}, [id, loadWebampUrl, loadedUrl, setUrl, url]);
return (
<StyledWebamp
ref={containerRef}
$minimized={minimized}
$zIndex={zIndex}
{...focusableProps}
{...windowTransitions}
/>
);
};
export default Webamp;