diff --git a/js/components/MilkdropWindow/Milkdrop.js b/js/components/MilkdropWindow/Milkdrop.js index 629dc2b6..9e44cb6f 100644 --- a/js/components/MilkdropWindow/Milkdrop.js +++ b/js/components/MilkdropWindow/Milkdrop.js @@ -1,4 +1,5 @@ import React from "react"; +import DropTarget from "../DropTarget"; import PresetOverlay from "./PresetOverlay"; const USER_PRESET_TRANSITION_SECONDS = 5.7; @@ -115,6 +116,51 @@ export default class Milkdrop extends React.Component { } }; + _addNewPresets(files) { + const presetKeys = this.props.presets.getKeys(); + const presets = {}; + const presetIndices = []; + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const fileName = file.name; + const presetName = fileName.substring(fileName, fileName.length - 5); // remove .milk + const presetIdx = presetKeys.indexOf(presetName); + if (presetIdx >= 0) { + presetIndices.push(presetIdx); + } else { + presets[presetName] = { file }; + } + } + + if (Object.keys(presets).length > 0) { + const filePresetIndices = this.props.presets.addPresets(presets); + for (let j = filePresetIndices[0]; j < filePresetIndices[1]; j++) { + presetIndices.push(j); + } + } + + return presetIndices; + } + + async _handleDrop(e) { + const files = e.dataTransfer.files; + if (files.length > 0) { + const milkFiles = Array.from(files).filter(file => + file.name.endsWith(".milk") + ); + if (milkFiles.length === 0) { + alert("Visualizer only supports .milk files"); + return; + } + + const presetIndices = this._addNewPresets(milkFiles); + this.selectPreset( + await this.props.presets.selectIndex(presetIndices[0]), + PRESET_TRANSITION_SECONDS + ); + } + } + async _nextPreset(blendTime) { this.selectPreset(await this.props.presets.next(), blendTime); } @@ -139,7 +185,7 @@ export default class Milkdrop extends React.Component { render() { return ( - + this._handleDrop(e)}> {this.state.presetOverlay && ( (this._canvasNode = node)} /> - + ); } } diff --git a/js/components/MilkdropWindow/Presets.js b/js/components/MilkdropWindow/Presets.js index 69acc746..81c05b26 100644 --- a/js/components/MilkdropWindow/Presets.js +++ b/js/components/MilkdropWindow/Presets.js @@ -9,6 +9,20 @@ function getLast(arr) { return arr[arr.length - 1]; } +async function readFileAsText(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e); + }; + + reader.readAsText(file); + }); +} + /** * Track a collection of async loaded presets * @@ -46,6 +60,16 @@ export default class Presets { this._randomize = val; } + addPresets(presets) { + const startIdx = this._keys.length; + this._keys = this._keys.concat(Object.keys(presets)); + const endIndx = this._keys.length; + + this._presets = Object.assign(this._presets, presets); + + return [startIdx, endIndx]; + } + async next() { let idx; if (this._randomize || this._history.length === 0) { @@ -72,6 +96,24 @@ export default class Presets { return this._selectIndex(idx); } + async _convertPreset(file) { + return new Promise((resolve, reject) => { + require.ensure( + ["milkdrop-preset-converter-aws"], + async require => { + const { convertPreset } = require("milkdrop-preset-converter-aws"); + try { + resolve(convertPreset(file)); + } catch (e) { + reject(e); + } + }, + reject, + "milkdrop-preset-converter" + ); + }); + } + async _selectIndex(idx) { const preset = this._presets[this._keys[idx]]; if (!preset) { @@ -83,6 +125,15 @@ export default class Presets { return null; } } + if (preset && preset.file) { + try { + const fileContents = await readFileAsText(preset.file); + const convertedPreset = await this._convertPreset(fileContents); + this._presets[this._keys[idx]] = convertedPreset; + } catch (e) { + alert(`Unable to convert MilkDrop preset ${this._keys[idx]}`); + } + } this._currentIndex = idx; return this.getCurrent(); } diff --git a/package.json b/package.json index 77c1bf26..d382ae62 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "jest-runner-eslint": "^0.4.0", "jsmediatags": "^3.8.1", "jszip": "^3.1.3", + "milkdrop-preset-converter-aws": "^0.0.9", "prettier": "^1.13.0", "prop-types": "^15.5.10", "puppeteer": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index 88a6ab1a..2b665eab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3571,6 +3571,10 @@ globby@^7.1.1: pify "^3.0.0" slash "^1.0.0" +glsl-optimizer-js@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/glsl-optimizer-js/-/glsl-optimizer-js-0.0.2.tgz#ac6eaa96bd8240c068dc9cdc9f42017312af6fdc" + graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -5341,6 +5345,26 @@ micromatch@^3.1.8: snapdragon "^0.8.1" to-regex "^3.0.2" +milkdrop-eel-parser@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/milkdrop-eel-parser/-/milkdrop-eel-parser-0.0.1.tgz#1c1a82bb7877d9df6d45e6f0b602b4cd1a5dc26d" + +milkdrop-preset-converter-aws@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/milkdrop-preset-converter-aws/-/milkdrop-preset-converter-aws-0.0.9.tgz#988cd926e0961c3347bef711dad168cc9cee583f" + dependencies: + babel-runtime "^6.26.0" + glsl-optimizer-js "^0.0.2" + milkdrop-eel-parser "^0.0.1" + milkdrop-preset-utils "^0.0.4" + +milkdrop-preset-utils@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/milkdrop-preset-utils/-/milkdrop-preset-utils-0.0.4.tgz#62676ee9067ea69f6758b20f643d87bb8e7a3188" + dependencies: + babel-runtime "^6.26.0" + lodash "^4.17.4" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"