Added settings app
This commit is contained in:
parent
3614461cea
commit
f435fd1f89
25 changed files with 318 additions and 113 deletions
|
|
@ -12,9 +12,9 @@ import { JSX } from "react/jsx-runtime";
|
||||||
export interface FileExplorerProps extends WindowProps {
|
export interface FileExplorerProps extends WindowProps {
|
||||||
path?: string;
|
path?: string;
|
||||||
selectorMode?: number;
|
selectorMode?: number;
|
||||||
Footer: FC;
|
Footer?: FC;
|
||||||
onSelectionChange: (params: OnSelectionChangeParams) => void;
|
onSelectionChange?: (params: OnSelectionChangeParams) => void;
|
||||||
onSelectionFinish: Function;
|
onSelectionFinish?: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSelectionChange, onSelectionFinish }: FileExplorerProps) {
|
export function FileExplorer({ app, path: startPath, selectorMode, Footer, onSelectionChange, onSelectionFinish }: FileExplorerProps) {
|
||||||
|
|
|
||||||
72
packages/apps/settings/README.md
Normal file
72
packages/apps/settings/README.md
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<div align="center">
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
<a href="https://os.prozilla.dev/"><img src="https://os.prozilla.dev/assets/logo.svg" height="200" alt="ProzillaOS" /></a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/prozilla-os/ProzillaOS/blob/main/LICENSE.md"><img alt="License" src="https://img.shields.io/github/license/Prozilla/ProzillaOS?style=flat-square&color=FF4D5B&label=License"></a>
|
||||||
|
<a href="https://github.com/prozilla-os/ProzillaOS"><img alt="Stars" src="https://img.shields.io/github/stars/Prozilla/ProzillaOS?style=flat-square&color=FED24C&label=%E2%AD%90"></a>
|
||||||
|
<a href="https://github.com/prozilla-os/ProzillaOS"><img alt="Forks" src="https://img.shields.io/github/forks/Prozilla/ProzillaOS?style=flat-square&color=4D9CFF&label=Forks&logo=github"></a>
|
||||||
|
<a href="https://www.npmjs.com/package/prozilla-os"><img alt="NPM Version" src="https://img.shields.io/npm/v/prozilla-os?logo=npm&style=flat-square&label=prozilla-os&color=FF4D5B"></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
`@prozilla-os/settings` is a ProzillaOS application for configuring settings.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
`@prozilla-os/core` is required to run this application.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install @prozilla-os/core @prozilla-os/settings
|
||||||
|
$ yarn add @prozilla-os/core @prozilla-os/settings
|
||||||
|
$ pnpm add @prozilla-os/core @prozilla-os/settings
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic setup
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Desktop, ModalsView, ProzillaOS, Taskbar, WindowsView, AppsConfig } from "@prozilla-os/core";
|
||||||
|
import { settings } from "@prozilla-os/settings";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<ProzillaOS
|
||||||
|
systemName="Example"
|
||||||
|
tagLine="Powered by ProzillaOS"
|
||||||
|
config={{
|
||||||
|
apps: new AppsConfig({
|
||||||
|
apps: [ settings ]
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Taskbar/>
|
||||||
|
<WindowsView/>
|
||||||
|
<ModalsView/>
|
||||||
|
<Desktop/>
|
||||||
|
</ProzillaOS>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Window options
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- [Website/demo][website]
|
||||||
|
- [GitHub][github]
|
||||||
|
- [npm][npm]
|
||||||
|
- [Ko-fi][ko-fi]
|
||||||
|
|
||||||
|
[website]: https://os.prozilla.dev/settings
|
||||||
|
[github]: https://github.com/prozilla-os/ProzillaOS/tree/convert-to-monorepo/packages/apps/settings
|
||||||
|
[npm]: https://www.npmjs.com/package/@prozilla-os/settings
|
||||||
|
[ko-fi]: https://ko-fi.com/prozilla
|
||||||
51
packages/apps/settings/package.json
Normal file
51
packages/apps/settings/package.json
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
"name": "@prozilla-os/settings",
|
||||||
|
"description": "A settings app for ProzillaOS.",
|
||||||
|
"version": "1.0.11",
|
||||||
|
"homepage": "https://os.prozilla.dev/settings",
|
||||||
|
"author": {
|
||||||
|
"name": "Prozilla",
|
||||||
|
"email": "business@prozilla.dev",
|
||||||
|
"url": "https://prozilla.dev/"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/main.js",
|
||||||
|
"types": "dist/main.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --project tsconfig.build.json && vite build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/prozilla-os/ProzillaOS.git",
|
||||||
|
"directory": "packages/apps/settings"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
|
"@prozilla-os/core": "workspace:*",
|
||||||
|
"@prozilla-os/file-explorer": "workspace:*",
|
||||||
|
"react": "^18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@prozilla-os/shared": "workspace:*",
|
||||||
|
"@types/node": "^20.14.5",
|
||||||
|
"@types/react": "^18.3.3",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.7.0",
|
||||||
|
"typescript": "^5.4.5",
|
||||||
|
"vite": "^5.3.1",
|
||||||
|
"vite-plugin-dts": "^3.9.1",
|
||||||
|
"vite-plugin-lib-inject-css": "^2.1.1"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"sideEffects": [
|
||||||
|
"**/*.css"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
import styles from "./Settings.module.css";
|
import styles from "./Settings.module.css";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faCircleInfo, faHardDrive, faPalette, faShapes } from "@fortawesome/free-solid-svg-icons";
|
import { faCircleInfo, faHardDrive, faPalette, faShapes } from "@fortawesome/free-solid-svg-icons";
|
||||||
import utilStyles from "../../../styles/utils.module.css";
|
|
||||||
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
|
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
|
||||||
import { AppearanceSettings } from "./tabs/AppearanceSettings";
|
import { AppearanceSettings } from "./tabs/AppearanceSettings";
|
||||||
import { AboutSettings } from "./tabs/AboutSettings";
|
import { AboutSettings } from "./tabs/AboutSettings";
|
||||||
import { StorageTab } from "./tabs/StorageSettings";
|
import { StorageTab } from "./tabs/StorageSettings";
|
||||||
import { AppsSettings } from "./tabs/AppsSettings";
|
import { AppsSettings } from "./tabs/AppsSettings";
|
||||||
import { WindowProps } from "../../windows/WindowView";
|
import { utilStyles, WindowProps } from "@prozilla-os/core";
|
||||||
|
|
||||||
interface SettingsProps extends WindowProps {
|
export interface SettingsProps extends WindowProps {
|
||||||
tab?: number;
|
tab?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
import { Button } from "../../../_utils/button/Button";
|
|
||||||
import styles from "../Settings.module.css";
|
import styles from "../Settings.module.css";
|
||||||
import utilStyles from "../../../../styles/utils.module.css";
|
import { Button, useSystemManager, useVirtualRoot, useWindowsManager, utilStyles, Vector2 } from "@prozilla-os/core";
|
||||||
import { Vector2 } from "../../../../features/math/vector2";
|
|
||||||
import { useWindowsManager } from "../../../../hooks/windows/windowsManagerContext";
|
|
||||||
import { useVirtualRoot } from "../../../../hooks/virtual-drive/virtualRootContext";
|
|
||||||
import { NAME } from "../../../../config/branding.config";
|
|
||||||
|
|
||||||
export function AboutSettings() {
|
export function AboutSettings() {
|
||||||
|
const { systemName } = useSystemManager();
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
|
|
||||||
return <div className={styles.Option}>
|
return <div className={styles.Option}>
|
||||||
<p className={styles.Label}>About {NAME}</p>
|
<p className={styles.Label}>About {systemName}</p>
|
||||||
<p className={utilStyles.TextLight}>{NAME} is a web-based operating system inspired by Ubuntu Linux and Windows made with React.js by Prozilla.</p>
|
<p className={utilStyles.TextLight}>{systemName} is a web-based operating system inspired by Ubuntu Linux and Windows made with React.js by Prozilla.</p>
|
||||||
<div className={styles.ButtonGroup}>
|
<div className={styles.ButtonGroup}>
|
||||||
<Button
|
<Button
|
||||||
className={`${styles.Button} ${utilStyles.TextBold}`}
|
className={`${styles.Button} ${utilStyles.TextBold}`}
|
||||||
|
|
@ -1,17 +1,8 @@
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { AppsManager } from "../../../../features/apps/appsManager";
|
|
||||||
import { ImagePreview } from "../../file-explorer/directory-list/ImagePreview";
|
|
||||||
import styles from "../Settings.module.css";
|
import styles from "../Settings.module.css";
|
||||||
import { faEllipsisVertical, faThumbTack } from "@fortawesome/free-solid-svg-icons";
|
import { faEllipsisVertical, faThumbTack } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { useWindowsManager } from "../../../../hooks/windows/windowsManagerContext";
|
|
||||||
import { useContextMenu } from "../../../../hooks/modals/contextMenu";
|
|
||||||
import { Actions } from "../../../actions/Actions";
|
|
||||||
import { ClickAction } from "../../../actions/actions/ClickAction";
|
|
||||||
import { removeFromArray } from "../../../../features/_utils/array.utils";
|
|
||||||
import { useSettingsManager } from "../../../../hooks/settings/settingsManagerContext";
|
|
||||||
import { SettingsManager } from "../../../../features/settings/settingsManager";
|
|
||||||
import { App } from "../../../../features/apps/app";
|
|
||||||
import { MouseEventHandler } from "react";
|
import { MouseEventHandler } from "react";
|
||||||
|
import { Actions, App, ClickAction, ImagePreview, removeFromArray, SettingsManager, useContextMenu, useSettingsManager, useWindowsManager } from "@prozilla-os/core";
|
||||||
|
|
||||||
interface AppOptionProps {
|
interface AppOptionProps {
|
||||||
app: App;
|
app: App;
|
||||||
|
|
@ -27,7 +18,7 @@ export function AppOption({ app, pins, setPins: _setPins }: AppOptionProps) {
|
||||||
|
|
||||||
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
<ClickAction label="Launch" icon={AppsManager.getAppIconUrl(app.id)} onTrigger={() => windowsManager?.open(app.id)}/>
|
<ClickAction label="Launch" icon={app.iconUrl as string | undefined} onTrigger={() => windowsManager?.open(app.id)}/>
|
||||||
<ClickAction label={isPinned ? "Unpin from taskbar" : "Pin to taskbar"} icon={faThumbTack} onTrigger={() => {
|
<ClickAction label={isPinned ? "Unpin from taskbar" : "Pin to taskbar"} icon={faThumbTack} onTrigger={() => {
|
||||||
const newPins = [...pins];
|
const newPins = [...pins];
|
||||||
if (isPinned) {
|
if (isPinned) {
|
||||||
|
|
@ -44,7 +35,7 @@ export function AppOption({ app, pins, setPins: _setPins }: AppOptionProps) {
|
||||||
|
|
||||||
return <div className={`${styles.Option} ${styles.OptionHorizontal}`}>
|
return <div className={`${styles.Option} ${styles.OptionHorizontal}`}>
|
||||||
<span className={styles.Label}>
|
<span className={styles.Label}>
|
||||||
<ImagePreview className={styles.Icon} source={AppsManager.getAppIconUrl(app.id)}/>
|
<ImagePreview className={styles.Icon} source={app.iconUrl as string}/>
|
||||||
{app.name}
|
{app.name}
|
||||||
</span>
|
</span>
|
||||||
<button className={styles.IconButton} onClick={onContextMenu as unknown as MouseEventHandler}>
|
<button className={styles.IconButton} onClick={onContextMenu as unknown as MouseEventHandler}>
|
||||||
|
|
@ -1,21 +1,11 @@
|
||||||
import { ChangeEventHandler, useEffect, useState } from "react";
|
import { ChangeEventHandler, useEffect, useState } from "react";
|
||||||
import { SettingsManager } from "../../../../features/settings/settingsManager";
|
|
||||||
import styles from "../Settings.module.css";
|
import styles from "../Settings.module.css";
|
||||||
import utilStyles from "../../../../styles/utils.module.css";
|
import { Button, SettingsManager, THEMES, useSettingsManager, useSystemManager, useVirtualRoot, useWindowedModal, utilStyles, IMAGE_EXTENSIONS, VirtualFile, VirtualFolder } from "@prozilla-os/core";
|
||||||
import { useVirtualRoot } from "../../../../hooks/virtual-drive/virtualRootContext";
|
import { FileSelectorMode, fileExplorer } from "@prozilla-os/file-explorer";
|
||||||
import { useSettingsManager } from "../../../../hooks/settings/settingsManagerContext";
|
import { WALLPAPERS_PATH } from "../../constants/settings.const";
|
||||||
import { WALLPAPERS_PATH } from "../../../../config/apps/settings.config";
|
|
||||||
import { useWindowedModal } from "../../../../hooks/modals/windowedModal";
|
|
||||||
import { Button } from "../../../_utils/button/Button";
|
|
||||||
import { FileSelector } from "../../../modals/file-selector/FileSelector";
|
|
||||||
import { SELECTOR_MODE } from "../../../../config/apps/fileExplorer.config";
|
|
||||||
import { DEFAULT_FILE_SELECTOR_SIZE } from "../../../../config/modals.config";
|
|
||||||
import { IMAGE_FORMATS } from "../../../../config/apps/mediaViewer.config";
|
|
||||||
import { VirtualFile } from "../../../../features/virtual-drive/file";
|
|
||||||
import { VirtualFolder } from "../../../../features/virtual-drive/folder/virtualFolder";
|
|
||||||
import { THEMES } from "../../../../config/themes.config";
|
|
||||||
|
|
||||||
export function AppearanceSettings() {
|
export function AppearanceSettings() {
|
||||||
|
const { modalsConfig } = useSystemManager();
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
const [theme, setTheme] = useState(0);
|
const [theme, setTheme] = useState(0);
|
||||||
|
|
@ -56,13 +46,13 @@ export function AppearanceSettings() {
|
||||||
className={`${styles.Button} ${utilStyles.TextBold}`}
|
className={`${styles.Button} ${utilStyles.TextBold}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openWindowedModal({
|
openWindowedModal({
|
||||||
size: DEFAULT_FILE_SELECTOR_SIZE,
|
size: modalsConfig.defaultFileSelectorSize,
|
||||||
Modal: (props: object) => <FileSelector
|
Modal: (props: object) => <fileExplorer.WindowContent
|
||||||
type={SELECTOR_MODE.SINGLE}
|
type={FileSelectorMode.Single}
|
||||||
allowedFormats={IMAGE_FORMATS}
|
allowedFormats={IMAGE_EXTENSIONS}
|
||||||
onFinish={(file) => {
|
onFinish={(file: VirtualFile) => {
|
||||||
if ((file as VirtualFile).source != null)
|
if ((file).source != null)
|
||||||
void desktopSettings?.set("wallpaper", (file as VirtualFile).source as string);
|
void desktopSettings?.set("wallpaper", file.source);
|
||||||
}}
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import styles from "../Settings.module.css";
|
import styles from "../Settings.module.css";
|
||||||
import { AppsManager } from "../../../../features/apps/appsManager";
|
|
||||||
import { useSettingsManager } from "../../../../hooks/settings/settingsManagerContext";
|
|
||||||
import { SettingsManager } from "../../../../features/settings/settingsManager";
|
|
||||||
import { AppOption } from "./AppOption";
|
import { AppOption } from "./AppOption";
|
||||||
|
import { SettingsManager, useSettingsManager, useSystemManager } from "@prozilla-os/core";
|
||||||
|
|
||||||
export function AppsSettings() {
|
export function AppsSettings() {
|
||||||
|
const { appsConfig } = useSystemManager();
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
const [pins, setPins] = useState<string[]>([]);
|
const [pins, setPins] = useState<string[]>([]);
|
||||||
|
|
||||||
|
|
@ -18,7 +17,7 @@ export function AppsSettings() {
|
||||||
|
|
||||||
return <div className={`${styles.Option} ${styles.OptionList}`}>
|
return <div className={`${styles.Option} ${styles.OptionList}`}>
|
||||||
<p className={styles.Label}>Apps</p>
|
<p className={styles.Label}>Apps</p>
|
||||||
{AppsManager.APPS.sort((a, b) =>
|
{appsConfig.apps.sort((a, b) =>
|
||||||
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
|
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
|
||||||
).map((app) =>
|
).map((app) =>
|
||||||
<AppOption key={app.id} app={app} pins={pins} setPins={setPins}/>
|
<AppOption key={app.id} app={app} pins={pins} setPins={setPins}/>
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
import styles from "../Settings.module.css";
|
import styles from "../Settings.module.css";
|
||||||
import utilStyles from "../../../../styles/utils.module.css";
|
import { Button, ProgressBar, round, StorageManager, useVirtualRoot, utilStyles } from "@prozilla-os/core";
|
||||||
import { ProgressBar } from "../../../_utils/progress-bar/ProgressBar";
|
|
||||||
import { Button } from "../../../_utils/button/Button";
|
|
||||||
import { useVirtualRoot } from "../../../../hooks/virtual-drive/virtualRootContext";
|
|
||||||
import { StorageManager } from "../../../../features/storage/storageManager";
|
|
||||||
import { round } from "../../../../features/_utils/math.utils";
|
|
||||||
|
|
||||||
export function StorageTab() {
|
export function StorageTab() {
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
8
packages/apps/settings/src/main.ts
Normal file
8
packages/apps/settings/src/main.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { App, AppsConfig } from "@prozilla-os/core";
|
||||||
|
import { Settings, SettingsProps } from "./components/Settings";
|
||||||
|
|
||||||
|
const settings = new App<SettingsProps>("Settings", "settings", Settings)
|
||||||
|
.setIconUrl("https://os.prozilla.dev/assets/apps/icons/settings.svg")
|
||||||
|
.setRole(AppsConfig.APP_ROLES.Settings);
|
||||||
|
|
||||||
|
export { settings };
|
||||||
10
packages/apps/settings/tsconfig.build.json
Normal file
10
packages/apps/settings/tsconfig.build.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@prozilla-os/core": ["packages/core/dist/main"],
|
||||||
|
"@prozilla-os/shared": ["packages/shared/dist/main"],
|
||||||
|
"@prozilla-os/file-explorer": ["packages/apps/file-explorer/dist/main"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/apps/settings/tsconfig.json
Normal file
18
packages/apps/settings/tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "../../..",
|
||||||
|
"composite": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"declaration": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"noEmit": false,
|
||||||
|
"paths": {
|
||||||
|
"@prozilla-os/core": ["./node_modules/@prozilla-os/core/src/main"],
|
||||||
|
"@prozilla-os/shared": ["./node_modules/@prozilla-os/shared/src/main"],
|
||||||
|
"@prozilla-os/file-explorer": ["./node_modules/@prozilla-os/file-explorer/src/main"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src", "vite.config.ts"],
|
||||||
|
"exclude": ["node_modules"],
|
||||||
|
}
|
||||||
6
packages/apps/settings/vite.config.ts
Normal file
6
packages/apps/settings/vite.config.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
import { appViteConfig } from "@prozilla-os/shared";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
...appViteConfig(__dirname, "src/main.ts")
|
||||||
|
});
|
||||||
|
|
@ -10,8 +10,8 @@ import { formatError } from "../core/_utils/terminal.utils";
|
||||||
import { CommandsManager } from "../core/commands";
|
import { CommandsManager } from "../core/commands";
|
||||||
|
|
||||||
export interface TerminalProps extends WindowProps {
|
export interface TerminalProps extends WindowProps {
|
||||||
path: string;
|
path?: string;
|
||||||
input: string;
|
input?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HistoryEntry {
|
interface HistoryEntry {
|
||||||
|
|
|
||||||
|
|
@ -31,8 +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 fileExplorerApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
|
||||||
const terminal = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Terminal);
|
const terminalApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Terminal);
|
||||||
|
const settingsApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Settings);
|
||||||
|
|
||||||
const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) =>
|
const { onContextMenu, ShortcutsListener } = useContextMenu({ Actions: (props) =>
|
||||||
<Actions {...props}>
|
<Actions {...props}>
|
||||||
|
|
@ -81,18 +82,20 @@ export const Desktop = memo(() => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ClickAction label="Change appearance" icon={faPaintBrush} onTrigger={() => {
|
{settingsApp != null &&
|
||||||
windowsManager?.open("settings", { tab: 2 });
|
<ClickAction label="Change appearance" icon={faPaintBrush} onTrigger={() => {
|
||||||
}}/>
|
windowsManager?.open(settingsApp.id, { tab: 2 });
|
||||||
<Divider/>
|
|
||||||
{fileExplorer != null &&
|
|
||||||
<ClickAction label={`Open in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={() => {
|
|
||||||
windowsManager?.open(fileExplorer.id, { path: directory?.path });
|
|
||||||
}}/>
|
}}/>
|
||||||
}
|
}
|
||||||
{terminal != null &&
|
<Divider/>
|
||||||
<ClickAction label={`Open in ${terminal.name}`} icon={terminal.iconUrl as string | undefined} onTrigger={() => {
|
{fileExplorerApp != null &&
|
||||||
windowsManager?.open(terminal.id, { path: directory?.path });
|
<ClickAction label={`Open in ${fileExplorerApp.name}`} icon={fileExplorerApp.iconUrl as string | undefined} onTrigger={() => {
|
||||||
|
windowsManager?.open(fileExplorerApp.id, { path: directory?.path });
|
||||||
|
}}/>
|
||||||
|
}
|
||||||
|
{terminalApp != null &&
|
||||||
|
<ClickAction label={`Open in ${terminalApp.name}`} icon={terminalApp.iconUrl as string | undefined} onTrigger={() => {
|
||||||
|
windowsManager?.open(terminalApp.id, { path: directory?.path });
|
||||||
}}/>
|
}}/>
|
||||||
}
|
}
|
||||||
<Divider/>
|
<Divider/>
|
||||||
|
|
@ -109,8 +112,8 @@ 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);
|
||||||
}}/>
|
}}/>
|
||||||
{fileExplorer != null &&
|
{fileExplorerApp != null &&
|
||||||
<ClickAction label={`Reveal in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={(event, file) => {
|
<ClickAction label={`Reveal in ${fileExplorerApp.name}`} icon={fileExplorerApp.iconUrl as string | undefined} onTrigger={(event, file) => {
|
||||||
if (windowsManager != null) (file as VirtualFile).parent?.open(windowsManager);
|
if (windowsManager != null) (file as VirtualFile).parent?.open(windowsManager);
|
||||||
}}/>
|
}}/>
|
||||||
}
|
}
|
||||||
|
|
@ -124,13 +127,13 @@ 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);
|
||||||
}}/>
|
}}/>
|
||||||
{fileExplorer != null &&
|
{fileExplorerApp != null &&
|
||||||
<ClickAction label={`Open in ${fileExplorer.name}`} icon={fileExplorer.iconUrl as string | undefined} onTrigger={(event, folder) => {
|
<ClickAction label={`Open in ${fileExplorerApp.name}`} icon={fileExplorerApp.iconUrl as string | undefined} onTrigger={(event, folder) => {
|
||||||
windowsManager?.open(fileExplorer.id, { path: (folder as VirtualFolder).path });
|
windowsManager?.open(fileExplorerApp.id, { path: (folder as VirtualFolder).path });
|
||||||
}}/>
|
}}/>
|
||||||
}
|
}
|
||||||
{terminal != null &&
|
{terminalApp != null &&
|
||||||
<ClickAction label={`Open in ${terminal.name}`} icon={terminal.iconUrl as string | undefined} onTrigger={(event, folder) => {
|
<ClickAction label={`Open in ${terminalApp.name}`} icon={terminalApp.iconUrl as string | undefined} onTrigger={(event, folder) => {
|
||||||
if (windowsManager != null) (folder as VirtualFolder).parent?.open(windowsManager);
|
if (windowsManager != null) (folder as VirtualFolder).parent?.open(windowsManager);
|
||||||
}}/>
|
}}/>
|
||||||
}
|
}
|
||||||
|
|
@ -195,8 +198,8 @@ export const Desktop = memo(() => {
|
||||||
windowsManager?.openFile(file, options);
|
windowsManager?.openFile(file, options);
|
||||||
}}
|
}}
|
||||||
onOpenFolder={(event, folder) => {
|
onOpenFolder={(event, folder) => {
|
||||||
if (fileExplorer != null) {
|
if (fileExplorerApp != null) {
|
||||||
windowsManager?.open(fileExplorer.id, {
|
windowsManager?.open(fileExplorerApp.id, {
|
||||||
path: (folder as VirtualFolderLink).linkedPath ?? folder.path
|
path: (folder as VirtualFolderLink).linkedPath ?? folder.path
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { CSSProperties, memo, MouseEvent, MutableRefObject, ReactEventHandler, UIEventHandler, useEffect, useRef, useState } from "react";
|
import { CSSProperties, memo, MouseEvent, MutableRefObject, ReactEventHandler, UIEventHandler, useEffect, useRef, useState } from "react";
|
||||||
import styles from "./Taskbar.module.css";
|
import styles from "./Taskbar.module.css";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faCog, faSearch } from "@fortawesome/free-solid-svg-icons";
|
import { faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { ReactSVG } from "react-svg";
|
import { ReactSVG } from "react-svg";
|
||||||
import { HomeMenu } from "./menus/HomeMenu";
|
import { HomeMenu } from "./menus/HomeMenu";
|
||||||
import { OutsideClickListener } from "../../hooks/_utils/outsideClick";
|
import { OutsideClickListener } from "../../hooks/_utils/outsideClick";
|
||||||
|
|
@ -19,7 +19,7 @@ import { ZIndexManager } from "../../features/z-index/zIndexManager";
|
||||||
import { useZIndex } from "../../hooks/z-index/zIndex";
|
import { useZIndex } from "../../hooks/z-index/zIndex";
|
||||||
import { Battery, Calendar, Network, Volume } from "./indicators";
|
import { Battery, Calendar, Network, Volume } from "./indicators";
|
||||||
import { useSystemManager } from "../../hooks";
|
import { useSystemManager } from "../../hooks";
|
||||||
import { App } from "../../features";
|
import { App, AppsConfig } from "../../features";
|
||||||
|
|
||||||
export const Taskbar = memo(() => {
|
export const Taskbar = memo(() => {
|
||||||
const { taskbarConfig, appsConfig } = useSystemManager();
|
const { taskbarConfig, appsConfig } = useSystemManager();
|
||||||
|
|
@ -38,16 +38,21 @@ export const Taskbar = memo(() => {
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const windowsManager = useWindowsManager();
|
const windowsManager = useWindowsManager();
|
||||||
const windows = useWindows();
|
const windows = useWindows();
|
||||||
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
|
||||||
<Actions avoidTaskbar={false} {...props}>
|
|
||||||
<ClickAction label={`Open ${"Settings"}`} icon={faCog} onTrigger={() => {
|
|
||||||
windowsManager?.open("settings");
|
|
||||||
}}/>
|
|
||||||
</Actions>
|
|
||||||
});
|
|
||||||
const [apps, setApps] = useState<App[]>([]);
|
const [apps, setApps] = useState<App[]>([]);
|
||||||
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.TASKBAR, index: 0 });
|
const zIndex = useZIndex({ groupIndex: ZIndexManager.GROUPS.TASKBAR, index: 0 });
|
||||||
|
|
||||||
|
const settingsApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Settings);
|
||||||
|
|
||||||
|
const { onContextMenu } = useContextMenu({ Actions: (props) =>
|
||||||
|
<Actions avoidTaskbar={false} {...props}>
|
||||||
|
{settingsApp != null &&
|
||||||
|
<ClickAction label={`Open ${settingsApp.name}`} icon={settingsApp.iconUrl as string | undefined} onTrigger={() => {
|
||||||
|
windowsManager?.open(settingsApp.id);
|
||||||
|
}}/>
|
||||||
|
}
|
||||||
|
</Actions>
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const settings = settingsManager?.getSettings(SettingsManager.VIRTUAL_PATHS.taskbar);
|
const settings = settingsManager?.getSettings(SettingsManager.VIRTUAL_PATHS.taskbar);
|
||||||
void settings?.get("pins", (pinList: string) => {
|
void settings?.get("pins", (pinList: string) => {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,9 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) {
|
||||||
|
|
||||||
useKeyboardListener({ onKeyDown, onKeyUp });
|
useKeyboardListener({ onKeyDown, onKeyUp });
|
||||||
|
|
||||||
const fileExplorer = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
|
const fileExplorerApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.FileExplorer);
|
||||||
|
const settingsApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.Settings);
|
||||||
|
const textEditorApp = appsConfig.getAppByRole(AppsConfig.APP_ROLES.TextEditor);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames.join(" ")}>
|
<div className={classNames.join(" ")}>
|
||||||
|
|
@ -65,35 +67,39 @@ export function HomeMenu({ active, setActive, search }: HomeMenuProps) {
|
||||||
<FontAwesomeIcon icon={faPowerOff}/>
|
<FontAwesomeIcon icon={faPowerOff}/>
|
||||||
<p className={utilStyles.TextRegular}>Shut down</p>
|
<p className={utilStyles.TextRegular}>Shut down</p>
|
||||||
</button>
|
</button>
|
||||||
<button tabIndex={tabIndex} onClick={() => {
|
{settingsApp != null &&
|
||||||
setActive(false);
|
|
||||||
windowsManager?.open("settings");
|
|
||||||
}}>
|
|
||||||
<FontAwesomeIcon icon={faGear}/>
|
|
||||||
<p className={utilStyles.TextRegular}>Settings</p>
|
|
||||||
</button>
|
|
||||||
<button tabIndex={tabIndex} onClick={() => {
|
|
||||||
setActive(false);
|
|
||||||
windowsManager?.open("text-editor", {
|
|
||||||
mode: "view",
|
|
||||||
file: virtualRoot?.navigate("~/Documents/Info.md"),
|
|
||||||
size: new Vector2(575, 675),
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
<FontAwesomeIcon icon={faCircleInfo}/>
|
|
||||||
<p className={utilStyles.TextRegular}>Info</p>
|
|
||||||
</button>
|
|
||||||
{fileExplorer != null && <>
|
|
||||||
<button tabIndex={tabIndex} onClick={() => {
|
<button tabIndex={tabIndex} onClick={() => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
windowsManager?.open(fileExplorer.id, { path: "~/Pictures" });
|
windowsManager?.open("settings");
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faGear}/>
|
||||||
|
<p className={utilStyles.TextRegular}>Settings</p>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
{textEditorApp != null &&
|
||||||
|
<button tabIndex={tabIndex} onClick={() => {
|
||||||
|
setActive(false);
|
||||||
|
windowsManager?.open("text-editor", {
|
||||||
|
mode: "view",
|
||||||
|
file: virtualRoot?.navigate("~/Documents/Info.md"),
|
||||||
|
size: new Vector2(575, 675),
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faCircleInfo}/>
|
||||||
|
<p className={utilStyles.TextRegular}>Info</p>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
{fileExplorerApp != null && <>
|
||||||
|
<button tabIndex={tabIndex} onClick={() => {
|
||||||
|
setActive(false);
|
||||||
|
windowsManager?.open(fileExplorerApp.id, { path: "~/Pictures" });
|
||||||
}}>
|
}}>
|
||||||
<FontAwesomeIcon icon={faImage}/>
|
<FontAwesomeIcon icon={faImage}/>
|
||||||
<p className={utilStyles.TextRegular}>Images</p>
|
<p className={utilStyles.TextRegular}>Images</p>
|
||||||
</button>
|
</button>
|
||||||
<button tabIndex={tabIndex} onClick={() => {
|
<button tabIndex={tabIndex} onClick={() => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
windowsManager?.open(fileExplorer.id, { path: "~/Documents" }); }
|
windowsManager?.open(fileExplorerApp.id, { path: "~/Documents" }); }
|
||||||
}>
|
}>
|
||||||
<FontAwesomeIcon icon={faFileLines}/>
|
<FontAwesomeIcon icon={faFileLines}/>
|
||||||
<p className={utilStyles.TextRegular}>Documents</p>
|
<p className={utilStyles.TextRegular}>Documents</p>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export { CODE_EXTENSIONS } from "./virtualDrive.const";
|
export { CODE_EXTENSIONS, IMAGE_EXTENSIONS } from "./virtualDrive.const";
|
||||||
export { ANSI } from "./utils.const";
|
export { ANSI } from "./utils.const";
|
||||||
export { THEMES } from "./themes.const";
|
export { THEMES } from "./themes.const";
|
||||||
|
|
@ -16,6 +16,7 @@ export class AppsConfig {
|
||||||
FileExplorer: "file-explorer",
|
FileExplorer: "file-explorer",
|
||||||
Terminal: "terminal",
|
Terminal: "terminal",
|
||||||
TextEditor: "text-editor",
|
TextEditor: "text-editor",
|
||||||
|
Settings: "settings"
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(options: OptionalInterface<AppsConfigOptions> = {}) {
|
constructor(options: OptionalInterface<AppsConfigOptions> = {}) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@prozilla-os/core": "workspace:*",
|
"@prozilla-os/core": "workspace:*",
|
||||||
"@prozilla-os/file-explorer": "workspace:*",
|
"@prozilla-os/file-explorer": "workspace:*",
|
||||||
|
"@prozilla-os/settings": "workspace:^",
|
||||||
"@prozilla-os/terminal": "workspace:*",
|
"@prozilla-os/terminal": "workspace:*",
|
||||||
"@prozilla-os/text-editor": "workspace:*",
|
"@prozilla-os/text-editor": "workspace:*",
|
||||||
"react-ga4": "^2.1.0"
|
"react-ga4": "^2.1.0"
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ export * from "@prozilla-os/core";
|
||||||
export * from "@prozilla-os/file-explorer";
|
export * from "@prozilla-os/file-explorer";
|
||||||
export * from "@prozilla-os/terminal";
|
export * from "@prozilla-os/terminal";
|
||||||
export * from "@prozilla-os/text-editor";
|
export * from "@prozilla-os/text-editor";
|
||||||
|
export * from "@prozilla-os/settings";
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,52 @@ importers:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 2.1.1(vite@5.3.1(@types/node@20.14.6)(less@4.2.0))
|
version: 2.1.1(vite@5.3.1(@types/node@20.14.6)(less@4.2.0))
|
||||||
|
|
||||||
|
packages/apps/settings:
|
||||||
|
dependencies:
|
||||||
|
'@fortawesome/fontawesome-svg-core':
|
||||||
|
specifier: ^6.5.2
|
||||||
|
version: 6.5.2
|
||||||
|
'@fortawesome/free-solid-svg-icons':
|
||||||
|
specifier: ^6.5.2
|
||||||
|
version: 6.5.2
|
||||||
|
'@fortawesome/react-fontawesome':
|
||||||
|
specifier: ^0.2.2
|
||||||
|
version: 0.2.2(@fortawesome/fontawesome-svg-core@6.5.2)(react@18.3.1)
|
||||||
|
'@prozilla-os/core':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../core
|
||||||
|
'@prozilla-os/file-explorer':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../file-explorer
|
||||||
|
react:
|
||||||
|
specifier: ^18.3.1
|
||||||
|
version: 18.3.1
|
||||||
|
devDependencies:
|
||||||
|
'@prozilla-os/shared':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../shared
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.14.5
|
||||||
|
version: 20.14.6
|
||||||
|
'@types/react':
|
||||||
|
specifier: ^18.3.3
|
||||||
|
version: 18.3.3
|
||||||
|
'@vitejs/plugin-react-swc':
|
||||||
|
specifier: ^3.7.0
|
||||||
|
version: 3.7.0(vite@5.3.1(@types/node@20.14.6)(less@4.2.0))
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.4.5
|
||||||
|
version: 5.4.5
|
||||||
|
vite:
|
||||||
|
specifier: ^5.3.1
|
||||||
|
version: 5.3.1(@types/node@20.14.6)(less@4.2.0)
|
||||||
|
vite-plugin-dts:
|
||||||
|
specifier: ^3.9.1
|
||||||
|
version: 3.9.1(@types/node@20.14.6)(rollup@4.18.0)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.6)(less@4.2.0))
|
||||||
|
vite-plugin-lib-inject-css:
|
||||||
|
specifier: ^2.1.1
|
||||||
|
version: 2.1.1(vite@5.3.1(@types/node@20.14.6)(less@4.2.0))
|
||||||
|
|
||||||
packages/apps/terminal:
|
packages/apps/terminal:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prozilla-os/core':
|
'@prozilla-os/core':
|
||||||
|
|
@ -289,6 +335,9 @@ importers:
|
||||||
'@prozilla-os/file-explorer':
|
'@prozilla-os/file-explorer':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../apps/file-explorer
|
version: link:../apps/file-explorer
|
||||||
|
'@prozilla-os/settings':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../apps/settings
|
||||||
'@prozilla-os/terminal':
|
'@prozilla-os/terminal':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../apps/terminal
|
version: link:../apps/terminal
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { AppsConfig, fileExplorer, terminal, textEditor } from "prozilla-os";
|
import { AppsConfig, fileExplorer, settings, terminal, textEditor } from "prozilla-os";
|
||||||
|
import { NAME } from "./branding.config";
|
||||||
|
|
||||||
export const appsConfig = new AppsConfig({
|
export const appsConfig = new AppsConfig({
|
||||||
apps: [
|
apps: [
|
||||||
|
|
@ -11,5 +12,8 @@ export const appsConfig = new AppsConfig({
|
||||||
textEditor.setName("Notes")
|
textEditor.setName("Notes")
|
||||||
.setDescription("Text editor for reading and writing text documents in a virtual file system using ProzillaOS.")
|
.setDescription("Text editor for reading and writing text documents in a virtual file system using ProzillaOS.")
|
||||||
.setIconUrl("/assets/apps/icons/text-editor.svg"),
|
.setIconUrl("/assets/apps/icons/text-editor.svg"),
|
||||||
|
settings.setName("Settings")
|
||||||
|
.setDescription(`Configure ${NAME}'s settings and customize your experience.`)
|
||||||
|
.setIconUrl("/assets/apps/icons/settings.svg"),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
Loading…
Reference in a new issue