diff --git a/demo/js/index.js b/demo/js/index.js index 28e24e5f..2187499c 100644 --- a/demo/js/index.js +++ b/demo/js/index.js @@ -152,6 +152,13 @@ Raven.context(async () => { // @ts-ignore "butterchurn"); }, + importConvertPreset: () => { + return import(/* webpackChunkName: "milkdrop-preset-converter" */ + // @ts-ignore + "milkdrop-preset-converter-aws"); + }, + presetConverterEndpoint: + "https://p2tpeb5v8b.execute-api.us-east-2.amazonaws.com/default/milkdropShaderConverter", getPresets: async () => { if ("URLSearchParams" in window) { const params = new URLSearchParams(location.search); diff --git a/js/actionCreators/milkdrop.ts b/js/actionCreators/milkdrop.ts index 1d83e111..073d5b20 100644 --- a/js/actionCreators/milkdrop.ts +++ b/js/actionCreators/milkdrop.ts @@ -66,29 +66,23 @@ export function loadPresets(presets: StatePreset[]): Dispatchable { } export function appendPresetFileList(fileList: FileList): Dispatchable { - return async dispatch => { - const presets: StatePreset[] = Array.from(fileList).map( - (file): StatePreset => { + return async (dispatch, getState, { convertPreset }) => { + const presets: StatePreset[] = Array.from(fileList) + .map(file => { const JSON_EXT = ".json"; const MILK_EXT = ".milk"; const filename = file.name.toLowerCase(); if (filename.endsWith(MILK_EXT)) { - throw new Error(".milk preset support not yet implemented"); - // Not sure why we need this type definition. - /* - const lazy: LazyButterchurnPresetJson = { - type: "LAZY_BUTTERCHURN_JSON", - name: file.name.slice(0, file.name.length - MILK_EXT.length), - getDefinition: async () => { - // TODO: Post this blob to the url end point and get the json back - return {}; + if (convertPreset == null) { + throw new Error("Invalid type"); } - }; - return lazy; - */ + return { + type: "UNRESOLVED", + name: file.name.slice(0, file.name.length - MILK_EXT.length), + getPreset: async () => convertPreset(file) + } as StatePreset; } else if (filename.endsWith(JSON_EXT)) { - // Not sure why we need this type definition. - const lazy: StatePreset = { + return { type: "UNRESOLVED", name: file.name.slice(0, file.name.length - JSON_EXT.length), getPreset: async () => { @@ -96,13 +90,13 @@ export function appendPresetFileList(fileList: FileList): Dispatchable { // TODO: How should we handle the case where json parsing fails? return JSON.parse(str); } - }; - return lazy; + } as StatePreset; } else { throw new Error("Invalid type"); } - } - ); + return null as never; + }) + .filter(Boolean); dispatch(loadPresets(presets)); // TODO: Select the first of these presets }; diff --git a/js/components/MilkdropWindow/options.ts b/js/components/MilkdropWindow/options.ts deleted file mode 100644 index 02c3738a..00000000 --- a/js/components/MilkdropWindow/options.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ButterchurnOptions } from "../../types"; - -async function loadConvertPreset() { - const { convertPreset } = - // prettier-ignore - await import( - /* webpackChunkName: "milkdrop-preset-converter" */ - // @ts-ignore - "milkdrop-preset-converter-aws" - ); - return convertPreset; -} diff --git a/js/types.ts b/js/types.ts index 47d27c4a..348c35cd 100644 --- a/js/types.ts +++ b/js/types.ts @@ -146,6 +146,11 @@ export type PresetId = string; export interface ButterchurnOptions { getPresets(): Promise; importButterchurn(): Promise; + importConvertPreset?: () => Promise<{ + convertPreset(file: string, endpoint: string): Promise; + }>; + presetConverterEndpoint?: string; + butterchurnOpen: boolean; } export interface EqfPreset { @@ -628,8 +633,9 @@ export interface IMusicMetadataBrowserApi { } export interface Extras { - requireJSZip: () => Promise; - requireMusicMetadata: () => Promise; + requireJSZip(): Promise; + requireMusicMetadata(): Promise; + convertPreset: ((file: File) => Promise) | null; } export type GetState = () => AppState; diff --git a/js/webampLazy.tsx b/js/webampLazy.tsx index 5d63b28d..c3ecef12 100644 --- a/js/webampLazy.tsx +++ b/js/webampLazy.tsx @@ -8,7 +8,8 @@ import { Track, LoadedURLTrack, Middleware, - WindowPosition + WindowPosition, + ButterchurnOptions } from "./types"; import getStore from "./store"; import App from "./components/App"; @@ -19,6 +20,7 @@ import * as Actions from "./actionCreators"; import { LOAD_STYLE } from "./constants"; import * as Utils from "./utils"; +import * as FileUtils from "./fileUtils"; import { SET_AVAILABLE_SKINS, @@ -118,7 +120,7 @@ interface PrivateOptions { position: WindowPosition; }; }; - __butterchurnOptions: { butterchurnOpen: boolean }; + __butterchurnOptions: ButterchurnOptions; } // Return a promise that resolves when the store matches a predicate. @@ -170,9 +172,29 @@ class Winamp { enableHotkeys = false, zIndex, requireJSZip, - requireMusicMetadata + requireMusicMetadata, + __butterchurnOptions } = this.options; + // TODO: Make this much cleaner + let convertPreset = null; + if (__butterchurnOptions != null) { + const { + importConvertPreset, + presetConverterEndpoint + } = __butterchurnOptions; + + if (importConvertPreset != null && presetConverterEndpoint != null) { + convertPreset = async (file: File): Promise => { + const { convertPreset } = await importConvertPreset(); + return convertPreset( + await FileUtils.genStringFromFileReference(file), + presetConverterEndpoint + ); + }; + } + } + // TODO: Validate required options this.media = new Media(); @@ -181,7 +203,7 @@ class Winamp { this._actionEmitter, this.options.__customMiddlewares, this.options.__initialState, - { requireJSZip, requireMusicMetadata } + { requireJSZip, requireMusicMetadata, convertPreset } ) as Store; if (navigator.onLine) {