Added application roles

This commit is contained in:
Prozilla 2024-06-20 21:13:16 +02:00
parent d139f80ab3
commit 8c722a29db
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
41 changed files with 280 additions and 120 deletions

View file

@ -14,6 +14,7 @@ export default tseslint.config(
project: ["./tsconfig.json", "./packages/*/tsconfig.json", "./packages/apps/*/tsconfig.json"], project: ["./tsconfig.json", "./packages/*/tsconfig.json", "./packages/apps/*/tsconfig.json"],
tsconfigRootDir: import.meta.dirname, tsconfigRootDir: import.meta.dirname,
allowAutomaticSingleRunInference: true, allowAutomaticSingleRunInference: true,
EXPERIMENTAL_useProjectService: true
}, },
}, },
ignores: [ ignores: [

View file

@ -1,5 +1,13 @@
# @prozilla-os/file-explorer # @prozilla-os/file-explorer
## 1.0.10
### Patch Changes
- Added application roles
- Updated dependencies
- @prozilla-os/core@1.0.13
## 1.0.9 ## 1.0.9
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@prozilla-os/file-explorer", "name": "@prozilla-os/file-explorer",
"description": "A standard ProzillaOS application for browsing files.", "description": "A standard ProzillaOS application for browsing files.",
"version": "1.0.9", "version": "1.0.10",
"homepage": "https://os.prozilla.dev/file-explorer", "homepage": "https://os.prozilla.dev/file-explorer",
"author": { "author": {
"name": "Prozilla", "name": "Prozilla",
@ -12,7 +12,7 @@
"main": "dist/main.js", "main": "dist/main.js",
"types": "dist/main.d.ts", "types": "dist/main.d.ts",
"scripts": { "scripts": {
"build": "tsc && vite build" "build": "tsc --project tsconfig.build.json && vite build"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -4,9 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowUp, faCaretLeft, faCaretRight, faCircleInfo, faCog, faDesktop, faFileLines, faHouse, faImage, faPlus, faSearch, faTrash } from "@fortawesome/free-solid-svg-icons"; import { faArrowUp, faCaretLeft, faCaretRight, faCircleInfo, faCog, faDesktop, faFileLines, faHouse, faImage, faPlus, faSearch, faTrash } from "@fortawesome/free-solid-svg-icons";
import { QuickAccessButton } from "./QuickAccessButton"; import { QuickAccessButton } from "./QuickAccessButton";
import { ImportButton } from "./ImportButton"; import { ImportButton } from "./ImportButton";
import { Actions, ClickAction, CODE_EXTENSIONS, DIALOG_CONTENT_TYPES, DialogBox, DirectoryList, Divider, FileEventHandler, FolderEventHandler, OnSelectionChangeParams, useAlert, useContextMenu, useHistory, useSystemManager, useVirtualRoot, useWindowedModal, useWindowsManager, utilStyles, Vector2, VirtualFile, VirtualFolder, VirtualFolderLink, VirtualRoot, WindowProps } from "@prozilla-os/core"; import { Actions, ClickAction, CODE_EXTENSIONS, DialogBox, DirectoryList, Divider, FileEventHandler, FolderEventHandler, ModalProps, ModalsConfig, OnSelectionChangeParams, useAlert, useContextMenu, useHistory, useSystemManager, useVirtualRoot, useWindowedModal, useWindowsManager, utilStyles, Vector2, VirtualFile, VirtualFolder, VirtualFolderLink, VirtualRoot, WindowProps } from "@prozilla-os/core";
import { SELECTOR_MODE } from "../constants/fileExplorer.const"; import { SELECTOR_MODE } from "../constants/fileExplorer.const";
import { FileProperties } from "./modals/file-properties/FileProperties"; import { FileProperties } from "./modals/file-properties/FileProperties";
import { JSX } from "react/jsx-runtime";
export interface FileExplorerProps extends WindowProps { export interface FileExplorerProps extends WindowProps {
path?: string; path?: string;
@ -140,10 +141,10 @@ export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSel
title: "Error", title: "Error",
iconUrl: app?.iconUrl as string | undefined, iconUrl: app?.iconUrl as string | undefined,
size: new Vector2(300, 150), size: new Vector2(300, 150),
Modal: (props: {}) => Modal: (props: JSX.IntrinsicAttributes & ModalProps) =>
<DialogBox {...props}> <DialogBox {...props}>
<p>Invalid path: "{value}"</p> <p>Invalid path: "{value}"</p>
<button data-type={DIALOG_CONTENT_TYPES.closeButton}>Ok</button> <button data-type={ModalsConfig.DIALOG_CONTENT_TYPES.CloseButton}>Ok</button>
</DialogBox> </DialogBox>
}); });
return; return;
@ -191,16 +192,16 @@ export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSel
tabIndex={0} tabIndex={0}
className={styles.IconButton} className={styles.IconButton}
onClick={() => { onClick={() => {
// openWindowedModal({ openWindowedModal({
// title: "Error", title: "Error",
// iconUrl: AppsManager.getAppIconUrl(APPS.FILE_EXPLORER), iconUrl: app?.iconUrl as string | undefined,
// size: new Vector2(300, 150), size: new Vector2(300, 150),
// Modal: (props) => Modal: (props: JSX.IntrinsicAttributes & ModalProps) =>
// <DialogBox {...props}> <DialogBox {...props}>
// <p>This folder is protected.</p> <p>This folder is protected.</p>
// <button data-type={DIALOG_CONTENT_TYPES.CloseButton}>Ok</button> <button data-type={ModalsConfig.DIALOG_CONTENT_TYPES.CloseButton}>Ok</button>
// </DialogBox> </DialogBox>
// }); });
// if (currentDirectory.canBeEdited) { // if (currentDirectory.canBeEdited) {
// onNew(event); // onNew(event);

View file

@ -1,8 +1,9 @@
import { App } from "@prozilla-os/core"; import { App, AppsConfig } from "@prozilla-os/core";
import { FileExplorer, FileExplorerProps } from "./components/FileExplorer"; import { FileExplorer, FileExplorerProps } from "./components/FileExplorer";
const fileExplorer = new App<FileExplorerProps>("File Explorer", "file-explorer", FileExplorer) const fileExplorer = new App<FileExplorerProps>("File Explorer", "file-explorer", FileExplorer)
.setIconUrl("https://os.prozilla.dev/assets/apps/icons/file-explorer.svg"); .setIconUrl("https://os.prozilla.dev/assets/apps/icons/file-explorer.svg")
.setRole(AppsConfig.APP_ROLES.FileExplorer);
export { fileExplorer }; export { fileExplorer };
export { FileSelectorMode } from "./types/utils"; export { FileSelectorMode } from "./types/utils";

View file

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"paths": {
"@prozilla-os/core": ["packages/core/dist/main"]
}
}
}

View file

@ -8,9 +8,9 @@
"emitDeclarationOnly": true, "emitDeclarationOnly": true,
"noEmit": false, "noEmit": false,
"paths": { "paths": {
"@prozilla-os/core": ["packages/core/dist/main"] "@prozilla-os/core": ["./node_modules/@prozilla-os/core/src/main"]
} }
}, },
"include": ["src", "vite.config.ts"], "include": ["src", "vite.config.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"],
} }

View file

@ -15,6 +15,7 @@ export default defineConfig({
rollupTypes: true, rollupTypes: true,
strictOutput: true, strictOutput: true,
pathsToAliases: false, pathsToAliases: false,
tsconfigPath: "tsconfig.build.json"
}) })
], ],
build: { build: {

View file

@ -1,5 +1,13 @@
# @prozilla-os/terminal # @prozilla-os/terminal
## 1.0.3
### Patch Changes
- Added application roles
- Updated dependencies
- @prozilla-os/core@1.0.13
## 1.0.2 ## 1.0.2
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@prozilla-os/terminal", "name": "@prozilla-os/terminal",
"description": "A terminal/shell application for ProzillaOS.", "description": "A terminal/shell application for ProzillaOS.",
"version": "1.0.2", "version": "1.0.3",
"homepage": "https://os.prozilla.dev/terminal", "homepage": "https://os.prozilla.dev/terminal",
"author": { "author": {
"name": "Prozilla", "name": "Prozilla",

View file

@ -1,7 +1,8 @@
import { App } from "@prozilla-os/core"; import { App, AppsConfig } from "@prozilla-os/core";
import { Terminal, TerminalProps } from "./components/Terminal"; import { Terminal, TerminalProps } from "./components/Terminal";
const terminal = new App<TerminalProps>("Terminal", "terminal", Terminal) const terminal = new App<TerminalProps>("Terminal", "terminal", Terminal)
.setIconUrl("https://os.prozilla.dev/assets/apps/icons/terminal.svg"); .setIconUrl("https://os.prozilla.dev/assets/apps/icons/terminal.svg")
.setRole(AppsConfig.APP_ROLES.Terminal);
export { terminal }; export { terminal };

View file

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"paths": {
"@prozilla-os/core": ["packages/core/dist/main"]
}
}
}

View file

@ -8,9 +8,9 @@
"emitDeclarationOnly": true, "emitDeclarationOnly": true,
"noEmit": false, "noEmit": false,
"paths": { "paths": {
"@prozilla-os/core": ["packages/core/dist/main"] "@prozilla-os/core": ["./node_modules/@prozilla-os/core/src/main"]
} }
}, },
"include": ["src", "vite.config.ts"], "include": ["src", "vite.config.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"],
} }

