mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 17:47:16 +00:00
Improve architecture of Milkdrop code
This commit is contained in:
parent
325a1dc536
commit
37b3340cd2
6 changed files with 130 additions and 161 deletions
|
|
@ -13,7 +13,6 @@ import zaxon from "../../skins/ZaxonRemake1-0.wsz";
|
|||
import green from "../../skins/Green-Dimension-V2.wsz";
|
||||
import base from "../../skins/base-2.91-png.wsz";
|
||||
import internetArchive from "../../skins/Internet-Archive.wsz";
|
||||
import partialButterchurnOptions from "../../js/components/MilkdropWindow/options";
|
||||
import { WINDOWS } from "../../js/constants";
|
||||
import * as Selectors from "../../js/selectors";
|
||||
|
||||
|
|
@ -147,6 +146,42 @@ Raven.context(async () => {
|
|||
let __butterchurnOptions = null;
|
||||
let __initialWindowLayout = null;
|
||||
if (isButterchurnSupported()) {
|
||||
const partialButterchurnOptions = {
|
||||
importButterchurn: () => {
|
||||
return import(/* webpackChunkName: "butterchurn-initial-dependencies" */
|
||||
// @ts-ignore
|
||||
"butterchurn");
|
||||
},
|
||||
getPresets: async () => {
|
||||
if ("URLSearchParams" in window) {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const butterchurnPresetUrlParam = params.get("butterchurnPresetUrl");
|
||||
const milkdropPresetUrl = params.get("milkdropPresetUrl");
|
||||
const initialPresets = [];
|
||||
if (butterchurnPresetUrlParam) {
|
||||
initialPresets.push({
|
||||
// TODO: Get name
|
||||
name: "foo",
|
||||
butterchurnPresetUrl: butterchurnPresetUrlParam
|
||||
});
|
||||
} else if (milkdropPresetUrl) {
|
||||
throw new Error("We still need to implement this");
|
||||
}
|
||||
const resp = await fetch(
|
||||
"https://unpkg.com/butterchurn-presets-weekly@0.0.2/weeks/week1/presets.json"
|
||||
);
|
||||
// TODO: Fallback to some other presets?
|
||||
const namesToPresetUrls = await resp.json();
|
||||
const presets = Object.entries(namesToPresetUrls).map(
|
||||
([name, butterchurnPresetUrl]) => {
|
||||
return { name, butterchurnPresetUrl };
|
||||
}
|
||||
);
|
||||
return [...initialPresets, ...presets];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
};
|
||||
const startWithMilkdropHidden =
|
||||
library ||
|
||||
document.body.clientWidth < MIN_MILKDROP_WIDTH ||
|
||||
|
|
|
|||
|
|
@ -10,44 +10,54 @@ import {
|
|||
Dispatchable,
|
||||
TransitionType,
|
||||
Preset,
|
||||
LazyButterchurnPresetJson
|
||||
ButterchurnOptions,
|
||||
StatePreset
|
||||
} from "../types";
|
||||
import * as FileUtils from "../fileUtils";
|
||||
|
||||
export function initializePresets(presetOptions: any): Dispatchable {
|
||||
return async dispatch => {
|
||||
const { loadInitialDependencies, loadNonMinimalPresets } = presetOptions;
|
||||
const {
|
||||
butterchurn,
|
||||
presetKeys,
|
||||
minimalPresets
|
||||
} = await loadInitialDependencies();
|
||||
dispatch({ type: GOT_BUTTERCHURN, butterchurn });
|
||||
|
||||
const presets: Preset[] = presetKeys.map((key: string) => {
|
||||
if (minimalPresets[key] != null) {
|
||||
return {
|
||||
type: "BUTTERCHURN_JSON",
|
||||
name: key,
|
||||
definition: minimalPresets[key]
|
||||
};
|
||||
function normalizePresetTypes(preset: Preset): StatePreset {
|
||||
const { name } = preset;
|
||||
if (preset.butterchurnPresetObject != null) {
|
||||
return {
|
||||
type: "RESOLVED",
|
||||
name,
|
||||
preset: preset.butterchurnPresetObject
|
||||
};
|
||||
} else if (preset.getButterchrunPresetObject) {
|
||||
return {
|
||||
type: "UNRESOLVED",
|
||||
name,
|
||||
getPreset: preset.getButterchrunPresetObject
|
||||
};
|
||||
} else if (preset.butterchurnPresetUrl != null) {
|
||||
return {
|
||||
type: "UNRESOLVED",
|
||||
name,
|
||||
getPreset: async () => {
|
||||
const resp = await fetch(preset.butterchurnPresetUrl);
|
||||
return resp.json();
|
||||
}
|
||||
return {
|
||||
type: "LAZY_BUTTERCHURN_JSON",
|
||||
name: key,
|
||||
getDefinition: async () => {
|
||||
// TODO: Avoid a race where we try to resolve this promise more than once in parallel.
|
||||
const nonMinimalPresets = await loadNonMinimalPresets();
|
||||
return nonMinimalPresets[key];
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
throw new Error("Invalid preset object");
|
||||
}
|
||||
|
||||
export function initializePresets(
|
||||
presetOptions: ButterchurnOptions
|
||||
): Dispatchable {
|
||||
return async dispatch => {
|
||||
const { getPresets, importButterchurn } = presetOptions;
|
||||
importButterchurn().then(butterchurn => {
|
||||
dispatch({ type: GOT_BUTTERCHURN, butterchurn: butterchurn.default });
|
||||
});
|
||||
|
||||
dispatch(loadPresets(presets));
|
||||
const presets = await getPresets();
|
||||
const normalizePresets = presets.map(normalizePresetTypes);
|
||||
dispatch(loadPresets(normalizePresets));
|
||||
};
|
||||
}
|
||||
|
||||
export function loadPresets(presets: Preset[]): Dispatchable {
|
||||
export function loadPresets(presets: StatePreset[]): Dispatchable {
|
||||
return (dispatch, getState) => {
|
||||
const presetLength = getState().milkdrop.presets.length;
|
||||
dispatch({ type: GOT_BUTTERCHURN_PRESETS, presets });
|
||||
|
|
@ -57,12 +67,15 @@ export function loadPresets(presets: Preset[]): Dispatchable {
|
|||
|
||||
export function appendPresetFileList(fileList: FileList): Dispatchable {
|
||||
return async dispatch => {
|
||||
const presets: Preset[] = Array.from(fileList).map(file => {
|
||||
const JSON_EXT = ".json";
|
||||
const MILK_EXT = ".milk";
|
||||
const filename = file.name.toLowerCase();
|
||||
if (filename.endsWith(MILK_EXT)) {
|
||||
// Not sure why we need this type definition.
|
||||
const presets: StatePreset[] = Array.from(fileList).map(
|
||||
(file): StatePreset => {
|
||||
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),
|
||||
|
|
@ -71,24 +84,25 @@ export function appendPresetFileList(fileList: FileList): Dispatchable {
|
|||
return {};
|
||||
}
|
||||
};
|
||||
throw new Error(".milk preset support not yet implemented");
|
||||
return lazy;
|
||||
} else if (filename.endsWith(JSON_EXT)) {
|
||||
// Not sure why we need this type definition.
|
||||
const lazy: LazyButterchurnPresetJson = {
|
||||
type: "LAZY_BUTTERCHURN_JSON",
|
||||
name: file.name.slice(0, file.name.length - JSON_EXT.length),
|
||||
getDefinition: async () => {
|
||||
const str = await FileUtils.genStringFromFileReference(file);
|
||||
// TODO: How should we handle the case where json parsing fails?
|
||||
return JSON.parse(str);
|
||||
}
|
||||
};
|
||||
return lazy;
|
||||
} else {
|
||||
throw new Error("Invalid type");
|
||||
*/
|
||||
} else if (filename.endsWith(JSON_EXT)) {
|
||||
// Not sure why we need this type definition.
|
||||
const lazy: StatePreset = {
|
||||
type: "UNRESOLVED",
|
||||
name: file.name.slice(0, file.name.length - JSON_EXT.length),
|
||||
getPreset: async () => {
|
||||
const str = await FileUtils.genStringFromFileReference(file);
|
||||
// TODO: How should we handle the case where json parsing fails?
|
||||
return JSON.parse(str);
|
||||
}
|
||||
};
|
||||
return lazy;
|
||||
} else {
|
||||
throw new Error("Invalid type");
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
dispatch(loadPresets(presets));
|
||||
// TODO: Select the first of these presets
|
||||
};
|
||||
|
|
@ -128,11 +142,11 @@ export function requestPresetAtIndex(
|
|||
return;
|
||||
}
|
||||
switch (preset.type) {
|
||||
case "BUTTERCHURN_JSON":
|
||||
case "RESOLVED":
|
||||
dispatch({ type: SELECT_PRESET_AT_INDEX, index, transitionType });
|
||||
return;
|
||||
case "LAZY_BUTTERCHURN_JSON":
|
||||
const json = await preset.getDefinition();
|
||||
case "UNRESOLVED":
|
||||
const json = await preset.getPreset();
|
||||
// What if the index has changed?
|
||||
// Perhaps we could hold a reference to the preset at the index before
|
||||
// we await and confirm that it hasn't changed after the await?
|
||||
|
|
|
|||
|
|
@ -1,42 +1,4 @@
|
|||
import {
|
||||
ButterchurnOptions,
|
||||
InitialButterchurnDependencies
|
||||
} from "../../types";
|
||||
|
||||
async function loadInitialDependencies(): Promise<
|
||||
InitialButterchurnDependencies
|
||||
> {
|
||||
const [butterchurn, butterchurnMinimalPresets, presetPackMeta] =
|
||||
// prettier-ignore
|
||||
await Promise.all([
|
||||
import(
|
||||
/* webpackChunkName: "butterchurn-initial-dependencies" */
|
||||
// @ts-ignore
|
||||
"butterchurn"
|
||||
),
|
||||
import(
|
||||
/* webpackChunkName: "butterchurn-initial-dependencies" */
|
||||
// @ts-ignore
|
||||
"butterchurn-presets/lib/butterchurnPresetsMinimal.min"
|
||||
),
|
||||
import(
|
||||
/* webpackChunkName: "butterchurn-initial-dependencies" */
|
||||
// @ts-ignore
|
||||
"butterchurn-presets/lib/butterchurnPresetPackMeta.min"
|
||||
)
|
||||
]);
|
||||
return {
|
||||
butterchurn: butterchurn.default,
|
||||
minimalPresets: butterchurnMinimalPresets.default.getPresets(),
|
||||
presetKeys: presetPackMeta.default.getMainPresetMeta().presets
|
||||
};
|
||||
}
|
||||
|
||||
async function loadNonMinimalPresets() {
|
||||
return (await import(/* webpackChunkName: "butterchurn-non-minimal-presets" */
|
||||
// @ts-ignore
|
||||
"butterchurn-presets/lib/butterchurnPresetsNonMinimal.min")).default.getPresets();
|
||||
}
|
||||
import { ButterchurnOptions } from "../../types";
|
||||
|
||||
async function loadConvertPreset() {
|
||||
const { convertPreset } =
|
||||
|
|
@ -48,19 +10,3 @@ async function loadConvertPreset() {
|
|||
);
|
||||
return convertPreset;
|
||||
}
|
||||
|
||||
const options: ButterchurnOptions = {
|
||||
loadConvertPreset,
|
||||
loadInitialDependencies,
|
||||
loadNonMinimalPresets,
|
||||
presetConverterEndpoint:
|
||||
"https://p2tpeb5v8b.execute-api.us-east-2.amazonaws.com/default/milkdropShaderConverter"
|
||||
};
|
||||
|
||||
if ("URLSearchParams" in window) {
|
||||
const params = new URLSearchParams(location.search);
|
||||
options.initialButterchurnPresetUrl = params.get("butterchurnPresetUrl");
|
||||
options.initialMilkdropPresetUrl = params.get("milkdropPresetUrl");
|
||||
}
|
||||
|
||||
export default options;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Action, PresetId, Preset } from "../types";
|
||||
import { Action, PresetId, StatePreset } from "../types";
|
||||
import {
|
||||
SET_MILKDROP_DESKTOP,
|
||||
GOT_BUTTERCHURN_PRESETS,
|
||||
|
|
@ -14,7 +14,7 @@ export interface MilkdropState {
|
|||
desktop: boolean;
|
||||
overlay: boolean;
|
||||
presetOrder: PresetId[];
|
||||
presets: Preset[];
|
||||
presets: StatePreset[];
|
||||
currentPresetIndex: number | null;
|
||||
butterchurn: any;
|
||||
transitionType: TransitionType;
|
||||
|
|
@ -42,24 +42,16 @@ export const milkdrop = (
|
|||
case GOT_BUTTERCHURN_PRESETS:
|
||||
return {
|
||||
...state,
|
||||
presets: state.presets.concat(
|
||||
action.presets.map(preset => {
|
||||
switch (preset.type) {
|
||||
case "BUTTERCHURN_JSON":
|
||||
case "LAZY_BUTTERCHURN_JSON":
|
||||
return preset;
|
||||
}
|
||||
})
|
||||
)
|
||||
presets: state.presets.concat(action.presets)
|
||||
};
|
||||
case RESOLVE_PRESET_AT_INDEX:
|
||||
const preset = state.presets[action.index];
|
||||
return {
|
||||
...state,
|
||||
presets: Utils.replaceAtIndex(state.presets, action.index, {
|
||||
type: "RESOLVED",
|
||||
name: preset.name,
|
||||
type: "BUTTERCHURN_JSON",
|
||||
definition: action.json
|
||||
preset: action.json
|
||||
})
|
||||
};
|
||||
case SELECT_PRESET_AT_INDEX:
|
||||
|
|
|
|||
|
|
@ -635,10 +635,10 @@ export function getCurrentPreset(state: AppState): any | null {
|
|||
return null;
|
||||
}
|
||||
const preset = state.milkdrop.presets[index];
|
||||
if (preset == null || preset.type !== "BUTTERCHURN_JSON") {
|
||||
if (preset == null || preset.type === "UNRESOLVED") {
|
||||
return null;
|
||||
}
|
||||
return preset.definition;
|
||||
return preset.preset;
|
||||
}
|
||||
|
||||
export function getPresetNames(state: AppState): string[] {
|
||||
|
|
|
|||
54
js/types.ts
54
js/types.ts
|
|
@ -115,57 +115,39 @@ type SkinData = {
|
|||
skinGenExColors: SkinGenExColors | null;
|
||||
};
|
||||
|
||||
export interface InitialButterchurnDependencies {
|
||||
// TODO: Type these
|
||||
butterchurn: any;
|
||||
minimalPresets: any;
|
||||
presetKeys: any;
|
||||
}
|
||||
|
||||
export interface ButterchurnOptions {
|
||||
loadNonMinimalPresets(): Promise<any>;
|
||||
loadInitialDependencies(): Promise<InitialButterchurnDependencies>;
|
||||
loadConvertPreset(): Promise<any>;
|
||||
presetConverterEndpoint: string;
|
||||
initialMilkdropPresetUrl?: string | null;
|
||||
initialButterchurnPresetUrl?: string | null;
|
||||
}
|
||||
|
||||
// This is what we actually pass to butterchurn
|
||||
type ButterchurnPresetJson = {
|
||||
type: "BUTTERCHURN_JSON";
|
||||
name: string;
|
||||
definition: Object;
|
||||
};
|
||||
|
||||
export type LazyButterchurnPresetJson = {
|
||||
type: "LAZY_BUTTERCHURN_JSON";
|
||||
name: string;
|
||||
getDefinition: () => Promise<Object>;
|
||||
butterchurnPresetObject: Object;
|
||||
};
|
||||
|
||||
// A URL that points to a Butterchurn preset
|
||||
interface ButterchurnPresetUrl {
|
||||
type: "BUTTERCHURN_URL";
|
||||
url: string;
|
||||
name: string;
|
||||
butterchurnPresetUrl: string;
|
||||
}
|
||||
|
||||
// A URL that points to a .milk preset
|
||||
interface MilkdropPresetUrl {
|
||||
type: "MILKDROP_URL";
|
||||
url: string;
|
||||
}
|
||||
export type LazyButterchurnPresetJson = {
|
||||
name: string;
|
||||
getButterchrunPresetObject: () => Promise<Object>;
|
||||
};
|
||||
|
||||
export type PresetDefinition =
|
||||
export type Preset =
|
||||
| ButterchurnPresetJson
|
||||
| LazyButterchurnPresetJson
|
||||
| ButterchurnPresetUrl
|
||||
| MilkdropPresetUrl;
|
||||
| LazyButterchurnPresetJson;
|
||||
|
||||
export type Preset = ButterchurnPresetJson | LazyButterchurnPresetJson;
|
||||
export type StatePreset =
|
||||
| { type: "RESOLVED"; name: string; preset: Object }
|
||||
| { type: "UNRESOLVED"; name: string; getPreset: () => Promise<Object> };
|
||||
|
||||
export type PresetId = string;
|
||||
|
||||
export interface ButterchurnOptions {
|
||||
getPresets(): Promise<Preset[]>;
|
||||
importButterchurn(): Promise<any>;
|
||||
}
|
||||
|
||||
export interface EqfPreset {
|
||||
name: string;
|
||||
hz60: number;
|
||||
|
|
@ -483,7 +465,7 @@ export type Action =
|
|||
}
|
||||
| {
|
||||
type: "GOT_BUTTERCHURN_PRESETS";
|
||||
presets: Preset[];
|
||||
presets: StatePreset[];
|
||||
}
|
||||
| {
|
||||
type: "GOT_BUTTERCHURN";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue