Skip to content

Commit

Permalink
feat(explorer): .wapp files are now folders
Browse files Browse the repository at this point in the history
  • Loading branch information
FranklinWaller committed Nov 6, 2019
1 parent 30dbd4a commit 9a58b5c
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/js/apps/Explorer/Explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function Explorer() {
<Dropzone currentPath={path} className={styles.files}>
{files.map((file) => {
if (file.isDirectory()) {
return <Folder key={file.name.toString()} folder={file} onClick={handleFileClick} />
return <Folder path={path} key={file.name.toString()} folder={file} onClick={handleFileClick} />
} else if (file.isFile()) {
return <File path={path} key={file.name.toString()} file={file} onClick={handleFileClick} />
}
Expand Down
12 changes: 2 additions & 10 deletions src/js/apps/Explorer/components/File/File.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,8 @@ export default function File(props: Props) {
const fileName: any = props.file.name;
const fileExtension = getFileExtension(fileName);

if (fileExtension === 'wapp') {
// We should read the wapp for an icon
const wasmFs = InstanceBag.get<WasmFs>('fs');
const file: any = await readFileAsync(wasmFs.fs, `${props.path}/${props.file.name}`);
const info = await getWappInformation(file);

if (info !== null) {
setIcon(info.icon);
setName(info.app.short_name);
}
if (fileExtension === 'jpg') {

}
}

Expand Down
15 changes: 14 additions & 1 deletion src/js/apps/Explorer/components/Folder/Folder.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@
height: 200px;
}

.iconWrapper {
width: 100%;
height: 50%;
text-align: center;
padding: 10px 0;
}

.icon {
width: 100%;
height: 60%;
height: 100%;
color: #6accf9;
cursor: pointer;
}

.appIcon {
height: 100%;
cursor: pointer;
border-radius: 5px;
}
44 changes: 42 additions & 2 deletions src/js/apps/Explorer/components/Folder/Folder.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,58 @@
import * as React from 'react';
import Dirent from 'memfs/lib/Dirent';
import FolderIcon from '@material-ui/icons/Folder';
import { getFileExtension, readFileAsync } from '../../../../services/FileSystemService';
import InstanceBag from '../../../../InstanceBag';
import { WasmFs } from '@wasmer/wasmfs';
import { getWappInformation } from '../../../../services/WappService';
const styles = require('./Folder.scss');

const WAPP_EXTENSION = 'wapp';

interface Props {
folder: Dirent
path: string;
onClick?: (folder: Dirent) => void;
}

export default function Folder(props: Props) {
const [icon, setIcon] = React.useState('');
const [name, setName] = React.useState(props.folder.name);

React.useEffect(() => {
async function processFile() {
// This is a special folder with an "extension"
const folderName: any = props.folder.name;
const folderExtension = getFileExtension(folderName);

if (folderExtension === WAPP_EXTENSION) {
const wappInfo = await getWappInformation(`${props.path}/${folderName}`);


// We should read the wapp for an icon
// const wasmFs = InstanceBag.get<WasmFs>('fs');
// const file: any = await readFileAsync(wasmFs.fs, `${props.path}/${props.file.name}`);
// const info = await getWappInformation(file);

if (wappInfo !== null) {
const newFolderName = folderName.replace('.' + WAPP_EXTENSION, '');

setIcon(wappInfo.icon);
setName(newFolderName);
}
}
}

processFile();
}, []);

return (
<div className={styles.folder}>
<FolderIcon className={styles.icon} onClick={() => props.onClick(props.folder)} />
<span>{props.folder.name}</span>
<div className={styles.iconWrapper} onClick={() => props.onClick(props.folder)}>
{icon === '' && <FolderIcon className={styles.icon} />}
{icon !== '' && <img className={styles.appIcon} src={icon} />}
</div>
<span>{name}</span>
</div>
);
}
15 changes: 13 additions & 2 deletions src/js/services/FileSystemService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export async function createFs() {
const wasmFs: WasmFsType = new WasmFs();

const wasm = await (await fetch('/wasm/cowsay.wasm')).arrayBuffer();
const wapp = await (await fetch('/wasm/wapp/cowsay/cowsay.wapp')).arrayBuffer();
const cowsayIcon = await (await fetch('/wasm/wapp/cowsay/icon.jpg')).arrayBuffer();
const manifest = await (await fetch('/wasm/wapp/cowsay/manifest.json')).arrayBuffer();

wasmFs.fs.mkdirSync('/Applications/');
wasmFs.fs.mkdirSync('/Library/');
Expand All @@ -19,8 +20,18 @@ export async function createFs() {
recursive: true,
});

wasmFs.fs.mkdirSync('/Applications/Cowsay.wapp/Resources/', {
recursive: true,
});
wasmFs.fs.mkdirSync('/Applications/Cowsay.wapp/Contents/', {
recursive: true,
});

wasmFs.fs.writeFileSync('/Applications/Cowsay.wapp/Resources/icon.jpg', new Uint8Array(cowsayIcon));
wasmFs.fs.writeFileSync('/Applications/Cowsay.wapp/manifest.json', new Uint8Array(manifest));
wasmFs.fs.writeFileSync('/Applications/Cowsay.wapp/Contents/main.wasm', new Uint8Array(wasm));

wasmFs.fs.writeFileSync('/Applications/cowsay.wasm', new Uint8Array(wasm));
wasmFs.fs.writeFileSync('/Applications/cowsay.wapp', new Uint8Array(wapp));
wasmFs.fs.writeFileSync('/dev/null', envContents);
// wasmFs.fs.writeFileSync('.env', envContents);
wasmFs.fs.writeFileSync('/Users/.env', envContents);
Expand Down
9 changes: 9 additions & 0 deletions src/js/services/TerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { fetchCommandFromWAPM } from "@wasmer/wasm-terminal/lib/unoptimized/wasm
// @ts-ignore
import { lowerI64Imports } from "@wasmer/wasm-transformer/lib/unoptimized/wasm-transformer.esm";
import { readFileAsync } from "./FileSystemService";
import { getApplicationFromWapp } from "./WappService";

export default class TerminalService {
wasmFs: WasmFs;
Expand All @@ -30,6 +31,14 @@ export default class TerminalService {
if (commandName.endsWith('.wasm')) {
// Fetch the binary from the file system and return it
return readFileAsync(this.wasmFs.fs, commandName);
} else if (commandName.endsWith('.wapp')) {
const appInfo = await getApplicationFromWapp(commandName);

if (appInfo.isWasm) {
return appInfo.wasm;
}

return 'TODO: Support PWAs';
}

// if (commandName === "pwd") {
Expand Down
57 changes: 48 additions & 9 deletions src/js/services/WappService.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import * as JSZip from 'jszip';
import * as path from 'path';
import { WasmFs } from '@wasmer/wasmfs';
import InstanceBag from '../InstanceBag';
import Application from '../models/Application';
import { readFileAsync } from './FileSystemService';

export async function getWappInformation(binary: Uint8Array) {
export async function getWappInformation(wappFolderPath: string) {
try {
const zip = new JSZip();
const zipFile = await zip.loadAsync(binary);
const manifestRaw = await zipFile.file('manifest.json').async('text');
const manifest: Application = JSON.parse(manifestRaw);
const iconSrc = (path.resolve('/', manifest.icons[0].src)).slice(1);
const icon = await zipFile.file(iconSrc).async("blob");
const wasmFs = InstanceBag.get<WasmFs>('fs');
const manifestRaw = await readFileAsync(wasmFs.fs, `${wappFolderPath}/manifest.json`);
const manifest: Application = JSON.parse(manifestRaw.toString());

const iconPath = path.resolve(wappFolderPath, manifest.icons[0].src);
const iconRaw: any = await readFileAsync(wasmFs.fs, iconPath);
const iconBlob = new Blob([iconRaw], { type: 'image/jpeg' });

return {
icon: URL.createObjectURL(icon),
icon: URL.createObjectURL(iconBlob),
app: manifest,
};
} catch (error) {
Expand All @@ -21,3 +24,39 @@ export async function getWappInformation(binary: Uint8Array) {
return null;
}
}

/**
* Gets the wasm binary and app information out of the zip file
*
* @export
* @param {string} wappFolderPath
* @returns
*/
export async function getApplicationFromWapp(wappFolderPath: string) {
try {
const wasmFs = InstanceBag.get<WasmFs>('fs');
const manifestRaw = await readFileAsync(wasmFs.fs, `${wappFolderPath}/manifest.json`);
const manifest: Application = JSON.parse(manifestRaw.toString());

let isWasm = false;
let wasm: Uint8Array = null;

if (manifest.start_url.endsWith('.wasm')) {
const wasmPath = path.resolve(wappFolderPath, manifest.start_url);
const wasmBin: any = await readFileAsync(wasmFs.fs, wasmPath);

wasm = wasmBin;
isWasm = true;
}

return {
wasm,
isWasm,
app: manifest,
}
} catch (error) {
console.error(error);

return null;
}
}
4 changes: 2 additions & 2 deletions wasm/wapp/cowsay/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"description": "A cow that says anyhting you want",
"icons": [
{
"src": "./icon.jpg",
"src": "./Resources/icon.jpg",
"type": "image/jpeg",
"sizes": "512x512"
}
],
"start_url": "./main.wasm",
"start_url": "./Contents/main.wasm",
"scope": "/",
"display": "standalone",
"background_color": "#2196F3",
Expand Down

0 comments on commit 9a58b5c

Please sign in to comment.