From 934555a3fe4bedbb8a4a55c2373b63e9e8dd7bdc Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sun, 20 Jan 2019 19:56:21 -0800 Subject: [PATCH] Move initial preset into thunk --- js/actionCreators/milkdrop.ts | 92 ++++++++++++++++++++- js/actionTypes.ts | 1 + js/components/MilkdropWindow/Milkdrop.js | 33 +++----- js/components/MilkdropWindow/index.js | 101 ++--------------------- js/reducers/milkdrop.ts | 13 ++- js/selectors.ts | 4 + js/types.ts | 4 + 7 files changed, 128 insertions(+), 120 deletions(-) diff --git a/js/actionCreators/milkdrop.ts b/js/actionCreators/milkdrop.ts index b4bfa4de..f026284f 100644 --- a/js/actionCreators/milkdrop.ts +++ b/js/actionCreators/milkdrop.ts @@ -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 }; } diff --git a/js/actionTypes.ts b/js/actionTypes.ts index 66abdd6b..bfea95a7 100644 --- a/js/actionTypes.ts +++ b/js/actionTypes.ts @@ -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"; diff --git a/js/components/MilkdropWindow/Milkdrop.js b/js/components/MilkdropWindow/Milkdrop.js index f6eececc..d7160f35 100644 --- a/js/components/MilkdropWindow/Milkdrop.js +++ b/js/components/MilkdropWindow/Milkdrop.js @@ -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); diff --git a/js/components/MilkdropWindow/index.js b/js/components/MilkdropWindow/index.js index bd8442d8..62c056f7 100644 --- a/js/components/MilkdropWindow/index.js +++ b/js/components/MilkdropWindow/index.js @@ -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 ( (this._wrapperNode = node)}> - {loaded && ( - - )} + ); } @@ -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, diff --git a/js/reducers/milkdrop.ts b/js/reducers/milkdrop.ts index bfa477c5..41b9e63b 100644 --- a/js/reducers/milkdrop.ts +++ b/js/reducers/milkdrop.ts @@ -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; } diff --git a/js/selectors.ts b/js/selectors.ts index 38e49963..de11668e 100644 --- a/js/selectors.ts +++ b/js/selectors.ts @@ -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; +} diff --git a/js/types.ts b/js/types.ts index 88eb8c67..3cf11660 100644 --- a/js/types.ts +++ b/js/types.ts @@ -443,6 +443,10 @@ export type Action = | { type: "INITIALIZE_PRESETS"; presets: any; + } + | { + type: "GOT_BUTTERCHURN"; + butterchurn: any; }; export type MediaTagRequestStatus =