import { memo, useCallback, useEffect, useRef, useState } from "react"; import useCloseOnEscape from "components/system/Dialogs/useCloseOnEscape"; import { type ComponentProcessProps } from "components/system/Apps/RenderComponent"; import StyledOpenWith from "components/system/Dialogs/OpenWith/StyledOpenWith"; import StyledOpenWithList from "components/system/Dialogs/OpenWith/StyledOpenWithList"; import { getProcessByFileExtension } from "components/system/Files/FileEntry/functions"; import { useProcesses } from "contexts/process"; import directory from "contexts/process/directory"; import { useSession } from "contexts/session"; import Button from "styles/common/Button"; import Icon from "styles/common/Icon"; import { PREVENT_SCROLL, TRANSITIONS_IN_MILLISECONDS } from "utils/constants"; import { getExtension, haltEvent } from "utils/functions"; const INCLUDED_PROCESSES = new Set([ "BoxedWine", "JSDOS", "Marked", "MonacoEditor", "OpenType", "PDF", "Paint", "Photos", "Ruffle", "TinyMCE", "V86", "VideoPlayer", "Vim", "Webamp", ]); type OpenWithEntryProps = { icon: string; onClick: () => void; selected: boolean; title: string; }; const OpenWithEntry: FC = ({ icon, onClick, selected, title, }) => (
  • ); const OpenWith: FC = ({ id }) => { const { closeWithTransition, open, processes: { [id]: process } = {}, } = useProcesses(); const { foregroundId, setForegroundId, updateRecentFiles } = useSession(); const { url } = process || {}; const urlExtension = url ? getExtension(url) : ""; const primaryExtensionProcesses = getProcessByFileExtension(urlExtension); const { title: primaryTitle, icon: primaryIcon } = (primaryExtensionProcesses && directory[primaryExtensionProcesses]) || {}; const [selectedPid, setSelectedPid] = useState(primaryExtensionProcesses); const [closeOnBlur, setCloseOnBlur] = useState(false); const recentlySelectedPid = useRef(""); const runApp = useCallback( (pid: string): void => { open(pid, { url }); closeWithTransition(id); if (url && pid) updateRecentFiles(url, pid); }, [closeWithTransition, id, open, updateRecentFiles, url] ); const updateSelectedPid = useCallback( (pid: string) => { if (recentlySelectedPid.current === pid) { runApp(pid); } else { recentlySelectedPid.current = pid; setTimeout(() => { recentlySelectedPid.current = ""; }, TRANSITIONS_IN_MILLISECONDS.DOUBLE_CLICK); setSelectedPid(pid); } }, [runApp] ); const closeOnEscape = useCloseOnEscape(id); useEffect(() => { const isForeground = foregroundId === id; if (closeOnBlur) { if (!isForeground) closeWithTransition(id); } else { if (!isForeground) setForegroundId(id); setTimeout( () => setCloseOnBlur(true), TRANSITIONS_IN_MILLISECONDS.WINDOW ); } }, [closeOnBlur, closeWithTransition, foregroundId, id, setForegroundId]); return ( { element?.focus(PREVENT_SCROLL); }} onContextMenu={haltEvent} {...closeOnEscape} >

    How do you want to open this file?

    {primaryTitle && primaryIcon && ( <>

    Keep using this app

    updateSelectedPid(primaryExtensionProcesses)} selected={selectedPid === primaryExtensionProcesses} title={primaryTitle} />

    Other options

    )} {Object.entries(directory) .filter( ([pid]) => INCLUDED_PROCESSES.has(pid) && pid !== primaryExtensionProcesses ) .map(([pid, { icon, title }]) => ( updateSelectedPid(pid)} selected={selectedPid === pid} title={title} /> ))}
    ); }; export default memo(OpenWith);