UNPKG

audio-source-composer

Version:

Audio Source Composer

372 lines (317 loc) 13.5 kB
import React from "react"; import PropTypes from "prop-types"; import {ASUIClickable, ASUIGlobalContext, ASUIMenuAction, ASUIMenuItem} from "../../../components"; import {PresetLibrary, ProgramLoader} from "../../../song"; import {PromptManager} from "../../../common"; import "./ASCPresetBrowser.css"; export default class ASCPresetBrowser extends React.Component { static DEFAULT_TIMEOUT_MS = 10000; /** Global Context **/ static contextType = ASUIGlobalContext; getGlobalContext() { return this.context; } setStatus(message) { this.context.addLogEntry(message); } setError(message) { this.context.addLogEntry(message, 'error'); } // getViewMode(viewKey) { this.context.getViewMode(viewKey); } // setViewMode(viewKey, mode) { this.context.setViewMode(viewKey, mode); } /** Property validation **/ static propTypes = { programLoad: PropTypes.func.isRequired, program: PropTypes.array.isRequired, programID: PropTypes.number.isRequired, }; constructor(props) { super(props); // const [currentPresetClass, currentPresetConfig] = props.program; this.state = { // currentPresetHash: library.getTitle() + ':' + currentPresetClass + ':' + currentPresetConfig.title, loading: false, presets: [], loadingPresets: [], currentLibrary: null, libraries: [], limit: 12, offset: 0, selected: 0, searchString: '' } // this.history = []; this.cb = { onWheel: e => this.onWheel(e) } console.log(this.constructor.name, this); } // getLibrary() { return this.state.library; } // getComposer() { return this.props.composer; } getProgramID() { return this.props.programID; } getProgram() { return this.props.program; } componentDidMount() { // this.updateList(); const defaultLibrary = PresetLibrary.loadDefault(); if(defaultLibrary) this.setLibrary(defaultLibrary) } async setLibrary(library) { if(!library) throw new Error("Invalid library"); this.setState({ currentLibrary: library, loading: true, offset: 0, }); if(typeof library.waitForAssetLoad === "function") await library.waitForAssetLoad() this.setState({ loading: false }); } // updateList() { // // const song = this.getComposer().getSong(); // const programID = this.getProgramID(); // const [currentPresetClass, currentPresetConfig] = song.programGetData(programID, false) // // const library = this.props.composer.library; // const presets = library.getPresets(); // const libraries = library.getLibraries(); // const currentPresetHash = library.getTitle() + ':' + currentPresetClass + ':' + currentPresetConfig.title; // // console.log('presets', currentPresetConfig, {presets, libraries, tags, currentPresetID}); // this.setState({presets, libraries, currentPresetHash, loading: false}); // } render() { let className = 'asc-preset-browser'; return ( <div className={className} ref={elm => { elm && elm.addEventListener('wheel', this.cb.onWheel, {passive: false}); }} > {this.state.currentLibrary ? <div className="library-current-text" children={`Library: ${this.state.currentLibrary.getTitle()}`} /> : null} <div className="preset-list"> {this.renderPresets()} </div> <div className="library-list-text"> Other Libraries </div> <div className="library-list"> {this.renderLibraries()} </div> </div> ); // return content; } renderLibraries() { return PresetLibrary .getLibraries() .filter(library => library !== this.state.currentLibrary) .map((library, i) => { return <ASUIClickable key={i} onAction={() => this.setLibrary(library)} children={library.getTitle()} /> }) } // getFilteredPresets() { // let presetList = this.state.presets; // if(this.state.searchString) { // const searchString = this.state.searchString.toLowerCase(); // presetList = presetList.filter(([presetClass, presetConfig], presetID) => { // if(presetConfig.title.toLowerCase().indexOf(searchString) !== -1) // return true; // if(presetConfig.tags) { // for (let i = 0; i < presetConfig.tags.length; i++) { // if(presetConfig.tags[i].toLowerCase().indexOf(searchString) !== -1) // return true; // } // } // return false; // }) // } // return presetList; // } renderPresets() { let content = []; if(this.state.loading ) { content.push(<ASUIClickable key="loading" loading={true} onAction={() => {}}>Loading Presets...</ASUIClickable>); } else if(!this.state.currentLibrary) { content.push(<ASUIClickable key="loading" loading={true} onAction={() => {}}>No library selected</ASUIClickable>); } else { const {offset, limit} = this.state; const library = this.state.currentLibrary; // this.getLibrary(); let presetList = library.getPresetList(); if(presetList) { const loadingPresets = this.state.loadingPresets || []; const searchString = (this.state.searchString || '').toLowerCase(); const [currentPresetClass, currentPresetConfig] = this.props.program; const compareKeys = ['title', 'url']; // const limitedList = presetList // .slice(offset, offset + limit); let presetCount=0; for(let presetID=0; presetID < presetList.length; presetID++) { if(limit <= content.length) break; const [presetClass, presetConfig] = presetList[presetID]; const currentPresetHash = library.getUUID() + ':' + presetClass + ':' + presetConfig.title; if(searchString) { let filtered = true; if(presetConfig.title.toLowerCase().indexOf(searchString) !== -1) filtered = false; if(presetConfig.tags) { for (let i = 0; i < presetConfig.tags.length; i++) { if(presetConfig.tags[i].toLowerCase().indexOf(searchString) !== -1) filtered = false; } } if(filtered) continue; } presetCount++; if(presetCount-1 < offset) continue; const selected = currentPresetClass === presetClass && compareConfig(currentPresetConfig, presetConfig, compareKeys); const loading = loadingPresets.indexOf(currentPresetHash) !== -1; content.push(<ASUIClickable key={presetID} onAction={() => this.presetLoad(currentPresetHash, presetClass, presetConfig)} selected={selected} loading={loading} title={presetConfig.title} // options={() => {}} children={loading ? 'Loading Preset...' : this.trimTitle(presetConfig.title)} />); } if(offset > 0) { let prevOffset = offset - limit; if(prevOffset < 0) prevOffset = 0; content.unshift(<ASUIClickable key="preset-previous" onAction={() => this.setOffset(prevOffset)} className="centered" children={`Prev Page`} />); } let nextOffset = offset + limit; if(presetCount < presetList.length) { content.push(<ASUIClickable key="preset-next" onAction={() => this.setOffset(nextOffset)} className="centered" children={`Next Page`} />); } if(presetList.length > limit) { content.unshift(<ASUIClickable key="preset-search" className="centered" onAction={() => this.promptSearch()} children={`Search${this.state.searchString ? `ing '${this.state.searchString}'` : ''}`} />); } } } return content; } addLoadingPreset(presetHash) { const loadingPresets = this.state.loadingPresets; let i = loadingPresets.indexOf(presetHash); if(i === -1) loadingPresets.push(presetHash); this.setState({loadingPresets}); } removeLoadingPreset(presetHash) { const loadingPresets = this.state.loadingPresets; let i = loadingPresets.indexOf(presetHash); if(i !== -1) loadingPresets.splice(i, 1); this.setState({loadingPresets}); } trimTitle(titleString) { if(titleString.length > 20) titleString = titleString.substr(0, 28) + '...'; return titleString; } /** Actions **/ async presetLoad(presetHash, presetClassName, presetConfig) { const presetTitle = presetConfig.title || presetClassName; this.setStatus(`Loading preset: ${presetTitle}`); this.addLoadingPreset(presetHash); const instance = ProgramLoader.loadInstance(presetClassName, presetConfig); let error = false; if(typeof instance.waitForAssetLoad === "function") { console.log('presetLoad', presetHash, presetClassName, presetConfig, instance); const timeout = setTimeout(() => { error = true; this.removeLoadingPreset(presetHash); this.setError(`Preset failed to load: ${presetTitle}. Please try again.`); }, ASCPresetBrowser.DEFAULT_TIMEOUT_MS); await instance.waitForAssetLoad(); clearTimeout(timeout); if(error) return; } this.removeLoadingPreset(presetHash); this.props.programLoad(presetClassName, presetConfig) this.setStatus("Loaded preset: " + presetTitle); // this.updateList(); } // popLibrary() { // if(this.history.length === 0) // throw new Error("Invalid library history"); // const oldLibrary = this.history.shift(); // this.setLibrary(oldLibrary, false); // } setOffset(offset) { this.setState({offset}) } async promptSearch() { console.log("searchString", this.state.searchString); const searchString = await PromptManager.openPromptDialog("Enter search keyword:", this.state.searchString); console.log("searchString2", searchString); this.setState({searchString, offset: 0}); } /** Input **/ onWheel(e) { e.preventDefault(); let offset = parseInt(this.state.offset) || 0; offset += e.deltaY > 0 ? 1 : -1; if(offset < 0) offset = 0; this.setState({offset}) } /** Menu **/ async renderMenuSelectLibrary() { const defaultLibrary = await PresetLibrary.loadDefault(); const library = this.state.currentLibrary; const libraries = await library.getLibraries(); return (<> {libraries.length === 0 ? <ASUIMenuItem>No child libraries available</ASUIMenuItem> : libraries.map((library, i) => <ASUIMenuAction key={i++} onAction={() => this.setLibrary(library)}> {library.getTitle()} </ASUIMenuAction> )} {defaultLibrary.data === library.data ? null : <ASUIMenuAction key={-1} onAction={() => this.setLibrary(defaultLibrary)}> {defaultLibrary.getTitle()} </ASUIMenuAction>} </>); } } function compareConfig(config1, config2, compareKeys=[]) { // console.log('compareConfig', config1, config2, compareKeys); // if (keys1.length !== keys2.length) // return false; for (let key of compareKeys) { if (config1[key] !== config2[key]) { return false; } } return true; }