mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2025-12-06 00:20:05 +01:00
Remove Prettier custom settings and change all files
This commit is contained in:
parent
df704f3152
commit
ea9c6efb28
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none"
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from "@testing-library/react";
|
||||||
import StyledApp from 'components/pages/StyledApp';
|
import StyledApp from "components/pages/StyledApp";
|
||||||
import Index from 'pages/index';
|
import Index from "pages/index";
|
||||||
|
|
||||||
test('renders main role', () => {
|
test("renders main role", () => {
|
||||||
render(
|
render(
|
||||||
<StyledApp>
|
<StyledApp>
|
||||||
<Index />
|
<Index />
|
||||||
</StyledApp>
|
</StyledApp>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByRole('main')).toBeInTheDocument();
|
expect(screen.getByRole("main")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
import FileManager from 'components/system/Files/FileManager';
|
import FileManager from "components/system/Files/FileManager";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from "react";
|
||||||
|
|
||||||
const FileExplorer = ({ id }: ComponentProcessProps): JSX.Element => {
|
const FileExplorer = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
processes: { [id]: { url = '' } = {} }
|
processes: { [id]: { url = "" } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledJSDOS = styled.div`
|
const StyledJSDOS = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
export const defaultConfig = '/libs/jsdos/dosbox.conf';
|
export const defaultConfig = "/libs/jsdos/dosbox.conf";
|
||||||
|
|
||||||
export const libs = ['/libs/jsdos/js-dos.js', '/libs/jsdos/js-dos.css'];
|
export const libs = ["/libs/jsdos/js-dos.js", "/libs/jsdos/js-dos.css"];
|
||||||
|
|
||||||
export const pathPrefix = '/libs/jsdos/';
|
export const pathPrefix = "/libs/jsdos/";
|
||||||
|
|
||||||
export const zipConfigPath = '.jsdos/dosbox.conf';
|
export const zipConfigPath = ".jsdos/dosbox.conf";
|
||||||
|
|
||||||
export const globals = [
|
export const globals = [
|
||||||
'__core-js_shared__',
|
"__core-js_shared__",
|
||||||
'compiled',
|
"compiled",
|
||||||
'core',
|
"core",
|
||||||
'emulatorsUi',
|
"emulatorsUi",
|
||||||
'exports',
|
"exports",
|
||||||
'WDOSBOX',
|
"WDOSBOX",
|
||||||
'worker'
|
"worker",
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import StyledJSDOS from 'components/apps/JSDOS/StyledJSDOS';
|
import StyledJSDOS from "components/apps/JSDOS/StyledJSDOS";
|
||||||
import useJSDOS from 'components/apps/JSDOS/useJSDOS';
|
import useJSDOS from "components/apps/JSDOS/useJSDOS";
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useRef } from 'react';
|
import { useRef } from "react";
|
||||||
|
|
||||||
const JSDOS = ({ id }: ComponentProcessProps): JSX.Element => {
|
const JSDOS = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
processes: { [id]: { url = '' } = {} }
|
processes: { [id]: { url = "" } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const screenRef = useRef<HTMLDivElement | null>(null);
|
const screenRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import type { FSModule } from 'browserfs/dist/node/core/FS';
|
import type { FSModule } from "browserfs/dist/node/core/FS";
|
||||||
import {
|
import {
|
||||||
defaultConfig,
|
defaultConfig,
|
||||||
globals,
|
globals,
|
||||||
libs,
|
libs,
|
||||||
pathPrefix,
|
pathPrefix,
|
||||||
zipConfigPath
|
zipConfigPath,
|
||||||
} from 'components/apps/JSDOS/config';
|
} from "components/apps/JSDOS/config";
|
||||||
import type { DosCI } from 'components/apps/JSDOS/types';
|
import type { DosCI } from "components/apps/JSDOS/types";
|
||||||
import { addFileToZip, isFileInZip } from 'components/apps/JSDOS/zipFunctions';
|
import { addFileToZip, isFileInZip } from "components/apps/JSDOS/zipFunctions";
|
||||||
import { closeWithTransition } from 'components/system/Window/functions';
|
import { closeWithTransition } from "components/system/Window/functions";
|
||||||
import useTitle from 'components/system/Window/useTitle';
|
import useTitle from "components/system/Window/useTitle";
|
||||||
import useWindowSize from 'components/system/Window/useWindowSize';
|
import useWindowSize from "components/system/Window/useWindowSize";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { bufferToUrl, cleanUpBufferUrl, loadFiles } from 'utils/functions';
|
import { bufferToUrl, cleanUpBufferUrl, loadFiles } from "utils/functions";
|
||||||
|
|
||||||
const addJsDosConfig = async (buffer: Buffer, fs: FSModule): Promise<Buffer> =>
|
const addJsDosConfig = async (buffer: Buffer, fs: FSModule): Promise<Buffer> =>
|
||||||
(await isFileInZip(buffer, zipConfigPath))
|
(await isFileInZip(buffer, zipConfigPath))
|
||||||
|
|
@ -37,7 +37,7 @@ const useJSDOS = (
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!dos && fs && url) {
|
if (!dos && fs && url) {
|
||||||
fs.readFile(url, (_error, contents = Buffer.from('')) =>
|
fs.readFile(url, (_error, contents = Buffer.from("")) =>
|
||||||
loadFiles(libs).then(async () => {
|
loadFiles(libs).then(async () => {
|
||||||
const objectURL = bufferToUrl(await addJsDosConfig(contents, fs));
|
const objectURL = bufferToUrl(await addJsDosConfig(contents, fs));
|
||||||
|
|
||||||
|
|
@ -70,12 +70,12 @@ const useJSDOS = (
|
||||||
updateWindowSize(dos.frameHeight, dos.frameWidth);
|
updateWindowSize(dos.frameHeight, dos.frameWidth);
|
||||||
|
|
||||||
dos.events().onMessage((_msgType, _eventType, command, message) => {
|
dos.events().onMessage((_msgType, _eventType, command, message) => {
|
||||||
if (command === 'LOG_EXEC') {
|
if (command === "LOG_EXEC") {
|
||||||
const [dosCommand] = message
|
const [dosCommand] = message
|
||||||
.replace('Parsing command line: ', '')
|
.replace("Parsing command line: ", "")
|
||||||
.split(' ');
|
.split(" ");
|
||||||
|
|
||||||
if (dosCommand.toUpperCase() === 'EXIT') {
|
if (dosCommand.toUpperCase() === "EXIT") {
|
||||||
closeWithTransition(close, id);
|
closeWithTransition(close, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import type { FSModule } from 'browserfs/dist/node/core/FS';
|
import type { FSModule } from "browserfs/dist/node/core/FS";
|
||||||
import type { AsyncZippable } from 'fflate';
|
import type { AsyncZippable } from "fflate";
|
||||||
import { unzip, zip } from 'fflate';
|
import { unzip, zip } from "fflate";
|
||||||
|
|
||||||
const addFileToZippable = (path: string, file: Buffer): AsyncZippable =>
|
const addFileToZippable = (path: string, file: Buffer): AsyncZippable =>
|
||||||
path.split('/').reduce((zippableData, pathPart, index, { length }) => {
|
path.split("/").reduce((zippableData, pathPart, index, { length }) => {
|
||||||
const endOfPath = index === length - 1;
|
const endOfPath = index === length - 1;
|
||||||
const walkedPath = Object.keys(zippableData)[index - 1] || '';
|
const walkedPath = Object.keys(zippableData)[index - 1] || "";
|
||||||
const currentPath = `${walkedPath}${pathPart}${endOfPath ? '' : '/'}`;
|
const currentPath = `${walkedPath}${pathPart}${endOfPath ? "" : "/"}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...zippableData,
|
...zippableData,
|
||||||
[currentPath]: endOfPath ? [file, { level: 0 }] : new Uint8Array()
|
[currentPath]: endOfPath ? [file, { level: 0 }] : new Uint8Array(),
|
||||||
};
|
};
|
||||||
}, {} as AsyncZippable);
|
}, {} as AsyncZippable);
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@ export const addFileToZip = (
|
||||||
): Promise<Buffer> =>
|
): Promise<Buffer> =>
|
||||||
new Promise((resolve) =>
|
new Promise((resolve) =>
|
||||||
unzip(buffer, (_unzipError, zipData) =>
|
unzip(buffer, (_unzipError, zipData) =>
|
||||||
fs.readFile(filePath, (_readError, contents = Buffer.from('')) =>
|
fs.readFile(filePath, (_readError, contents = Buffer.from("")) =>
|
||||||
zip(
|
zip(
|
||||||
{
|
{
|
||||||
...zipData,
|
...zipData,
|
||||||
...addFileToZippable(zipFilePath, contents)
|
...addFileToZippable(zipFilePath, contents),
|
||||||
},
|
},
|
||||||
(_zipError, newZipFile) => resolve(newZipFile as Buffer)
|
(_zipError, newZipFile) => resolve(newZipFile as Buffer)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledV86 = styled.div`
|
const StyledV86 = styled.div`
|
||||||
canvas {
|
canvas {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ export const config = {
|
||||||
autostart: true,
|
autostart: true,
|
||||||
log_level: 0,
|
log_level: 0,
|
||||||
filesystem: {
|
filesystem: {
|
||||||
basefs: '/.index/fs.9p.json',
|
basefs: "/.index/fs.9p.json",
|
||||||
baseurl: '/'
|
baseurl: "/",
|
||||||
},
|
},
|
||||||
network_relay_url: 'wss://relay.widgetry.org/',
|
network_relay_url: "wss://relay.widgetry.org/",
|
||||||
wasm_path: '/libs/v86/v86.wasm',
|
wasm_path: "/libs/v86/v86.wasm",
|
||||||
bios: { url: '/libs/v86/bios/seabios.bin' },
|
bios: { url: "/libs/v86/bios/seabios.bin" },
|
||||||
vga_bios: { url: '/libs/v86/bios/vgabios.bin' }
|
vga_bios: { url: "/libs/v86/bios/vgabios.bin" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const libs = ['/libs/v86/libv86.js'];
|
export const libs = ["/libs/v86/libv86.js"];
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires, no-console */
|
/* eslint-disable @typescript-eslint/no-var-requires, no-console */
|
||||||
|
|
||||||
const { readdir, readlink, stat, writeFile } = require('fs');
|
const { readdir, readlink, stat, writeFile } = require("fs");
|
||||||
const { basename, relative, join, resolve: resolvePath } = require('path');
|
const { basename, relative, join, resolve: resolvePath } = require("path");
|
||||||
|
|
||||||
const VERSION = 3;
|
const VERSION = 3;
|
||||||
|
|
||||||
|
|
@ -16,11 +16,11 @@ const IDX_TARGET = 6;
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const argPath = resolvePath(args[args.length - 1]);
|
const argPath = resolvePath(args[args.length - 1]);
|
||||||
const excludedPaths = [];
|
const excludedPaths = [];
|
||||||
let outputPath = '';
|
let outputPath = "";
|
||||||
|
|
||||||
args.forEach((arg, index) => {
|
args.forEach((arg, index) => {
|
||||||
if (arg === '--exclude') excludedPaths.push(args[index + 1]);
|
if (arg === "--exclude") excludedPaths.push(args[index + 1]);
|
||||||
if (arg === '--out') outputPath = resolvePath(args[index + 1]);
|
if (arg === "--out") outputPath = resolvePath(args[index + 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const fs2json = (dir) => {
|
const fs2json = (dir) => {
|
||||||
|
|
@ -101,17 +101,17 @@ const fs2json = (dir) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
console.info('Creating file tree ...');
|
console.info("Creating file tree ...");
|
||||||
|
|
||||||
return walk(dir).then((data) => {
|
return walk(dir).then((data) => {
|
||||||
console.info('Creating json ...');
|
console.info("Creating json ...");
|
||||||
|
|
||||||
writeFile(
|
writeFile(
|
||||||
outputPath,
|
outputPath,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
fsroot: data,
|
fsroot: data,
|
||||||
version: VERSION,
|
version: VERSION,
|
||||||
size: totalSize
|
size: totalSize,
|
||||||
}),
|
}),
|
||||||
() => process.exit()
|
() => process.exit()
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ type V86Image = {
|
||||||
use_parts?: boolean;
|
use_parts?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type V86ImageType = 'cdrom' | 'fda' | 'hda';
|
type V86ImageType = "cdrom" | "fda" | "hda";
|
||||||
|
|
||||||
export type V86ImageConfig = Partial<Record<V86ImageType, V86Image>>;
|
export type V86ImageConfig = Partial<Record<V86ImageType, V86Image>>;
|
||||||
|
|
||||||
// https://github.com/copy/v86/blob/master/src/floppy.js#L64
|
// https://github.com/copy/v86/blob/master/src/floppy.js#L64
|
||||||
const SUPPORTED_FLOPPY_TYPES = [
|
const SUPPORTED_FLOPPY_TYPES = [
|
||||||
160, 180, 200, 320, 360, 400, 720, 1200, 1440, 1722, 2880
|
160, 180, 200, 320, 360, 400, 720, 1200, 1440, 1722, 2880,
|
||||||
];
|
];
|
||||||
|
|
||||||
// https://github.com/copy/v86/blob/master/src/floppy.js#L83
|
// https://github.com/copy/v86/blob/master/src/floppy.js#L83
|
||||||
|
|
@ -21,4 +21,4 @@ const isFloppyImage = (size: number): boolean =>
|
||||||
SUPPORTED_FLOPPY_TYPES.includes(size >> 10) && (size & 0x3ff) === 0;
|
SUPPORTED_FLOPPY_TYPES.includes(size >> 10) && (size & 0x3ff) === 0;
|
||||||
|
|
||||||
export const getImageType = (size: number): string =>
|
export const getImageType = (size: number): string =>
|
||||||
isFloppyImage(size) ? 'fda' : 'hda';
|
isFloppyImage(size) ? "fda" : "hda";
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import StyledV86 from 'components/apps/V86/StyledV86';
|
import StyledV86 from "components/apps/V86/StyledV86";
|
||||||
import useV86 from 'components/apps/V86/useV86';
|
import useV86 from "components/apps/V86/useV86";
|
||||||
import useV86ScreenSize from 'components/apps/V86/useV86ScreenSize';
|
import useV86ScreenSize from "components/apps/V86/useV86ScreenSize";
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useRef } from 'react';
|
import { useRef } from "react";
|
||||||
|
|
||||||
const V86 = ({ id }: ComponentProcessProps): JSX.Element => {
|
const V86 = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
processes: { [id]: { url = '' } = {} }
|
processes: { [id]: { url = "" } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const screenRef = useRef<HTMLDivElement | null>(null);
|
const screenRef = useRef<HTMLDivElement | null>(null);
|
||||||
const { emulator, lockMouse } = useV86(id, url, screenRef);
|
const { emulator, lockMouse } = useV86(id, url, screenRef);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import type { config as v86Config } from 'components/apps/V86/config';
|
import type { config as v86Config } from "components/apps/V86/config";
|
||||||
import type { V86ImageConfig } from 'components/apps/V86/image';
|
import type { V86ImageConfig } from "components/apps/V86/image";
|
||||||
|
|
||||||
export type ModeCallback = (isGraphical: boolean) => void;
|
export type ModeCallback = (isGraphical: boolean) => void;
|
||||||
export type SizeCallback = (dimensions: number[]) => void;
|
export type SizeCallback = (dimensions: number[]) => void;
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ import {
|
||||||
BOOT_CD_FD_HD,
|
BOOT_CD_FD_HD,
|
||||||
BOOT_FD_CD_HD,
|
BOOT_FD_CD_HD,
|
||||||
config,
|
config,
|
||||||
libs
|
libs,
|
||||||
} from 'components/apps/V86/config';
|
} from "components/apps/V86/config";
|
||||||
import type { V86ImageConfig } from 'components/apps/V86/image';
|
import type { V86ImageConfig } from "components/apps/V86/image";
|
||||||
import { getImageType } from 'components/apps/V86/image';
|
import { getImageType } from "components/apps/V86/image";
|
||||||
import type { V86, V86Starter } from 'components/apps/V86/types';
|
import type { V86, V86Starter } from "components/apps/V86/types";
|
||||||
import useTitle from 'components/system/Window/useTitle';
|
import useTitle from "components/system/Window/useTitle";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { extname } from 'path';
|
import { extname } from "path";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { bufferToUrl, cleanUpBufferUrl, loadFiles } from 'utils/functions';
|
import { bufferToUrl, cleanUpBufferUrl, loadFiles } from "utils/functions";
|
||||||
|
|
||||||
const useV86 = (
|
const useV86 = (
|
||||||
id: string,
|
id: string,
|
||||||
|
|
@ -24,20 +24,20 @@ const useV86 = (
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!emulator && fs && url) {
|
if (!emulator && fs && url) {
|
||||||
fs?.readFile(url, (_error, contents = Buffer.from('')) => {
|
fs?.readFile(url, (_error, contents = Buffer.from("")) => {
|
||||||
loadFiles(libs).then(() => {
|
loadFiles(libs).then(() => {
|
||||||
if (screenContainer?.current) {
|
if (screenContainer?.current) {
|
||||||
const isISO = extname(url).toLowerCase() === '.iso';
|
const isISO = extname(url).toLowerCase() === ".iso";
|
||||||
const { deviceMemory = 8 } = navigator;
|
const { deviceMemory = 8 } = navigator;
|
||||||
const memoryRatio = deviceMemory / 8;
|
const memoryRatio = deviceMemory / 8;
|
||||||
const bufferUrl = bufferToUrl(contents);
|
const bufferUrl = bufferToUrl(contents);
|
||||||
const v86ImageConfig: V86ImageConfig = {
|
const v86ImageConfig: V86ImageConfig = {
|
||||||
[isISO ? 'cdrom' : getImageType(contents.length)]: {
|
[isISO ? "cdrom" : getImageType(contents.length)]: {
|
||||||
async: false,
|
async: false,
|
||||||
size: contents.length,
|
size: contents.length,
|
||||||
url: bufferUrl,
|
url: bufferUrl,
|
||||||
use_parts: false
|
use_parts: false,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
const v86 = new window.V86Starter({
|
const v86 = new window.V86Starter({
|
||||||
memory_size: memoryRatio * 1024 * 1024 * 1024,
|
memory_size: memoryRatio * 1024 * 1024 * 1024,
|
||||||
|
|
@ -45,10 +45,10 @@ const useV86 = (
|
||||||
boot_order: isISO ? BOOT_CD_FD_HD : BOOT_FD_CD_HD,
|
boot_order: isISO ? BOOT_CD_FD_HD : BOOT_FD_CD_HD,
|
||||||
screen_container: screenContainer.current,
|
screen_container: screenContainer.current,
|
||||||
...v86ImageConfig,
|
...v86ImageConfig,
|
||||||
...config
|
...config,
|
||||||
});
|
});
|
||||||
|
|
||||||
v86.add_listener('emulator-loaded', () => {
|
v86.add_listener("emulator-loaded", () => {
|
||||||
appendFileToTitle(url);
|
appendFileToTitle(url);
|
||||||
cleanUpBufferUrl(bufferUrl);
|
cleanUpBufferUrl(bufferUrl);
|
||||||
});
|
});
|
||||||
|
|
@ -64,7 +64,7 @@ const useV86 = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
emulator,
|
emulator,
|
||||||
lockMouse: emulator?.lock_mouse
|
lockMouse: emulator?.lock_mouse,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import type {
|
import type {
|
||||||
ModeCallback,
|
ModeCallback,
|
||||||
SizeCallback,
|
SizeCallback,
|
||||||
V86Starter
|
V86Starter,
|
||||||
} from 'components/apps/V86/types';
|
} from "components/apps/V86/types";
|
||||||
import useWindowSize from 'components/system/Window/useWindowSize';
|
import useWindowSize from "components/system/Window/useWindowSize";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import { pxToNum } from 'utils/functions';
|
import { pxToNum } from "utils/functions";
|
||||||
|
|
||||||
const SET_SCREEN_MODE = 'screen-set-mode';
|
const SET_SCREEN_MODE = "screen-set-mode";
|
||||||
const SET_SCREEN_GFX = 'screen-set-size-graphical';
|
const SET_SCREEN_GFX = "screen-set-size-graphical";
|
||||||
const SET_SCREEN_TXT = 'screen-set-size-text';
|
const SET_SCREEN_TXT = "screen-set-size-text";
|
||||||
|
|
||||||
const useV86ScreenSize = (
|
const useV86ScreenSize = (
|
||||||
id: string,
|
id: string,
|
||||||
|
|
@ -18,8 +18,8 @@ const useV86ScreenSize = (
|
||||||
): React.CSSProperties => {
|
): React.CSSProperties => {
|
||||||
const {
|
const {
|
||||||
sizes: {
|
sizes: {
|
||||||
window: { lineHeight }
|
window: { lineHeight },
|
||||||
}
|
},
|
||||||
} = useTheme();
|
} = useTheme();
|
||||||
const { updateWindowSize } = useWindowSize(id);
|
const { updateWindowSize } = useWindowSize(id);
|
||||||
const [isGraphical, setIsGraphical] = useState(false);
|
const [isGraphical, setIsGraphical] = useState(false);
|
||||||
|
|
@ -49,8 +49,8 @@ const useV86ScreenSize = (
|
||||||
return {
|
return {
|
||||||
font: `${lineHeight} monospace`,
|
font: `${lineHeight} monospace`,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
position: 'relative',
|
position: "relative",
|
||||||
top: isGraphical ? '' : '2px' // Why + 2?
|
top: isGraphical ? "" : "2px", // Why + 2?
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from "framer-motion";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledWebamp = styled(motion.div)`
|
const StyledWebamp = styled(motion.div)`
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,29 @@
|
||||||
import type { Track, WebampCI } from 'components/apps/Webamp/types';
|
import type { Track, WebampCI } from "components/apps/Webamp/types";
|
||||||
import { centerPosition } from 'components/system/Window/functions';
|
import { centerPosition } from "components/system/Window/functions";
|
||||||
import type { IAudioMetadata } from 'music-metadata-browser';
|
import type { IAudioMetadata } from "music-metadata-browser";
|
||||||
import { parseBuffer } from 'music-metadata-browser';
|
import { parseBuffer } from "music-metadata-browser";
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
import { bufferToBlob, cleanUpBufferUrl } from 'utils/functions';
|
import { bufferToBlob, cleanUpBufferUrl } from "utils/functions";
|
||||||
|
|
||||||
export const BASE_WEBAMP_OPTIONS = {
|
export const BASE_WEBAMP_OPTIONS = {
|
||||||
availableSkins: [
|
availableSkins: [
|
||||||
{ url: '/skins/Aqua_X.wsz', name: 'Aqua X' },
|
{ url: "/skins/Aqua_X.wsz", name: "Aqua X" },
|
||||||
{ url: '/skins/Nucleo_NLog_v102.wsz', name: 'Nucleo NLog v2G' },
|
{ url: "/skins/Nucleo_NLog_v102.wsz", name: "Nucleo NLog v2G" },
|
||||||
{
|
{
|
||||||
url: '/skins/SpyAMP_Professional_Edition_v5.wsz',
|
url: "/skins/SpyAMP_Professional_Edition_v5.wsz",
|
||||||
name: 'SpyAMP Professional Edition v5'
|
name: "SpyAMP Professional Edition v5",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const BASE_WINDOW_SIZE = {
|
const BASE_WINDOW_SIZE = {
|
||||||
height: 116,
|
height: 116,
|
||||||
width: 275
|
width: 275,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cleanBufferOnSkinLoad = (
|
export const cleanBufferOnSkinLoad = (
|
||||||
webamp: WebampCI,
|
webamp: WebampCI,
|
||||||
url = ''
|
url = ""
|
||||||
): Promise<void> =>
|
): Promise<void> =>
|
||||||
webamp.skinIsLoaded().then(() => {
|
webamp.skinIsLoaded().then(() => {
|
||||||
if (url) cleanUpBufferUrl(url);
|
if (url) cleanUpBufferUrl(url);
|
||||||
|
|
@ -31,12 +31,12 @@ export const cleanBufferOnSkinLoad = (
|
||||||
|
|
||||||
export const closeEqualizer = (webamp: WebampCI): void =>
|
export const closeEqualizer = (webamp: WebampCI): void =>
|
||||||
webamp.store.dispatch({
|
webamp.store.dispatch({
|
||||||
type: 'CLOSE_WINDOW',
|
type: "CLOSE_WINDOW",
|
||||||
windowId: 'equalizer'
|
windowId: "equalizer",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getWebampElement = (): HTMLDivElement =>
|
export const getWebampElement = (): HTMLDivElement =>
|
||||||
document.getElementById('webamp') as HTMLDivElement;
|
document.getElementById("webamp") as HTMLDivElement;
|
||||||
|
|
||||||
export const updateWebampPosition = (
|
export const updateWebampPosition = (
|
||||||
webamp: WebampCI,
|
webamp: WebampCI,
|
||||||
|
|
@ -48,37 +48,37 @@ export const updateWebampPosition = (
|
||||||
position || centerPosition({ height: height * 2, width }, taskbarHeight);
|
position || centerPosition({ height: height * 2, width }, taskbarHeight);
|
||||||
|
|
||||||
webamp.store.dispatch({
|
webamp.store.dispatch({
|
||||||
type: 'UPDATE_WINDOW_POSITIONS',
|
type: "UPDATE_WINDOW_POSITIONS",
|
||||||
positions: {
|
positions: {
|
||||||
main: { x, y },
|
main: { x, y },
|
||||||
playlist: { x, y: height + y }
|
playlist: { x, y: height + y },
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const focusWindow = (webamp: WebampCI, window: string): void =>
|
export const focusWindow = (webamp: WebampCI, window: string): void =>
|
||||||
webamp.store.dispatch({
|
webamp.store.dispatch({
|
||||||
type: 'SET_FOCUSED_WINDOW',
|
type: "SET_FOCUSED_WINDOW",
|
||||||
window
|
window,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const unFocus = (webamp: WebampCI): void =>
|
export const unFocus = (webamp: WebampCI): void =>
|
||||||
webamp.store.dispatch({
|
webamp.store.dispatch({
|
||||||
type: 'SET_FOCUSED_WINDOW',
|
type: "SET_FOCUSED_WINDOW",
|
||||||
window: ''
|
window: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const parseTrack = (file: Buffer, fileName: string): Promise<Track> =>
|
export const parseTrack = (file: Buffer, fileName: string): Promise<Track> =>
|
||||||
new Promise((resolve) =>
|
new Promise((resolve) =>
|
||||||
parseBuffer(file).then(
|
parseBuffer(file).then(
|
||||||
({
|
({
|
||||||
common: { artist = '', title = fileName },
|
common: { artist = "", title = fileName },
|
||||||
format: { duration = 0 }
|
format: { duration = 0 },
|
||||||
}: IAudioMetadata) =>
|
}: IAudioMetadata) =>
|
||||||
resolve({
|
resolve({
|
||||||
blob: bufferToBlob(file),
|
blob: bufferToBlob(file),
|
||||||
duration: Math.floor(duration),
|
duration: Math.floor(duration),
|
||||||
metaData: { artist, title }
|
metaData: { artist, title },
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,30 @@ import {
|
||||||
cleanBufferOnSkinLoad,
|
cleanBufferOnSkinLoad,
|
||||||
focusWindow,
|
focusWindow,
|
||||||
parseTrack,
|
parseTrack,
|
||||||
unFocus
|
unFocus,
|
||||||
} from 'components/apps/Webamp/functions';
|
} from "components/apps/Webamp/functions";
|
||||||
import StyledWebamp from 'components/apps/Webamp/StyledWebamp';
|
import StyledWebamp from "components/apps/Webamp/StyledWebamp";
|
||||||
import useWebamp from 'components/apps/Webamp/useWebamp';
|
import useWebamp from "components/apps/Webamp/useWebamp";
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
import useFocusable from 'components/system/Window/useFocusable';
|
import useFocusable from "components/system/Window/useFocusable";
|
||||||
import useWindowTransitions from 'components/system/Window/useWindowTransitions';
|
import useWindowTransitions from "components/system/Window/useWindowTransitions";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { basename, extname } from 'path';
|
import { basename, extname } from "path";
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { bufferToUrl, loadFiles } from 'utils/functions';
|
import { bufferToUrl, loadFiles } from "utils/functions";
|
||||||
|
|
||||||
const Webamp = ({ id }: ComponentProcessProps): JSX.Element => {
|
const Webamp = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const { fs } = useFileSystem();
|
const { fs } = useFileSystem();
|
||||||
const { processes: { [id]: { url = '' } = {} } = {} } = useProcesses();
|
const { processes: { [id]: { url = "" } = {} } = {} } = useProcesses();
|
||||||
const [currentUrl, setCurrentUrl] = useState(url);
|
const [currentUrl, setCurrentUrl] = useState(url);
|
||||||
const { loadWebamp, webampCI } = useWebamp(id);
|
const { loadWebamp, webampCI } = useWebamp(id);
|
||||||
const windowTransitions = useWindowTransitions(id, containerRef);
|
const windowTransitions = useWindowTransitions(id, containerRef);
|
||||||
const focusEvents = useMemo(
|
const focusEvents = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
onBlur: () => webampCI && unFocus(webampCI),
|
onBlur: () => webampCI && unFocus(webampCI),
|
||||||
onFocus: () => webampCI && focusWindow(webampCI, 'main')
|
onFocus: () => webampCI && focusWindow(webampCI, "main"),
|
||||||
}),
|
}),
|
||||||
[webampCI]
|
[webampCI]
|
||||||
);
|
);
|
||||||
|
|
@ -38,7 +38,7 @@ const Webamp = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (fs) {
|
if (fs) {
|
||||||
fs?.readFile(url, (_error, contents) => {
|
fs?.readFile(url, (_error, contents) => {
|
||||||
loadFiles(['/libs/webamp/webamp.bundle.min.js']).then(() =>
|
loadFiles(["/libs/webamp/webamp.bundle.min.js"]).then(() =>
|
||||||
loadWebamp(containerRef?.current, url, contents)
|
loadWebamp(containerRef?.current, url, contents)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -47,8 +47,8 @@ const Webamp = ({ id }: ComponentProcessProps): JSX.Element => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (url && url !== currentUrl && webampCI) {
|
if (url && url !== currentUrl && webampCI) {
|
||||||
fs?.readFile(url, (_error, contents = Buffer.from('')) => {
|
fs?.readFile(url, (_error, contents = Buffer.from("")) => {
|
||||||
if (extname(url) === '.mp3') {
|
if (extname(url) === ".mp3") {
|
||||||
parseTrack(contents, basename(url)).then((track) => {
|
parseTrack(contents, basename(url)).then((track) => {
|
||||||
setCurrentUrl(url);
|
setCurrentUrl(url);
|
||||||
webampCI?.appendTracks([track]);
|
webampCI?.appendTracks([track]);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
|
|
||||||
type WebampDispatchOptionalProps = {
|
type WebampDispatchOptionalProps = {
|
||||||
positions?: {
|
positions?: {
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,18 @@ import {
|
||||||
closeEqualizer,
|
closeEqualizer,
|
||||||
getWebampElement,
|
getWebampElement,
|
||||||
parseTrack,
|
parseTrack,
|
||||||
updateWebampPosition
|
updateWebampPosition,
|
||||||
} from 'components/apps/Webamp/functions';
|
} from "components/apps/Webamp/functions";
|
||||||
import type { WebampCI, WebampOptions } from 'components/apps/Webamp/types';
|
import type { WebampCI, WebampOptions } from "components/apps/Webamp/types";
|
||||||
import useWindowActions from 'components/system/Window/Titlebar/useWindowActions';
|
import useWindowActions from "components/system/Window/Titlebar/useWindowActions";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import type { Process } from 'contexts/process/types';
|
import type { Process } from "contexts/process/types";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { basename, extname } from 'path';
|
import { basename, extname } from "path";
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import { WINDOW_TRANSITION_DURATION_IN_MILLISECONDS } from 'utils/constants';
|
import { WINDOW_TRANSITION_DURATION_IN_MILLISECONDS } from "utils/constants";
|
||||||
import { bufferToUrl } from 'utils/functions';
|
import { bufferToUrl } from "utils/functions";
|
||||||
|
|
||||||
type Webamp = {
|
type Webamp = {
|
||||||
loadWebamp: (
|
loadWebamp: (
|
||||||
|
|
@ -30,16 +30,16 @@ const useWebamp = (id: string): Webamp => {
|
||||||
const { onClose, onMinimize } = useWindowActions(id);
|
const { onClose, onMinimize } = useWindowActions(id);
|
||||||
const {
|
const {
|
||||||
setWindowStates,
|
setWindowStates,
|
||||||
windowStates: { [id]: { position = undefined } = {} } = {}
|
windowStates: { [id]: { position = undefined } = {} } = {},
|
||||||
} = useSession();
|
} = useSession();
|
||||||
const {
|
const {
|
||||||
sizes: {
|
sizes: {
|
||||||
taskbar: { height: taskbarHeight }
|
taskbar: { height: taskbarHeight },
|
||||||
}
|
},
|
||||||
} = useTheme();
|
} = useTheme();
|
||||||
const {
|
const {
|
||||||
linkElement,
|
linkElement,
|
||||||
processes: { [id]: windowProcess = {} }
|
processes: { [id]: windowProcess = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { componentWindow } = windowProcess as Process;
|
const { componentWindow } = windowProcess as Process;
|
||||||
const [webampCI, setWebampCI] = useState<WebampCI | null>(null);
|
const [webampCI, setWebampCI] = useState<WebampCI | null>(null);
|
||||||
|
|
@ -52,14 +52,14 @@ const useWebamp = (id: string): Webamp => {
|
||||||
const runWebamp = (options?: WebampOptions) => {
|
const runWebamp = (options?: WebampOptions) => {
|
||||||
const webamp: WebampCI = new window.Webamp({
|
const webamp: WebampCI = new window.Webamp({
|
||||||
...BASE_WEBAMP_OPTIONS,
|
...BASE_WEBAMP_OPTIONS,
|
||||||
...options
|
...options,
|
||||||
});
|
});
|
||||||
const setupElements = () => {
|
const setupElements = () => {
|
||||||
const webampElement = getWebampElement();
|
const webampElement = getWebampElement();
|
||||||
const [main] = webampElement.getElementsByClassName('window');
|
const [main] = webampElement.getElementsByClassName("window");
|
||||||
|
|
||||||
if (!componentWindow && main && Object.keys(windowProcess).length) {
|
if (!componentWindow && main && Object.keys(windowProcess).length) {
|
||||||
linkElement(id, 'componentWindow', main as HTMLElement);
|
linkElement(id, "componentWindow", main as HTMLElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
containerElement.appendChild(webampElement);
|
containerElement.appendChild(webampElement);
|
||||||
|
|
@ -68,15 +68,15 @@ const useWebamp = (id: string): Webamp => {
|
||||||
webamp.onWillClose((cancel) => {
|
webamp.onWillClose((cancel) => {
|
||||||
cancel();
|
cancel();
|
||||||
|
|
||||||
const [main] = getWebampElement().getElementsByClassName('window');
|
const [main] = getWebampElement().getElementsByClassName("window");
|
||||||
const { x, y } = main.getBoundingClientRect();
|
const { x, y } = main.getBoundingClientRect();
|
||||||
|
|
||||||
onClose();
|
onClose();
|
||||||
setWindowStates((currentWindowStates) => ({
|
setWindowStates((currentWindowStates) => ({
|
||||||
...currentWindowStates,
|
...currentWindowStates,
|
||||||
[id]: {
|
[id]: {
|
||||||
position: { x, y }
|
position: { x, y },
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -84,7 +84,7 @@ const useWebamp = (id: string): Webamp => {
|
||||||
webamp.close();
|
webamp.close();
|
||||||
}, WINDOW_TRANSITION_DURATION_IN_MILLISECONDS);
|
}, WINDOW_TRANSITION_DURATION_IN_MILLISECONDS);
|
||||||
}),
|
}),
|
||||||
webamp.onMinimize(() => onMinimize())
|
webamp.onMinimize(() => onMinimize()),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (options?.initialSkin?.url) {
|
if (options?.initialSkin?.url) {
|
||||||
|
|
@ -101,7 +101,7 @@ const useWebamp = (id: string): Webamp => {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
if (extname(url) === '.mp3') {
|
if (extname(url) === ".mp3") {
|
||||||
parseTrack(file, basename(url)).then((track) =>
|
parseTrack(file, basename(url)).then((track) =>
|
||||||
runWebamp({ initialTracks: [track] })
|
runWebamp({ initialTracks: [track] })
|
||||||
);
|
);
|
||||||
|
|
@ -116,7 +116,7 @@ const useWebamp = (id: string): Webamp => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loadWebamp,
|
loadWebamp,
|
||||||
webampCI
|
webampCI,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Head from 'next/head';
|
import Head from "next/head";
|
||||||
import packageJson from 'package.json';
|
import packageJson from "package.json";
|
||||||
|
|
||||||
const { description, name } = packageJson;
|
const { description, name } = packageJson;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { SessionConsumer } from 'contexts/session';
|
import { SessionConsumer } from "contexts/session";
|
||||||
import { ThemeProvider } from 'styled-components';
|
import { ThemeProvider } from "styled-components";
|
||||||
import GlobalStyle from 'styles/GlobalStyle';
|
import GlobalStyle from "styles/GlobalStyle";
|
||||||
import themes from 'styles/themes';
|
import themes from "styles/themes";
|
||||||
|
|
||||||
type StyledAppProps = {
|
type StyledAppProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import RenderComponent from 'components/system/Apps/RenderComponent';
|
import RenderComponent from "components/system/Apps/RenderComponent";
|
||||||
import { ProcessConsumer } from 'contexts/process';
|
import { ProcessConsumer } from "contexts/process";
|
||||||
import { AnimatePresence } from 'framer-motion';
|
import { AnimatePresence } from "framer-motion";
|
||||||
|
|
||||||
const AppsLoader = (): JSX.Element => (
|
const AppsLoader = (): JSX.Element => (
|
||||||
<ProcessConsumer>
|
<ProcessConsumer>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const Window = dynamic(() => import('components/system/Window'));
|
const Window = dynamic(() => import("components/system/Window"));
|
||||||
|
|
||||||
export type ComponentProcessProps = {
|
export type ComponentProcessProps = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -15,7 +15,7 @@ type RenderComponentProps = {
|
||||||
const RenderComponent = ({
|
const RenderComponent = ({
|
||||||
Component,
|
Component,
|
||||||
hasWindow = true,
|
hasWindow = true,
|
||||||
id
|
id,
|
||||||
}: RenderComponentProps): JSX.Element =>
|
}: RenderComponentProps): JSX.Element =>
|
||||||
hasWindow ? (
|
hasWindow ? (
|
||||||
<Window id={id}>
|
<Window id={id}>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledDesktop = styled.main`
|
const StyledDesktop = styled.main`
|
||||||
background-color: ${({ theme }) => theme.colors.background};
|
background-color: ${({ theme }) => theme.colors.background};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import StyledDesktop from 'components/system/Desktop/StyledDesktop';
|
import StyledDesktop from "components/system/Desktop/StyledDesktop";
|
||||||
import useWallpaper from 'components/system/Desktop/wallpapers/useWallpaper';
|
import useWallpaper from "components/system/Desktop/wallpapers/useWallpaper";
|
||||||
import { useRef } from 'react';
|
import { useRef } from "react";
|
||||||
|
|
||||||
type DesktopProps = {
|
type DesktopProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { adjustHue } from 'polished';
|
import { adjustHue } from "polished";
|
||||||
import { MILLISECONDS_IN_SECOND } from 'utils/constants';
|
import { MILLISECONDS_IN_SECOND } from "utils/constants";
|
||||||
|
|
||||||
const fps = 15;
|
const fps = 15;
|
||||||
const timePerFrame = MILLISECONDS_IN_SECOND / fps;
|
const timePerFrame = MILLISECONDS_IN_SECOND / fps;
|
||||||
|
|
@ -26,7 +26,7 @@ const colorCycle = (
|
||||||
|
|
||||||
callback(
|
callback(
|
||||||
Number(
|
Number(
|
||||||
adjustHue(degree, `#${initialColor.toString(16)}`).replace('#', '0x')
|
adjustHue(degree, `#${initialColor.toString(16)}`).replace("#", "0x")
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from "react";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
|
|
||||||
const useWallpaper = (
|
const useWallpaper = (
|
||||||
desktopRef: React.RefObject<HTMLElement | null>
|
desktopRef: React.RefObject<HTMLElement | null>
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
import colorCycle from 'components/system/Desktop/wallpapers/colorCycle';
|
import colorCycle from "components/system/Desktop/wallpapers/colorCycle";
|
||||||
import type { VantaWavesConfig } from 'components/system/Desktop/wallpapers/vantaWaves/types';
|
import type { VantaWavesConfig } from "components/system/Desktop/wallpapers/vantaWaves/types";
|
||||||
import { loadFiles } from 'utils/functions';
|
import { loadFiles } from "utils/functions";
|
||||||
|
|
||||||
const disableControls = {
|
const disableControls = {
|
||||||
mouseControls: false,
|
mouseControls: false,
|
||||||
touchControls: false
|
touchControls: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const isWebGLAvailable = typeof WebGLRenderingContext !== 'undefined';
|
const isWebGLAvailable = typeof WebGLRenderingContext !== "undefined";
|
||||||
|
|
||||||
const libs = ['/libs/vanta/three.min.js', '/libs/vanta/vanta.waves.min.js'];
|
const libs = ["/libs/vanta/three.min.js", "/libs/vanta/vanta.waves.min.js"];
|
||||||
|
|
||||||
const vantaWaves =
|
const vantaWaves =
|
||||||
(config: VantaWavesConfig) =>
|
(config: VantaWavesConfig) =>
|
||||||
(el: HTMLElement | null): void => {
|
(el: HTMLElement | null): void => {
|
||||||
loadFiles(libs).then(() => {
|
loadFiles(libs).then(() => {
|
||||||
const {
|
const {
|
||||||
VANTA: { current: currentEffect, WAVES }
|
VANTA: { current: currentEffect, WAVES },
|
||||||
} = window;
|
} = window;
|
||||||
currentEffect?.destroy();
|
currentEffect?.destroy();
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ const vantaWaves =
|
||||||
? WAVES({
|
? WAVES({
|
||||||
el,
|
el,
|
||||||
...disableControls,
|
...disableControls,
|
||||||
...config
|
...config,
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import StyledRenameBox from 'components/system/Files/Views/StyledRenameBox';
|
import StyledRenameBox from "components/system/Files/Views/StyledRenameBox";
|
||||||
import { extname } from 'path';
|
import { extname } from "path";
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
type RenameBoxProps = {
|
type RenameBoxProps = {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -21,7 +21,7 @@ const RenameBox = ({ name, path, renameFile }: RenameBoxProps): JSX.Element => {
|
||||||
<StyledRenameBox
|
<StyledRenameBox
|
||||||
defaultValue={name}
|
defaultValue={name}
|
||||||
onBlur={saveRename}
|
onBlur={saveRename}
|
||||||
onKeyDown={({ key }) => key === 'Enter' && saveRename()}
|
onKeyDown={({ key }) => key === "Enter" && saveRename()}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,37 +6,37 @@ type Extensions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const extensions: Extensions = {
|
export const extensions: Extensions = {
|
||||||
'.img': {
|
".img": {
|
||||||
icon: 'image',
|
icon: "image",
|
||||||
process: ['V86']
|
process: ["V86"],
|
||||||
},
|
},
|
||||||
'.iso': {
|
".iso": {
|
||||||
icon: 'image',
|
icon: "image",
|
||||||
process: ['FileExplorer', 'V86']
|
process: ["FileExplorer", "V86"],
|
||||||
},
|
},
|
||||||
'.jsdos': {
|
".jsdos": {
|
||||||
icon: 'compressed',
|
icon: "compressed",
|
||||||
process: ['JSDOS']
|
process: ["JSDOS"],
|
||||||
},
|
},
|
||||||
'.mp3': {
|
".mp3": {
|
||||||
icon: 'music',
|
icon: "music",
|
||||||
process: ['Webamp']
|
process: ["Webamp"],
|
||||||
},
|
},
|
||||||
'.wsz': {
|
".wsz": {
|
||||||
icon: 'music',
|
icon: "music",
|
||||||
process: ['Webamp']
|
process: ["Webamp"],
|
||||||
|
},
|
||||||
|
".zip": {
|
||||||
|
icon: "compressed",
|
||||||
|
process: ["FileExplorer", "JSDOS"],
|
||||||
},
|
},
|
||||||
'.zip': {
|
|
||||||
icon: 'compressed',
|
|
||||||
process: ['FileExplorer', 'JSDOS']
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getIconByFileExtension = (extension: string): string =>
|
export const getIconByFileExtension = (extension: string): string =>
|
||||||
`/icons/${extensions[extension]?.icon || 'unknown'}.png`;
|
`/icons/${extensions[extension]?.icon || "unknown"}.png`;
|
||||||
|
|
||||||
export const getProcessByFileExtension = (extension: string): string => {
|
export const getProcessByFileExtension = (extension: string): string => {
|
||||||
const [defaultProcess = ''] = extensions[extension]?.process || [];
|
const [defaultProcess = ""] = extensions[extension]?.process || [];
|
||||||
|
|
||||||
return defaultProcess;
|
return defaultProcess;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import RenameBox from 'components/system/Files/FileEntry/RenameBox';
|
import RenameBox from "components/system/Files/FileEntry/RenameBox";
|
||||||
import useContextMenu from 'components/system/Files/FileEntry/useContextMenu';
|
import useContextMenu from "components/system/Files/FileEntry/useContextMenu";
|
||||||
import useFile from 'components/system/Files/FileEntry/useFile';
|
import useFile from "components/system/Files/FileEntry/useFile";
|
||||||
import useFileInfo from 'components/system/Files/FileEntry/useFileInfo';
|
import useFileInfo from "components/system/Files/FileEntry/useFileInfo";
|
||||||
import { FileEntryIconSize } from 'components/system/Files/Views';
|
import { FileEntryIconSize } from "components/system/Files/Views";
|
||||||
import useDoubleClick from 'components/system/useDoubleClick';
|
import useDoubleClick from "components/system/useDoubleClick";
|
||||||
import { useMenu } from 'contexts/menu';
|
import { useMenu } from "contexts/menu";
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import Button from 'styles/common/Button';
|
import Button from "styles/common/Button";
|
||||||
import Icon from 'styles/common/Icon';
|
import Icon from "styles/common/Icon";
|
||||||
|
|
||||||
type FileEntryProps = {
|
type FileEntryProps = {
|
||||||
deleteFile: (path: string) => void;
|
deleteFile: (path: string) => void;
|
||||||
|
|
@ -22,7 +22,7 @@ const FileEntry = ({
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
renameFile,
|
renameFile,
|
||||||
view
|
view,
|
||||||
}: FileEntryProps): JSX.Element => {
|
}: FileEntryProps): JSX.Element => {
|
||||||
const { icon, pid, url } = useFileInfo(path);
|
const { icon, pid, url } = useFileInfo(path);
|
||||||
const [renaming, setRenaming] = useState(false);
|
const [renaming, setRenaming] = useState(false);
|
||||||
|
|
@ -31,7 +31,7 @@ const FileEntry = ({
|
||||||
const deleteEntry = () => deleteFile(path);
|
const deleteEntry = () => deleteFile(path);
|
||||||
const renameEntry = () => setRenaming(true);
|
const renameEntry = () => setRenaming(true);
|
||||||
const menu = useContextMenu(url, pid, path, deleteEntry, renameEntry);
|
const menu = useContextMenu(url, pid, path, deleteEntry, renameEntry);
|
||||||
const singleClick = view === 'list';
|
const singleClick = view === "list";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { extensions } from 'components/system/Files/FileEntry/functions';
|
import { extensions } from "components/system/Files/FileEntry/functions";
|
||||||
import useFile from 'components/system/Files/FileEntry/useFile';
|
import useFile from "components/system/Files/FileEntry/useFile";
|
||||||
import type { MenuItem } from 'contexts/menu/useMenuContextState';
|
import type { MenuItem } from "contexts/menu/useMenuContextState";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import processDirectory from 'contexts/process/directory';
|
import processDirectory from "contexts/process/directory";
|
||||||
import { dirname, extname } from 'path';
|
import { dirname, extname } from "path";
|
||||||
import { SHORTCUT_EXTENSION } from 'utils/constants';
|
import { SHORTCUT_EXTENSION } from "utils/constants";
|
||||||
|
|
||||||
const useContextMenu = (
|
const useContextMenu = (
|
||||||
url: string,
|
url: string,
|
||||||
|
|
@ -19,40 +19,40 @@ const useContextMenu = (
|
||||||
const { icon: pidIcon } = processDirectory[pid] || {};
|
const { icon: pidIcon } = processDirectory[pid] || {};
|
||||||
const openFile = useFile(url);
|
const openFile = useFile(url);
|
||||||
const menuItems: MenuItem[] = [
|
const menuItems: MenuItem[] = [
|
||||||
{ label: 'Delete', action: deleteFile },
|
{ label: "Delete", action: deleteFile },
|
||||||
{ label: 'Rename', action: renameFile }
|
{ label: "Rename", action: renameFile },
|
||||||
];
|
];
|
||||||
|
|
||||||
if (pid) {
|
if (pid) {
|
||||||
const isShortcut =
|
const isShortcut =
|
||||||
extname(path) === SHORTCUT_EXTENSION && url && url !== '/';
|
extname(path) === SHORTCUT_EXTENSION && url && url !== "/";
|
||||||
|
|
||||||
menuItems.unshift({ separator: 1 });
|
menuItems.unshift({ separator: 1 });
|
||||||
|
|
||||||
if (openWithFiltered.length) {
|
if (openWithFiltered.length) {
|
||||||
menuItems.unshift({
|
menuItems.unshift({
|
||||||
label: 'Open with',
|
label: "Open with",
|
||||||
menu: openWithFiltered.map((id): MenuItem => {
|
menu: openWithFiltered.map((id): MenuItem => {
|
||||||
const { icon, title: label } = processDirectory[id] || {};
|
const { icon, title: label } = processDirectory[id] || {};
|
||||||
const action = () => openFile(id);
|
const action = () => openFile(id);
|
||||||
|
|
||||||
return { icon, label, action };
|
return { icon, label, action };
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isShortcut) {
|
if (isShortcut) {
|
||||||
menuItems.unshift({
|
menuItems.unshift({
|
||||||
label: 'Open file location',
|
label: "Open file location",
|
||||||
action: () => open('FileExplorer', dirname(url))
|
action: () => open("FileExplorer", dirname(url)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItems.unshift({
|
menuItems.unshift({
|
||||||
icon: isShortcut || extname(url) ? pidIcon : undefined,
|
icon: isShortcut || extname(url) ? pidIcon : undefined,
|
||||||
label: 'Open',
|
label: "Open",
|
||||||
primary: true,
|
primary: true,
|
||||||
action: () => openFile(pid)
|
action: () => openFile(pid),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { createPid } from 'contexts/process/functions';
|
import { createPid } from "contexts/process/functions";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
|
|
||||||
type UseFile = (pid: string) => void;
|
type UseFile = (pid: string) => void;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
getIconByFileExtension,
|
getIconByFileExtension,
|
||||||
getProcessByFileExtension
|
getProcessByFileExtension,
|
||||||
} from 'components/system/Files/FileEntry/functions';
|
} from "components/system/Files/FileEntry/functions";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import ini from 'ini';
|
import ini from "ini";
|
||||||
import { parseBuffer } from 'music-metadata-browser';
|
import { parseBuffer } from "music-metadata-browser";
|
||||||
import { extname } from 'path';
|
import { extname } from "path";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { IMAGE_FILE_EXTENSIONS, SHORTCUT_EXTENSION } from 'utils/constants';
|
import { IMAGE_FILE_EXTENSIONS, SHORTCUT_EXTENSION } from "utils/constants";
|
||||||
import { bufferToUrl } from 'utils/functions';
|
import { bufferToUrl } from "utils/functions";
|
||||||
|
|
||||||
type FileInfo = {
|
type FileInfo = {
|
||||||
icon: string;
|
icon: string;
|
||||||
|
|
@ -18,9 +18,9 @@ type FileInfo = {
|
||||||
|
|
||||||
const useFileInfo = (path: string): FileInfo => {
|
const useFileInfo = (path: string): FileInfo => {
|
||||||
const [info, setInfo] = useState<FileInfo>({
|
const [info, setInfo] = useState<FileInfo>({
|
||||||
icon: '',
|
icon: "",
|
||||||
pid: '',
|
pid: "",
|
||||||
url: ''
|
url: "",
|
||||||
});
|
});
|
||||||
const { fs } = useFileSystem();
|
const { fs } = useFileSystem();
|
||||||
|
|
||||||
|
|
@ -33,9 +33,9 @@ const useFileInfo = (path: string): FileInfo => {
|
||||||
const isDirectory = stats ? stats.isDirectory() : false;
|
const isDirectory = stats ? stats.isDirectory() : false;
|
||||||
|
|
||||||
setInfo({
|
setInfo({
|
||||||
icon: `/icons/${isDirectory ? 'folder.png' : 'unknown.png'}`,
|
icon: `/icons/${isDirectory ? "folder.png" : "unknown.png"}`,
|
||||||
pid: isDirectory ? 'FileExplorer' : '',
|
pid: isDirectory ? "FileExplorer" : "",
|
||||||
url: path
|
url: path,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -43,39 +43,39 @@ const useFileInfo = (path: string): FileInfo => {
|
||||||
setInfo({
|
setInfo({
|
||||||
icon: icon || getIconByFileExtension(extension),
|
icon: icon || getIconByFileExtension(extension),
|
||||||
pid: getProcessByFileExtension(extension),
|
pid: getProcessByFileExtension(extension),
|
||||||
url: path
|
url: path,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (extension === SHORTCUT_EXTENSION) {
|
if (extension === SHORTCUT_EXTENSION) {
|
||||||
fs.readFile(path, (error, contents = Buffer.from('')) => {
|
fs.readFile(path, (error, contents = Buffer.from("")) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
getInfoByFileExtension();
|
getInfoByFileExtension();
|
||||||
} else {
|
} else {
|
||||||
const {
|
const {
|
||||||
InternetShortcut: {
|
InternetShortcut: {
|
||||||
BaseURL: pid = '',
|
BaseURL: pid = "",
|
||||||
IconFile: icon = '',
|
IconFile: icon = "",
|
||||||
URL: url = ''
|
URL: url = "",
|
||||||
}
|
},
|
||||||
} = ini.parse(contents.toString());
|
} = ini.parse(contents.toString());
|
||||||
|
|
||||||
setInfo({ icon, pid, url });
|
setInfo({ icon, pid, url });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (IMAGE_FILE_EXTENSIONS.includes(extension)) {
|
} else if (IMAGE_FILE_EXTENSIONS.includes(extension)) {
|
||||||
fs.readFile(path, (error, contents = Buffer.from('')) =>
|
fs.readFile(path, (error, contents = Buffer.from("")) =>
|
||||||
getInfoByFileExtension(
|
getInfoByFileExtension(
|
||||||
error ? '/icons/photo.png' : bufferToUrl(contents)
|
error ? "/icons/photo.png" : bufferToUrl(contents)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (extension === '.mp3') {
|
} else if (extension === ".mp3") {
|
||||||
fs.readFile(path, (error, contents = Buffer.from('')) =>
|
fs.readFile(path, (error, contents = Buffer.from("")) =>
|
||||||
parseBuffer(contents).then(
|
parseBuffer(contents).then(
|
||||||
({ common: { picture: [picture] = [] } = {} }) =>
|
({ common: { picture: [picture] = [] } = {} }) =>
|
||||||
getInfoByFileExtension(
|
getInfoByFileExtension(
|
||||||
!error && picture
|
!error && picture
|
||||||
? bufferToUrl(picture.data)
|
? bufferToUrl(picture.data)
|
||||||
: '/icons/music.png'
|
: "/icons/music.png"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import FileEntry from 'components/system/Files/FileEntry';
|
import FileEntry from "components/system/Files/FileEntry";
|
||||||
import useFileDrop from 'components/system/Files/FileManager/useFileDrop';
|
import useFileDrop from "components/system/Files/FileManager/useFileDrop";
|
||||||
import useFiles from 'components/system/Files/FileManager/useFiles';
|
import useFiles from "components/system/Files/FileManager/useFiles";
|
||||||
import type { FileManagerViewNames } from 'components/system/Files/Views';
|
import type { FileManagerViewNames } from "components/system/Files/Views";
|
||||||
import { FileManagerViews } from 'components/system/Files/Views';
|
import { FileManagerViews } from "components/system/Files/Views";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { basename, extname, resolve } from 'path';
|
import { basename, extname, resolve } from "path";
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from "react";
|
||||||
import { MOUNTABLE_EXTENSIONS, SHORTCUT_EXTENSION } from 'utils/constants';
|
import { MOUNTABLE_EXTENSIONS, SHORTCUT_EXTENSION } from "utils/constants";
|
||||||
|
|
||||||
type FileManagerProps = {
|
type FileManagerProps = {
|
||||||
url: string;
|
url: string;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { basename, dirname, extname } from 'path';
|
import { basename, dirname, extname } from "path";
|
||||||
|
|
||||||
const haltDragEvent = (event: React.DragEvent<HTMLElement>): void => {
|
const haltDragEvent = (event: React.DragEvent<HTMLElement>): void => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -35,8 +35,8 @@ const useFileDrop = (
|
||||||
): void => {
|
): void => {
|
||||||
const writePath = !iteration ? path : iterateFileName(path, iteration);
|
const writePath = !iteration ? path : iterateFileName(path, iteration);
|
||||||
|
|
||||||
fs?.writeFile(writePath, fileBuffer, { flag: 'wx' }, (error) => {
|
fs?.writeFile(writePath, fileBuffer, { flag: "wx" }, (error) => {
|
||||||
if (error?.code === 'EEXIST') {
|
if (error?.code === "EEXIST") {
|
||||||
writeUniqueName(path, fileBuffer, iteration + 1);
|
writeUniqueName(path, fileBuffer, iteration + 1);
|
||||||
} else if (!error) {
|
} else if (!error) {
|
||||||
updateFiles(writePath);
|
updateFiles(writePath);
|
||||||
|
|
@ -61,7 +61,7 @@ const useFileDrop = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onDragOver: haltDragEvent,
|
onDragOver: haltDragEvent,
|
||||||
onDrop
|
onDrop,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { basename } from 'path';
|
import { basename } from "path";
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { SHORTCUT_EXTENSION } from 'utils/constants';
|
import { SHORTCUT_EXTENSION } from "utils/constants";
|
||||||
|
|
||||||
type Files = {
|
type Files = {
|
||||||
deleteFile: (path: string) => void;
|
deleteFile: (path: string) => void;
|
||||||
|
|
@ -14,7 +14,7 @@ const useFiles = (directory: string): Files => {
|
||||||
const [files, setFiles] = useState<string[]>([]);
|
const [files, setFiles] = useState<string[]>([]);
|
||||||
const { fs } = useFileSystem();
|
const { fs } = useFileSystem();
|
||||||
const updateFiles = useCallback(
|
const updateFiles = useCallback(
|
||||||
(appendFile = '') =>
|
(appendFile = "") =>
|
||||||
fs?.readdir(directory, (_error, contents = []) =>
|
fs?.readdir(directory, (_error, contents = []) =>
|
||||||
setFiles((currentFiles) =>
|
setFiles((currentFiles) =>
|
||||||
appendFile ? [...currentFiles, basename(appendFile)] : contents
|
appendFile ? [...currentFiles, basename(appendFile)] : contents
|
||||||
|
|
@ -31,7 +31,7 @@ const useFiles = (directory: string): Files => {
|
||||||
const renameFile = (path: string, name?: string) => {
|
const renameFile = (path: string, name?: string) => {
|
||||||
if (name) {
|
if (name) {
|
||||||
const newPath = `${directory}/${name}${
|
const newPath = `${directory}/${name}${
|
||||||
path.endsWith(SHORTCUT_EXTENSION) ? SHORTCUT_EXTENSION : ''
|
path.endsWith(SHORTCUT_EXTENSION) ? SHORTCUT_EXTENSION : ""
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
fs?.rename(path, newPath, () =>
|
fs?.rename(path, newPath, () =>
|
||||||
|
|
@ -50,7 +50,7 @@ const useFiles = (directory: string): Files => {
|
||||||
deleteFile,
|
deleteFile,
|
||||||
files,
|
files,
|
||||||
renameFile,
|
renameFile,
|
||||||
updateFiles
|
updateFiles,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledFileEntry = styled.li`
|
const StyledFileEntry = styled.li`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -13,7 +13,7 @@ const StyledFileEntry = styled.li`
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
bottom: -1px;
|
bottom: -1px;
|
||||||
content: '';
|
content: "";
|
||||||
left: -1px;
|
left: -1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -1px;
|
right: -1px;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import StyledWindow from 'components/system/Window/StyledWindow';
|
import StyledWindow from "components/system/Window/StyledWindow";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledFileManager = styled.ol`
|
const StyledFileManager = styled.ol`
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledFileEntry = styled.li`
|
const StyledFileEntry = styled.li`
|
||||||
figure {
|
figure {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledFileManager = styled.ol`
|
const StyledFileManager = styled.ol`
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledRenameBox = styled.input.attrs({
|
const StyledRenameBox = styled.input.attrs({
|
||||||
spellCheck: false,
|
spellCheck: false,
|
||||||
type: 'text'
|
type: "text",
|
||||||
})`
|
})`
|
||||||
border: 1px solid rgb(100, 100, 100);
|
border: 1px solid rgb(100, 100, 100);
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
import StyledIconFileEntry from 'components/system/Files/Views/Icon/StyledFileEntry';
|
import StyledIconFileEntry from "components/system/Files/Views/Icon/StyledFileEntry";
|
||||||
import StyledIconFileManager from 'components/system/Files/Views/Icon/StyledFileManager';
|
import StyledIconFileManager from "components/system/Files/Views/Icon/StyledFileManager";
|
||||||
import StyledListFileEntry from 'components/system/Files/Views/List/StyledFileEntry';
|
import StyledListFileEntry from "components/system/Files/Views/List/StyledFileEntry";
|
||||||
import StyledListFileManager from 'components/system/Files/Views/List/StyledFileManager';
|
import StyledListFileManager from "components/system/Files/Views/List/StyledFileManager";
|
||||||
import type { DefaultTheme, StyledComponent } from 'styled-components';
|
import type { DefaultTheme, StyledComponent } from "styled-components";
|
||||||
import type { IconProps } from 'styles/common/Icon';
|
import type { IconProps } from "styles/common/Icon";
|
||||||
|
|
||||||
type FileManagerView = {
|
type FileManagerView = {
|
||||||
StyledFileEntry: StyledComponent<'li', DefaultTheme>;
|
StyledFileEntry: StyledComponent<"li", DefaultTheme>;
|
||||||
StyledFileManager: StyledComponent<'ol', DefaultTheme>;
|
StyledFileManager: StyledComponent<"ol", DefaultTheme>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FileManagerViewNames = 'icon' | 'list';
|
export type FileManagerViewNames = "icon" | "list";
|
||||||
|
|
||||||
export const FileManagerViews: Record<FileManagerViewNames, FileManagerView> = {
|
export const FileManagerViews: Record<FileManagerViewNames, FileManagerView> = {
|
||||||
icon: {
|
icon: {
|
||||||
StyledFileEntry: StyledIconFileEntry,
|
StyledFileEntry: StyledIconFileEntry,
|
||||||
StyledFileManager: StyledIconFileManager
|
StyledFileManager: StyledIconFileManager,
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
StyledFileEntry: StyledListFileEntry,
|
StyledFileEntry: StyledListFileEntry,
|
||||||
StyledFileManager: StyledListFileManager
|
StyledFileManager: StyledListFileManager,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FileEntryIconSize: { [view: string]: IconProps } = {
|
export const FileEntryIconSize: { [view: string]: IconProps } = {
|
||||||
icon: {
|
icon: {
|
||||||
imgSize: 48
|
imgSize: 48,
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
displaySize: 24,
|
displaySize: 24,
|
||||||
imgSize: 48
|
imgSize: 48,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import Menu from 'components/system/Menu';
|
import Menu from "components/system/Menu";
|
||||||
import { ChevronRight } from 'components/system/Menu/MenuIcons';
|
import { ChevronRight } from "components/system/Menu/MenuIcons";
|
||||||
import type { MenuItem } from 'contexts/menu/useMenuContextState';
|
import type { MenuItem } from "contexts/menu/useMenuContextState";
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from "react";
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import Icon from 'styles/common/Icon';
|
import Icon from "styles/common/Icon";
|
||||||
|
|
||||||
type MenuItemEntryProps = MenuItem & {
|
type MenuItemEntryProps = MenuItem & {
|
||||||
resetMenu: () => void;
|
resetMenu: () => void;
|
||||||
|
|
@ -17,7 +17,7 @@ const MenuItemEntry = ({
|
||||||
menu,
|
menu,
|
||||||
primary,
|
primary,
|
||||||
resetMenu,
|
resetMenu,
|
||||||
separator
|
separator,
|
||||||
}: MenuItemEntryProps): JSX.Element => {
|
}: MenuItemEntryProps): JSX.Element => {
|
||||||
const entryRef = useRef<HTMLLIElement | null>(null);
|
const entryRef = useRef<HTMLLIElement | null>(null);
|
||||||
const [subMenuOffset, setSubMenuOffset] = useState<Position>({ x: 0, y: 0 });
|
const [subMenuOffset, setSubMenuOffset] = useState<Position>({ x: 0, y: 0 });
|
||||||
|
|
@ -37,7 +37,7 @@ const MenuItemEntry = ({
|
||||||
|
|
||||||
setSubMenuOffset({
|
setSubMenuOffset({
|
||||||
x: width - sizes.contextMenu.subMenuOffset,
|
x: width - sizes.contextMenu.subMenuOffset,
|
||||||
y: -height - sizes.contextMenu.subMenuOffset
|
y: -height - sizes.contextMenu.subMenuOffset,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [menu, sizes.contextMenu.subMenuOffset]);
|
}, [menu, sizes.contextMenu.subMenuOffset]);
|
||||||
|
|
@ -48,7 +48,7 @@ const MenuItemEntry = ({
|
||||||
<hr />
|
<hr />
|
||||||
) : (
|
) : (
|
||||||
<figure
|
<figure
|
||||||
className={showSubMenu ? 'active' : ''}
|
className={showSubMenu ? "active" : ""}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
action?.();
|
action?.();
|
||||||
resetMenu();
|
resetMenu();
|
||||||
|
|
@ -56,7 +56,7 @@ const MenuItemEntry = ({
|
||||||
{...subMenuEvents}
|
{...subMenuEvents}
|
||||||
>
|
>
|
||||||
{icon && <Icon src={icon} alt={label} imgSize={16} />}
|
{icon && <Icon src={icon} alt={label} imgSize={16} />}
|
||||||
<figcaption className={primary ? 'primary' : ''}>{label}</figcaption>
|
<figcaption className={primary ? "primary" : ""}>{label}</figcaption>
|
||||||
{menu && <ChevronRight />}
|
{menu && <ChevronRight />}
|
||||||
</figure>
|
</figure>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type StyledMenuProps = {
|
type StyledMenuProps = {
|
||||||
isSubMenu: boolean;
|
isSubMenu: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import MenuItemEntry from 'components/system/Menu/MenuItemEntry';
|
import MenuItemEntry from "components/system/Menu/MenuItemEntry";
|
||||||
import StyledMenu from 'components/system/Menu/StyledMenu';
|
import StyledMenu from "components/system/Menu/StyledMenu";
|
||||||
import { useMenu } from 'contexts/menu/index';
|
import { useMenu } from "contexts/menu/index";
|
||||||
import type { MenuState } from 'contexts/menu/useMenuContextState';
|
import type { MenuState } from "contexts/menu/useMenuContextState";
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
type MenuProps = {
|
type MenuProps = {
|
||||||
subMenu?: MenuState;
|
subMenu?: MenuState;
|
||||||
|
|
@ -13,7 +13,7 @@ const Menu = ({ subMenu }: MenuProps): JSX.Element => {
|
||||||
const { items, x = 0, y = 0 } = subMenu || baseMenu;
|
const { items, x = 0, y = 0 } = subMenu || baseMenu;
|
||||||
const menuRef = useRef<HTMLElement | null>(null);
|
const menuRef = useRef<HTMLElement | null>(null);
|
||||||
const resetMenu = ({
|
const resetMenu = ({
|
||||||
relatedTarget
|
relatedTarget,
|
||||||
}: Partial<FocusEvent | MouseEvent> = {}) => {
|
}: Partial<FocusEvent | MouseEvent> = {}) => {
|
||||||
if (!menuRef.current?.contains(relatedTarget as HTMLElement)) {
|
if (!menuRef.current?.contains(relatedTarget as HTMLElement)) {
|
||||||
setMenu({});
|
setMenu({});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
|
|
||||||
export const AllApps = (): JSX.Element => (
|
export const AllApps = (): JSX.Element => (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledSidebar = styled.nav`
|
const StyledSidebar = styled.nav`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type StyledSidebarButtonProps = {
|
type StyledSidebarButtonProps = {
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
|
@ -14,8 +14,8 @@ const StyledSidebarButton = styled.li<StyledSidebarButtonProps>`
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
border-left: ${({ active, theme }) =>
|
border-left: ${({ active, theme }) =>
|
||||||
`4px solid ${active ? theme.colors.highlight : 'transparent'}`};
|
`4px solid ${active ? theme.colors.highlight : "transparent"}`};
|
||||||
content: '';
|
content: "";
|
||||||
height: 48px;
|
height: 48px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 48px;
|
width: 48px;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import {
|
||||||
AllApps,
|
AllApps,
|
||||||
Documents,
|
Documents,
|
||||||
Power,
|
Power,
|
||||||
SideMenu
|
SideMenu,
|
||||||
} from 'components/system/StartMenu/Sidebar/SidebarIcons';
|
} from "components/system/StartMenu/Sidebar/SidebarIcons";
|
||||||
import StyledSidebar from 'components/system/StartMenu/Sidebar/StyledSidebar';
|
import StyledSidebar from "components/system/StartMenu/Sidebar/StyledSidebar";
|
||||||
import StyledSidebarButton from 'components/system/StartMenu/Sidebar/StyledSidebarButton';
|
import StyledSidebarButton from "components/system/StartMenu/Sidebar/StyledSidebarButton";
|
||||||
|
|
||||||
type SidebarButtonProps = {
|
type SidebarButtonProps = {
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
|
@ -14,13 +14,13 @@ type SidebarButtonProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const topButtons = [
|
const topButtons = [
|
||||||
{ name: 'START', icon: <SideMenu /> },
|
{ name: "START", icon: <SideMenu /> },
|
||||||
{ name: 'All apps', icon: <AllApps />, active: true }
|
{ name: "All apps", icon: <AllApps />, active: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
const bottomButtons = [
|
const bottomButtons = [
|
||||||
{ name: 'Documents', icon: <Documents /> },
|
{ name: "Documents", icon: <Documents /> },
|
||||||
{ name: 'Power', icon: <Power /> }
|
{ name: "Power", icon: <Power /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
const SidebarButton = ({ active, icon, name }: SidebarButtonProps) => (
|
const SidebarButton = ({ active, icon, name }: SidebarButtonProps) => (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledStartMenu = styled.nav`
|
const StyledStartMenu = styled.nav`
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
import FileManager from 'components/system/Files/FileManager';
|
import FileManager from "components/system/Files/FileManager";
|
||||||
import Sidebar from 'components/system/StartMenu/Sidebar';
|
import Sidebar from "components/system/StartMenu/Sidebar";
|
||||||
import StyledStartMenu from 'components/system/StartMenu/StyledStartMenu';
|
import StyledStartMenu from "components/system/StartMenu/StyledStartMenu";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
const StartMenu = (): JSX.Element => {
|
const StartMenu = (): JSX.Element => {
|
||||||
const { toggleStartMenu } = useSession();
|
const { toggleStartMenu } = useSession();
|
||||||
const menuRef = useRef<HTMLElement | null>(null);
|
const menuRef = useRef<HTMLElement | null>(null);
|
||||||
const maybeCloseMenu: React.FocusEventHandler<HTMLElement> = ({
|
const maybeCloseMenu: React.FocusEventHandler<HTMLElement> = ({
|
||||||
relatedTarget
|
relatedTarget,
|
||||||
}) => {
|
}) => {
|
||||||
if (!menuRef.current?.contains(relatedTarget as HTMLElement)) {
|
if (!menuRef.current?.contains(relatedTarget as HTMLElement)) {
|
||||||
if (
|
if (
|
||||||
menuRef.current?.nextSibling &&
|
menuRef.current?.nextSibling &&
|
||||||
![
|
![
|
||||||
relatedTarget,
|
relatedTarget,
|
||||||
(relatedTarget as HTMLElement)?.parentElement
|
(relatedTarget as HTMLElement)?.parentElement,
|
||||||
].includes(menuRef.current?.nextSibling)
|
].includes(menuRef.current?.nextSibling)
|
||||||
) {
|
) {
|
||||||
toggleStartMenu(false);
|
toggleStartMenu(false);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledClock = styled.time`
|
const StyledClock = styled.time`
|
||||||
color: ${({ theme }) => theme.colors.text};
|
color: ${({ theme }) => theme.colors.text};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import StyledClock from 'components/system/Taskbar/Clock/StyledClock';
|
import StyledClock from "components/system/Taskbar/Clock/StyledClock";
|
||||||
import useClock from 'components/system/Taskbar/Clock/useClock';
|
import useClock from "components/system/Taskbar/Clock/useClock";
|
||||||
import useLocaleDateTime from 'components/system/Taskbar/Clock/useLocaleDateTime';
|
import useLocaleDateTime from "components/system/Taskbar/Clock/useLocaleDateTime";
|
||||||
|
|
||||||
const Clock = (): JSX.Element => {
|
const Clock = (): JSX.Element => {
|
||||||
const now = useClock();
|
const now = useClock();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { MILLISECONDS_IN_SECOND } from 'utils/constants';
|
import { MILLISECONDS_IN_SECOND } from "utils/constants";
|
||||||
|
|
||||||
const useClock = (): Date => {
|
const useClock = (): Date => {
|
||||||
const [now, setNow] = useState(new Date());
|
const [now, setNow] = useState(new Date());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import { DEFAULT_LOCALE } from 'utils/constants';
|
import { DEFAULT_LOCALE } from "utils/constants";
|
||||||
|
|
||||||
type LocaleTimeDate = {
|
type LocaleTimeDate = {
|
||||||
date: string;
|
date: string;
|
||||||
|
|
@ -14,7 +14,7 @@ const useLocaleDateTime = (now: Date): LocaleTimeDate => {
|
||||||
formats.date
|
formats.date
|
||||||
).format(now);
|
).format(now);
|
||||||
const day = new Intl.DateTimeFormat(DEFAULT_LOCALE, {
|
const day = new Intl.DateTimeFormat(DEFAULT_LOCALE, {
|
||||||
weekday: 'long'
|
weekday: "long",
|
||||||
}).format(now);
|
}).format(now);
|
||||||
const date = `${formattedDate}\n${day}`;
|
const date = `${formattedDate}\n${day}`;
|
||||||
const time = new Intl.DateTimeFormat(DEFAULT_LOCALE, formats.time).format(
|
const time = new Intl.DateTimeFormat(DEFAULT_LOCALE, formats.time).format(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import Button from 'styles/common/Button';
|
import Button from "styles/common/Button";
|
||||||
|
|
||||||
type StyledStartButtonProps = {
|
type StyledStartButtonProps = {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import StyledStartButton from 'components/system/Taskbar/StartButton/StyledStartButton';
|
import StyledStartButton from "components/system/Taskbar/StartButton/StyledStartButton";
|
||||||
import WindowsIcon from 'components/system/Taskbar/StartButton/WindowsIcon';
|
import WindowsIcon from "components/system/Taskbar/StartButton/WindowsIcon";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
|
|
||||||
const StartButton = (): JSX.Element => {
|
const StartButton = (): JSX.Element => {
|
||||||
const { startMenuVisible, toggleStartMenu } = useSession();
|
const { startMenuVisible, toggleStartMenu } = useSession();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledTaskbar = styled.nav`
|
const StyledTaskbar = styled.nav`
|
||||||
backdrop-filter: ${({ theme }) => `blur(${theme.sizes.taskbar.blur})`};
|
backdrop-filter: ${({ theme }) => `blur(${theme.sizes.taskbar.blur})`};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledTaskbarEntries = styled.ol`
|
const StyledTaskbarEntries = styled.ol`
|
||||||
column-gap: 1px;
|
column-gap: 1px;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import StyledTaskbarEntries from 'components/system/Taskbar/TaskbarEntries/StyledTaskbarEntries';
|
import StyledTaskbarEntries from "components/system/Taskbar/TaskbarEntries/StyledTaskbarEntries";
|
||||||
import TaskbarEntry from 'components/system/Taskbar/TaskbarEntry';
|
import TaskbarEntry from "components/system/Taskbar/TaskbarEntry";
|
||||||
import { ProcessConsumer } from 'contexts/process';
|
import { ProcessConsumer } from "contexts/process";
|
||||||
|
|
||||||
const TaskbarEntries = (): JSX.Element => (
|
const TaskbarEntries = (): JSX.Element => (
|
||||||
<StyledTaskbarEntries>
|
<StyledTaskbarEntries>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
const StyledPeekWindow = styled.div`
|
const StyledPeekWindow = styled.div`
|
||||||
background-color: ${({ theme }) => theme.colors.taskbar.hover};
|
background-color: ${({ theme }) => theme.colors.taskbar.hover};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import StyledPeekWindow from 'components/system/Taskbar/TaskbarEntry/Peek/StyledPeekWindow';
|
import StyledPeekWindow from "components/system/Taskbar/TaskbarEntry/Peek/StyledPeekWindow";
|
||||||
import useWindowActions from 'components/system/Window/Titlebar/useWindowActions';
|
import useWindowActions from "components/system/Window/Titlebar/useWindowActions";
|
||||||
import { CloseIcon } from 'components/system/Window/Titlebar/WindowActionIcons';
|
import { CloseIcon } from "components/system/Window/Titlebar/WindowActionIcons";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { toPng } from 'html-to-image';
|
import { toPng } from "html-to-image";
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import Button from 'styles/common/Button';
|
import Button from "styles/common/Button";
|
||||||
import { MILLISECONDS_IN_SECOND } from 'utils/constants';
|
import { MILLISECONDS_IN_SECOND } from "utils/constants";
|
||||||
|
|
||||||
type WindowPeek = {
|
type WindowPeek = {
|
||||||
PeekComponent?: React.ComponentType;
|
PeekComponent?: React.ComponentType;
|
||||||
|
|
@ -18,13 +18,13 @@ type WindowPeek = {
|
||||||
const useWindowPeek = (id: string): WindowPeek => {
|
const useWindowPeek = (id: string): WindowPeek => {
|
||||||
const {
|
const {
|
||||||
processes: {
|
processes: {
|
||||||
[id]: { componentWindow = undefined, minimized = false, title = '' } = {}
|
[id]: { componentWindow = undefined, minimized = false, title = "" } = {},
|
||||||
}
|
},
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const mouseTimer = useRef<NodeJS.Timer | null>(null);
|
const mouseTimer = useRef<NodeJS.Timer | null>(null);
|
||||||
const previewTimer = useRef<NodeJS.Timer | null>(null);
|
const previewTimer = useRef<NodeJS.Timer | null>(null);
|
||||||
const [showPeek, setShowPeek] = useState(false);
|
const [showPeek, setShowPeek] = useState(false);
|
||||||
const [previewSrc, setPreviewSrc] = useState('');
|
const [previewSrc, setPreviewSrc] = useState("");
|
||||||
const { onClose } = useWindowActions(id);
|
const { onClose } = useWindowActions(id);
|
||||||
const PeekWindow = (): JSX.Element => (
|
const PeekWindow = (): JSX.Element => (
|
||||||
<StyledPeekWindow>
|
<StyledPeekWindow>
|
||||||
|
|
@ -56,13 +56,13 @@ const useWindowPeek = (id: string): WindowPeek => {
|
||||||
if (previewTimer?.current) clearInterval(previewTimer.current);
|
if (previewTimer?.current) clearInterval(previewTimer.current);
|
||||||
|
|
||||||
setShowPeek(false);
|
setShowPeek(false);
|
||||||
setPreviewSrc('');
|
setPreviewSrc("");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (minimized) {
|
if (minimized) {
|
||||||
setShowPeek(false);
|
setShowPeek(false);
|
||||||
setPreviewSrc('');
|
setPreviewSrc("");
|
||||||
}
|
}
|
||||||
}, [minimized]);
|
}, [minimized]);
|
||||||
|
|
||||||
|
|
@ -74,8 +74,8 @@ const useWindowPeek = (id: string): WindowPeek => {
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave
|
onMouseLeave,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type StyledTaskbarEntryProps = {
|
type StyledTaskbarEntryProps = {
|
||||||
foreground: boolean;
|
foreground: boolean;
|
||||||
|
|
@ -13,17 +13,17 @@ const StyledTaskbarEntry = styled.li<StyledTaskbarEntryProps>`
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
background-color: ${({ foreground, theme }) =>
|
background-color: ${({ foreground, theme }) =>
|
||||||
foreground ? theme.colors.taskbar.active : ''};
|
foreground ? theme.colors.taskbar.active : ""};
|
||||||
border-bottom: ${({ theme }) => `
|
border-bottom: ${({ theme }) => `
|
||||||
${theme.sizes.taskbar.entry.borderSize} solid ${theme.colors.highlight}
|
${theme.sizes.taskbar.entry.borderSize} solid ${theme.colors.highlight}
|
||||||
`};
|
`};
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
content: '';
|
content: "";
|
||||||
height: ${({ foreground }) => (foreground ? '100%' : 0)};
|
height: ${({ foreground }) => (foreground ? "100%" : 0)};
|
||||||
margin: ${({ foreground }) => (foreground ? '' : '0 4px')};
|
margin: ${({ foreground }) => (foreground ? "" : "0 4px")};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: ${({ foreground }) => (foreground ? 'all 0.2s' : 'width 0.1s')};
|
transition: ${({ foreground }) => (foreground ? "all 0.2s" : "width 0.1s")};
|
||||||
width: ${({ foreground }) => (foreground ? '100%' : `calc(100% - 8px)`)};
|
width: ${({ foreground }) => (foreground ? "100%" : `calc(100% - 8px)`)};
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import useWindowPeek from 'components/system/Taskbar/TaskbarEntry/Peek/useWindowPeek';
|
import useWindowPeek from "components/system/Taskbar/TaskbarEntry/Peek/useWindowPeek";
|
||||||
import StyledTaskbarEntry from 'components/system/Taskbar/TaskbarEntry/StyledTaskbarEntry';
|
import StyledTaskbarEntry from "components/system/Taskbar/TaskbarEntry/StyledTaskbarEntry";
|
||||||
import useNextFocusable from 'components/system/Window/useNextFocusable';
|
import useNextFocusable from "components/system/Window/useNextFocusable";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from "react";
|
||||||
import Button from 'styles/common/Button';
|
import Button from "styles/common/Button";
|
||||||
import Icon from 'styles/common/Icon';
|
import Icon from "styles/common/Icon";
|
||||||
|
|
||||||
type TaskbarEntryProps = {
|
type TaskbarEntryProps = {
|
||||||
icon: string;
|
icon: string;
|
||||||
|
|
@ -20,11 +20,11 @@ const TaskbarEntry = ({ icon, id, title }: TaskbarEntryProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
linkElement,
|
linkElement,
|
||||||
minimize,
|
minimize,
|
||||||
processes: { [id]: { minimized = false } = {} }
|
processes: { [id]: { minimized = false } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const linkTaskbarEntry = useCallback(
|
const linkTaskbarEntry = useCallback(
|
||||||
(taskbarEntry: HTMLButtonElement) =>
|
(taskbarEntry: HTMLButtonElement) =>
|
||||||
taskbarEntry && linkElement(id, 'taskbarEntry', taskbarEntry),
|
taskbarEntry && linkElement(id, "taskbarEntry", taskbarEntry),
|
||||||
[id, linkElement]
|
[id, linkElement]
|
||||||
);
|
);
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import StartMenu from 'components/system/StartMenu';
|
import StartMenu from "components/system/StartMenu";
|
||||||
import Clock from 'components/system/Taskbar/Clock';
|
import Clock from "components/system/Taskbar/Clock";
|
||||||
import StartButton from 'components/system/Taskbar/StartButton';
|
import StartButton from "components/system/Taskbar/StartButton";
|
||||||
import StyledTaskbar from 'components/system/Taskbar/StyledTaskbar';
|
import StyledTaskbar from "components/system/Taskbar/StyledTaskbar";
|
||||||
import TaskbarEntries from 'components/system/Taskbar/TaskbarEntries';
|
import TaskbarEntries from "components/system/Taskbar/TaskbarEntries";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
|
|
||||||
const Taskbar = (): JSX.Element => {
|
const Taskbar = (): JSX.Element => {
|
||||||
const { startMenuVisible } = useSession();
|
const { startMenuVisible } = useSession();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import useRnd from 'components/system/Window/RndWindow/useRnd';
|
import useRnd from "components/system/Window/RndWindow/useRnd";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import type { Process } from 'contexts/process/types';
|
import type { Process } from "contexts/process/types";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from "react";
|
||||||
import { Rnd } from 'react-rnd';
|
import { Rnd } from "react-rnd";
|
||||||
|
|
||||||
type RndWindowProps = {
|
type RndWindowProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
@ -14,8 +14,8 @@ type RndWindowProps = {
|
||||||
const reRouteFocus =
|
const reRouteFocus =
|
||||||
(focusElement?: HTMLElement) =>
|
(focusElement?: HTMLElement) =>
|
||||||
(element?: Element): void => {
|
(element?: Element): void => {
|
||||||
element?.setAttribute('tabindex', '-1');
|
element?.setAttribute("tabindex", "-1");
|
||||||
element?.addEventListener('mousedown', (event) => {
|
element?.addEventListener("mousedown", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
focusElement?.focus();
|
focusElement?.focus();
|
||||||
});
|
});
|
||||||
|
|
@ -24,7 +24,7 @@ const reRouteFocus =
|
||||||
const RndWindow = ({ children, id, zIndex }: RndWindowProps): JSX.Element => {
|
const RndWindow = ({ children, id, zIndex }: RndWindowProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
linkElement,
|
linkElement,
|
||||||
processes: { [id]: windowProcess = {} }
|
processes: { [id]: windowProcess = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { componentWindow, maximized, minimized } = windowProcess as Process;
|
const { componentWindow, maximized, minimized } = windowProcess as Process;
|
||||||
const rndRef = useRef<Rnd | null>(null);
|
const rndRef = useRef<Rnd | null>(null);
|
||||||
|
|
@ -44,7 +44,7 @@ const RndWindow = ({ children, id, zIndex }: RndWindowProps): JSX.Element => {
|
||||||
windowContainer &&
|
windowContainer &&
|
||||||
Object.keys(windowProcess).length
|
Object.keys(windowProcess).length
|
||||||
) {
|
) {
|
||||||
linkElement(id, 'componentWindow', windowContainer as HTMLElement);
|
linkElement(id, "componentWindow", windowContainer as HTMLElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () =>
|
return () =>
|
||||||
|
|
@ -52,8 +52,8 @@ const RndWindow = ({ children, id, zIndex }: RndWindowProps): JSX.Element => {
|
||||||
...currentWindowStates,
|
...currentWindowStates,
|
||||||
[id]: {
|
[id]: {
|
||||||
position: currentWindow?.props?.position,
|
position: currentWindow?.props?.position,
|
||||||
size: currentWindow?.props?.size
|
size: currentWindow?.props?.size,
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
}, [
|
}, [
|
||||||
componentWindow,
|
componentWindow,
|
||||||
|
|
@ -61,15 +61,15 @@ const RndWindow = ({ children, id, zIndex }: RndWindowProps): JSX.Element => {
|
||||||
linkElement,
|
linkElement,
|
||||||
maximized,
|
maximized,
|
||||||
setWindowStates,
|
setWindowStates,
|
||||||
windowProcess
|
windowProcess,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Rnd
|
<Rnd
|
||||||
ref={rndRef}
|
ref={rndRef}
|
||||||
style={{
|
style={{
|
||||||
pointerEvents: minimized ? 'none' : 'all',
|
pointerEvents: minimized ? "none" : "all",
|
||||||
zIndex
|
zIndex,
|
||||||
}}
|
}}
|
||||||
{...rndProps}
|
{...rndProps}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,62 @@
|
||||||
import type { HandleStyles } from 'react-rnd';
|
import type { HandleStyles } from "react-rnd";
|
||||||
|
|
||||||
const rndDefaults = {
|
const rndDefaults = {
|
||||||
bounds: 'main',
|
bounds: "main",
|
||||||
cancel: '.cancel',
|
cancel: ".cancel",
|
||||||
dragHandleClassName: 'handle',
|
dragHandleClassName: "handle",
|
||||||
enableUserSelectHack: false,
|
enableUserSelectHack: false,
|
||||||
minHeight: '30px',
|
minHeight: "30px",
|
||||||
minWidth: '167px',
|
minWidth: "167px",
|
||||||
resizeHandleStyles: {
|
resizeHandleStyles: {
|
||||||
bottom: {
|
bottom: {
|
||||||
bottom: '-3px',
|
bottom: "-3px",
|
||||||
cursor: 'ns-resize',
|
cursor: "ns-resize",
|
||||||
height: '6px'
|
height: "6px",
|
||||||
},
|
},
|
||||||
bottomLeft: {
|
bottomLeft: {
|
||||||
bottom: '-3px',
|
bottom: "-3px",
|
||||||
cursor: 'nesw-resize',
|
cursor: "nesw-resize",
|
||||||
height: '12px',
|
height: "12px",
|
||||||
left: '-3px',
|
left: "-3px",
|
||||||
width: '12px'
|
width: "12px",
|
||||||
},
|
},
|
||||||
bottomRight: {
|
bottomRight: {
|
||||||
bottom: '-3px',
|
bottom: "-3px",
|
||||||
cursor: 'nwse-resize',
|
cursor: "nwse-resize",
|
||||||
height: '12px',
|
height: "12px",
|
||||||
right: '-3px',
|
right: "-3px",
|
||||||
width: '12px'
|
width: "12px",
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
cursor: 'ew-resize',
|
cursor: "ew-resize",
|
||||||
left: '-3px',
|
left: "-3px",
|
||||||
width: '6px'
|
width: "6px",
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
cursor: 'ew-resize',
|
cursor: "ew-resize",
|
||||||
right: '-3px',
|
right: "-3px",
|
||||||
width: '6px'
|
width: "6px",
|
||||||
},
|
},
|
||||||
top: {
|
top: {
|
||||||
cursor: 'ns-resize',
|
cursor: "ns-resize",
|
||||||
height: '6px',
|
height: "6px",
|
||||||
top: '-3px'
|
top: "-3px",
|
||||||
},
|
},
|
||||||
topLeft: {
|
topLeft: {
|
||||||
cursor: 'nwse-resize',
|
cursor: "nwse-resize",
|
||||||
height: '12px',
|
height: "12px",
|
||||||
left: '-3px',
|
left: "-3px",
|
||||||
top: '-3px',
|
top: "-3px",
|
||||||
width: '12px'
|
width: "12px",
|
||||||
},
|
},
|
||||||
topRight: {
|
topRight: {
|
||||||
cursor: 'nesw-resize',
|
cursor: "nesw-resize",
|
||||||
height: '12px',
|
height: "12px",
|
||||||
right: '-3px',
|
right: "-3px",
|
||||||
top: '-3px',
|
top: "-3px",
|
||||||
width: '12px'
|
width: "12px",
|
||||||
}
|
},
|
||||||
} as HandleStyles
|
} as HandleStyles,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default rndDefaults;
|
export default rndDefaults;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
import { DEFAULT_WINDOW_POSITION } from 'utils/constants';
|
import { DEFAULT_WINDOW_POSITION } from "utils/constants";
|
||||||
|
|
||||||
type Draggable = [Position, React.Dispatch<React.SetStateAction<Position>>];
|
type Draggable = [Position, React.Dispatch<React.SetStateAction<Position>>];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import type { Props } from 'react-rnd';
|
import type { Props } from "react-rnd";
|
||||||
import { DEFAULT_WINDOW_SIZE } from 'utils/constants';
|
import { DEFAULT_WINDOW_SIZE } from "utils/constants";
|
||||||
|
|
||||||
export type Size = NonNullable<Props['size']>;
|
export type Size = NonNullable<Props["size"]>;
|
||||||
|
|
||||||
type Resizable = [Size, React.Dispatch<React.SetStateAction<Size>>];
|
type Resizable = [Size, React.Dispatch<React.SetStateAction<Size>>];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
import { centerPosition } from 'components/system/Window/functions';
|
import { centerPosition } from "components/system/Window/functions";
|
||||||
import rndDefaults from 'components/system/Window/RndWindow/rndDefaults';
|
import rndDefaults from "components/system/Window/RndWindow/rndDefaults";
|
||||||
import useDraggable from 'components/system/Window/RndWindow/useDraggable';
|
import useDraggable from "components/system/Window/RndWindow/useDraggable";
|
||||||
import useResizable from 'components/system/Window/RndWindow/useResizable';
|
import useResizable from "components/system/Window/RndWindow/useResizable";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import type { DraggableEventHandler } from 'react-draggable';
|
import type { DraggableEventHandler } from "react-draggable";
|
||||||
import type { Props, RndResizeCallback } from 'react-rnd';
|
import type { Props, RndResizeCallback } from "react-rnd";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
|
|
||||||
const useRnd = (id: string, maximized = false): Props => {
|
const useRnd = (id: string, maximized = false): Props => {
|
||||||
const {
|
const {
|
||||||
processes: { [id]: { autoSizing = false, lockAspectRatio = false } = {} }
|
processes: { [id]: { autoSizing = false, lockAspectRatio = false } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { windowStates: { [id]: windowState } = {} } = useSession();
|
const { windowStates: { [id]: windowState } = {} } = useSession();
|
||||||
const { position: statePosition, size: stateSize } = windowState || {};
|
const { position: statePosition, size: stateSize } = windowState || {};
|
||||||
const {
|
const {
|
||||||
sizes: {
|
sizes: {
|
||||||
taskbar: { height: taskbarHeight }
|
taskbar: { height: taskbarHeight },
|
||||||
}
|
},
|
||||||
} = useTheme();
|
} = useTheme();
|
||||||
const [size, setSize] = useResizable(autoSizing, stateSize);
|
const [size, setSize] = useResizable(autoSizing, stateSize);
|
||||||
const [position, setPosition] = useDraggable(
|
const [position, setPosition] = useDraggable(
|
||||||
|
|
@ -46,7 +46,7 @@ const useRnd = (id: string, maximized = false): Props => {
|
||||||
onResizeStop,
|
onResizeStop,
|
||||||
position,
|
position,
|
||||||
size,
|
size,
|
||||||
...rndDefaults
|
...rndDefaults,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from "framer-motion";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type StyledWindowProps = {
|
type StyledWindowProps = {
|
||||||
foreground: boolean;
|
foreground: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { DefaultTheme } from 'styled-components';
|
import type { DefaultTheme } from "styled-components";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
|
|
||||||
type StyledTitlebarProps = {
|
type StyledTitlebarProps = {
|
||||||
foreground: boolean;
|
foreground: boolean;
|
||||||
|
|
@ -7,7 +7,7 @@ type StyledTitlebarProps = {
|
||||||
|
|
||||||
const styledBorder = ({
|
const styledBorder = ({
|
||||||
foreground,
|
foreground,
|
||||||
theme
|
theme,
|
||||||
}: StyledTitlebarProps & { theme: DefaultTheme }) =>
|
}: StyledTitlebarProps & { theme: DefaultTheme }) =>
|
||||||
foreground
|
foreground
|
||||||
? `1px solid ${theme.colors.titleBar.background}`
|
? `1px solid ${theme.colors.titleBar.background}`
|
||||||
|
|
@ -107,7 +107,7 @@ const StyledTitlebar = styled.header<StyledTitlebarProps>`
|
||||||
&:disabled {
|
&:disabled {
|
||||||
svg {
|
svg {
|
||||||
fill: ${({ foreground }) =>
|
fill: ${({ foreground }) =>
|
||||||
foreground ? 'rgb(50, 50, 50)' : 'rgb(60, 60, 60)'};
|
foreground ? "rgb(50, 50, 50)" : "rgb(60, 60, 60)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import useDoubleClick from 'components/system/useDoubleClick';
|
import useDoubleClick from "components/system/useDoubleClick";
|
||||||
import StyledTitlebar from 'components/system/Window/Titlebar/StyledTitlebar';
|
import StyledTitlebar from "components/system/Window/Titlebar/StyledTitlebar";
|
||||||
import useWindowActions from 'components/system/Window/Titlebar/useWindowActions';
|
import useWindowActions from "components/system/Window/Titlebar/useWindowActions";
|
||||||
import {
|
import {
|
||||||
CloseIcon,
|
CloseIcon,
|
||||||
MaximizedIcon,
|
MaximizedIcon,
|
||||||
MaximizeIcon,
|
MaximizeIcon,
|
||||||
MinimizeIcon
|
MinimizeIcon,
|
||||||
} from 'components/system/Window/Titlebar/WindowActionIcons';
|
} from "components/system/Window/Titlebar/WindowActionIcons";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import Button from 'styles/common/Button';
|
import Button from "styles/common/Button";
|
||||||
import Icon from 'styles/common/Icon';
|
import Icon from "styles/common/Icon";
|
||||||
|
|
||||||
type TitlebarProps = {
|
type TitlebarProps = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -21,12 +21,12 @@ const Titlebar = ({ id }: TitlebarProps): JSX.Element => {
|
||||||
processes: {
|
processes: {
|
||||||
[id]: {
|
[id]: {
|
||||||
autoSizing = false,
|
autoSizing = false,
|
||||||
icon = '',
|
icon = "",
|
||||||
lockAspectRatio = false,
|
lockAspectRatio = false,
|
||||||
title = '',
|
title = "",
|
||||||
maximized = false
|
maximized = false,
|
||||||
} = {}
|
} = {},
|
||||||
}
|
},
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { foregroundId } = useSession();
|
const { foregroundId } = useSession();
|
||||||
const isForeground = id === foregroundId;
|
const isForeground = id === foregroundId;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { closeWithTransition } from 'components/system/Window/functions';
|
import { closeWithTransition } from "components/system/Window/functions";
|
||||||
import useNextFocusable from 'components/system/Window/useNextFocusable';
|
import useNextFocusable from "components/system/Window/useNextFocusable";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
|
|
||||||
type WindowActions = {
|
type WindowActions = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import type { Size } from 'components/system/Window/RndWindow/useResizable';
|
import type { Size } from "components/system/Window/RndWindow/useResizable";
|
||||||
import type { ProcessContextState } from 'contexts/process/useProcessContextState';
|
import type { ProcessContextState } from "contexts/process/useProcessContextState";
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
import { WINDOW_TRANSITION_DURATION_IN_MILLISECONDS } from 'utils/constants';
|
import { WINDOW_TRANSITION_DURATION_IN_MILLISECONDS } from "utils/constants";
|
||||||
import { pxToNum } from 'utils/functions';
|
import { pxToNum } from "utils/functions";
|
||||||
|
|
||||||
type processCloser = ProcessContextState['close'];
|
type processCloser = ProcessContextState["close"];
|
||||||
|
|
||||||
export const centerPosition = (
|
export const centerPosition = (
|
||||||
{ height, width }: Size,
|
{ height, width }: Size,
|
||||||
|
|
@ -14,7 +14,7 @@ export const centerPosition = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: Math.floor(vw / 2 - pxToNum(width) / 2),
|
x: Math.floor(vw / 2 - pxToNum(width) / 2),
|
||||||
y: Math.floor((vh - pxToNum(taskbarHeight)) / 2 - pxToNum(height) / 2)
|
y: Math.floor((vh - pxToNum(taskbarHeight)) / 2 - pxToNum(height) / 2),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
import RndWindow from 'components/system/Window/RndWindow';
|
import RndWindow from "components/system/Window/RndWindow";
|
||||||
import StyledWindow from 'components/system/Window/StyledWindow';
|
import StyledWindow from "components/system/Window/StyledWindow";
|
||||||
import Titlebar from 'components/system/Window/Titlebar';
|
import Titlebar from "components/system/Window/Titlebar";
|
||||||
import useFocusable from 'components/system/Window/useFocusable';
|
import useFocusable from "components/system/Window/useFocusable";
|
||||||
import useWindowTransitions from 'components/system/Window/useWindowTransitions';
|
import useWindowTransitions from "components/system/Window/useWindowTransitions";
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useRef } from 'react';
|
import { useRef } from "react";
|
||||||
|
|
||||||
type WindowProps = ComponentProcessProps & {
|
type WindowProps = ComponentProcessProps & {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
@ -14,7 +14,7 @@ type WindowProps = ComponentProcessProps & {
|
||||||
|
|
||||||
const Window = ({ children, id }: WindowProps): JSX.Element => {
|
const Window = ({ children, id }: WindowProps): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
processes: { [id]: { backgroundColor = '' } = {} }
|
processes: { [id]: { backgroundColor = "" } = {} },
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { foregroundId } = useSession();
|
const { foregroundId } = useSession();
|
||||||
const isForeground = id === foregroundId;
|
const isForeground = id === foregroundId;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
type Events = {
|
type Events = {
|
||||||
onBlur: (event: React.FocusEvent<HTMLElement>) => void;
|
onBlur: (event: React.FocusEvent<HTMLElement>) => void;
|
||||||
|
|
@ -21,8 +21,8 @@ const useFocusable = (
|
||||||
useSession();
|
useSession();
|
||||||
const {
|
const {
|
||||||
processes: {
|
processes: {
|
||||||
[id]: { minimized = false, taskbarEntry = undefined, url = '' } = {}
|
[id]: { minimized = false, taskbarEntry = undefined, url = "" } = {},
|
||||||
}
|
},
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const zIndex =
|
const zIndex =
|
||||||
stackOrder.length + (minimized ? 1 : -stackOrder.indexOf(id)) + 1;
|
stackOrder.length + (minimized ? 1 : -stackOrder.indexOf(id)) + 1;
|
||||||
|
|
@ -30,7 +30,7 @@ const useFocusable = (
|
||||||
const onBlur: React.FocusEventHandler<HTMLElement> = (event) => {
|
const onBlur: React.FocusEventHandler<HTMLElement> = (event) => {
|
||||||
const { relatedTarget } = event;
|
const { relatedTarget } = event;
|
||||||
|
|
||||||
if (isForeground && relatedTarget !== taskbarEntry) setForegroundId('');
|
if (isForeground && relatedTarget !== taskbarEntry) setForegroundId("");
|
||||||
|
|
||||||
callbackEvents?.onBlur?.(event);
|
callbackEvents?.onBlur?.(event);
|
||||||
};
|
};
|
||||||
|
|
@ -52,7 +52,7 @@ const useFocusable = (
|
||||||
prependToStack,
|
prependToStack,
|
||||||
setForegroundId,
|
setForegroundId,
|
||||||
taskbarEntry,
|
taskbarEntry,
|
||||||
windowRef
|
windowRef,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ const useFocusable = (
|
||||||
onBlur,
|
onBlur,
|
||||||
onFocus: moveToFront,
|
onFocus: moveToFront,
|
||||||
tabIndex: -1,
|
tabIndex: -1,
|
||||||
zIndex
|
zIndex,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
|
|
||||||
const useNextFocusable = (id: string): string => {
|
const useNextFocusable = (id: string): string => {
|
||||||
const { stackOrder } = useSession();
|
const { stackOrder } = useSession();
|
||||||
|
|
@ -9,7 +9,7 @@ const useNextFocusable = (id: string): string => {
|
||||||
(stackId) => stackId !== id && !processes?.[stackId]?.minimized
|
(stackId) => stackId !== id && !processes?.[stackId]?.minimized
|
||||||
);
|
);
|
||||||
|
|
||||||
return nextFocusableId || '';
|
return nextFocusableId || "";
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useNextFocusable;
|
export default useNextFocusable;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import processDirectory from 'contexts/process/directory';
|
import processDirectory from "contexts/process/directory";
|
||||||
import { basename } from 'path';
|
import { basename } from "path";
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from "react";
|
||||||
import { PROCESS_DELIMITER } from 'utils/constants';
|
import { PROCESS_DELIMITER } from "utils/constants";
|
||||||
|
|
||||||
type Title = {
|
type Title = {
|
||||||
appendFileToTitle: (url: string) => void;
|
appendFileToTitle: (url: string) => void;
|
||||||
|
|
@ -18,7 +18,7 @@ const useTitle = (id: string): Title => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appendFileToTitle
|
appendFileToTitle,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useSession } from 'contexts/session';
|
import { useSession } from "contexts/session";
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from "react";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import { pxToNum } from 'utils/functions';
|
import { pxToNum } from "utils/functions";
|
||||||
|
|
||||||
type WindowSize = {
|
type WindowSize = {
|
||||||
updateWindowSize: (height: number, width: number) => void;
|
updateWindowSize: (height: number, width: number) => void;
|
||||||
|
|
@ -10,7 +10,7 @@ type WindowSize = {
|
||||||
const useWindowSize = (id: string): WindowSize => {
|
const useWindowSize = (id: string): WindowSize => {
|
||||||
const { setWindowStates } = useSession();
|
const { setWindowStates } = useSession();
|
||||||
const {
|
const {
|
||||||
sizes: { titleBar }
|
sizes: { titleBar },
|
||||||
} = useTheme();
|
} = useTheme();
|
||||||
|
|
||||||
const updateWindowSize = useCallback(
|
const updateWindowSize = useCallback(
|
||||||
|
|
@ -20,15 +20,15 @@ const useWindowSize = (id: string): WindowSize => {
|
||||||
[id]: {
|
[id]: {
|
||||||
size: {
|
size: {
|
||||||
height: height + pxToNum(titleBar.height),
|
height: height + pxToNum(titleBar.height),
|
||||||
width
|
width,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})),
|
})),
|
||||||
[id, setWindowStates, titleBar.height]
|
[id, setWindowStates, titleBar.height]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
updateWindowSize
|
updateWindowSize,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,36 @@
|
||||||
import { useProcesses } from 'contexts/process';
|
import { useProcesses } from "contexts/process";
|
||||||
import type { MotionProps, Variant } from 'framer-motion';
|
import type { MotionProps, Variant } from "framer-motion";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { useTheme } from 'styled-components';
|
import { useTheme } from "styled-components";
|
||||||
import {
|
import {
|
||||||
MILLISECONDS_IN_SECOND,
|
MILLISECONDS_IN_SECOND,
|
||||||
WINDOW_TRANSITION_DURATION_IN_MILLISECONDS
|
WINDOW_TRANSITION_DURATION_IN_MILLISECONDS,
|
||||||
} from 'utils/constants';
|
} from "utils/constants";
|
||||||
import { pxToNum } from 'utils/functions';
|
import { pxToNum } from "utils/functions";
|
||||||
|
|
||||||
const active = {
|
const active = {
|
||||||
height: 'inherit',
|
height: "inherit",
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
width: 'inherit'
|
width: "inherit",
|
||||||
};
|
};
|
||||||
|
|
||||||
const initial = {
|
const initial = {
|
||||||
height: 'inherit',
|
height: "inherit",
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
scale: 0.95,
|
scale: 0.95,
|
||||||
width: 'inherit'
|
width: "inherit",
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseMaximize = {
|
const baseMaximize = {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
width: '100vw'
|
width: "100vw",
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseMinimize = {
|
const baseMinimize = {
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
scale: 0.7
|
scale: 0.7,
|
||||||
};
|
};
|
||||||
|
|
||||||
const useWindowTransitions = (
|
const useWindowTransitions = (
|
||||||
|
|
@ -42,9 +42,9 @@ const useWindowTransitions = (
|
||||||
[id]: {
|
[id]: {
|
||||||
maximized = false,
|
maximized = false,
|
||||||
minimized = false,
|
minimized = false,
|
||||||
taskbarEntry = undefined
|
taskbarEntry = undefined,
|
||||||
} = {}
|
} = {},
|
||||||
}
|
},
|
||||||
} = useProcesses();
|
} = useProcesses();
|
||||||
const { sizes: { taskbar } = {} } = useTheme();
|
const { sizes: { taskbar } = {} } = useTheme();
|
||||||
const [maximize, setMaximize] = useState<Variant>({});
|
const [maximize, setMaximize] = useState<Variant>({});
|
||||||
|
|
@ -58,7 +58,7 @@ const useWindowTransitions = (
|
||||||
...baseMaximize,
|
...baseMaximize,
|
||||||
height: `${window.innerHeight - pxToNum(taskbar?.height)}px`,
|
height: `${window.innerHeight - pxToNum(taskbar?.height)}px`,
|
||||||
x: -windowX,
|
x: -windowX,
|
||||||
y: -windowY
|
y: -windowY,
|
||||||
});
|
});
|
||||||
}, [maximized, taskbar?.height, windowRef]);
|
}, [maximized, taskbar?.height, windowRef]);
|
||||||
|
|
||||||
|
|
@ -67,31 +67,31 @@ const useWindowTransitions = (
|
||||||
height: taskbarHeight = 0,
|
height: taskbarHeight = 0,
|
||||||
width: taskbarWidth = 0,
|
width: taskbarWidth = 0,
|
||||||
x: taskbarX = 0,
|
x: taskbarX = 0,
|
||||||
y: taskbarY = 0
|
y: taskbarY = 0,
|
||||||
} = taskbarEntry?.getBoundingClientRect() || {};
|
} = taskbarEntry?.getBoundingClientRect() || {};
|
||||||
const {
|
const {
|
||||||
height: windowHeight = 0,
|
height: windowHeight = 0,
|
||||||
width: windowWidth = 0,
|
width: windowWidth = 0,
|
||||||
x: windowX = 0,
|
x: windowX = 0,
|
||||||
y: windowY = 0
|
y: windowY = 0,
|
||||||
} = windowRef?.current?.getBoundingClientRect() || {};
|
} = windowRef?.current?.getBoundingClientRect() || {};
|
||||||
|
|
||||||
setMinimize({
|
setMinimize({
|
||||||
...baseMinimize,
|
...baseMinimize,
|
||||||
x: taskbarX - windowX - windowWidth / 2 + taskbarWidth / 2,
|
x: taskbarX - windowX - windowWidth / 2 + taskbarWidth / 2,
|
||||||
y: taskbarY - windowY - windowHeight / 2 + taskbarHeight / 2
|
y: taskbarY - windowY - windowHeight / 2 + taskbarHeight / 2,
|
||||||
});
|
});
|
||||||
}, [minimized, taskbarEntry, windowRef]);
|
}, [minimized, taskbarEntry, windowRef]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
animate: (minimized && 'minimize') || (maximized && 'maximize') || 'active',
|
animate: (minimized && "minimize") || (maximized && "maximize") || "active",
|
||||||
exit: 'initial',
|
exit: "initial",
|
||||||
initial: 'initial',
|
initial: "initial",
|
||||||
transition: {
|
transition: {
|
||||||
duration:
|
duration:
|
||||||
WINDOW_TRANSITION_DURATION_IN_MILLISECONDS / MILLISECONDS_IN_SECOND
|
WINDOW_TRANSITION_DURATION_IN_MILLISECONDS / MILLISECONDS_IN_SECOND,
|
||||||
},
|
},
|
||||||
variants: { active, initial, maximize, minimize }
|
variants: { active, initial, maximize, minimize },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useRef } from 'react';
|
import { useRef } from "react";
|
||||||
import { DOUBLE_CLICK_TIMEOUT_IN_MILLISECONDS } from 'utils/constants';
|
import { DOUBLE_CLICK_TIMEOUT_IN_MILLISECONDS } from "utils/constants";
|
||||||
|
|
||||||
type DoubleClick = (
|
type DoubleClick = (
|
||||||
handler: React.MouseEventHandler,
|
handler: React.MouseEventHandler,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { createContext, useContext } from 'react';
|
import { createContext, useContext } from "react";
|
||||||
|
|
||||||
type ProcessProviderProps = {
|
type ProcessProviderProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
@ -30,7 +30,7 @@ const contextFactory: ContextFactory = (
|
||||||
return {
|
return {
|
||||||
Consumer: Context.Consumer,
|
Consumer: Context.Consumer,
|
||||||
Provider: ProcessProvider,
|
Provider: ProcessProvider,
|
||||||
useContext: () => useContext(Context)
|
useContext: () => useContext(Context),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
import type { FileSystemConfiguration } from 'browserfs';
|
import type { FileSystemConfiguration } from "browserfs";
|
||||||
import bfsJson from 'public/.index/fs.bfs.json';
|
import bfsJson from "public/.index/fs.bfs.json";
|
||||||
|
|
||||||
const FileSystemConfig: FileSystemConfiguration = {
|
const FileSystemConfig: FileSystemConfiguration = {
|
||||||
fs: 'MountableFileSystem',
|
fs: "MountableFileSystem",
|
||||||
options: {
|
options: {
|
||||||
'/': {
|
"/": {
|
||||||
fs: 'OverlayFS',
|
fs: "OverlayFS",
|
||||||
options: {
|
options: {
|
||||||
readable: {
|
readable: {
|
||||||
fs: 'XmlHttpRequest',
|
fs: "XmlHttpRequest",
|
||||||
options: {
|
options: {
|
||||||
index: bfsJson
|
index: bfsJson,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
writable: {
|
writable: {
|
||||||
fs: 'IndexedDB',
|
fs: "IndexedDB",
|
||||||
options: {
|
options: {
|
||||||
storeName: 'browser-fs-cache'
|
storeName: "browser-fs-cache",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FileSystemConfig;
|
export default FileSystemConfig;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import contextFactory from 'contexts/contextFactory';
|
import contextFactory from "contexts/contextFactory";
|
||||||
import type { FileSystemContextState } from 'contexts/fileSystem/useFileSystemContextState';
|
import type { FileSystemContextState } from "contexts/fileSystem/useFileSystemContextState";
|
||||||
import useFileSystemContextState from 'contexts/fileSystem/useFileSystemContextState';
|
import useFileSystemContextState from "contexts/fileSystem/useFileSystemContextState";
|
||||||
import { initialFileSystemContextState } from 'contexts/initialContextStates';
|
import { initialFileSystemContextState } from "contexts/initialContextStates";
|
||||||
|
|
||||||
const { Consumer, Provider, useContext } =
|
const { Consumer, Provider, useContext } =
|
||||||
contextFactory<FileSystemContextState>(
|
contextFactory<FileSystemContextState>(
|
||||||
|
|
@ -12,5 +12,5 @@ const { Consumer, Provider, useContext } =
|
||||||
export {
|
export {
|
||||||
Consumer as FileSystemConsumer,
|
Consumer as FileSystemConsumer,
|
||||||
Provider as FileSystemProvider,
|
Provider as FileSystemProvider,
|
||||||
useContext as useFileSystem
|
useContext as useFileSystem,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { BFSRequire, configure, FileSystem } from 'browserfs';
|
import { BFSRequire, configure, FileSystem } from "browserfs";
|
||||||
import type IsoFS from 'browserfs/dist/node/backend/IsoFS';
|
import type IsoFS from "browserfs/dist/node/backend/IsoFS";
|
||||||
import type MountableFileSystem from 'browserfs/dist/node/backend/MountableFileSystem';
|
import type MountableFileSystem from "browserfs/dist/node/backend/MountableFileSystem";
|
||||||
import type ZipFS from 'browserfs/dist/node/backend/ZipFS';
|
import type ZipFS from "browserfs/dist/node/backend/ZipFS";
|
||||||
import type { BFSCallback } from 'browserfs/dist/node/core/file_system';
|
import type { BFSCallback } from "browserfs/dist/node/core/file_system";
|
||||||
import type { FSModule } from 'browserfs/dist/node/core/FS';
|
import type { FSModule } from "browserfs/dist/node/core/FS";
|
||||||
import FileSystemConfig from 'contexts/fileSystem/FileSystemConfig';
|
import FileSystemConfig from "contexts/fileSystem/FileSystemConfig";
|
||||||
import { extname } from 'path';
|
import { extname } from "path";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export type FileSystemContextState = {
|
export type FileSystemContextState = {
|
||||||
fs: FSModule | null;
|
fs: FSModule | null;
|
||||||
|
|
@ -18,8 +18,8 @@ const useFileSystemContextState = (): FileSystemContextState => {
|
||||||
const [fs, setFs] = useState<FSModule | null>(null);
|
const [fs, setFs] = useState<FSModule | null>(null);
|
||||||
const rootFs = fs?.getRootFS() as MountableFileSystem;
|
const rootFs = fs?.getRootFS() as MountableFileSystem;
|
||||||
const mountFs = (url: string, callback: () => void): void =>
|
const mountFs = (url: string, callback: () => void): void =>
|
||||||
fs?.readFile(url, (_readError, fileData = Buffer.from('')) => {
|
fs?.readFile(url, (_readError, fileData = Buffer.from("")) => {
|
||||||
const isISO = extname(url) === '.iso';
|
const isISO = extname(url) === ".iso";
|
||||||
const createFs: BFSCallback<IsoFS | ZipFS> = (_createError, newFs) => {
|
const createFs: BFSCallback<IsoFS | ZipFS> = (_createError, newFs) => {
|
||||||
if (newFs) {
|
if (newFs) {
|
||||||
rootFs?.mount(url, newFs);
|
rootFs?.mount(url, newFs);
|
||||||
|
|
@ -37,7 +37,7 @@ const useFileSystemContextState = (): FileSystemContextState => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!fs) {
|
if (!fs) {
|
||||||
configure(FileSystemConfig, () => setFs(BFSRequire('fs')));
|
configure(FileSystemConfig, () => setFs(BFSRequire("fs")));
|
||||||
}
|
}
|
||||||
}, [fs]);
|
}, [fs]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import type { FileSystemContextState } from 'contexts/fileSystem/useFileSystemContextState';
|
import type { FileSystemContextState } from "contexts/fileSystem/useFileSystemContextState";
|
||||||
import type { MenuContextState } from 'contexts/menu/useMenuContextState';
|
import type { MenuContextState } from "contexts/menu/useMenuContextState";
|
||||||
import type { ProcessContextState } from 'contexts/process/useProcessContextState';
|
import type { ProcessContextState } from "contexts/process/useProcessContextState";
|
||||||
import type { SessionContextState } from 'contexts/session/useSessionContextState';
|
import type { SessionContextState } from "contexts/session/useSessionContextState";
|
||||||
|
|
||||||
export const initialFileSystemContextState: FileSystemContextState = {
|
export const initialFileSystemContextState: FileSystemContextState = {
|
||||||
fs: null,
|
fs: null,
|
||||||
mountFs: () => undefined,
|
mountFs: () => undefined,
|
||||||
unMountFs: () => undefined
|
unMountFs: () => undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initialMenuContextState: MenuContextState = {
|
export const initialMenuContextState: MenuContextState = {
|
||||||
contextMenu: () => () => undefined,
|
contextMenu: () => () => undefined,
|
||||||
menu: {},
|
menu: {},
|
||||||
setMenu: () => undefined
|
setMenu: () => undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initialProcessContextState: ProcessContextState = {
|
export const initialProcessContextState: ProcessContextState = {
|
||||||
|
|
@ -22,11 +22,11 @@ export const initialProcessContextState: ProcessContextState = {
|
||||||
minimize: () => undefined,
|
minimize: () => undefined,
|
||||||
open: () => undefined,
|
open: () => undefined,
|
||||||
processes: {},
|
processes: {},
|
||||||
title: () => undefined
|
title: () => undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initialSessionContextState: SessionContextState = {
|
export const initialSessionContextState: SessionContextState = {
|
||||||
foregroundId: '',
|
foregroundId: "",
|
||||||
prependToStack: () => undefined,
|
prependToStack: () => undefined,
|
||||||
removeFromStack: () => undefined,
|
removeFromStack: () => undefined,
|
||||||
setForegroundId: () => undefined,
|
setForegroundId: () => undefined,
|
||||||
|
|
@ -34,7 +34,7 @@ export const initialSessionContextState: SessionContextState = {
|
||||||
setWindowStates: () => undefined,
|
setWindowStates: () => undefined,
|
||||||
stackOrder: [],
|
stackOrder: [],
|
||||||
startMenuVisible: false,
|
startMenuVisible: false,
|
||||||
themeName: '',
|
themeName: "",
|
||||||
toggleStartMenu: () => undefined,
|
toggleStartMenu: () => undefined,
|
||||||
windowStates: {}
|
windowStates: {},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import Menu from 'components/system/Menu';
|
import Menu from "components/system/Menu";
|
||||||
import contextFactory from 'contexts/contextFactory';
|
import contextFactory from "contexts/contextFactory";
|
||||||
import { initialMenuContextState } from 'contexts/initialContextStates';
|
import { initialMenuContextState } from "contexts/initialContextStates";
|
||||||
import type { MenuContextState } from 'contexts/menu/useMenuContextState';
|
import type { MenuContextState } from "contexts/menu/useMenuContextState";
|
||||||
import useMenuContextState from 'contexts/menu/useMenuContextState';
|
import useMenuContextState from "contexts/menu/useMenuContextState";
|
||||||
|
|
||||||
const { Consumer, Provider, useContext } = contextFactory<MenuContextState>(
|
const { Consumer, Provider, useContext } = contextFactory<MenuContextState>(
|
||||||
initialMenuContextState,
|
initialMenuContextState,
|
||||||
|
|
@ -13,5 +13,5 @@ const { Consumer, Provider, useContext } = contextFactory<MenuContextState>(
|
||||||
export {
|
export {
|
||||||
Consumer as MenuConsumer,
|
Consumer as MenuConsumer,
|
||||||
Provider as MenuProvider,
|
Provider as MenuProvider,
|
||||||
useContext as useMenu
|
useContext as useMenu,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
|
|
||||||
export type MenuItem = {
|
export type MenuItem = {
|
||||||
action?: () => void;
|
action?: () => void;
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,35 @@
|
||||||
import type { Processes } from 'contexts/process/types';
|
import type { Processes } from "contexts/process/types";
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const processDirectory: Processes = {
|
const processDirectory: Processes = {
|
||||||
FileExplorer: {
|
FileExplorer: {
|
||||||
backgroundColor: '#202020',
|
backgroundColor: "#202020",
|
||||||
Component: dynamic(() => import('components/apps/FileExplorer')),
|
Component: dynamic(() => import("components/apps/FileExplorer")),
|
||||||
icon: '/icons/explorer.png',
|
icon: "/icons/explorer.png",
|
||||||
title: 'File Explorer'
|
title: "File Explorer",
|
||||||
},
|
},
|
||||||
JSDOS: {
|
JSDOS: {
|
||||||
autoSizing: true,
|
autoSizing: true,
|
||||||
backgroundColor: '#000',
|
backgroundColor: "#000",
|
||||||
Component: dynamic(() => import('components/apps/JSDOS')),
|
Component: dynamic(() => import("components/apps/JSDOS")),
|
||||||
icon: '/icons/jsdos.png',
|
icon: "/icons/jsdos.png",
|
||||||
lockAspectRatio: true,
|
lockAspectRatio: true,
|
||||||
title: 'js-dos v7'
|
title: "js-dos v7",
|
||||||
},
|
},
|
||||||
V86: {
|
V86: {
|
||||||
autoSizing: true,
|
autoSizing: true,
|
||||||
backgroundColor: '#000',
|
backgroundColor: "#000",
|
||||||
Component: dynamic(() => import('components/apps/V86')),
|
Component: dynamic(() => import("components/apps/V86")),
|
||||||
icon: '/icons/v86.png',
|
icon: "/icons/v86.png",
|
||||||
title: 'Virtual x86'
|
title: "Virtual x86",
|
||||||
},
|
},
|
||||||
Webamp: {
|
Webamp: {
|
||||||
Component: dynamic(() => import('components/apps/Webamp')),
|
Component: dynamic(() => import("components/apps/Webamp")),
|
||||||
hasWindow: false,
|
hasWindow: false,
|
||||||
icon: '/icons/webamp.png',
|
icon: "/icons/webamp.png",
|
||||||
singleton: true,
|
singleton: true,
|
||||||
title: 'Webamp'
|
title: "Webamp",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default processDirectory;
|
export default processDirectory;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import processDirectory from 'contexts/process/directory';
|
import processDirectory from "contexts/process/directory";
|
||||||
import type {
|
import type {
|
||||||
Process,
|
Process,
|
||||||
ProcessElements,
|
ProcessElements,
|
||||||
Processes
|
Processes,
|
||||||
} from 'contexts/process/types';
|
} from "contexts/process/types";
|
||||||
import { PROCESS_DELIMITER } from 'utils/constants';
|
import { PROCESS_DELIMITER } from "utils/constants";
|
||||||
|
|
||||||
export const setProcessSettings =
|
export const setProcessSettings =
|
||||||
(processId: string, settings: Partial<Process>) =>
|
(processId: string, settings: Partial<Process>) =>
|
||||||
|
|
@ -13,7 +13,7 @@ export const setProcessSettings =
|
||||||
|
|
||||||
newProcesses[processId] = {
|
newProcesses[processId] = {
|
||||||
...newProcesses[processId],
|
...newProcesses[processId],
|
||||||
...settings
|
...settings,
|
||||||
};
|
};
|
||||||
|
|
||||||
return newProcesses;
|
return newProcesses;
|
||||||
|
|
@ -52,8 +52,8 @@ export const openProcess =
|
||||||
...currentProcesses,
|
...currentProcesses,
|
||||||
[id]: {
|
[id]: {
|
||||||
...processDirectory[processId],
|
...processDirectory[processId],
|
||||||
url
|
url,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,14 +61,14 @@ export const maximizeProcess =
|
||||||
(processId: string) =>
|
(processId: string) =>
|
||||||
(currentProcesses: Processes): Processes =>
|
(currentProcesses: Processes): Processes =>
|
||||||
setProcessSettings(processId, {
|
setProcessSettings(processId, {
|
||||||
maximized: !currentProcesses[processId].maximized
|
maximized: !currentProcesses[processId].maximized,
|
||||||
})(currentProcesses);
|
})(currentProcesses);
|
||||||
|
|
||||||
export const minimizeProcess =
|
export const minimizeProcess =
|
||||||
(processId: string) =>
|
(processId: string) =>
|
||||||
(currentProcesses: Processes): Processes =>
|
(currentProcesses: Processes): Processes =>
|
||||||
setProcessSettings(processId, {
|
setProcessSettings(processId, {
|
||||||
minimized: !currentProcesses[processId].minimized
|
minimized: !currentProcesses[processId].minimized,
|
||||||
})(currentProcesses);
|
})(currentProcesses);
|
||||||
|
|
||||||
export const setProcessElement =
|
export const setProcessElement =
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import contextFactory from 'contexts/contextFactory';
|
import contextFactory from "contexts/contextFactory";
|
||||||
import { initialProcessContextState } from 'contexts/initialContextStates';
|
import { initialProcessContextState } from "contexts/initialContextStates";
|
||||||
import type { ProcessContextState } from 'contexts/process/useProcessContextState';
|
import type { ProcessContextState } from "contexts/process/useProcessContextState";
|
||||||
import useProcessContextState from 'contexts/process/useProcessContextState';
|
import useProcessContextState from "contexts/process/useProcessContextState";
|
||||||
|
|
||||||
const { Consumer, Provider, useContext } = contextFactory<ProcessContextState>(
|
const { Consumer, Provider, useContext } = contextFactory<ProcessContextState>(
|
||||||
initialProcessContextState,
|
initialProcessContextState,
|
||||||
|
|
@ -11,5 +11,5 @@ const { Consumer, Provider, useContext } = contextFactory<ProcessContextState>(
|
||||||
export {
|
export {
|
||||||
Consumer as ProcessConsumer,
|
Consumer as ProcessConsumer,
|
||||||
Provider as ProcessProvider,
|
Provider as ProcessProvider,
|
||||||
useContext as useProcesses
|
useContext as useProcesses,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ComponentProcessProps } from 'components/system/Apps/RenderComponent';
|
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||||
|
|
||||||
export type ProcessElements = {
|
export type ProcessElements = {
|
||||||
componentWindow?: HTMLElement;
|
componentWindow?: HTMLElement;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import {
|
||||||
minimizeProcess,
|
minimizeProcess,
|
||||||
openProcess,
|
openProcess,
|
||||||
setProcessElement,
|
setProcessElement,
|
||||||
setTitle
|
setTitle,
|
||||||
} from 'contexts/process/functions';
|
} from "contexts/process/functions";
|
||||||
import type { ProcessElements, Processes } from 'contexts/process/types';
|
import type { ProcessElements, Processes } from "contexts/process/types";
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export type ProcessContextState = {
|
export type ProcessContextState = {
|
||||||
close: (id: string, closing?: boolean) => void;
|
close: (id: string, closing?: boolean) => void;
|
||||||
|
|
@ -58,7 +58,7 @@ const useProcessContextState = (): ProcessContextState => {
|
||||||
minimize,
|
minimize,
|
||||||
open,
|
open,
|
||||||
processes,
|
processes,
|
||||||
title
|
title,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import contextFactory from 'contexts/contextFactory';
|
import contextFactory from "contexts/contextFactory";
|
||||||
import { initialSessionContextState } from 'contexts/initialContextStates';
|
import { initialSessionContextState } from "contexts/initialContextStates";
|
||||||
import type { SessionContextState } from 'contexts/session/useSessionContextState';
|
import type { SessionContextState } from "contexts/session/useSessionContextState";
|
||||||
import useSessionContextState from 'contexts/session/useSessionContextState';
|
import useSessionContextState from "contexts/session/useSessionContextState";
|
||||||
|
|
||||||
const { Consumer, Provider, useContext } = contextFactory<SessionContextState>(
|
const { Consumer, Provider, useContext } = contextFactory<SessionContextState>(
|
||||||
initialSessionContextState,
|
initialSessionContextState,
|
||||||
|
|
@ -11,5 +11,5 @@ const { Consumer, Provider, useContext } = contextFactory<SessionContextState>(
|
||||||
export {
|
export {
|
||||||
Consumer as SessionConsumer,
|
Consumer as SessionConsumer,
|
||||||
Provider as SessionProvider,
|
Provider as SessionProvider,
|
||||||
useContext as useSession
|
useContext as useSession,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { Size } from 'components/system/Window/RndWindow/useResizable';
|
import type { Size } from "components/system/Window/RndWindow/useResizable";
|
||||||
import { useFileSystem } from 'contexts/fileSystem';
|
import { useFileSystem } from "contexts/fileSystem";
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import type { Position } from 'react-rnd';
|
import type { Position } from "react-rnd";
|
||||||
|
|
||||||
type WindowState = {
|
type WindowState = {
|
||||||
position?: Position;
|
position?: Position;
|
||||||
|
|
@ -26,14 +26,14 @@ export type SessionContextState = {
|
||||||
windowStates: WindowStates;
|
windowStates: WindowStates;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SESSION_FILE = '/session.json';
|
const SESSION_FILE = "/session.json";
|
||||||
|
|
||||||
const useSessionContextState = (): SessionContextState => {
|
const useSessionContextState = (): SessionContextState => {
|
||||||
const { fs } = useFileSystem();
|
const { fs } = useFileSystem();
|
||||||
const [sessionLoaded, setSessionLoaded] = useState(false);
|
const [sessionLoaded, setSessionLoaded] = useState(false);
|
||||||
const [foregroundId, setForegroundId] = useState('');
|
const [foregroundId, setForegroundId] = useState("");
|
||||||
const [stackOrder, setStackOrder] = useState<string[]>([]);
|
const [stackOrder, setStackOrder] = useState<string[]>([]);
|
||||||
const [themeName, setThemeName] = useState('');
|
const [themeName, setThemeName] = useState("");
|
||||||
const [windowStates, setWindowStates] = useState<WindowStates>({});
|
const [windowStates, setWindowStates] = useState<WindowStates>({});
|
||||||
const [startMenuVisible, setStartMenuVisible] = useState(false);
|
const [startMenuVisible, setStartMenuVisible] = useState(false);
|
||||||
const toggleStartMenu = (showMenu?: boolean) =>
|
const toggleStartMenu = (showMenu?: boolean) =>
|
||||||
|
|
@ -42,7 +42,7 @@ const useSessionContextState = (): SessionContextState => {
|
||||||
(id: string) =>
|
(id: string) =>
|
||||||
setStackOrder((currentStackOrder) => [
|
setStackOrder((currentStackOrder) => [
|
||||||
id,
|
id,
|
||||||
...currentStackOrder.filter((stackId) => stackId !== id)
|
...currentStackOrder.filter((stackId) => stackId !== id),
|
||||||
]),
|
]),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
@ -62,7 +62,7 @@ const useSessionContextState = (): SessionContextState => {
|
||||||
foregroundId,
|
foregroundId,
|
||||||
stackOrder,
|
stackOrder,
|
||||||
themeName,
|
themeName,
|
||||||
windowStates
|
windowStates,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ const useSessionContextState = (): SessionContextState => {
|
||||||
() =>
|
() =>
|
||||||
fs?.readFile(SESSION_FILE, (_error, contents) => {
|
fs?.readFile(SESSION_FILE, (_error, contents) => {
|
||||||
if (contents) {
|
if (contents) {
|
||||||
const session = JSON.parse(contents.toString() || '{}');
|
const session = JSON.parse(contents.toString() || "{}");
|
||||||
|
|
||||||
setThemeName(session.themeName);
|
setThemeName(session.themeName);
|
||||||
setWindowStates(session.windowStates);
|
setWindowStates(session.windowStates);
|
||||||
|
|
@ -94,7 +94,7 @@ const useSessionContextState = (): SessionContextState => {
|
||||||
startMenuVisible,
|
startMenuVisible,
|
||||||
themeName,
|
themeName,
|
||||||
toggleStartMenu,
|
toggleStartMenu,
|
||||||
windowStates
|
windowStates,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
moduleDirectories: ['.', 'node_modules'],
|
moduleDirectories: [".", "node_modules"],
|
||||||
setupFilesAfterEnv: [
|
setupFilesAfterEnv: [
|
||||||
'@testing-library/jest-dom/extend-expect',
|
"@testing-library/jest-dom/extend-expect",
|
||||||
'<rootDir>/jest.setup.js'
|
"<rootDir>/jest.setup.js",
|
||||||
],
|
],
|
||||||
testEnvironment: 'jsdom'
|
testEnvironment: "jsdom",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user