View file

@ -1,5 +1,13 @@
# @prozilla-os/text-editor # @prozilla-os/text-editor
## 1.0.3
### Patch Changes
- Added application roles
- Updated dependencies
- @prozilla-os/core@1.0.13
## 1.0.2 ## 1.0.2
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@prozilla-os/text-editor", "name": "@prozilla-os/text-editor",
"description": "A text editor application for ProzillaOS.", "description": "A text editor application for ProzillaOS.",
"version": "1.0.2", "version": "1.0.3",
"homepage": "https://os.prozilla.dev/text-editor", "homepage": "https://os.prozilla.dev/text-editor",
"author": { "author": {
"name": "Prozilla", "name": "Prozilla",

View file

@ -2,7 +2,7 @@ import { MouseEventHandler, ReactNode, useMemo } from "react";
import { faClipboard, faExternalLink } from "@fortawesome/free-solid-svg-icons"; import { faClipboard, faExternalLink } from "@fortawesome/free-solid-svg-icons";
import { MarkdownProps } from "../TextEditor"; import { MarkdownProps } from "../TextEditor";
import styles from "../TextEditor.module.css"; import styles from "../TextEditor.module.css";
import { Actions, ClickAction, copyToClipboard, DIALOG_CONTENT_TYPES, DialogBox, ModalProps, removeUrlProtocol, TextDisplay, useContextMenu, useWindowedModal, Vector2 } from "@prozilla-os/core"; import { Actions, ClickAction, copyToClipboard, DialogBox, ModalProps, ModalsConfig, removeUrlProtocol, TextDisplay, useContextMenu, useWindowedModal, Vector2 } from "@prozilla-os/core";
import { sanitizeProps } from "../../core/_utils/sanitizeProps"; import { sanitizeProps } from "../../core/_utils/sanitizeProps";
interface MarkdownLinkProps extends MarkdownProps { interface MarkdownLinkProps extends MarkdownProps {
@ -32,7 +32,7 @@ export function MarkdownLink({ href, children, windowsManager, currentFile, setC
Modal: (props: ModalProps) => Modal: (props: ModalProps) =>
<DialogBox {...props}> <DialogBox {...props}>
<p>Target not found: "{href}"</p> <p>Target not found: "{href}"</p>
<button data-type={DIALOG_CONTENT_TYPES.closeButton}>Ok</button> <button data-type={ModalsConfig.DIALOG_CONTENT_TYPES.CloseButton}>Ok</button>
</DialogBox> </DialogBox>
}); });
} }

