From 219e712e9f2b2049d12c5a5e30ccdc1de3f45cf6 Mon Sep 17 00:00:00 2001 From: Prozilla Date: Tue, 15 Aug 2023 12:58:58 +0200 Subject: [PATCH] Refactored settings app --- package-lock.json | 21 ++ package.json | 1 + src/App.jsx | 6 +- .../applications/settings/AboutSettings.jsx | 42 ++++ .../settings/AppearanceSettings.jsx | 42 ++++ .../applications/settings/Settings.jsx | 181 +++--------------- .../applications/settings/Settings.module.css | 22 ++- .../applications/settings/StorageSettings.jsx | 38 ++++ src/components/desktop/Desktop.jsx | 4 +- src/hooks/settings/SettingsContext.js | 4 +- src/styles/global.css | 2 +- 11 files changed, 197 insertions(+), 166 deletions(-) create mode 100644 src/components/applications/settings/AboutSettings.jsx create mode 100644 src/components/applications/settings/AppearanceSettings.jsx create mode 100644 src/components/applications/settings/StorageSettings.jsx diff --git a/package-lock.json b/package-lock.json index 11c12ba..0813e75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "react-draggable": "^4.4.5", "react-scripts": "5.0.1", "react-svg": "^16.1.18", + "react-tabs": "^6.0.2", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -14960,6 +14961,26 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-tabs": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", + "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", + "dependencies": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/react-tabs/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 0cb9d9a..e0433b6 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react-draggable": "^4.4.5", "react-scripts": "5.0.1", "react-svg": "^16.1.18", + "react-tabs": "^6.0.2", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.jsx b/src/App.jsx index b704074..7a5cb83 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,7 +4,7 @@ import { WindowsManagerProvider } from "./hooks/windows/WindowsManagerContext.js import { WindowsView } from "./components/windows/WindowsView.jsx"; import { VirtualRootProvider } from "./hooks/virtual-drive/VirtualRootContext.js"; import { Desktop } from "./components/desktop/Desktop.jsx"; -import { SettingsProvider } from "./hooks/settings/SettingsContext.js"; +import { SettingsManagerProvider } from "./hooks/settings/SettingsContext.js"; import { ModalsView } from "./components/modals/ModalsView.jsx"; import { useEffect } from "react"; @@ -24,14 +24,14 @@ function App() { return ( - +
-
+
); diff --git a/src/components/applications/settings/AboutSettings.jsx b/src/components/applications/settings/AboutSettings.jsx new file mode 100644 index 0000000..ece35ff --- /dev/null +++ b/src/components/applications/settings/AboutSettings.jsx @@ -0,0 +1,42 @@ +import { Button } from "../../utils/Button.jsx"; +import styles from "./Settings.module.css"; +import utilStyles from "../../../styles/utils.module.css"; +import Vector2 from "../../../features/math/vector2.js"; +import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.js"; +import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js"; + +export function AboutSettings() { + const windowsManager = useWindowsManager(); + const virtualRoot = useVirtualRoot(); + + return (<> +
+

About ProzillaOS

+

ProzillaOS is a web-based operating system inspired by Ubuntu Linux and Windows made with React.js by Prozilla.

+
+ + +
+
+ ); +} \ No newline at end of file diff --git a/src/components/applications/settings/AppearanceSettings.jsx b/src/components/applications/settings/AppearanceSettings.jsx new file mode 100644 index 0000000..be6fa9f --- /dev/null +++ b/src/components/applications/settings/AppearanceSettings.jsx @@ -0,0 +1,42 @@ +import { useEffect, useState } from "react"; +import { SettingsManager } from "../../../features/settings/settings.js"; +import styles from "./Settings.module.css"; +import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js"; +import { useSettingsManager } from "../../../hooks/settings/SettingsContext.js"; + +export function AppearanceSettings() { + const virtualRoot = useVirtualRoot(); + const settingsManager = useSettingsManager(); + const [wallpaper, setWallpaper] = useState(null); + const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop); + + useEffect(() => { + settings.get("wallpaper", setWallpaper); + }, [settings]); + + const onChange = (event) => { + const value = event.target.value; + settings.set("wallpaper", value); + }; + + return (<> +
+

Wallpaper

+
+ {virtualRoot.navigate("~/Images")?.getFiles()?.map(({ id, source }) => + + )} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/applications/settings/Settings.jsx b/src/components/applications/settings/Settings.jsx index a2828e9..055d8f0 100644 --- a/src/components/applications/settings/Settings.jsx +++ b/src/components/applications/settings/Settings.jsx @@ -1,168 +1,47 @@ -import { useEffect, useState } from "react"; import styles from "./Settings.module.css"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCircleInfo, faHardDrive, faPalette } from "@fortawesome/free-solid-svg-icons"; -import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js"; -import { useSettings } from "../../../hooks/settings/SettingsContext.js"; -import { SettingsManager } from "../../../features/settings/settings.js"; -import { VirtualRoot } from "../../../features/virtual-drive/virtual-root.js"; -import { StorageManager } from "../../../features/storage/storage.js"; -import { round } from "../../../features/math/round.js"; -import { Button } from "../../utils/Button.jsx"; -import { ProgressBar } from "../../utils/ProgressBar.jsx"; import utilStyles from "../../../styles/utils.module.css"; -import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.js"; -import Vector2 from "../../../features/math/vector2.js"; +import { Tab, TabList, TabPanel, Tabs } from "react-tabs"; +import { AppearanceSettings } from "./AppearanceSettings.jsx"; +import { AboutSettings } from "./AboutSettings.jsx"; +import { StorageTab } from "./StorageSettings.jsx"; /** - * @param {object} props - * @param {VirtualRoot} props.virtualRoot - * @param {SettingsManager} props.settingsManager - */ -function AppearanceTab({ virtualRoot, settingsManager }) { - const [wallpaper, setWallpaper] = useState(null); - const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop); - - useEffect(() => { - settings.get("wallpaper", setWallpaper); - }, [settings]); - - const onChange = (event) => { - const value = event.target.value; - settings.set("wallpaper", value); - }; - - return (<> -
-

Wallpaper

-
- {virtualRoot.navigate("~/Images")?.getFiles()?.map(({ name, id, source }) => - - )} -
-
- ); -} - -/** - * @param {object} root - * @param {VirtualRoot} root.virtualRoot - */ -function StorageTab({ virtualRoot }) { - const maxBytes = StorageManager.MAX_BYTES; - const usedBytes = StorageManager.getByteSize(virtualRoot.toString()); - - const maxKB = StorageManager.byteToKilobyte(maxBytes); - const usedKB = StorageManager.byteToKilobyte(usedBytes); - const freeKB = maxKB - usedKB; - - return (<> -
-

Virtual Drive ({round(maxKB, 1)} KB)

- - -

{round(usedKB, 1)} KB used

-

{round(freeKB, 1)} KB free

-
-
-
-

Manage data

- -
- ); -} - -function AboutTab({ windowsManager, virtualRoot }) { - return (<> -
-

About ProzillaOS

-

ProzillaOS is a web-based operating system inspired by Ubuntu Linux and Windows made with React.js by Prozilla.

-
- - -
-
- ); -} - -/** - * @param {number} param0 + * @param {object} props + * @param {number} props.initialTabIndex */ export function Settings({ initialTabIndex }) { - const [tabIndex, setTabIndex] = useState(initialTabIndex ?? 0); - const virtualRoot = useVirtualRoot(); - const settingsManager = useSettings(); - const windowsManager = useWindowsManager(); - - const getClassName = (index) => { - const classNames = [styles["Tab-button"]]; - - if (index === tabIndex) - classNames.push(styles["Active-tab"]); - - return classNames.join(" "); - }; - return ( -
-
- - - -
-
- {tabIndex === 0 - ? - : tabIndex === 1 - ? - : tabIndex === 2 - ? - : null - } -
-
+ + + + + + + + + + + + ); } \ No newline at end of file diff --git a/src/components/applications/settings/Settings.module.css b/src/components/applications/settings/Settings.module.css index 8c167b8..4be41c2 100644 --- a/src/components/applications/settings/Settings.module.css +++ b/src/components/applications/settings/Settings.module.css @@ -17,6 +17,7 @@ height: 100%; max-width: 50%; padding: 0.5rem; + margin: 0; background-color: var(--background-color-ba); resize: horizontal; overflow: hidden; @@ -27,13 +28,10 @@ gap: 0.5rem; align-items: center; width: 100%; + min-width: fit-content; padding: 0.75rem; - background: none; - border: none; border-radius: 0.5rem; - outline: none; - cursor: pointer; - transition: background-color 100ms ease-in-out; + font-size: 0.875rem; } .Tab-button.Active-tab { @@ -64,6 +62,10 @@ overflow: auto; } +.Tab-panel:not(.Active-panel) { + display: none; +} + .Option { display: flex; flex-direction: column; @@ -100,14 +102,20 @@ height: 0; } +.Image-select > input:hover + img, +.Image-select > input:focus-visible + img { + filter: brightness(110%); +} + .Image-select > input:checked + img { - outline: 0.25rem solid var(--foreground-color-a); + outline: 0.25em solid var(--foreground-color-a); } .Image-select > img { width: 100%; height: 100%; border-radius: 0.5rem; + transition: filter 100ms ease-in-out; cursor: pointer; } @@ -115,7 +123,7 @@ display: flex; gap: 1rem; flex-wrap: wrap; - margin-bottom: 0.75rem; + margin: 0.75rem 0; } .Button-group .Button { diff --git a/src/components/applications/settings/StorageSettings.jsx b/src/components/applications/settings/StorageSettings.jsx new file mode 100644 index 0000000..ad04296 --- /dev/null +++ b/src/components/applications/settings/StorageSettings.jsx @@ -0,0 +1,38 @@ +import styles from "./Settings.module.css"; +import utilStyles from "../../../styles/utils.module.css"; +import { round } from "../../../features/math/round.js"; +import { ProgressBar } from "../../utils/ProgressBar.jsx"; +import { Button } from "../../utils/Button.jsx"; +import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js"; +import { StorageManager } from "../../../features/storage/storage.js"; + +export function StorageTab() { + const virtualRoot = useVirtualRoot(); + + const maxBytes = StorageManager.MAX_BYTES; + const usedBytes = StorageManager.getByteSize(virtualRoot.toString()); + + const maxKB = StorageManager.byteToKilobyte(maxBytes); + const usedKB = StorageManager.byteToKilobyte(usedBytes); + const freeKB = maxKB - usedKB; + + return (<> +
+

Virtual Drive ({round(maxKB, 1)} KB)

+ + +

{round(usedKB, 1)} KB used

+

{round(freeKB, 1)} KB free

+
+
+
+

Manage data

+ +
+ ); +} \ No newline at end of file diff --git a/src/components/desktop/Desktop.jsx b/src/components/desktop/Desktop.jsx index f6ce0e5..2ee0278 100644 --- a/src/components/desktop/Desktop.jsx +++ b/src/components/desktop/Desktop.jsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { SettingsManager } from "../../features/settings/settings.js"; -import { useSettings } from "../../hooks/settings/SettingsContext.js"; +import { useSettingsManager } from "../../hooks/settings/SettingsContext.js"; import styles from "./Desktop.module.css"; import { useEffect } from "react"; import { useModals } from "../../hooks/modals/Modals.js"; @@ -9,7 +9,7 @@ import { useWindowsManager } from "../../hooks/windows/WindowsManagerContext.js" import { useContextMenu } from "../../hooks/modals/ContextMenu.js"; export function Desktop() { - const settingsManager = useSettings(); + const settingsManager = useSettingsManager(); const [wallpaper, setWallpaper] = useState(null); const [modalsManager, modals] = useModals(); const windowsManager = useWindowsManager(); diff --git a/src/hooks/settings/SettingsContext.js b/src/hooks/settings/SettingsContext.js index cc02b3a..126bd7a 100644 --- a/src/hooks/settings/SettingsContext.js +++ b/src/hooks/settings/SettingsContext.js @@ -10,7 +10,7 @@ const SettingsContext = createContext(); * @param props.children * @returns {import("react").Provider} */ -export function SettingsProvider({ children }) { +export function SettingsManagerProvider({ children }) { const virtualRoot = useVirtualRoot(); const settingsManager = new SettingsManager(virtualRoot); @@ -24,6 +24,6 @@ export function SettingsProvider({ children }) { /** * @returns {SettingsManager} */ -export function useSettings() { +export function useSettingsManager() { return useContext(SettingsContext); } \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index fa0076d..25e9890 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -87,7 +87,7 @@ h4 { font-size: 1.4em; } h5 { font-size: 1.2em; } h6 { font-size: 1em; } -button { +button, li[data-rttab="true"] { margin: 0; border: none; outline: none;