/* Copyright (c) 2015 William Toohey * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ (function(window, document) { "use strict"; // NOTE: Any packs referenced need CORS enabled or loads fail var packsURL = "http://cdn.0x40hu.es/getRespacks.php"; function Resources(core) { this.core = core; this.hasUI = false; this.resourcePacks = []; this.allSongs = []; this.allImages = []; this.enabledSongs = []; this.enabledImages = []; this.toLoad = 0; this.progressState = []; this.rToLoad = []; this.progressCallback = null; this.root = null; // For songs/images this.listView = null; this.enabledSongList = null; this.enabledImageList = null; this.packView = { pack: null, name: null, creator: null, size: null, desc: null, songCount: null, imageCount: null, songList: null, imageList: null, packButtons: null, totalSongs: null, totalImages: null }; this.packsView = { respackList: null, remoteList: null, loadRemote: null, progressBar: null, progressStatus: null, progressCurrent: null, progressTop: null, progressPercent: null }; this.remotes = null; this.fileInput = null; this.fileParseQueue = []; this.currentlyParsing = false; if(!core.settings.defaults.noUI) { this.initUI(); } } // Array of URLs to load, and a callback for when we're done // Preserves order of URLs being loaded Resources.prototype.addAll = function(urls, progressCallback) { return new Promise(function(resolve, reject) { this.toLoad += urls.length; if(progressCallback) { this.progressCallback = progressCallback; this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0); } for(var i = 0; i < urls.length; i++) { var r = new Respack(); this.rToLoad.push(r); r.loadFromURL(urls[i], function() { this.toLoad--; if(this.toLoad <= 0) { for(var i = 0; i < this.rToLoad.length; i++) { this.addPack(this.rToLoad[i]); } this.rToLoad = []; this.progressCallback = null; resolve(); } }.bind(this), function(index, progress, pack) { this.progressState[index] = progress; this.updateProgress(pack); }.bind(this, i)); } }.bind(this)); }; Resources.prototype.updateProgress = function(pack) { var total = 0; for(var i = 0; i < this.progressState.length; i++) { total += this.progressState[i]; } total /= this.progressState.length; this.progressCallback(total, pack); }; Resources.prototype.addPack = function(pack) { console.log("Added", pack.name, "to respacks"); var id = this.resourcePacks.length; this.resourcePacks.push(pack); this.addResourcesToArrays(pack); this.rebuildEnabled(); this.updateTotals(); var self = this; this.appendListItem("respacks", pack.name, "res" + id, this.packsView.respackList, function() { pack.enabled = this.checked; self.rebuildEnabled(); }, function(id) { this.selectPack(id); }.bind(this, id) ); }; Resources.prototype.addResourcesToArrays = function(pack) { this.allImages = this.allImages.concat(pack.images); this.allSongs = this.allSongs.concat(pack.songs); }; Resources.prototype.rebuildArrays = function() { this.allSongs = []; this.allImages = []; this.allAnimations = []; for(var i = 0; i < this.resourcePacks.length; i++) { this.addResourcesToArrays(this.resourcePacks[i]); } }; Resources.prototype.rebuildEnabled = function() { this.enabledSongs = []; this.enabledImages = []; for(var i = 0; i < this.resourcePacks.length; i++) { var pack = this.resourcePacks[i]; if (pack.enabled !== true) { continue; } for(var j = 0; j < pack.songs.length; j++) { var song = pack.songs[j]; if (song.enabled && this.enabledSongs.indexOf(song) == -1) { this.enabledSongs.push(song); } } for(var j = 0; j < pack.images.length; j++) { var image = pack.images[j]; if (image.enabled && this.enabledImages.indexOf(image) == -1) { this.enabledImages.push(image); } } } if(this.hasUI) { var songList = this.enabledSongList; while(songList.firstElementChild) { songList.removeChild(songList.firstElementChild); } var imageList = this.enabledImageList; while(imageList.firstElementChild) { imageList.removeChild(imageList.firstElementChild); } for(var i = 0; i < this.enabledSongs.length; i++) { var song = this.enabledSongs[i]; this.appendSimpleListItem(song.title, songList, function(index) { this.core.setSong(index); }.bind(this, i)); } for(var i = 0; i < this.enabledImages.length; i++) { var image = this.enabledImages[i]; this.appendSimpleListItem(image.name, imageList, function(index) { this.core.setImage(index); this.core.setIsFullAuto(false); }.bind(this, i)); } } this.updateTotals(); }; Resources.prototype.removePack = function(pack) { var index = this.resourcePacks.indexOf(pack); if (index != -1) { this.resourcePacks.splice(index, 1); this.rebuildArrays(); } }; Resources.prototype.removeAllPacks = function() { this.resourcePacks = []; this.rebuildArrays(); }; Resources.prototype.getSongNames = function() { var names = []; for(var i = 0; i < this.allSongs.length; i++) { names.push(this.allSongs[i]); } return names; }; Resources.prototype.loadLocal = function() { console.log("Loading local zip(s)"); var files = this.fileInput.files; for(var i = 0; i < files.length; i++) { this.fileParseQueue.push(files[i]); } this.parseLocalQueue(); }; Resources.prototype.parseLocalQueue = function(recursing) { // avoid race conditions if(this.currentlyParsing && !recursing) { return; } this.currentlyParsing = true; if(this.fileParseQueue.length) { var r = new Respack(); r.loadBlob(this.fileParseQueue.shift(), function() { this.addPack(r); this.localComplete(); this.parseLocalQueue(true); }.bind(this), function(progress, respack) {this.localProgress(progress, respack);}.bind(this), function() {this.parseLocalQueue(true);}.bind(this)); } else { console.log("Local respack parsing complete"); this.currentlyParsing = false; } }; Resources.prototype.localProgress = function(progress, respack) { if(!this.hasUI) {return;} this.packsView.progressStatus.textContent = "Processing..."; this.packsView.progressBar.style.width = (progress * 100) + "%"; this.packsView.progressCurrent.textContent = respack.filesLoaded; this.packsView.progressTop.textContent = respack.filesToLoad; this.packsView.progressPercent.textContent = Math.round(progress * 100) + "%"; }; Resources.prototype.localComplete = function(progress) { var progStat = this.packsView.progressStatus; progStat.textContent = "Complete"; window.setTimeout(function() {progStat.textContent = "Idle";}, 2000); this.packsView.progressBar.style.width = "100%"; this.packsView.progressCurrent.textContent = "0b"; this.packsView.progressTop.textContent = "0b"; this.packsView.progressPercent.textContent = "0%"; }; Resources.prototype.initUI = function() { this.root = document.getElementById("huesResources"); var packsContainer = document.createElement("div"); packsContainer.className = "res-packscontainer"; var packHeader = document.createElement("div"); packHeader.textContent = "Current respacks"; packHeader.className = "res-header"; packHeader.id = "res-curheader"; var packList = document.createElement("div"); packList.className = "res-list"; packList.id = "res-packlist"; this.packsView.respackList = packList; // so we don't use it out of scope in the next if var remoteHeader = null; var remoteList = null; if(!this.core.settings.defaults.disableRemoteResources) { remoteHeader = document.createElement("div"); remoteHeader.textContent = "Remote respacks"; remoteHeader.className = "res-header"; remoteList = document.createElement("div"); remoteList.className = "res-list"; remoteList.id = "res-remotelist"; this.appendSimpleListItem("Click to load the list", remoteList, function() {this.loadRemotes();}.bind(this)); this.packsView.remoteList = remoteList; } else { packList.className += " noremotes"; } var buttons = document.createElement("div"); buttons.className = "res-buttons"; var loadRemote = document.createElement("div"); loadRemote.className = "hues-button hidden"; loadRemote.textContent = "LOAD REMOTE"; loadRemote.onclick = function() {this.loadCurrentRemote();}.bind(this); var loadLocal = document.createElement("div"); loadLocal.className = "hues-button"; loadLocal.textContent = "LOAD ZIPS"; loadLocal.onclick = function() {this.fileInput.click();}.bind(this); buttons.appendChild(loadLocal); buttons.appendChild(loadRemote); this.packsView.loadRemote = loadRemote; this.fileInput = document.createElement("input"); this.fileInput.type ="file"; this.fileInput.accept="application/zip"; this.fileInput.multiple = true; this.fileInput.onchange = function() {this.loadLocal();}.bind(this); var progressContainer = document.createElement("div"); progressContainer.id = "res-progress-container"; var progressBar = document.createElement("div"); progressBar.id = "res-progress-bar"; var progressFilled = document.createElement("span"); progressFilled.id = "res-progress-filled"; progressBar.appendChild(progressFilled); var progressStatus = document.createElement("div"); progressStatus.textContent = "Idle"; var progressTexts = document.createElement("div"); progressTexts.id = "res-progress-texts"; var progressCurrent = document.createElement("div"); progressCurrent.id = "res-progress-current"; progressCurrent.textContent = "0b"; var progressTop = document.createElement("div"); progressTop.id = "res-progress-top"; progressTop.textContent = "0b"; var progressPercent = document.createElement("div"); progressPercent.id = "res-progress-percent"; progressPercent.textContent = "0%"; progressTexts.appendChild(progressCurrent); progressTexts.appendChild(progressTop); progressTexts.appendChild(progressPercent); this.packsView.progressBar = progressFilled; this.packsView.progressStatus = progressStatus; this.packsView.progressCurrent = progressCurrent; this.packsView.progressTop = progressTop; this.packsView.progressPercent = progressPercent; progressContainer.appendChild(progressStatus); progressContainer.appendChild(progressBar); progressContainer.appendChild(progressTexts); packsContainer.appendChild(packHeader); packsContainer.appendChild(packList); if(!this.core.settings.defaults.disableRemoteResources) { packsContainer.appendChild(remoteHeader); packsContainer.appendChild(remoteList); } packsContainer.appendChild(buttons); packsContainer.appendChild(progressContainer); var indivView = document.createElement("div"); indivView.className = "res-packcontainer"; var packName = document.createElement("div"); packName.textContent = "