mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-24 02:36:00 +00:00
158 lines
4.2 KiB
JavaScript
158 lines
4.2 KiB
JavaScript
function getRandomIndex(arr) {
|
|
return Math.floor(Math.random() * arr.length);
|
|
}
|
|
function getRandomValue(arr) {
|
|
return arr[getRandomIndex(arr)];
|
|
}
|
|
|
|
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
|
|
*
|
|
* Presets can be changed via `next`, `previous` or `selectIndex`. In each case,
|
|
* a promise is returned. If the promise resolves to `null` it means the
|
|
* selection was canceled by a subsequent request before it could be fulfilled.
|
|
* If the request is successful, the promise resolves to the selected preset.
|
|
*
|
|
* We assume a model where some portion of the preset are supplied at initialization
|
|
* and the remainder can be loaded async via the function `getRest`.
|
|
*/
|
|
export default class Presets {
|
|
constructor({
|
|
keys,
|
|
initialPresets,
|
|
getRest,
|
|
presetConverterEndpoint,
|
|
loadConvertPreset,
|
|
randomize = true
|
|
}) {
|
|
this._keys = keys; // Alphabetical list of preset names
|
|
this._presets = initialPresets; // Presets indexed by name
|
|
this._getRest = getRest; // An async function to get the rest of the presets
|
|
this._presetConverterEndpoint = presetConverterEndpoint;
|
|
this._loadConvertPreset = loadConvertPreset;
|
|
this._history = []; // Indexes into _keys
|
|
|
|
this._randomize = randomize;
|
|
|
|
// Initialize with a key that we already have.
|
|
const avaliableKeys = Object.keys(initialPresets);
|
|
const currentKey = randomize
|
|
? getRandomValue(avaliableKeys)
|
|
: avaliableKeys[0];
|
|
this._currentIndex = this._keys.indexOf(currentKey);
|
|
this._history.push(this._currentIndex);
|
|
}
|
|
|
|
toggleRandomize() {
|
|
this._randomize = !this._randomize;
|
|
}
|
|
|
|
setRandomize(val) {
|
|
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];
|
|
}
|
|
|
|
loadPresets(presets) {
|
|
this._keys = Object.keys(presets);
|
|
this._presets = presets;
|
|
this._history = [];
|
|
|
|
return this._keys.length;
|
|
}
|
|
|
|
async next() {
|
|
let idx;
|
|
if (this._randomize || this._history.length === 0) {
|
|
idx = getRandomIndex(this._keys);
|
|
} else {
|
|
idx = (getLast(this._history) + 1) % this._keys.length;
|
|
}
|
|
this._history.push(idx);
|
|
return this._selectIndex(idx);
|
|
}
|
|
|
|
async previous() {
|
|
if (this._history.length > 1) {
|
|
this._history.pop();
|
|
return this._selectIndex(getLast(this._history));
|
|
}
|
|
// We are at the very beginning. There is no "previous" preset.
|
|
return Promise.resolve();
|
|
}
|
|
|
|
async selectIndex(idx) {
|
|
// The public version of this method must add to the history
|
|
this._history.push(idx);
|
|
return this._selectIndex(idx);
|
|
}
|
|
|
|
async _convertPreset(file) {
|
|
const convertPreset = await this._loadConvertPreset();
|
|
return convertPreset(file, this._presetConverterEndpoint);
|
|
}
|
|
|
|
async _selectIndex(idx) {
|
|
const preset = this._presets[this._keys[idx]];
|
|
if (!preset) {
|
|
const rest = await this._getRest();
|
|
this._presets = Object.assign(this._presets, rest);
|
|
if (getLast(this._history) !== idx) {
|
|
// This selection must be obsolete. Return null so that
|
|
// the caller knows this request got canceled.
|
|
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) {
|
|
console.error(e);
|
|
alert(`Unable to convert MilkDrop preset ${this._keys[idx]}`);
|
|
}
|
|
}
|
|
this._currentIndex = idx;
|
|
return this.getCurrent();
|
|
}
|
|
|
|
getKeys() {
|
|
return this._keys;
|
|
}
|
|
|
|
getCurrentIndex() {
|
|
return this._currentIndex;
|
|
}
|
|
|
|
getCurrent() {
|
|
// #matryoshka
|
|
return this._presets[this._keys[this._currentIndex]];
|
|
}
|
|
}
|