Skip to content

Commit

Permalink
Merge pull request #54 from robbiebyrd/react
Browse files Browse the repository at this point in the history
Finder work
  • Loading branch information
robbiebyrd authored Apr 14, 2024
2 parents eda3265 + 73d3393 commit a40f93b
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 143 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"react-dom": "^18.2.0",
"react-json-tree": "^0.18.0",
"sass": "^1.70.0",
"sha512-crypt-ts": "^0.1.27",
"stylelint": "^16.2.1",
"sync-fetch": "^0.5.2",
"url-safe-string": "^1.1.0"
Expand Down
2 changes: 1 addition & 1 deletion src/app/SystemFolder/Finder/Finder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Finder = () => {
React.useEffect(() => {
const drives = fs.filterByType("", "drive");

drives.forEach(([a, b]) => {
Object.entries(drives).forEach(([a, b]) => {
desktopEventDispatch({
type: "PlatinumDesktopIconAdd",
app: {
Expand Down
259 changes: 199 additions & 60 deletions src/app/SystemFolder/SystemResources/File/FileSystem.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,100 @@
import {sha512} from 'sha512-crypt-ts';

let defaultFSContent = {
"Macintosh HD": {
"_type": "drive",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/drives/disk.png`,
"test3.txt": {
"_type": "file",
"_mimeType": "",
"_data": "File Contents",
"Applications": {
"_type": "directory",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/folders/directory.png`,
"TextEdit.app": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents",
},
"Calculator.app": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents",
}
},
"Library": {
"_type": "directory",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/folders/directory.png`,
"Extensions": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents"
}
},
"test": {
"System Folder": {
"_type": "directory",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/folders/directory.png`,
"Finder": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents"
},
"System": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents"
}
},
"test2": {
"Users": {
"_type": "directory",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/folders/directory.png`,
"test1.txt": {
"Guest": {
"_type": "file",
"_mimeType": "",
"_mimeType": "text/plain",
"_data": "File Contents"
},
"test.txt": {
"Shared": {
"_type": "file",
"_mimeType": "",
"_mimeType": "text/plain",
"_data": "File Contents"
}
},
"Utilities": {
"_type": "directory",
"_icon": `${process.env.NEXT_PUBLIC_BASE_PATH}/img/icons/system/folders/directory.png`,
"Disk Utility.app": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents",
},
"Terminal.app": {
"_type": "file",
"_mimeType": "text/plain",
"_data": "File Contents",
}
}
}
}

export type FileSystemEntry = {
"_type": "drive" | "directory" | "file";
export type PlatinumFileSystemEntry = {
"_type": "drive" | "directory" | "file" | "shortcut" | "app_shortcut";
"_icon"?: string;
"_mimeType"?: string;
"_data"?: any;
"_createdOn"?: Date;
"_modifiedOn"?: Date;
"_label"?: string;
"_comments"?: string;
"_version": number;
"_version"?: number;
"_locked"?: boolean;
"_count"?: number;
"_size"?: number | string;
"_readOnly"?: boolean;
"_systemFile"?: boolean;
[entry: string]: any;
}

type pathOrObject = PlatinumFileSystemEntry | string

export class PlatinumFileSystem {
basePath: string;
fs: FileSystemEntry;
fs: PlatinumFileSystemEntry;
separator: string;

constructor(basePath: string = "", defaultFS: any = defaultFSContent, separator = ":") {
Expand All @@ -54,29 +105,119 @@ export class PlatinumFileSystem {
this.separator = separator;
}

size(path: string) {
return new Blob([this.readFileRaw(path)]).size;
load(data: string) {
this.fs = JSON.parse(data) as PlatinumFileSystemEntry;
}

pathArray(path: string) {
return [this.basePath, ...path.split(this.separator)].filter((v) => v !== "");
snapshot(): string {
return JSON.stringify(this.fs, null, 2);
}

resolve(path: string): PlatinumFileSystemEntry {
const pathArray = (path: string) => {
return [this.basePath, ...path.split(this.separator)].filter((v) => v !== "");
}
return pathArray(path).reduce((prev, curr) => prev?.[curr], this.fs)
}

formatSize(bytes: number, measure: "bits" | "bytes" = "bytes", decimals: number = 2): string {
if (!+bytes) return '0 ' + measure;
const sizes = measure === "bits"
? ['Bits', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb', 'Eb', 'Zb', 'Yb']
: ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

const i = Math.floor(Math.log(bytes) / Math.log(1024));
bytes = measure === "bits" ? bytes * 8 : bytes;

return `${parseFloat((bytes / Math.pow(1024, i)).toFixed(Math.max(0, decimals)))} ${sizes[i]}`;
}

filterMetadata(content: any, mode: "only" | "remove" = "remove") {
let items: PlatinumFileSystemEntry | object = {};

Object.entries(content).forEach(([key, value]) => {
switch (mode) {
case "only": {
if (key.startsWith("_")) {
items[key] = value
}
break;
}
default: {
if (!key.startsWith("_")) {
items[key] = value
}
break;
}
}
});
return items
}

resolve(path: string) {
return this.pathArray(path).reduce((prev, curr) => prev?.[curr], this.fs)
filterByType(path: string, byType: string | string[] = ["file", "directory"]) {
let items: PlatinumFileSystemEntry | object = {};
Object.entries(this.resolve(path)).forEach(([b, a]) => {
if (byType.includes(a["_type"])) {
items[b] = a
}
});
return items
}

readFile(path: string) {
statFile(path: string, formatSize?: boolean, sizeIn: "bits" | "bytes" = "bytes"): PlatinumFileSystemEntry {
let item = this.resolve(path);
if ('_data' in item && '_mimeType' in item) {
return this.renderFile(item['_mimeType'], item['_data']);
if (formatSize) {
item['_size'] = this.formatSize(this.size(path), sizeIn)
} else {
item['_size'] = this.size(path)
}
return item
}

readFileRaw(path: string) {
let item = this.resolve(path);
if ('_data' in item) {
return item['_data'];
size(path: pathOrObject): number {
if (typeof path === 'string') {
return new Blob([this.readFileRaw(path)]).size;
}
if (path instanceof Object && '_data' in path) {
return new Blob([path['_data'] as string]).size;
}
}

hash(path: pathOrObject) {
if (typeof path === 'string') {
return sha512.crypt(this.readFileRaw(path), "");
}
if (path instanceof Object && '_data' in path) {
return sha512.crypt(path['_data'], "");
}
}

readFileRaw(path: pathOrObject): string {
if (path instanceof Object && '_data' in path) {
return path['_data'] as string
}
if (typeof path === 'string') {
let item: PlatinumFileSystemEntry = this.resolve(path);
if (item && '_data' in item) {
return item['_data'];
}
}
}

readFile(path: pathOrObject) {
if (path instanceof Object && '_data' in path) {
return this.readFileRaw(path)
}
if (typeof path === 'string') {

let item: PlatinumFileSystemEntry = this.resolve(path);
if ('_data' in item) {
if ('_mimeType' in item) {
return this.renderFile(item['_mimeType'], item['_data']);
} else {
return item['_data'];
}
}
}
}

Expand All @@ -88,51 +229,49 @@ export class PlatinumFileSystem {
}
}

ls(path: string) {
let current = this.resolve(path);
return Object.entries(current);
}

filterMetadata(content: any, mode: "only" | "remove" = "remove") {
return Object.entries(content).filter(([a, _]) => {
switch (mode) {
case "only": {
if (a.startsWith("_")) return a
break;
}
default : {
if (!a.startsWith("_")) return a;
break;
calculateSizeDir(path: PlatinumFileSystemEntry | string): number {
const gatherSizes = (entry: PlatinumFileSystemEntry, field: string, value: string): any[] => {
let results: string[] = [];
for (const key in entry) {
if (key === field && entry[key] === value) {
results.push(String(this.size(entry)));
} else if (typeof entry[key] === 'object' && entry[key] !== null) {
results = results.concat(gatherSizes(entry[key] as PlatinumFileSystemEntry, field, value));
}
}
});
return results;
}

if (typeof path === 'string') {
path = this.resolve(path)
}

return gatherSizes(path, "_type", "file").reduce((a, c) => a + (+c), 0)
}

filterByType(path: string, byType: string | string[] = ["file", "directory"]) {
return Object.entries(this.resolve(path)).filter(([name, props]: [string, any]) => {
return typeof props === "object" && '_type' in props && byType.includes(props["_type"]);
})
countFilesInDir(path: string): number {
return Object.entries(this.filterMetadata(this.resolve(path))).length
}

statDir(path: string) {
let current = this.resolve(path);
statDir(path: string): PlatinumFileSystemEntry {
let current: PlatinumFileSystemEntry = this.resolve(path);
let metaData = this.filterMetadata(current, "only");

let name = path.split(":").slice(-1);
let name = path.split(this.separator).slice(-1);

let returnValue = {
"_path": path,
"_name": name[0],
"_count": this.filterMetadata(this.resolve(path)).length
}
let returnValue: PlatinumFileSystemEntry = {
'_count': this.countFilesInDir(path),
'_name': name[0],
'_path': path,
'_size': this.calculateSizeDir(current),
"_type": "directory"
};

metaData.forEach((a) => {
returnValue[a[0]] = a[1]
Object.entries(metaData).forEach(([key, value]) => {
returnValue[key] = value
})

return returnValue
}
}

const main = () => {

}
Loading

0 comments on commit a40f93b

Please sign in to comment.