View file

@ -1,7 +1,8 @@
import { App } from "@prozilla-os/core"; import { App, AppsConfig } from "@prozilla-os/core";
import { TextEditor, TextEditorProps } from "./components/TextEditor"; import { TextEditor, TextEditorProps } from "./components/TextEditor";
const textEditor = new App<TextEditorProps>("Text Editor", "text-editor", TextEditor) const textEditor = new App<TextEditorProps>("Text Editor", "text-editor", TextEditor)
.setIconUrl("https://os.prozilla.dev/assets/apps/icons/text-editor.svg"); .setIconUrl("https://os.prozilla.dev/assets/apps/icons/text-editor.svg")
.setRole(AppsConfig.APP_ROLES.TextEditor);
export { textEditor }; export { textEditor };

View file

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"paths": {
"@prozilla-os/core": ["packages/core/dist/main"]
}
}
}

View file

@ -8,7 +8,7 @@
"emitDeclarationOnly": true, "emitDeclarationOnly": true,
"noEmit": false, "noEmit": false,
"paths": { "paths": {
"@prozilla-os/core": ["packages/core/dist/main"] "@prozilla-os/core": ["./node_modules/@prozilla-os/core/src/main"]
} }
}, },
"include": ["src", "vite.config.ts"], "include": ["src", "vite.config.ts"],

View file

