Move initial preset into thunk

This commit is contained in:
Jordan Eldredge 2019-01-20 19:56:21 -08:00
parent c8b3dcc05a
commit 934555a3fe
7 changed files with 128 additions and 120 deletions

View file

@ -1,6 +1,92 @@
import { INITIALIZE_PRESETS } from "../actionTypes";
import { INITIALIZE_PRESETS, GOT_BUTTERCHURN } from "../actionTypes";
import { Dispatchable } from "../types";
import Presets from "../components/MilkdropWindow/Presets";
export function initializePresets(presets: any): Dispatchable {
return { type: INITIALIZE_PRESETS, presets };
export function initializePresets(presetOptions: any): Dispatchable {
return async dispatch => {
const [
{ butterchurn, presetKeys, minimalPresets },
initialPreset
] = await Promise.all([
presetOptions.loadInitialDependencies(),
_loadInitialPreset(presetOptions)
]);
const presets = new Presets({
keys: presetKeys,
initialPresets: minimalPresets,
getRest: presetOptions.loadNonMinimalPresets,
presetConverterEndpoint: presetOptions.presetConverterEndpoint,
loadConvertPreset: presetOptions.loadConvertPreset
});
if (initialPreset) {
const presetIndices = presets.addPresets(initialPreset);
const presetIndex = presetIndices[0];
await presets.selectIndex(presetIndex);
}
dispatch({ type: GOT_BUTTERCHURN, butterchurn });
dispatch({ type: INITIALIZE_PRESETS, presets });
};
}
function _presetNameFromURL(url: string): string {
try {
const urlParts = url.split("/");
const lastPart = urlParts[urlParts.length - 1];
const presetName = lastPart.substring(0, lastPart.length - 5); // remove .milk or .json
return decodeURIComponent(presetName);
} catch (e) {
// if something goes wrong parsing url, just use url as the preset name
console.error(e);
return url;
}
}
async function _loadInitialPreset({
initialButterchurnPresetUrl,
initialMilkdropPresetUrl
}: {
initialButterchurnPresetUrl: string;
initialMilkdropPresetUrl: string;
}) {
if (initialButterchurnPresetUrl && initialMilkdropPresetUrl) {
alert(
"Unable to handle both milkdropPresetUrl and butterchurnPresetUrl. Please specify one or the other."
);
} else if (initialButterchurnPresetUrl) {
return _fetchPreset(initialButterchurnPresetUrl, { isButterchurn: true });
} else if (initialMilkdropPresetUrl) {
return _fetchPreset(initialMilkdropPresetUrl, { isButterchurn: false });
}
return null;
}
async function _fetchPreset(
presetUrl: string,
{ isButterchurn }: { isButterchurn: boolean }
) {
const response = await fetch(presetUrl);
if (!response.ok) {
console.error(response.statusText);
alert(`Unable to load MilkDrop preset from ${presetUrl}`);
return null;
}
const presetName = _presetNameFromURL(presetUrl);
let preset = null;
if (isButterchurn) {
try {
preset = await response.json();
} catch (e) {
console.error(e);
alert(`Failed to parse MilkDrop preset from ${presetUrl}`);
return null;
}
} else {
preset = { file: await response.blob() };
}
return { [presetName]: preset };
}

View file

@ -78,3 +78,4 @@ export const ENABLE_MILKDROP = "ENABLE_MILKDROP";
export const SET_MILKDROP_DESKTOP = "SET_MILKDROP_DESKTOP";
export const SET_VISUALIZER_STYLE = "SET_VISUALIZER_STYLE";
export const INITIALIZE_PRESETS = "INITIALIZE_PRESETS";
export const GOT_BUTTERCHURN = "GOT_BUTTERCHURN";

View file

@ -20,7 +20,13 @@ class Milkdrop extends React.Component {
}
async componentDidMount() {
this.__debugState = "MOUNT_STARTED";
this._initializeIfNeeded();
}
async _initializeIfNeeded() {
if (this.visualizer || !this.props.butterchurn || !this.props.presets) {
return;
}
this.visualizer = this.props.butterchurn.createVisualizer(
this.props.analyser.context,
this._canvasNode,
@ -38,18 +44,8 @@ class Milkdrop extends React.Component {
}
this.__debugState = "VISUALIZER_CREATED";
this.visualizer.connectAudio(this.props.analyser);
this.presetCycle = !this.props.initialPreset;
if (this.props.initialPreset) {
const presetIndices = this.props.presets.addPresets(
this.props.initialPreset
);
this.selectPreset(
await this.props.presets.selectIndex(presetIndices[0]),
0
);
} else {
this.selectPreset(this.props.presets.getCurrent(), 0);
}
this.presetCycle = true;
this.selectPreset(this.props.presets.getCurrent(), 0);
// Kick off the animation loop
const loop = () => {
@ -80,13 +76,7 @@ class Milkdrop extends React.Component {
}
componentDidUpdate(prevProps) {
this.__updates++;
if (this.visualizer == null) {
// https://github.com/captbaritone/webamp/issues/731
throw new Error(
`Weird bug: State=${this.__debugState} updates=${this.__updates}`
);
}
this._initializeIfNeeded();
if (
this.props.width !== prevProps.width ||
this.props.height !== prevProps.height
@ -275,7 +265,8 @@ class Milkdrop extends React.Component {
const mapStateToProps = state => ({
trackTitle: Selectors.getCurrentTrackDisplayName(state),
presets: Selectors.getPresets(state)
presets: Selectors.getPresets(state),
butterchurn: Selectors.getButterchurn(state)
});
export default connect(mapStateToProps)(Milkdrop);

View file

@ -9,7 +9,6 @@ import * as Actions from "../../actionCreators";
import MilkdropContextMenu from "./MilkdropContextMenu";
import Desktop from "./Desktop";
import Presets from "./Presets";
import Milkdrop from "./Milkdrop";
import Background from "./Background";
@ -21,12 +20,7 @@ import "../../../css/milkdrop-window.css";
class PresetsLoader extends React.Component {
constructor(props) {
super(props);
this.options = props.options;
this.state = {
initialPreset: null,
butterchurn: null,
isFullscreen: false
};
this.state = { isFullscreen: false };
}
isHidden() {
@ -34,27 +28,8 @@ class PresetsLoader extends React.Component {
}
async componentDidMount() {
const [
{ butterchurn, presetKeys, minimalPresets },
initialPreset
] = await Promise.all([
this.options.loadInitialDependencies(),
loadInitialPreset(this.options)
]);
this.props.initializePresets(this.props.options);
const presets = new Presets({
keys: presetKeys,
initialPresets: minimalPresets,
getRest: this.options.loadNonMinimalPresets,
presetConverterEndpoint: this.options.presetConverterEndpoint,
loadConvertPreset: this.options.loadConvertPreset
});
this.props.initializePresets(presets);
this.setState({
butterchurn,
initialPreset
});
screenfull.onchange(this._handleFullscreenChange);
}
@ -77,8 +52,6 @@ class PresetsLoader extends React.Component {
};
_renderMilkdrop(size) {
const { butterchurn, initialPreset } = this.state;
const loaded = butterchurn != null;
const { width, height } = this.state.isFullscreen
? { width: screen.width, height: screen.height }
: size;
@ -87,16 +60,12 @@ class PresetsLoader extends React.Component {
// does not cause this node to change identity.
return (
<Background innerRef={node => (this._wrapperNode = node)}>
{loaded && (
<Milkdrop
{...this.props}
width={width}
height={height}
isFullscreen={this.state.isFullscreen}
initialPreset={initialPreset}
butterchurn={butterchurn}
/>
)}
<Milkdrop
{...this.props}
width={width}
height={height}
isFullscreen={this.state.isFullscreen}
/>
</Background>
);
}
@ -143,60 +112,6 @@ class PresetsLoader extends React.Component {
}
}
function presetNameFromURL(url) {
try {
const urlParts = url.split("/");
const lastPart = urlParts[urlParts.length - 1];
const presetName = lastPart.substring(0, lastPart.length - 5); // remove .milk or .json
return decodeURIComponent(presetName);
} catch (e) {
// if something goes wrong parsing url, just use url as the preset name
console.error(e);
return url;
}
}
async function loadInitialPreset({
initialButterchurnPresetUrl,
initialMilkdropPresetUrl
}) {
if (initialButterchurnPresetUrl && initialMilkdropPresetUrl) {
alert(
"Unable to handle both milkdropPresetUrl and butterchurnPresetUrl. Please specify one or the other."
);
} else if (initialButterchurnPresetUrl) {
return fetchPreset(initialButterchurnPresetUrl, { isButterchurn: true });
} else if (initialMilkdropPresetUrl) {
return fetchPreset(initialMilkdropPresetUrl, { isButterchurn: false });
}
return null;
}
async function fetchPreset(presetUrl, { isButterchurn }) {
const response = await fetch(presetUrl);
if (!response.ok) {
console.error(response.statusText);
alert(`Unable to load MilkDrop preset from ${presetUrl}`);
return null;
}
const presetName = presetNameFromURL(presetUrl);
let preset = null;
if (isButterchurn) {
try {
preset = await response.json();
} catch (e) {
console.error(e);
alert(`Failed to parse MilkDrop preset from ${presetUrl}`);
return null;
}
} else {
preset = { file: await response.blob() };
}
return { [presetName]: preset };
}
const mapStateToProps = state => ({
isEnabledVisualizer:
Selectors.getVisualizerStyle(state) === VISUALIZERS.MILKDROP,

View file

@ -1,15 +1,20 @@
import { Action } from "../types";
import { SET_MILKDROP_DESKTOP, INITIALIZE_PRESETS } from "../actionTypes";
import { bindActionCreators } from "redux";
import {
SET_MILKDROP_DESKTOP,
INITIALIZE_PRESETS,
GOT_BUTTERCHURN
} from "../actionTypes";
export interface MilkdropState {
desktop: boolean;
presets: any;
butterchurn: any;
}
const defaultMilkdropState = {
desktop: false,
presets: null
presets: null,
butterchurn: null
};
export const milkdrop = (
@ -21,6 +26,8 @@ export const milkdrop = (
return { ...state, desktop: action.enabled };
case INITIALIZE_PRESETS:
return { ...state, presets: action.presets };
case GOT_BUTTERCHURN:
return { ...state, butterchurn: action.butterchurn };
default:
return state;
}

View file

@ -616,3 +616,7 @@ export function getMilkdropDesktopEnabled(state: AppState): boolean {
export function getPresets(state: AppState): any {
return state.milkdrop.presets;
}
export function getButterchurn(state: AppState): any {
return state.milkdrop.butterchurn;
}

View file

@ -443,6 +443,10 @@ export type Action =
| {
type: "INITIALIZE_PRESETS";
presets: any;
}
| {
type: "GOT_BUTTERCHURN";
butterchurn: any;
};
export type MediaTagRequestStatus =