ProzillaOS/src/components/desktop/Desktop.tsx
2024-05-07 21:06:07 +02:00

171 lines
No EOL
6.7 KiB
TypeScript

import { memo, useState } from "react";
import { SettingsManager } from "../../features/settings/settingsManager";
import { useSettingsManager } from "../../hooks/settings/settingsManagerContext";
import styles from "./Desktop.module.css";
import { useEffect } from "react";
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext";
import { useContextMenu } from "../../hooks/modals/contextMenu";
import { FALLBACK_ICON_SIZE, FALLBACK_WALLPAPER } from "../../config/desktop.config";
import { reloadViewport } from "../../features/_utils/browser.utils";
import { useVirtualRoot } from "../../hooks/virtual-drive/virtualRootContext";
import { DirectoryList } from "../apps/file-explorer/directory-list/DirectoryList";
import { APPS, APP_ICONS, APP_NAMES } from "../../config/apps.config";
import Vector2 from "../../features/math/vector2";
import { Actions } from "../actions/Actions";
import { ClickAction } from "../actions/actions/ClickAction";
import { faArrowsRotate, faEye, faFolder, faPaintBrush, faTerminal, faTrash } from "@fortawesome/free-solid-svg-icons";
import { ToggleAction } from "../actions/actions/ToggleAction";
import { DropdownAction } from "../actions/actions/DropdownAction";
import { RadioAction } from "../actions/actions/RadioAction";
import { Divider } from "../actions/actions/Divider";
import { isValidInteger } from "../../features/_utils/number.utils";
import { useWindowedModal } from "../../hooks/modals/windowedModal";
import { Share } from "../modals/share/Share";
import ModalsManager from "../../features/modals/modalsManager";
import { VirtualFolder } from "../../features/virtual-drive/folder/virtualFolder";
import { VirtualFolderLink } from "../../features/virtual-drive/folder/virtualFolderLink";
export const Desktop = memo(() => {
const settingsManager = useSettingsManager();
const [wallpaper, setWallpaper] = useState(null);
const windowsManager = useWindowsManager();
const virtualRoot = useVirtualRoot();
const [showIcons, setShowIcons] = useState(false);
const [iconSize, setIconSize] = useState(FALLBACK_ICON_SIZE);
const { openWindowedModal } = useWindowedModal();
const directory = virtualRoot.navigate("~/Desktop");
const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) =>
<Actions {...props}>
<DropdownAction label="View" icon={faEye}>
<RadioAction initialIndex={iconSize} onTrigger={(event, params, value: string) => {
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
settings.set("icon-size", value);
}} options={[
{ label: "Small icons" },
{ label: "Medium icons" },
{ label: "Large icons" }
]}/>
<Divider/>
<ToggleAction label="Show dekstop icons" initialValue={showIcons} onTrigger={(event, params, value) => {
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
settings.set("show-icons", (!showIcons).toString());
}}/>
</DropdownAction>
<ClickAction label="Reload" shortcut={["Control", "r"]} icon={faArrowsRotate} onTrigger={() => {
reloadViewport();
}}/>
<ClickAction label="Change appearance" icon={faPaintBrush} onTrigger={() => {
windowsManager.open("settings", { tab: 0 });
}}/>
<Divider/>
<ClickAction label={`Open in ${APP_NAMES.FILE_EXPLORER}`} icon={APP_ICONS.FILE_EXPLORER} onTrigger={() => {
windowsManager.open(APPS.FILE_EXPLORER, { startPath: directory.path });
}}/>
<ClickAction label={`Open in ${APP_NAMES.TERMINAL}`} icon={APP_ICONS.TERMINAL} onTrigger={() => {
windowsManager.open(APPS.TERMINAL, { startPath: directory.path });
}}/>
<Divider/>
<ClickAction label={"Share"} icon={ModalsManager.getModalIconUrl("share")} onTrigger={() => {
openWindowedModal({
size: new Vector2(350, 350),
Modal: (props) => <Share {...props}/>
});
}}/>
</Actions>
});
const { onContextMenu: onContextMenuFile } = useContextMenu({ Actions: (props) =>
<Actions {...props}>
<ClickAction label="Open" onTrigger={(event, file) => {
file.open(windowsManager);
}}/>
<ClickAction label={`Reveal in ${APP_NAMES.FILE_EXPLORER}`} icon={faFolder} onTrigger={(event, file) => {
file.parent.open(windowsManager);
}}/>
<ClickAction label="Delete" icon={faTrash} onTrigger={(event, file) => {
file.delete();
}}/>
</Actions>
});
const { onContextMenu: onContextMenuFolder } = useContextMenu({ Actions: (props) =>
<Actions {...props}>
<ClickAction label="Open" onTrigger={(event, folder) => {
folder.open(windowsManager);
}}/>
<ClickAction label={`Open in ${APP_NAMES.TERMINAL}`} icon={faTerminal} onTrigger={(event, folder) => {
windowsManager.open(APPS.TERMINAL, { startPath: folder.path });
}}/>
<ClickAction label={`Reveal in ${APP_NAMES.FILE_EXPLORER}`} icon={faFolder} onTrigger={(event, folder) => {
folder.parent.open(windowsManager);
}}/>
<Divider/>
<ClickAction label="Delete" icon={faTrash} onTrigger={(event, folder) => {
folder.delete();
}}/>
</Actions>
});
useEffect(() => {
(async () => {
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
settings.get("wallpaper", setWallpaper);
settings.get("show-icons", (value) => {
if (value != null) {
setShowIcons(value === "true");
} else {
setShowIcons(true);
}
});
settings.get("icon-size", (value) => {
if (isValidInteger(value))
setIconSize(parseInt(value));
});
})();
}, [settingsManager]);
const onError = () => {
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
settings.set("wallpaper", FALLBACK_WALLPAPER);
};
const iconScale = 1 + ((isValidInteger(iconSize) ? iconSize : FALLBACK_ICON_SIZE) - 1) / 4;
return (<>
<ShortcutsListener/>
<div
className={styles.Container}
onContextMenu={onContextMenu}
>
{showIcons && <DirectoryList
directory={directory as VirtualFolder}
className={styles.Content}
style={{
"--scale": `${iconScale}rem`
}}
fileClassName={styles["Item"]}
folderClassName={styles["Item"]}
onOpenFile={(event, file) => {
(event as Event).preventDefault();
const options: Record<string, any> = {};
if (file.name === "info.md")
options.size = new Vector2(575, 675);
if (file.extension === "md")
options.mode = "view";
windowsManager.openFile(file, options);
}}
onOpenFolder={(event, { linkedPath, path }: VirtualFolderLink & VirtualFolder) => {
windowsManager.open(APPS.FILE_EXPLORER, { startPath: linkedPath ?? path });
}}
onContextMenuFile={onContextMenuFile}
onContextMenuFolder={onContextMenuFolder}
/>}
{wallpaper
? <img src={wallpaper} className={styles.Wallpaper} alt="Desktop wallpaper" onError={onError}/>
: null
}
</div>
</>);
});