@ -1,5 +1,11 @@
# @prozilla-os/core # @prozilla-os/core
## 1.0.13
### Patch Changes
- Added application roles
## 1.0.12 ## 1.0.12
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@prozilla-os/core", "name": "@prozilla-os/core",
"description": "A React component library written in TypeScript for building web-based operating systems, made by Prozilla.", "description": "A React component library written in TypeScript for building web-based operating systems, made by Prozilla.",
"version": "1.0.12", "version": "1.0.13",
"homepage": "https://os.prozilla.dev", "homepage": "https://os.prozilla.dev",
"author": { "author": {
"name": "Prozilla", "name": "Prozilla",

View file

@ -3,23 +3,22 @@ import styles from "./Desktop.module.css";
import { useEffect } from "react"; import { useEffect } from "react";
import { Actions } from "../actions/Actions"; import { Actions } from "../actions/Actions";
import { ClickAction } from "../actions/actions/ClickAction"; import { ClickAction } from "../actions/actions/ClickAction";
import { faArrowsRotate, faCompress, faExpand, faEye, faFolder, faPaintBrush, faTerminal, faTrash } from "@fortawesome/free-solid-svg-icons"; import { faArrowsRotate, faCompress, faExpand, faEye, faPaintBrush, faTrash } from "@fortawesome/free-solid-svg-icons";
import { ToggleAction } from "../actions/actions/ToggleAction"; import { ToggleAction } from "../actions/actions/ToggleAction";
import { DropdownAction } from "../actions/actions/DropdownAction"; import { DropdownAction } from "../actions/actions/DropdownAction";
import { RadioAction } from "../actions/actions/RadioAction"; import { RadioAction } from "../actions/actions/RadioAction";
import { Divider } from "../actions/actions/Divider"; import { Divider } from "../actions/actions/Divider";
import { Share } from "../modals/share/Share"; import { Share } from "../modals/share/Share";
import { ModalProps } from "../modals/ModalView"; import { ModalProps } from "../modals/ModalView";
import { SettingsManager, reloadViewport, ModalsManager, Vector2, isValidInteger } from "../../features"; import { SettingsManager, reloadViewport, ModalsManager, Vector2, isValidInteger, AppsConfig } from "../../features";
import { VirtualFile } from "../../features/virtual-drive/file"; import { VirtualFile } from "../../features/virtual-drive/file";
import { VirtualFolder, VirtualFolderLink } from "../../features/virtual-drive/folder"; import { VirtualFolder, VirtualFolderLink } from "../../features/virtual-drive/folder";
import { useSettingsManager, useWindowsManager, useVirtualRoot, useWindowedModal, useContextMenu, useSystemManager } from "../../hooks"; import { useSettingsManager, useWindowsManager, useVirtualRoot, useWindowedModal, useContextMenu, useSystemManager } from "../../hooks";
import { DirectoryList } from "../_utils"; import { DirectoryList } from "../_utils";
import { FileEventHandler, FolderEventHandler } from "../_utils/directory-list/DirectoryList"; import { FileEventHandler, FolderEventHandler } from "../_utils/directory-list/DirectoryList";
// import { fileExplorer } from "@prozilla-os/file-explorer";
export const Desktop = memo(() => { export const Desktop = memo(() => {
const { desktopConfig } = useSystemManager(); const { desktopConfig, appsConfig } = useSystemManager();
const settingsManager = useSettingsManager(); const settingsManager = useSettingsManager();
const windowsManager = useWindowsManager(); const windowsManager = useWindowsManager();
const virtualRoot = useVirtualRoot(); const virtualRoot = useVirtualRoot();
@ -32,6 +31,9 @@ export const Desktop = memo(() => {
const directory = virtualRoot?.navigate("~/Desktop"); const directory = virtualRoot?.navigate("~/Desktop");
const fileExplorer = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
const terminal = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Terminal);
const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) => const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) =>
<Actions {...props}> <Actions {...props}>
<DropdownAction label="View" icon={faEye}> <DropdownAction label="View" icon={faEye}>
@ -83,12 +85,16 @@ export const Desktop = memo(() => {
windowsManager?.open("settings", { tab: 2 }); windowsManager?.open("settings", { tab: 2 });
}}/> }}/>
<Divider/> <Divider/>
{/* <ClickAction label={`Open in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={() => { {fileExplorer != null &&
windowsManager?.open(fileExplorer.id, { path: directory?.path }); <ClickAction label={`Open in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={() => {
}}/> */} windowsManager?.open(fileExplorer.id, { path: directory?.path });
{/* <ClickAction label={`Open in ${"APP_NAMES.TERMINAL"}`} icon={APP_ICONS.TERMINAL} onTrigger={() => { }}/>
windowsManager?.open(APPS.TERMINAL, { path: directory?.path }); }
}}/> */} {terminal != null &&
<ClickAction label={`Open in ${terminal.name}`} icon={terminal.iconUrl as string | undefined} onTrigger={() => {
windowsManager?.open(terminal.id, { path: directory?.path });
}}/>
}
<Divider/> <Divider/>
<ClickAction label={"Share"} icon={ModalsManager.getModalIconUrl("share")} onTrigger={() => { <ClickAction label={"Share"} icon={ModalsManager.getModalIconUrl("share")} onTrigger={() => {
openWindowedModal({ openWindowedModal({
@ -103,9 +109,11 @@ export const Desktop = memo(() => {
<ClickAction label="Open" onTrigger={(event, file) => { <ClickAction label="Open" onTrigger={(event, file) => {
if (windowsManager != null) (file as VirtualFile).open(windowsManager); if (windowsManager != null) (file as VirtualFile).open(windowsManager);
}}/> }}/>
{/* <ClickAction label={`Reveal in ${fileExplorer.name}`} icon={faFolder} onTrigger={(event, file) => { {fileExplorer != null &&
if (windowsManager != null) (file as VirtualFile).parent?.open(windowsManager); <ClickAction label={`Reveal in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={(event, file) => {
}}/> */} if (windowsManager != null) (file as VirtualFile).parent?.open(windowsManager);
}}/>
}
<ClickAction label="Delete" icon={faTrash} onTrigger={(event, file) => { <ClickAction label="Delete" icon={faTrash} onTrigger={(event, file) => {
(file as VirtualFile).delete(); (file as VirtualFile).delete();
}}/> }}/>
@ -116,12 +124,16 @@ export const Desktop = memo(() => {
<ClickAction label="Open" onTrigger={(event, folder) => { <ClickAction label="Open" onTrigger={(event, folder) => {
if (windowsManager != null) (folder as VirtualFolder).open(windowsManager); if (windowsManager != null) (folder as VirtualFolder).open(windowsManager);
}}/> }}/>
{/* <ClickAction label={`Open in ${APP_NAMES.TERMINAL}`} icon={faTerminal} onTrigger={(event, folder) => { {fileExplorer != null &&
windowsManager?.open(APPS.TERMINAL, { path: (folder as VirtualFolder).path }); <ClickAction label={`Open in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={(event, folder) => {
}}/> */} windowsManager?.open(fileExplorer.id, { path: (folder as VirtualFolder).path });
{/* <ClickAction label={`Reveal in ${fileExplorer.name}`} icon={faFolder} onTrigger={(event, folder) => { }}/>
if (windowsManager != null) (folder as VirtualFolder).parent?.open(windowsManager); }
}}/> */} {terminal != null &&
<ClickAction label={`Open in ${terminal.name}`} icon={terminal.iconUrl as string | undefined} onTrigger={(event, folder) => {
if (windowsManager != null) (folder as VirtualFolder).parent?.open(windowsManager);
}}/>
}
<Divider/> <Divider/>
<ClickAction label="Delete" icon={faTrash} onTrigger={(event, folder) => { <ClickAction label="Delete" icon={faTrash} onTrigger={(event, folder) => {
(folder as VirtualFolder).delete(); (folder as VirtualFolder).delete();
@ -183,9 +195,11 @@ export const Desktop = memo(() => {
windowsManager?.openFile(file, options); windowsManager?.openFile(file, options);
}} }}
onOpenFolder={(event, folder) => { onOpenFolder={(event, folder) => {
// windowsManager?.open(fileExplorer.id, { if (fileExplorer != null) {
// path: (folder as VirtualFolderLink).linkedPath ?? folder.path windowsManager?.open(fileExplorer.id, {
// }); path: (folder as VirtualFolderLink).linkedPath ?? folder.path
});
}
}} }}
onContextMenuFile={onContextMenuFile as unknown as FileEventHandler} onContextMenuFile={onContextMenuFile as unknown as FileEventHandler}
onContextMenuFolder={onContextMenuFolder as unknown as FolderEventHandler} onContextMenuFolder={onContextMenuFolder as unknown as FolderEventHandler}

View file

@ -1,4 +1,4 @@
import { DIALOG_CONTENT_TYPES } from "../../../constants/modals.const"; import { ModalsConfig } from "../../../features/system/configs";
import { WindowedModal } from "../_utils/WindowedModal"; import { WindowedModal } from "../_utils/WindowedModal";
import { ModalProps } from "../ModalView"; import { ModalProps } from "../ModalView";
import styles from "./DialogBox.module.css"; import styles from "./DialogBox.module.css";
@ -12,7 +12,7 @@ export function DialogBox({ modal, params, children, ...props }: ModalProps) {
const type = parseInt(attribute); const type = parseInt(attribute);
switch (type) { switch (type) {
case DIALOG_CONTENT_TYPES.closeButton: case ModalsConfig.DIALOG_CONTENT_TYPES.CloseButton:
modal?.close(); modal?.close();
break; break;
} }

View file

@ -5,10 +5,9 @@ import taskbarStyles from "../Taskbar.module.css";
import { faCircleInfo, faFileLines, faGear, faImage, faPowerOff } from "@fortawesome/free-solid-svg-icons"; import { faCircleInfo, faFileLines, faGear, faImage, faPowerOff } from "@fortawesome/free-solid-svg-icons";
import { ReactSVG } from "react-svg"; import { ReactSVG } from "react-svg";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { closeViewport, Vector2 } from "../../../features"; import { AppsConfig, closeViewport, Vector2 } from "../../../features";
import { useWindowsManager, useVirtualRoot, useKeyboardListener, useSystemManager } from "../../../hooks"; import { useWindowsManager, useVirtualRoot, useKeyboardListener, useSystemManager } from "../../../hooks";
import { utilStyles } from "../../../styles"; import { utilStyles } from "../../../styles";
// import { fileExplorer } from "@prozilla-os/file-explorer";
interface HomeMenuProps { interface HomeMenuProps {
active: boolean; active: boolean;
@ -56,6 +55,8 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) {
useKeyboardListener({ onKeyDown, onKeyUp }); useKeyboardListener({ onKeyDown, onKeyUp });
const fileExplorer = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
return ( return (
<div className={classNames.join(" ")}> <div className={classNames.join(" ")}>
<div className={`${styles.HomeMenu} ${taskbarStyles.Menu}`}> <div className={`${styles.HomeMenu} ${taskbarStyles.Menu}`}>
@ -82,20 +83,22 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) {
<FontAwesomeIcon icon={faCircleInfo}/> <FontAwesomeIcon icon={faCircleInfo}/>
<p className={utilStyles.TextRegular}>Info</p> <p className={utilStyles.TextRegular}>Info</p>
</button> </button>
{/* <button tabIndex={tabIndex} onClick={() => { {fileExplorer != null && <>
setActive(false); <button tabIndex={tabIndex} onClick={() => {
windowsManager?.open(fileExplorer.id, { path: "~/Pictures" }); setActive(false);
}}> windowsManager?.open(fileExplorer.id, { path: "~/Pictures" });
<FontAwesomeIcon icon={faImage}/> }}>
<p className={utilStyles.TextRegular}>Images</p> <FontAwesomeIcon icon={faImage}/>
</button> <p className={utilStyles.TextRegular}>Images</p>
<button tabIndex={tabIndex} onClick={() => { </button>
setActive(false); <button tabIndex={tabIndex} onClick={() => {
windowsManager?.open(fileExplorer.id, { path: "~/Documents" }); } setActive(false);
}> windowsManager?.open(fileExplorer.id, { path: "~/Documents" }); }
<FontAwesomeIcon icon={faFileLines}/> }>
<p className={utilStyles.TextRegular}>Documents</p> <FontAwesomeIcon icon={faFileLines}/>
</button> */} <p className={utilStyles.TextRegular}>Documents</p>
</button>
</>}
</div> </div>
<div className={styles.Apps}> <div className={styles.Apps}>
<span className={styles.Logo}> <span className={styles.Logo}>

View file

@ -1,4 +1,3 @@
export { DIALOG_CONTENT_TYPES } from "./modals.const";
export { CODE_EXTENSIONS } from "./virtualDrive.const"; export { CODE_EXTENSIONS } from "./virtualDrive.const";
export { ANSI } from "./utils.const"; export { ANSI } from "./utils.const";
export { THEMES } from "./themes.const"; export { THEMES } from "./themes.const";

View file

@ -1,3 +0,0 @@
export const DIALOG_CONTENT_TYPES = {
closeButton: 0
};

View file

@ -4,24 +4,57 @@ import { FC } from "react";
const validIdRegex = /^[a-zA-Z0-9-]+$/; const validIdRegex = /^[a-zA-Z0-9-]+$/;
/**
* An application that can be ran by ProzillaOS
* Applications can be installed by adding them to the `apps` array in {@link AppsConfig}
*/
export class App<AppProps extends WindowProps = WindowProps> { export class App<AppProps extends WindowProps = WindowProps> {
/**
* The display name of this application
*/
name: string = "App"; name: string = "App";
/**
* The unique ID of this application
*/
id: string = "app"; id: string = "app";
/**
* Main component that renders this app inside a window
*/
windowContent: FC<AppProps>; windowContent: FC<AppProps>;
/**
* Default options that get passed to the {@link this.windowContent} component
*/
windowOptions?: { windowOptions?: {
size: Vector2; size: Vector2;
[key: string]: unknown; [key: string]: unknown;
}; };
/**
* Description of this application
*/
description: string | null = null; description: string | null = null;
/**
* URL of the icon of this application
*/
iconUrl: string | null = null; iconUrl: string | null = null;
/**
* Defines what the app can handle and how it can be used elsewhere in the system
*/
role: string | null = null;
/**
* An array of file extensions that this application can interpret
*/
associatedExtensions: string[] = [];
isActive: boolean = false; isActive: boolean = false;
isPinned?: boolean; isPinned?: boolean;
/**
* @param windowOptions - Default window options
*/
constructor(name: App["name"], id: App["id"], windowContent: App<AppProps>["windowContent"], windowOptions?: App["windowOptions"]) { constructor(name: App["name"], id: App["id"], windowContent: App<AppProps>["windowContent"], windowOptions?: App["windowOptions"]) {
this.name = name; this.name = name;
this.id = id; this.id = id;
@ -36,25 +69,49 @@ export class App<AppProps extends WindowProps = WindowProps> {
WindowContent = (props: AppProps) => { WindowContent = (props: AppProps) => {
props = { ...props, ...this.windowOptions }; props = { ...props, ...this.windowOptions };
if (this.windowContent == null) { if (this.windowContent == null)
return null; return null;
}
return <this.windowContent {...props}/>; return <this.windowContent {...props}/>;
}; };
/**
* Set the display name of this application
*/
setName(name: string): this {
this.name = name;
return this;
}
/**
* Set the description of this application
*/
setDescription(description: App["description"]): this { setDescription(description: App["description"]): this {
this.description = description; this.description = description;
return this; return this;
} }
/**
* Set the URL of the icon of this application
*/
setIconUrl(iconUrl: App["iconUrl"]): this { setIconUrl(iconUrl: App["iconUrl"]): this {
this.iconUrl = iconUrl; this.iconUrl = iconUrl;
return this; return this;
} }
setName(name: string): this { /**
this.name = name; * Set the role of this application
*/
setRole(role: string | null): this {
this.role = role;
return this;
}
/**
* Set the associated extensions of this application
*/
setAssociatedExtensions(extensions: string[] | null): this {
this.associatedExtensions = extensions ?? [];
return this; return this;
} }
} }

View file

@ -2,6 +2,9 @@ import { App } from ".";
import { OptionalInterface } from "../../../types/utils"; import { OptionalInterface } from "../../../types/utils";
export interface AppsConfigOptions { export interface AppsConfigOptions {
/**
* An array of applications
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
apps: App<any>[]; apps: App<any>[];
} }
@ -9,6 +12,12 @@ export interface AppsConfigOptions {
export class AppsConfig { export class AppsConfig {
apps: AppsConfigOptions["apps"] = []; apps: AppsConfigOptions["apps"] = [];
static APP_ROLES = {
FileExplorer: "file-explorer",
Terminal: "terminal",
TextEditor: "text-editor",
};
constructor(options: OptionalInterface<AppsConfigOptions> = {}) { constructor(options: OptionalInterface<AppsConfigOptions> = {}) {
const { apps } = options as AppsConfigOptions; const { apps } = options as AppsConfigOptions;
@ -29,7 +38,7 @@ export class AppsConfig {
let resultApp: App | null = null; let resultApp: App | null = null;
this.apps.forEach((app) => { this.apps.forEach((app) => {
if (app.id === id) { if (resultApp == null && app.id === id) {
resultApp = app; resultApp = app;
return; return;
} }
@ -42,19 +51,31 @@ export class AppsConfig {
* Get the app associated with a file extension * Get the app associated with a file extension
*/ */
getAppByFileExtension(fileExtension: string): App | null { getAppByFileExtension(fileExtension: string): App | null {
return null; let resultApp: App | null = null;
// let app: App | null = null; this.apps.forEach((app) => {
if (resultApp == null && app.associatedExtensions?.includes(fileExtension)) {
resultApp = app;
return;
}
});
// if (IMAGE_FORMATS.includes(fileExtension)) return resultApp ?? this.getAppByRole(AppsConfig.APP_ROLES.TextEditor);
// return this.getAppById(APPS.MEDIA_VIEWER); }
// switch (fileExtension) { /**
// default: * Get the app with a specific role
// app = this.getAppById(APPS.TEXT_EDITOR); */
// break; getAppByRole(role: string): App | null {
// } let resultApp: App | null = null;
// return app; this.apps.forEach((app) => {
if (resultApp == null && app.role == role) {
resultApp = app;
return;
}
});
return resultApp;
} }
} }

View file

@ -6,4 +6,4 @@ export { ModalsConfig } from "./modalsConfig";
export { TaskbarConfig } from "./taskbarConfig"; export { TaskbarConfig } from "./taskbarConfig";
export { TrackingConfig } from "./trackingConfig"; export { TrackingConfig } from "./trackingConfig";
export { WindowsConfig } from "./windowsConfig"; export { WindowsConfig } from "./windowsConfig";
export { VirtualDriveConfig } from "./virtualDriveConfig"; export { VirtualDriveConfig } from "./virtualDriveConfig";

View file

@ -19,6 +19,10 @@ export class ModalsConfig {
defaultDialogSize: ModalsConfigOptions["defaultDialogSize"]; defaultDialogSize: ModalsConfigOptions["defaultDialogSize"];
defaultFileSelectorSize: ModalsConfigOptions["defaultFileSelectorSize"]; defaultFileSelectorSize: ModalsConfigOptions["defaultFileSelectorSize"];
static DIALOG_CONTENT_TYPES = {
CloseButton: 0
};
constructor(options: OptionalInterface<ModalsConfigOptions> = {}) { constructor(options: OptionalInterface<ModalsConfigOptions> = {}) {
const { defaultDialogSize, defaultFileSelectorSize } = options as ModalsConfigOptions; const { defaultDialogSize, defaultFileSelectorSize } = options as ModalsConfigOptions;

View file

@ -4,7 +4,7 @@ import { VirtualFileJson } from "../file/virtualFile";
import { VirtualBase, VirtualBaseJson } from "../virtualBase"; import { VirtualBase, VirtualBaseJson } from "../virtualBase";
import { VirtualFolderLink } from "."; import { VirtualFolderLink } from ".";
import { VirtualFile, VirtualFileLink } from "../file"; import { VirtualFile, VirtualFileLink } from "../file";
// import { fileExplorer } from "@prozilla-os/file-explorer"; import { AppsConfig } from "../../system/configs";
export interface VirtualFolderJson extends VirtualBaseJson { export interface VirtualFolderJson extends VirtualBaseJson {
fls?: VirtualFileJson[]; fls?: VirtualFileJson[];
@ -288,7 +288,10 @@ export class VirtualFolder extends VirtualBase {
* Opens this folder in file explorer * Opens this folder in file explorer
*/ */
open(windowsManager: WindowsManager) { open(windowsManager: WindowsManager) {
return windowsManager.open("file-explorer", { path: this.path }); const { appsConfig } = this.getRoot().systemManager;
const fileExplorer = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
if (fileExplorer != null)
return windowsManager.open(fileExplorer.id, { path: this.path });
} }
/** /**

View file

@ -7,7 +7,7 @@ import { VirtualRoot } from "./virtualRoot";
* Loads default data on the virtual root * Loads default data on the virtual root
*/ */
export function loadDefaultData(systemManager: SystemManager, virtualRoot: VirtualRoot) { export function loadDefaultData(systemManager: SystemManager, virtualRoot: VirtualRoot) {
const { desktopConfig, virtualDriveConfig } = systemManager; const { desktopConfig, virtualDriveConfig, appsConfig } = systemManager;
const linkedPaths: Record<string, string> = {}; const linkedPaths: Record<string, string> = {};
virtualRoot.createFolder("home", (folder) => { virtualRoot.createFolder("home", (folder) => {
@ -15,13 +15,18 @@ export function loadDefaultData(systemManager: SystemManager, virtualRoot: Virtu
folder.setAlias("~") folder.setAlias("~")
.createFolder(".config", (folder) => { .createFolder(".config", (folder) => {
folder.createFile("desktop", "xml", (file) => { folder.createFile("desktop", "xml", (file) => {
file.setSource("/config/desktop.xml"); file.setContent(`<options>
<wallpaper>${desktopConfig.defaultWallpaper}</wallpaper>
<show-icons>true</show-icons>
</options>`);
}).createFile("taskbar", "xml", (file) => { }).createFile("taskbar", "xml", (file) => {
file.setSource("/config/taskbar.xml"); file.setContent(`<options>
<pins>${appsConfig.apps.map(({ id }) => id).join(",")}</pins>
</options>`);
}).createFile("apps", "xml", (file) => { }).createFile("apps", "xml", (file) => {
file.setSource("/config/apps.xml"); file.setContent("<options></options>");
}).createFile("theme", "xml", (file) => { }).createFile("theme", "xml", (file) => {
file.setSource("/config/theme.xml"); file.setContent("<options><theme>0</theme></options>");
}); });
}) })
.createFolder("Pictures", (folder) => { .createFolder("Pictures", (folder) => {

View file

@ -1,9 +1,8 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { DialogBox } from "../../components/modals/dialog-box/DialogBox"; import { DialogBox } from "../../components/modals/dialog-box/DialogBox";
import { DIALOG_CONTENT_TYPES } from "../../constants/modals.const";
import { useWindowedModal } from "./windowedModal"; import { useWindowedModal } from "./windowedModal";
import { ModalProps } from "../../components/modals/ModalView"; import { ModalProps } from "../../components/modals/ModalView";
import { Vector2 } from "../../features"; import { ModalsConfig, Vector2 } from "../../features";
interface AlertParams { interface AlertParams {
title: string; title: string;
@ -25,7 +24,7 @@ export function useAlert() {
Modal: (props: ModalProps) => Modal: (props: ModalProps) =>
<DialogBox {...props}> <DialogBox {...props}>
<p>{text}</p> <p>{text}</p>
<button data-type={DIALOG_CONTENT_TYPES.closeButton}>Ok</button> <button data-type={ModalsConfig.DIALOG_CONTENT_TYPES.CloseButton}>Ok</button>
</DialogBox> </DialogBox>
}); });
}, [openWindowedModal]); }, [openWindowedModal]);

View file

@ -1,5 +1,16 @@
# prozilla-os # prozilla-os
## 1.0.13
### Patch Changes
- Added application roles
- Updated dependencies
- @prozilla-os/file-explorer@1.0.10
- @prozilla-os/text-editor@1.0.3
- @prozilla-os/terminal@1.0.3
- @prozilla-os/core@1.0.13
## 1.0.12 ## 1.0.12
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "prozilla-os", "name": "prozilla-os",
"description": "a React component library written in TypeScript for building web-based operating systems, made by Prozilla.", "description": "a React component library written in TypeScript for building web-based operating systems, made by Prozilla.",
"version": "1.0.12", "version": "1.0.13",
"homepage": "https://os.prozilla.dev", "homepage": "https://os.prozilla.dev",
"author": { "author": {
"name": "Prozilla", "name": "Prozilla",

View file

@ -1,3 +0,0 @@
<options>
<startup></startup>
</options>

View file

@ -1,4 +0,0 @@
<options>
<wallpaper>/assets/wallpapers/vibrant-wallpaper-purple-yellow.png</wallpaper>
<show-icons>true</show-icons>
</options>

View file

@ -1,3 +0,0 @@
<options>
<pins>file-explorer,terminal,settings,media-viewer,browser,text-editor,wordle,ball-maze,minesweeper</pins>
</options>

View file

@ -1,3 +0,0 @@
<options>
<theme>0</theme>
</options>

View file

@ -12,5 +12,5 @@ export const desktopConfig = new DesktopConfig({
"/assets/wallpapers/flame-abstract-wallpaper-orange.png", "/assets/wallpapers/flame-abstract-wallpaper-orange.png",
"/assets/wallpapers/wave-abstract-wallpaper-teal.png", "/assets/wallpapers/wave-abstract-wallpaper-teal.png",
], ],
defaultWallpaper: "/assets/wallpapers/colorful-mesh-gradient-red-green.png" defaultWallpaper: "/assets/wallpapers/abstract-mesh-gradient-orange-red-purple.png"
}); });

View file

@ -30,7 +30,7 @@
"baseUrl": "./", "baseUrl": "./",
"paths": { "paths": {
"prozilla-os": ["packages/prozilla-os/dist/main"], "prozilla-os": ["packages/prozilla-os/dist/main"],
"@prozilla-os/*": ["packages/*/dist/main", "packages/apps/*/dist/main"], "@prozilla-os/*": ["packages/*/dist/main", "packages/*/src/main", "packages/apps/*/dist/main"],
} }
}, },
"include": [ "include": [