Added settings app
This commit is contained in:
parent
43387d369f
commit
3625c383ee
6 changed files with 194 additions and 15 deletions
18
public/media/applications/icons/settings.svg
Normal file
18
public/media/applications/icons/settings.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M190.391 123.321L173.75 113.711C175.43 104.649 175.43 95.3519 173.75 86.2894L190.391 76.6801C192.305 75.5863 193.164 73.3207 192.539 71.2113C188.204 57.3051 180.821 44.7269 171.172 34.2582C169.688 32.6566 167.266 32.266 165.391 33.3597L148.75 42.9691C141.758 36.9535 133.711 32.3051 125 29.2582V10.0785C125 7.89099 123.477 5.97693 121.329 5.50818C106.993 2.30505 92.3051 2.4613 78.6723 5.50818C76.5239 5.97693 75.0004 7.89099 75.0004 10.0785V29.2972C66.3286 32.3832 58.2817 37.0316 51.2504 43.0082L34.6489 33.3988C32.7348 32.3051 30.352 32.6566 28.8676 34.2972C19.2192 44.7269 11.8364 57.3051 7.50044 71.2504C6.83637 73.3597 7.73481 75.6254 9.64887 76.7191L26.2895 86.3285C24.6098 95.391 24.6098 104.688 26.2895 113.75L9.64887 123.36C7.73481 124.453 6.87544 126.719 7.50044 128.828C11.8364 142.735 19.2192 155.313 28.8676 165.782C30.352 167.383 32.7739 167.774 34.6489 166.68L51.2895 157.071C58.2817 163.086 66.3286 167.735 75.0395 170.782V190C75.0395 192.188 76.5629 194.102 78.7114 194.571C93.0473 197.774 107.735 197.618 121.368 194.571C123.516 194.102 125.039 192.188 125.039 190V170.782C133.711 167.696 141.758 163.047 148.789 157.071L165.43 166.68C167.344 167.774 169.727 167.422 171.211 165.782C180.86 155.352 188.243 142.774 192.579 128.828C193.164 126.68 192.305 124.414 190.391 123.321ZM100 131.25C82.7739 131.25 68.7504 117.227 68.7504 100C68.7504 82.7738 82.7739 68.7504 100 68.7504C117.227 68.7504 131.25 82.7738 131.25 100C131.25 117.227 117.227 131.25 100 131.25Z" fill="#8395A7"/>
|
||||
<g filter="url(#filter0_d_98_54)">
|
||||
<circle cx="100" cy="100" r="40" fill="#C8D6E5"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_98_54" x="40" y="40" width="120" height="120" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_98_54"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_98_54" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
65
src/components/applications/settings/Settings.jsx
Normal file
65
src/components/applications/settings/Settings.jsx
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import styles from "./Settings.module.css";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { 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";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { VirtualRoot } from "../../../features/virtual-drive/virtual-root.js";
|
||||
|
||||
/**
|
||||
* @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 (
|
||||
<div className={styles["Option"]}>
|
||||
<p>Wallpaper</p>
|
||||
<div className={styles["Input"]}>
|
||||
{virtualRoot.navigate("~/Images").getFiles().map(({ name, id, source }) =>
|
||||
<label className={styles["Image-select"]} key={id}>
|
||||
<input type="radio" value={source} checked={source === wallpaper ? "checked" : ""} onChange={onChange}/>
|
||||
<img src={source} alt={id}/>
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Settings() {
|
||||
const [tabIndex, setTabIndex] = useState(0);
|
||||
const virtualRoot = useVirtualRoot();
|
||||
const settingsManager = useSettings();
|
||||
|
||||
return (
|
||||
<div className={styles.Container}>
|
||||
<div className={styles.Tabs}>
|
||||
<button title="Home" className={styles["Tab-button"]} onClick={() => { setTabIndex(0); }}>
|
||||
<FontAwesomeIcon icon={faPalette}/>
|
||||
Appearance
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles["Tab-panel"]}>
|
||||
{tabIndex === 0
|
||||
? <AppearanceTab virtualRoot={virtualRoot} settingsManager={settingsManager}/>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
89
src/components/applications/settings/Settings.module.css
Normal file
89
src/components/applications/settings/Settings.module.css
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
.Container {
|
||||
--tabs-width: 10rem;
|
||||
|
||||
flex: 1;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--background-color-c);
|
||||
}
|
||||
|
||||
.Tabs {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
flex-direction: column;
|
||||
min-width: calc(var(--tabs-width) / 2);
|
||||
width: var(--tabs-width);
|
||||
height: 100%;
|
||||
max-width: 50%;
|
||||
padding: 0.5rem;
|
||||
background-color: var(--background-color-b);
|
||||
resize: horizontal;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.Tab-button {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 100ms ease-in-out;
|
||||
}
|
||||
|
||||
.Tab-button:hover {
|
||||
background-color: rgba(255, 255, 255, 10%);
|
||||
}
|
||||
|
||||
.Tab-button svg {
|
||||
height: 1.35rem;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.Tab-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
height: 100%;
|
||||
padding: 0.5rem 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.Option {
|
||||
text-align: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.Input {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.Input > label {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.Image-select > input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.Image-select > input:checked + img {
|
||||
outline: 0.25rem solid var(--foreground-color-a);
|
||||
}
|
||||
|
||||
.Image-select > img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -50,7 +50,10 @@ export function HomeMenu({ active, setActive, search }) {
|
|||
<button title="Power" onClick={() => { closeTab(); }}>
|
||||
<FontAwesomeIcon icon={faPowerOff}/>
|
||||
</button>
|
||||
<button title="Settings">
|
||||
<button title="Settings" onClick={() => {
|
||||
setActive(false);
|
||||
windowsManager.open("settings");
|
||||
}}>
|
||||
<FontAwesomeIcon icon={faGear}/>
|
||||
</button>
|
||||
<button title="Info" onClick={() => {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
/* eslint-disable eqeqeq */
|
||||
import Application from "./application.js";
|
||||
import { FileExplorer } from "../../components/applications/file-explorer/FileExplorer.jsx";
|
||||
import { MediaViewer } from "../../components/applications/media-viewer/MediaViewer.jsx";
|
||||
import { WebView } from "../../components/applications/.templates/WebView.jsx";
|
||||
import { Terminal } from "../../components/applications/terminal/Terminal.jsx";
|
||||
import { TextEditor } from "../../components/applications/text-editor/TextEditor.jsx";
|
||||
import Application from "./application.js";
|
||||
import { Settings } from "../../components/applications/settings/Settings.jsx";
|
||||
|
||||
export default class ApplicationsManager {
|
||||
static APPLICATIONS = [
|
||||
new Application("Terminal", "terminal", Terminal),
|
||||
new Application("Settings", "settings", Settings),
|
||||
// new Application("Browser", "browser"),
|
||||
new Application("Text Editor", "text-editor", TextEditor),
|
||||
new Application("Code Editor", "code-editor"),
|
||||
// new Application("Code Editor", "code-editor"),
|
||||
new Application("File Explorer", "file-explorer", FileExplorer),
|
||||
new Application("Media Viewer", "media-viewer", MediaViewer),
|
||||
new Application("Wordle", "wordle", WebView, { source: "https://prozilla.dev/wordle" }),
|
||||
|
|
|
|||
|
|
@ -271,18 +271,7 @@ export class VirtualFolder extends VirtualBase {
|
|||
|
||||
/**
|
||||
* @param {Boolean=false} showHidden
|
||||
*/
|
||||
getSubFolders(showHidden = false) {
|
||||
if (showHidden)
|
||||
return this.subFolders;
|
||||
|
||||
return this.subFolders.filter(({ name }) =>
|
||||
!name.startsWith(".")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Boolean=false} showHidden
|
||||
* @returns {Array<VirtualFile>}
|
||||
*/
|
||||
getFiles(showHidden = false) {
|
||||
if (showHidden)
|
||||
|
|
@ -292,4 +281,17 @@ export class VirtualFolder extends VirtualBase {
|
|||
!name.startsWith(".")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Boolean=false} showHidden
|
||||
* @returns {Array<VirtualFolder>}
|
||||
*/
|
||||
getSubFolders(showHidden = false) {
|
||||
if (showHidden)
|
||||
return this.subFolders;
|
||||
|
||||
return this.subFolders.filter(({ name }) =>
|
||||
!name.startsWith(".")
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue