Fixed virtual drive saving and loading
This commit is contained in:
parent
334676084a
commit
9c65c7c1f8
10 changed files with 248 additions and 58 deletions
|
|
@ -59,7 +59,7 @@ export function FileExplorer({ startPath }) {
|
||||||
|
|
||||||
if (directory) {
|
if (directory) {
|
||||||
setCurrentDirectory(directory);
|
setCurrentDirectory(directory);
|
||||||
setPath(directory.path);
|
setPath(directory.root ? "/" : directory.path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -68,10 +68,16 @@ export function FileExplorer({ startPath }) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onKeyDown = (event) => {
|
const onKeyDown = (event) => {
|
||||||
const value = event.target.value;
|
let value = event.target.value;
|
||||||
|
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
setCurrentDirectory(virtualRoot.navigate(value));
|
if (value === "")
|
||||||
|
value = "~";
|
||||||
|
|
||||||
|
const directory = virtualRoot.navigate(value);
|
||||||
|
|
||||||
|
setCurrentDirectory(directory);
|
||||||
|
setPath(directory.root ? "/" : directory.path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -139,6 +145,16 @@ export function FileExplorer({ startPath }) {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.Main}>
|
<div className={styles.Main}>
|
||||||
|
{currentDirectory?.getSubFolders(showHidden)?.map(({ name }, index) =>
|
||||||
|
<button key={index} tabIndex={0} className={styles["Folder-button"]}
|
||||||
|
onClick={() => {
|
||||||
|
changeDirectory(name);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faFolder}/>
|
||||||
|
<p>{name}</p>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{currentDirectory?.getFiles(showHidden)?.map((file, index) =>
|
{currentDirectory?.getFiles(showHidden)?.map((file, index) =>
|
||||||
<button key={index} tabIndex={0} className={styles["File-button"]}
|
<button key={index} tabIndex={0} className={styles["File-button"]}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
|
|
@ -150,16 +166,6 @@ export function FileExplorer({ startPath }) {
|
||||||
<p>{file.id}</p>
|
<p>{file.id}</p>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{currentDirectory?.getSubFolders(showHidden)?.map(({ name }, index) =>
|
|
||||||
<button key={index} tabIndex={0} className={styles["Folder-button"]}
|
|
||||||
onClick={() => {
|
|
||||||
changeDirectory(name);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon icon={faFolder}/>
|
|
||||||
<p>{name}</p>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import styles from "./Settings.module.css";
|
||||||
import { useVirtualRoot } from "../../../hooks/virtual-drive/virtualRootContext.js";
|
import { useVirtualRoot } from "../../../hooks/virtual-drive/virtualRootContext.js";
|
||||||
import { useSettingsManager } from "../../../hooks/settings/settingsManagerContext.js";
|
import { useSettingsManager } from "../../../hooks/settings/settingsManagerContext.js";
|
||||||
|
|
||||||
|
const wallpapersPath = "~/Images/Wallpapers";
|
||||||
|
|
||||||
export function AppearanceSettings() {
|
export function AppearanceSettings() {
|
||||||
const virtualRoot = useVirtualRoot();
|
const virtualRoot = useVirtualRoot();
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
|
|
@ -23,7 +25,7 @@ export function AppearanceSettings() {
|
||||||
<div className={styles["Option"]}>
|
<div className={styles["Option"]}>
|
||||||
<p className={styles["Label"]}>Wallpaper</p>
|
<p className={styles["Label"]}>Wallpaper</p>
|
||||||
<div className={styles["Input"]}>
|
<div className={styles["Input"]}>
|
||||||
{virtualRoot.navigate("~/Images")?.getFiles()?.map(({ id, source }) =>
|
{virtualRoot.navigate(wallpapersPath)?.getFiles()?.toReversed().map(({ id, source }) =>
|
||||||
<label className={styles["Image-select"]} key={id}>
|
<label className={styles["Image-select"]} key={id}>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { useModals } from "../../hooks/modals/modals.js";
|
||||||
import { ModalsView } from "../modals/ModalsView.jsx";
|
import { ModalsView } from "../modals/ModalsView.jsx";
|
||||||
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
import { useWindowsManager } from "../../hooks/windows/windowsManagerContext.js";
|
||||||
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
import { useContextMenu } from "../../hooks/modals/contextMenu.js";
|
||||||
|
import { FALLBACK_WALLPAPER } from "../../constants/desktop.js";
|
||||||
|
|
||||||
export const Desktop = memo(() => {
|
export const Desktop = memo(() => {
|
||||||
const settingsManager = useSettingsManager();
|
const settingsManager = useSettingsManager();
|
||||||
|
|
@ -28,12 +29,20 @@ export const Desktop = memo(() => {
|
||||||
})();
|
})();
|
||||||
}, [settingsManager]);
|
}, [settingsManager]);
|
||||||
|
|
||||||
|
const onError = () => {
|
||||||
|
const settings = settingsManager.get(SettingsManager.VIRTUAL_PATHS.desktop);
|
||||||
|
settings.set("wallpaper", FALLBACK_WALLPAPER);
|
||||||
|
};
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<div
|
<div
|
||||||
className={styles.Container}
|
className={styles.Container}
|
||||||
style={{ backgroundImage: wallpaper ? `url(${wallpaper})` : null }}
|
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
|
{wallpaper
|
||||||
|
? <img src={wallpaper} className={styles.Wallpaper} alt="Desktop wallpaper" onError={onError}/>
|
||||||
|
: null
|
||||||
|
}
|
||||||
<ModalsView modalsManager={modalsManager} modals={modals}/>
|
<ModalsView modalsManager={modalsManager} modals={modals}/>
|
||||||
</div>
|
</div>
|
||||||
</>);
|
</>);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,14 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
background-size: cover;
|
}
|
||||||
background-position: center;
|
|
||||||
|
.Wallpaper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
@ -7,4 +7,6 @@ export const WALLPAPERS = [
|
||||||
"/media/wallpapers/vibrant-wallpaper-blue-purple-red.png",
|
"/media/wallpapers/vibrant-wallpaper-blue-purple-red.png",
|
||||||
"/media/wallpapers/vibrant-wallpaper-purple-yellow.png",
|
"/media/wallpapers/vibrant-wallpaper-purple-yellow.png",
|
||||||
"/media/wallpapers/wave-abstract-wallpaper-teal.png",
|
"/media/wallpapers/wave-abstract-wallpaper-teal.png",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const FALLBACK_WALLPAPER = WALLPAPERS[4];
|
||||||
|
|
@ -6,6 +6,9 @@ export class StorageManager {
|
||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
static store(key, value) {
|
static store(key, value) {
|
||||||
|
if (key == null || value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
localStorage.setItem(key, value);
|
localStorage.setItem(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,6 +17,9 @@ export class StorageManager {
|
||||||
* @returns {string | null}
|
* @returns {string | null}
|
||||||
*/
|
*/
|
||||||
static load(key) {
|
static load(key) {
|
||||||
|
if (key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
return localStorage.getItem(key);
|
return localStorage.getItem(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { EventEmitter } from "../utils/events.js";
|
import { EventEmitter } from "../utils/events.js";
|
||||||
|
|
||||||
import { VirtualRoot } from "./virtualRoot.js";
|
import { VirtualRoot } from "./virtualRoot.js";
|
||||||
|
|
||||||
export class VirtualBase extends EventEmitter {
|
export class VirtualBase extends EventEmitter {
|
||||||
|
|
@ -20,8 +19,12 @@ export class VirtualBase extends EventEmitter {
|
||||||
* @returns {VirtualBase}
|
* @returns {VirtualBase}
|
||||||
*/
|
*/
|
||||||
setName(name) {
|
setName(name) {
|
||||||
|
if (this.name === name || !this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,12 +33,13 @@ export class VirtualBase extends EventEmitter {
|
||||||
* @returns {ThisType}
|
* @returns {ThisType}
|
||||||
*/
|
*/
|
||||||
setAlias(alias) {
|
setAlias(alias) {
|
||||||
if (this.alias === alias)
|
if (this.alias === alias || !this.canBeEdited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.alias = alias;
|
this.alias = alias;
|
||||||
this.getRoot().addShortcut(alias, this);
|
this.getRoot().addShortcut(alias, this);
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,34 +48,92 @@ export class VirtualBase extends EventEmitter {
|
||||||
* @returns {VirtualBase}
|
* @returns {VirtualBase}
|
||||||
*/
|
*/
|
||||||
setParent(parent) {
|
setParent(parent) {
|
||||||
if (this.parent === parent)
|
if (this.parent === parent || !this.canBeEdited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} value
|
||||||
|
* @returns {VirtualBase}
|
||||||
|
*/
|
||||||
|
setProtected(value) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.isProtected = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete() {
|
delete() {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
const parent = this.parent;
|
const parent = this.parent;
|
||||||
|
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
parent.remove?.(this);
|
parent.remove?.(this);
|
||||||
parent.getRoot()?.saveData();
|
this.confirmChanges(parent.getRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {VirtualRoot} [root]
|
||||||
|
*/
|
||||||
|
confirmChanges(root = null) {
|
||||||
|
if (this.getRoot().loadedDefaultData)
|
||||||
|
this.editedByUser = true;
|
||||||
|
|
||||||
|
if (root == null)
|
||||||
|
root = this.getRoot();
|
||||||
|
|
||||||
|
root?.saveData();
|
||||||
}
|
}
|
||||||
|
|
||||||
open() {}
|
open() {}
|
||||||
|
|
||||||
get path() {
|
get path() {
|
||||||
return this.alias ?? this.absolutePath;
|
return this.alias ?? this.displayPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
get absolutePath() {
|
/**
|
||||||
|
* Returns path without using alias
|
||||||
|
*/
|
||||||
|
get displayPath() {
|
||||||
return this.parent?.path + "/" + this.id;
|
return this.parent?.path + "/" + this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns path without using any aliases
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get absolutePath() {
|
||||||
|
if (this.parent?.isRoot) {
|
||||||
|
return "/" + this.id;
|
||||||
|
} else {
|
||||||
|
return this.parent?.absolutePath + "/" + this.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this can be edited in its current state
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get canBeEdited() {
|
||||||
|
const isProtected = this.isProtected && this.getRoot().loadedDefaultData;
|
||||||
|
|
||||||
|
if (!isProtected && this.parent != null) {
|
||||||
|
return this.parent.canBeEdited;
|
||||||
|
} else {
|
||||||
|
return !isProtected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {VirtualRoot}
|
* @returns {VirtualRoot}
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,6 +147,9 @@ export class VirtualBase extends EventEmitter {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {object | null}
|
||||||
|
*/
|
||||||
toJSON() {
|
toJSON() {
|
||||||
const object = {
|
const object = {
|
||||||
nam: this.name
|
nam: this.name
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,15 @@ export class VirtualFile extends VirtualBase {
|
||||||
* @returns {VirtualFile}
|
* @returns {VirtualFile}
|
||||||
*/
|
*/
|
||||||
setSource(source) {
|
setSource(source) {
|
||||||
if (this.source === source)
|
if (this.source === source || !this.canBeEdited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.content = null;
|
this.content = null;
|
||||||
|
|
||||||
this.emit(VirtualFile.EVENT_NAMES.CONTENT_CHANGE, this);
|
this.emit(VirtualFile.EVENT_NAMES.CONTENT_CHANGE, this);
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,15 +53,15 @@ export class VirtualFile extends VirtualBase {
|
||||||
* @returns {VirtualFile}
|
* @returns {VirtualFile}
|
||||||
*/
|
*/
|
||||||
setContent(content) {
|
setContent(content) {
|
||||||
if (this.content === content)
|
if (this.content === content || !this.canBeEdited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.source = null;
|
this.source = null;
|
||||||
|
|
||||||
this.emit(VirtualFile.EVENT_NAMES.CONTENT_CHANGE, this);
|
this.emit(VirtualFile.EVENT_NAMES.CONTENT_CHANGE, this);
|
||||||
this.getRoot().saveData();
|
|
||||||
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,8 +93,18 @@ export class VirtualFile extends VirtualBase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {object | null}
|
||||||
|
*/
|
||||||
toJSON() {
|
toJSON() {
|
||||||
|
// Don't return file if it can't or hasn't been edited
|
||||||
|
if (!this.canBeEdited || (this.editedByUser == null || !this.editedByUser))
|
||||||
|
return null;
|
||||||
|
|
||||||
const object = super.toJSON();
|
const object = super.toJSON();
|
||||||
|
|
||||||
|
if (object == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (this.extension != null) {
|
if (this.extension != null) {
|
||||||
object.ext = this.extension;
|
object.ext = this.extension;
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ export class VirtualFolder extends VirtualBase {
|
||||||
* @returns {VirtualFolder}
|
* @returns {VirtualFolder}
|
||||||
*/
|
*/
|
||||||
createFile(name, extension, callback) {
|
createFile(name, extension, callback) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
let newFile = this.findFile(name, extension);
|
let newFile = this.findFile(name, extension);
|
||||||
if (newFile == null) {
|
if (newFile == null) {
|
||||||
newFile = new VirtualFile(name, extension);
|
newFile = new VirtualFile(name, extension);
|
||||||
|
|
@ -104,7 +107,8 @@ export class VirtualFolder extends VirtualBase {
|
||||||
newFile.parent = this;
|
newFile.parent = this;
|
||||||
}
|
}
|
||||||
callback?.(newFile);
|
callback?.(newFile);
|
||||||
this.getRoot().saveData();
|
|
||||||
|
newFile.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,10 +120,14 @@ export class VirtualFolder extends VirtualBase {
|
||||||
* @returns {VirtualFolder}
|
* @returns {VirtualFolder}
|
||||||
*/
|
*/
|
||||||
createFiles(files) {
|
createFiles(files) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
files.forEach(({name, extension}) => {
|
files.forEach(({name, extension}) => {
|
||||||
this.createFile(name, extension);
|
this.createFile(name, extension);
|
||||||
});
|
});
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,6 +143,9 @@ export class VirtualFolder extends VirtualBase {
|
||||||
* @param {createFolderCallback} callback
|
* @param {createFolderCallback} callback
|
||||||
*/
|
*/
|
||||||
createFolder(name, callback) {
|
createFolder(name, callback) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
let newFolder = this.findSubFolder(name);
|
let newFolder = this.findSubFolder(name);
|
||||||
if (newFolder == null) {
|
if (newFolder == null) {
|
||||||
newFolder = new VirtualFolder(name);
|
newFolder = new VirtualFolder(name);
|
||||||
|
|
@ -142,7 +153,8 @@ export class VirtualFolder extends VirtualBase {
|
||||||
newFolder.parent = this;
|
newFolder.parent = this;
|
||||||
}
|
}
|
||||||
callback?.(newFolder);
|
callback?.(newFolder);
|
||||||
this.getRoot().saveData();
|
|
||||||
|
newFolder.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,18 +164,25 @@ export class VirtualFolder extends VirtualBase {
|
||||||
* @returns {VirtualFolder}
|
* @returns {VirtualFolder}
|
||||||
*/
|
*/
|
||||||
createFolders(folders) {
|
createFolders(folders) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
folders.forEach((name) => {
|
folders.forEach((name) => {
|
||||||
this.createFolder(name);
|
this.createFolder(name);
|
||||||
});
|
});
|
||||||
this.getRoot().saveData();
|
|
||||||
|
this.confirmChanges();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a file or folder from this folder
|
* Removes a file or folder from this folder
|
||||||
* @param {VirtualFile|VirtualFolder} child
|
* @param {VirtualFile | VirtualFolder} child
|
||||||
*/
|
*/
|
||||||
remove(child) {
|
remove(child) {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
child.parent = null;
|
child.parent = null;
|
||||||
|
|
||||||
if (child instanceof VirtualFile) {
|
if (child instanceof VirtualFile) {
|
||||||
|
|
@ -172,13 +191,13 @@ export class VirtualFolder extends VirtualBase {
|
||||||
removeFromArray(child, this.subFolders);
|
removeFromArray(child, this.subFolders);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getRoot()?.saveData();
|
child.confirmChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the file or folder at a relative path or null if it doesn't exist
|
* Returns the file or folder at a relative path or null if it doesn't exist
|
||||||
* @param {string} relativePath
|
* @param {string} relativePath
|
||||||
* @returns {VirtualFile|VirtualFolder|null}
|
* @returns {VirtualFile | VirtualFolder | null}
|
||||||
*/
|
*/
|
||||||
navigate(relativePath) {
|
navigate(relativePath) {
|
||||||
const segments = relativePath.split("/");
|
const segments = relativePath.split("/");
|
||||||
|
|
@ -231,16 +250,20 @@ export class VirtualFolder extends VirtualBase {
|
||||||
* Deletes this folder and all its files and sub-folders recursively
|
* Deletes this folder and all its files and sub-folders recursively
|
||||||
*/
|
*/
|
||||||
delete() {
|
delete() {
|
||||||
|
if (!this.canBeEdited)
|
||||||
|
return;
|
||||||
|
|
||||||
super.delete();
|
super.delete();
|
||||||
|
|
||||||
this.files.concat(this.subFolders).forEach((item) => {
|
this.files.concat(this.subFolders).forEach((item) => {
|
||||||
item.delete();
|
item.delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getRoot()?.saveData();
|
this.confirmChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns all files inside this folder
|
||||||
* @param {Boolean=false} showHidden
|
* @param {Boolean=false} showHidden
|
||||||
* @returns {Array<VirtualFile>}
|
* @returns {Array<VirtualFile>}
|
||||||
*/
|
*/
|
||||||
|
|
@ -254,6 +277,7 @@ export class VirtualFolder extends VirtualBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns all subfolders inside this folder
|
||||||
* @param {Boolean=false} showHidden
|
* @param {Boolean=false} showHidden
|
||||||
* @returns {Array<VirtualFolder>}
|
* @returns {Array<VirtualFolder>}
|
||||||
*/
|
*/
|
||||||
|
|
@ -266,16 +290,36 @@ export class VirtualFolder extends VirtualBase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {object | null}
|
||||||
|
*/
|
||||||
toJSON() {
|
toJSON() {
|
||||||
const object = super.toJSON();
|
const object = super.toJSON();
|
||||||
|
|
||||||
|
if (object == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (this.files.length > 0) {
|
if (this.files.length > 0) {
|
||||||
object.fls = this.files.map((file) => file.toJSON());
|
const files = this.files
|
||||||
|
.map((file) => file.toJSON())
|
||||||
|
.filter((file) => file != null);
|
||||||
|
|
||||||
|
if (files.length > 0)
|
||||||
|
object.fls = files;
|
||||||
}
|
}
|
||||||
if (this.subFolders.length > 0) {
|
if (this.subFolders.length > 0) {
|
||||||
object.fds = this.subFolders.map((folder) => folder.toJSON());
|
const folders = this.subFolders
|
||||||
|
.map((folder) => folder.toJSON())
|
||||||
|
.filter((folder) => folder != null);
|
||||||
|
|
||||||
|
if (folders.length > 0)
|
||||||
|
object.fds = folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't store folder if it's empty
|
||||||
|
if ((!object.fls || object.fls.length === 0) && (!object.fds || object.fds.length === 0))
|
||||||
|
return null;
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,14 +7,16 @@ import { VirtualFolder } from "./virtualFolder.js";
|
||||||
* A virtual folder that serves as the root folder
|
* A virtual folder that serves as the root folder
|
||||||
*/
|
*/
|
||||||
export class VirtualRoot extends VirtualFolder {
|
export class VirtualRoot extends VirtualFolder {
|
||||||
/**
|
/** @type {boolean} */
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
initiated = false;
|
initiated = false;
|
||||||
|
|
||||||
|
/** @type {boolean} */
|
||||||
|
loadedDefaultData = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("root");
|
super("root");
|
||||||
this.root = this;
|
this.root = this;
|
||||||
|
this.isRoot = true;
|
||||||
this.shortcuts = {};
|
this.shortcuts = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,18 +53,21 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.createFolder("Images", (folder) => {
|
.createFolder("Images", (folder) => {
|
||||||
for (let i = 0; i < WALLPAPERS.length; i++) {
|
folder.createFolder("Wallpapers", (folder) => {
|
||||||
const source = WALLPAPERS[i];
|
folder.setProtected(true);
|
||||||
folder.createFile(`Wallpaper${i + 1}`, "png", (file) => {
|
for (let i = 0; i < WALLPAPERS.length; i++) {
|
||||||
file.setSource(source);
|
const source = WALLPAPERS[i];
|
||||||
});
|
folder.createFile(`Wallpaper${i + 1}`, "png", (file) => {
|
||||||
}
|
file.setSource(source);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.createFolder("Documents", (folder) => {
|
.createFolder("Documents", (folder) => {
|
||||||
folder.createFile("text", "txt", (file) => {
|
folder.createFile("text", "txt", (file) => {
|
||||||
file.setContent("Hello world!");
|
file.setContent("Hello world!");
|
||||||
}).createFile("info", "md", (file) => {
|
}).createFile("info", "md", (file) => {
|
||||||
file.setSource("/documents/info.md");
|
file.setProtected(true).setSource("/documents/info.md");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.createFolder("Desktop");
|
.createFolder("Desktop");
|
||||||
|
|
@ -117,10 +122,10 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
|
|
||||||
const addFolder = ({ nam: name, fds: folders, fls: files }, parent = this) => {
|
const addFolder = ({ nam: name, fds: folders, fls: files }, parent = this) => {
|
||||||
parent.createFolder(name, (folder) => {
|
parent.createFolder(name, (folder) => {
|
||||||
if (Object.values(shortcuts).includes(folder.absolutePath)) {
|
if (Object.values(shortcuts).includes(folder.displayPath)) {
|
||||||
let alias;
|
let alias;
|
||||||
for (const [key, value] of Object.entries(shortcuts)) {
|
for (const [key, value] of Object.entries(shortcuts)) {
|
||||||
if (value === folder.absolutePath)
|
if (value === folder.displayPath)
|
||||||
alias = key;
|
alias = key;
|
||||||
}
|
}
|
||||||
folder.setAlias(alias);
|
folder.setAlias(alias);
|
||||||
|
|
@ -148,23 +153,40 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
addFile(file);
|
addFile(file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the storage manager's store function with this root's data as a string
|
||||||
|
*/
|
||||||
saveData() {
|
saveData() {
|
||||||
if (!this.initiated)
|
if (!this.initiated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StorageManager.store("data", this.toString());
|
const data = this.toString();
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
StorageManager.store("data", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates this root by loading the default data and then the user's data on top
|
||||||
|
* @returns {VirtualRoot}
|
||||||
|
*/
|
||||||
init() {
|
init() {
|
||||||
this.initiated = false;
|
this.initiated = false;
|
||||||
|
|
||||||
|
// Load default data
|
||||||
|
this.loadedDefaultData = false;
|
||||||
this.setAlias("/");
|
this.setAlias("/");
|
||||||
this.loadDefaultData();
|
this.loadDefaultData();
|
||||||
|
this.loadedDefaultData = true;
|
||||||
|
|
||||||
|
// Load user's data
|
||||||
this.loadData();
|
this.loadData();
|
||||||
this.initiated = true;
|
this.initiated = true;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,6 +201,9 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells the storage manager to clear all data and reloads the window
|
||||||
|
*/
|
||||||
reset() {
|
reset() {
|
||||||
if (window.confirm("Are you sure you want to reset all your data?")) {
|
if (window.confirm("Are you sure you want to reset all your data?")) {
|
||||||
StorageManager.clear();
|
StorageManager.clear();
|
||||||
|
|
@ -202,13 +227,19 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
get absolutePath() {
|
get displayPath() {
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {object | null}
|
||||||
|
*/
|
||||||
toJSON() {
|
toJSON() {
|
||||||
const object = super.toJSON();
|
const object = super.toJSON();
|
||||||
|
|
||||||
|
if (object == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (Object.entries(this.shortcuts).length > 0) {
|
if (Object.entries(this.shortcuts).length > 0) {
|
||||||
object.scs = {};
|
object.scs = {};
|
||||||
|
|
||||||
|
|
@ -220,8 +251,15 @@ export class VirtualRoot extends VirtualFolder {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string | null}
|
||||||
|
*/
|
||||||
toString() {
|
toString() {
|
||||||
const json = this.toJSON();
|
const json = this.toJSON();
|
||||||
|
|
||||||
|
if (json == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
return JSON.stringify(json);
|
return JSON.stringify(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue