mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-24 02:27:37 +00:00
* Improve typing of Actions * Make typing of MakiObjects more explicit * Make parent optional * Allow group to be initialized with all nulls * Whitelist all runtime ts files for type checking * Typecheck the entire modern codebase! * Ignore typescript
121 lines
3.4 KiB
TypeScript
121 lines
3.4 KiB
TypeScript
import {
|
|
MakiTree,
|
|
ModernAction,
|
|
ModernStore,
|
|
XmlTree,
|
|
XmlNode,
|
|
Thunk,
|
|
} from "./types";
|
|
import JSZip from "jszip";
|
|
import * as Utils from "./utils";
|
|
import initialize from "./initialize";
|
|
import initializeStateTree from "./initializeStateTree";
|
|
import { run } from "./maki-interpreter/virtualMachine";
|
|
import System from "./runtime/System";
|
|
import runtime from "./runtime";
|
|
import MakiObject from "./runtime/MakiObject";
|
|
import JsScript from "./runtime/JsScript";
|
|
|
|
export function setMakiTree(makiTree: MakiTree): ModernAction {
|
|
return { type: "SET_MAKI_TREE", makiTree };
|
|
}
|
|
|
|
export function setXmlTree(xmlTree: XmlTree): Thunk {
|
|
return async dispatch => {
|
|
dispatch({
|
|
type: "SET_XML_TREE",
|
|
xmlTree: await initializeStateTree(xmlTree),
|
|
});
|
|
};
|
|
}
|
|
|
|
export function gotSkinUrl(skinUrl: string, store: ModernStore): Thunk {
|
|
return async dispatch => {
|
|
const resp = await fetch(skinUrl);
|
|
dispatch(gotSkinBlob(await resp.blob(), store));
|
|
};
|
|
}
|
|
|
|
export function gotSkinBlob(blob: Blob, store: ModernStore): Thunk {
|
|
return async dispatch => {
|
|
dispatch(gotSkinZip(await JSZip.loadAsync(blob), store));
|
|
};
|
|
}
|
|
|
|
async function unloadSkin(makiTree: MakiTree): Promise<void> {
|
|
await Utils.asyncTreeFlatMap(makiTree, async (node: MakiObject) => {
|
|
if (node instanceof JsScript && node.system) {
|
|
node.system.onscriptunloading();
|
|
}
|
|
|
|
return node;
|
|
});
|
|
}
|
|
|
|
export function gotSkinZip(zip: JSZip, store: ModernStore): Thunk {
|
|
return async dispatch => {
|
|
// unload current skin if one has been loaded
|
|
if (store.getState().modernSkin.skinLoaded) {
|
|
await unloadSkin(store.getState().modernSkin.makiTree);
|
|
dispatch({ type: "SKIN_UNLOADED" });
|
|
}
|
|
|
|
const skinXml = await Utils.readXml(zip, "skin.xml");
|
|
if (skinXml == null) {
|
|
throw new Error("Could not find skin.xml in skin");
|
|
}
|
|
const rawXmlTree = await Utils.inlineIncludes(skinXml, zip);
|
|
const xmlTree = Utils.mapTreeBreadth(
|
|
rawXmlTree,
|
|
(node: XmlNode, parent: XmlNode) => {
|
|
return { ...node, uid: Utils.getId(), parent };
|
|
}
|
|
);
|
|
|
|
dispatch(setXmlTree(xmlTree));
|
|
|
|
const makiTree: MakiObject = await initialize(zip, xmlTree);
|
|
// Execute scripts
|
|
await Utils.asyncTreeFlatMap(makiTree, async (node: MakiObject) => {
|
|
if (!(node instanceof JsScript)) {
|
|
return node;
|
|
}
|
|
const scriptPath = node.getScriptPath();
|
|
if (scriptPath == null) {
|
|
return node;
|
|
}
|
|
if (scriptPath.endsWith("standardframe.maki")) {
|
|
// TODO: stop ignoring standardframe
|
|
return node;
|
|
}
|
|
|
|
// removes groupdefs from consideration (only run scripts when actually referenced by group)
|
|
if (Utils.findParentNodeOfType(node, new Set(["groupdef"]))) {
|
|
return node;
|
|
}
|
|
const scriptGroup = Utils.findParentNodeOfType(
|
|
node,
|
|
new Set(["group", "winampabstractionlayer", "wasabixml"])
|
|
);
|
|
node.system = new System(scriptGroup, store);
|
|
const script = await Utils.readUint8array(zip, scriptPath);
|
|
if (script == null) {
|
|
console.warn(`Unable to find script at ${scriptPath}`);
|
|
return node;
|
|
}
|
|
run({
|
|
runtime,
|
|
data: script,
|
|
system: node.system,
|
|
log: false,
|
|
});
|
|
return node;
|
|
});
|
|
|
|
dispatch(setMakiTree(makiTree));
|
|
};
|
|
}
|
|
|
|
export function setVolume(volume: number): ModernAction {
|
|
return { type: "SET_VOLUME", volume };
|
|
}
|