mirror of
https://forge.murkfall.net/bluesaxman/librePECS.git
synced 2026-03-13 02:04:20 -06:00
added persistance for options, implimented some options
This commit is contained in:
264
main.js
264
main.js
@@ -51,12 +51,188 @@ function systemMsg (message,level=0) { // abstraction?
|
||||
// but later we will also have it push an error toast in the ui.
|
||||
}
|
||||
|
||||
function initDatabase (e) {
|
||||
var db = e.target.result;
|
||||
var objectStore = db.createObjectStore("pecs", {keyPath: "word"});
|
||||
objectStore.createIndex("word", "word", {unique: true});
|
||||
objectStore.createIndex("locate", "locate");
|
||||
}
|
||||
|
||||
function saveApp () {
|
||||
var idbHandle = window.indexedDB.open("masterLibrary");
|
||||
idbHandle.onerror = (e) => {
|
||||
systemMsg("Error loading database",2);
|
||||
};
|
||||
idbHandle.onupgradeneeded = initDatabase;
|
||||
idbHandle.onsuccess = (e) => {
|
||||
var masterLibrary = idbHandle.result;
|
||||
var saving = masterLibrary.transaction("pecs","readwrite",{durability:"strict"});
|
||||
var pecStore = saving.objectStore("pecs");
|
||||
library.forEach(pecItem=>{
|
||||
var action = pecStore.get(pecItem.word);
|
||||
action.onsuccess = (e)=>{
|
||||
var record = action.result;
|
||||
if (record == undefined) {
|
||||
record = {
|
||||
word: pecItem.word,
|
||||
image: pecItem.image,
|
||||
locate: "library"
|
||||
};
|
||||
} else {
|
||||
record.locate = "library";
|
||||
}
|
||||
pecStore.put(record);
|
||||
};
|
||||
});
|
||||
for (var boardID = 0; boardID < app.boards.length; boardID++) {
|
||||
var curBoard = app.boards[boardID];
|
||||
for (var index = 0; index < curBoard.pecs.length; index++) {
|
||||
var curPec = curBoard.pecs[index];
|
||||
if (null == curPec) { continue; } //don't store nulls
|
||||
var action = pecStore.get(curPec.word);
|
||||
action.curPec = curPec;
|
||||
action.boardID = boardID;
|
||||
action.pecIndex = index;
|
||||
action.onsuccess = (e)=>{
|
||||
var record = e.target.result;
|
||||
if (record == undefined) {
|
||||
record = {
|
||||
word: e.target.curPec.word,
|
||||
image: e.target.curPec.image,
|
||||
locate: e.target.boardID + "-" + e.target.pecIndex
|
||||
};
|
||||
} else {
|
||||
record.locate = e.target.boardID + "-" + e.target.pecIndex;
|
||||
}
|
||||
pecStore.put(record);
|
||||
};
|
||||
}
|
||||
}
|
||||
saving.oncomplete = (e)=>{
|
||||
masterLibrary.close();
|
||||
saveOptions();
|
||||
loadApp();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function saveOptions () {
|
||||
localStorage.setItem("librepecSettings", JSON.stringify(app.options));
|
||||
}
|
||||
|
||||
function loadOptions () {
|
||||
var options = JSON.parse(localStorage.getItem("librepecSettings"));
|
||||
if (null != options) { app.options = options; }
|
||||
var darkmode = document.getElementById("darkmode-checkbox");
|
||||
var kidsmode = document.getElementById("kidsmode-checkbox");
|
||||
var feedback = document.getElementById("audio-feedback-toggle");
|
||||
var floodLimit = document.getElementById("flood-limit");
|
||||
var floodTimeout = document.getElementById("flood-timeout");
|
||||
darkmode.checked = (undefined == app.options?.darkmode) ? false : (app.options.darkmode ? true : false);
|
||||
toggleDarkmode(darkmode.checked);
|
||||
kidsmode.checked = (undefined == app.options?.kidsmode) ? false : (app.options.kidsmode ? true : false);
|
||||
feedback.checked = (undefined == app.options?.audioFeedback) ? false : (app.options.audioFeedback ? true : false);
|
||||
floodLimit.value = (undefined == app.options?.feedbackFloodLimit) ? 3 : app.options.feedbackFloodLimit;
|
||||
floodTimeout.value = (undefined == app.options?.feedbackTimeout) ? 60 : app.options.feedbackTimeout;
|
||||
}
|
||||
|
||||
import { library as library } from './library.js';
|
||||
|
||||
function initApp () {
|
||||
// Create our initial board
|
||||
app.boards = [];
|
||||
app.boards.push(new pecBoard());
|
||||
app.currentBoard = app.boards[0];
|
||||
repopBoards(0);
|
||||
repopGrid(app.currentBoard);
|
||||
|
||||
// Populate Library
|
||||
app.library = library;
|
||||
repopLibrary();
|
||||
|
||||
// Populate Options
|
||||
app.options = {};
|
||||
app.options.darkmode = false; // should always be an option
|
||||
app.options.kidsMode = false; // disables most interactions
|
||||
app.options.audioFeedback = false; // read word aloude
|
||||
app.options.feedbackFloodLimit = 3;
|
||||
app.options.feedbackTimeout = 60; // 60 seconds
|
||||
// overload defaults with options stored in localstorage
|
||||
}
|
||||
|
||||
function hardResetApp () {
|
||||
alert("App ahs been hard reset");
|
||||
initApp();
|
||||
saveApp();
|
||||
}
|
||||
|
||||
function loadAppPec (item) {
|
||||
var locate = item.locate;
|
||||
if ("library" == locate) {
|
||||
app.library.push(new pec(item.word, item.image));
|
||||
} else {
|
||||
locate = locate.split("-").map(n=>parseInt(n));
|
||||
if (!(app.boards[locate[0]] instanceof pecBoard)) {
|
||||
app.boards[locate[0]] = new pecBoard();
|
||||
}
|
||||
app.boards[locate[0]].pecs[locate[1]] = new pec(item.word, item.image);
|
||||
}
|
||||
}
|
||||
|
||||
function loadApp () {
|
||||
var idbHandle = window.indexedDB.open("masterLibrary");
|
||||
idbHandle.onerror = (e) => {
|
||||
systemMsg("Error loading database",2);
|
||||
};
|
||||
idbHandle.onupgradeneeded = initDatabase;
|
||||
window.currentBoardID = app.boards.indexOf(app.currentBoard);
|
||||
currentBoardID = isNaN(currentBoardID) ? 0 : currentBoardID;
|
||||
idbHandle.onsuccess = (e) => {
|
||||
var masterLibrary = idbHandle.result;
|
||||
var loading = masterLibrary.transaction("pecs","readonly",{durability:"strict"});
|
||||
var pecStore = loading.objectStore("pecs");
|
||||
var lengthCheck = pecStore.count();
|
||||
lengthCheck.onsuccess = (e)=>{
|
||||
if (0 < e.target.result) {
|
||||
app.library = []; // Clear out library cache
|
||||
app.boards = []; // Clear out boards cache
|
||||
app.boards.push(new pecBoard());
|
||||
app.currentBoard = app.boards[0];
|
||||
var cursor = pecStore.openCursor();
|
||||
cursor.onsuccess = (e) => {
|
||||
var c = e.target.result;
|
||||
if (c) {
|
||||
loadAppPec(c.value);
|
||||
c.continue();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// DB is empty, reinit app because
|
||||
// we have nothing to load
|
||||
hardResetApp();
|
||||
}
|
||||
};
|
||||
loading.oncomplete = (e) => {
|
||||
masterLibrary.close();
|
||||
loadOptions();
|
||||
app.currentBoard = app.boards[currentBoardID];
|
||||
repopLibrary();
|
||||
repopBoards();
|
||||
repopGrid(app.currentBoard);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function toggleDarkmode () {
|
||||
var html = document.documentElement;
|
||||
if (html.classList.contains("darkmode")) {
|
||||
html.classList.remove("darkmode");
|
||||
if (app.options.darkmode) {
|
||||
if (!(html.classList.contains("darkmode"))) {
|
||||
html.classList.add("darkmode");
|
||||
}
|
||||
} else {
|
||||
html.classList.add("darkmode");
|
||||
if (html.classList.contains("darkmode")) {
|
||||
html.classList.remove("darkmode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +242,7 @@ function inRange(target,min,max) {
|
||||
}
|
||||
|
||||
function invokeLibrary(e) {
|
||||
if (app.options.kidsmode) { return; }
|
||||
// Breaking this out of event so its not an
|
||||
// annon function, so we can swap it in and out
|
||||
var targetID = ((e.currentTarget.getAttribute("id")).split("pec"))[1];
|
||||
@@ -122,6 +299,7 @@ function repopBoards (current=0) {
|
||||
if (i == app.boards.length) {
|
||||
name = "+";
|
||||
boardTab.addEventListener("click",(e)=>{
|
||||
if (app.options.kidsmode) { return; }
|
||||
var current = app.boards.findIndex(i=>i==app.currentBoard);
|
||||
app.boards.push(new pecBoard());
|
||||
repopBoards(current);
|
||||
@@ -139,6 +317,7 @@ function repopBoards (current=0) {
|
||||
} else {
|
||||
boardTab.classList.add("active_board");
|
||||
}
|
||||
if (undefined == app.boards[i]) { app.boards[i] = new pecBoard(); }
|
||||
if (undefined != app.boards[i].name) {
|
||||
name = app.boards[i].name;
|
||||
}
|
||||
@@ -165,6 +344,7 @@ function useThisPec (e) {
|
||||
var sourceID = ((e.currentTarget.getAttribute("id")).split("lPec"))[1];
|
||||
app.gui.library.root.classList.remove("focused");
|
||||
app.currentBoard.pecs[app.targetPecIndex] = app.library.splice(sourceID,1)[0];
|
||||
saveApp();
|
||||
repopLibrary();
|
||||
repopGrid(app.currentBoard);
|
||||
}
|
||||
@@ -173,6 +353,7 @@ function createNewPec () {
|
||||
var name = app.gui.newpec_name.value;
|
||||
var image = app.gui.newpec_image.files[0];
|
||||
app.library.push(new pec(name, URL.createObjectURL(image)));
|
||||
saveApp();
|
||||
repopLibrary();
|
||||
app.gui.newpec.root.classList.remove("focused");
|
||||
}
|
||||
@@ -233,6 +414,7 @@ function repopLibrary () {
|
||||
app.gui.library.body.appendChild(newPec);
|
||||
}
|
||||
|
||||
|
||||
// Initialize gui
|
||||
|
||||
window.app = {};
|
||||
@@ -258,7 +440,25 @@ app.gui.main.append(app.gui.library.root);
|
||||
app.gui.options = new auxillery_dialog("Options");
|
||||
app.gui.options.body.classList.add("options_body");
|
||||
app.gui.main.append(app.gui.options.root);
|
||||
app.gui.optionsButton.addEventListener("click", ()=>{ app.gui.options.root.classList.add("focused") });
|
||||
app.gui.optionsButton.addEventListener("click", ()=>{
|
||||
if (app.options.kidsmode) { return; }
|
||||
loadOptions();
|
||||
app.gui.options.root.classList.add("focused");
|
||||
});
|
||||
app.gui.optionsButton.addEventListener("mousedown", ()=>{
|
||||
if (!app.options.kidsmode) { return; }
|
||||
app.gui.optionsButton.classList.add("holding");
|
||||
app.optionHold = setTimeout(()=>{
|
||||
app.gui.optionsButton.classList.remove("holding");
|
||||
loadOptions();
|
||||
app.gui.options.root.classList.add("focused");
|
||||
},3000);
|
||||
});
|
||||
app.gui.optionsButton.addEventListener("mouseup", ()=>{
|
||||
if (!app.options.kidsmode) { return; }
|
||||
app.gui.optionsButton.classList.remove("holding");
|
||||
clearTimeout(app.optionHold);
|
||||
});
|
||||
// New Pec popup
|
||||
app.gui.newpec = new auxillery_dialog("Create New Pec");
|
||||
app.gui.newpec.body.classList.add("newpec_body");
|
||||
@@ -273,48 +473,61 @@ for (var x = 0; x < 16; x++) {
|
||||
clearPec(x);
|
||||
app.gui.view.appendChild(thisPec);
|
||||
}
|
||||
// Create our initial board
|
||||
app.boards = [];
|
||||
app.boards.push(new pecBoard());
|
||||
app.currentBoard = app.boards[0];
|
||||
repopBoards(0);
|
||||
repopGrid(app.currentBoard);
|
||||
|
||||
// Populate Library
|
||||
import { library as library } from './library.js';
|
||||
app.library = library;
|
||||
repopLibrary();
|
||||
|
||||
// Populate Options
|
||||
app.options = {};
|
||||
app.options.darkmode = false; // should always be an option
|
||||
app.options.audioFeedback = false; // read word aloude
|
||||
app.options.feedbackFloodLimit = 3;
|
||||
app.options.feedbackTimeout = 60; // 60 seconds
|
||||
// overload defaults with options stored in localstorage
|
||||
|
||||
// build Options UI
|
||||
app.gui.options_darkmode = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_darkmode);
|
||||
app.gui.options_darkmode.innerHTML = '<label for="darkmode-checkbox">Darkmode</label> <input id="darkmode-checkbox" type="checkbox" class="dm-indicator" />';
|
||||
app.gui.options_darkmode.addEventListener("change", toggleDarkmode);
|
||||
app.gui.options_darkmode.addEventListener("change", (e)=>{
|
||||
app.options.darkmode = e.target.checked;
|
||||
toggleDarkmode();
|
||||
saveOptions();
|
||||
});
|
||||
|
||||
app.gui.options_kidsmode = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_kidsmode);
|
||||
app.gui.options_kidsmode.innerHTML = '<label for="kidsmode-checkbox">Kids Mode (Disables adding pecs, boards, and accessing options (hold for 3 seconds to access)</label> <input id="kidsmode-checkbox" type="checkbox" class="toggle-switch" />';
|
||||
app.gui.options_kidsmode.addEventListener("change", (e) => {
|
||||
app.options.kidsmode = e.target.checked;
|
||||
saveOptions();
|
||||
});
|
||||
|
||||
app.gui.options_audioFeedback = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_audioFeedback);
|
||||
app.gui.options_audioFeedback.innerHTML = '<label for="audio-feedback-toggle">Read Allowed</label> <input id="audio-feedback-toggle" type="checkbox" class="toggle-switch" />';
|
||||
app.gui.options_audioFeedback.addEventListener("change", (e) => {
|
||||
app.options.audioFeedback = e.target.checked;
|
||||
saveOptions();
|
||||
});
|
||||
|
||||
app.gui.options_feedbackFloodLimit = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_feedbackFloodLimit);
|
||||
app.gui.options_feedbackFloodLimit.innerHTML = '<label for="flood-limit">Audio Flood Limit</label> <input id="flood-limit" type="number" min=1 step=2 max=10 />';
|
||||
app.gui.options_feedbackFloodLimit.addEventListener("change", (e) => {
|
||||
app.options.feedbackFloodLimit = e.target.value;
|
||||
saveOptions();
|
||||
});
|
||||
|
||||
app.gui.options_feedbackTimeout = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_feedbackTimeout);
|
||||
app.gui.options_feedbackTimeout.innerHTML = '<label for="flood-timeout">Audio Flood Timeout</label> <input id="flood-timeout" type="number" min=0 step=10 />';
|
||||
app.gui.options_feedbackTimeout.addEventListener("change", (e) => {
|
||||
app.options.feedbackTimeout = e.target.value;
|
||||
saveOptions();
|
||||
});
|
||||
|
||||
app.gui.options_reset = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_reset);
|
||||
app.gui.options_reset.innerHTML = '<span id="reset-hard-reset" class="button">Completely Reset App (hold down for 3 seconds)</span><span id="reset-soft-reset" class="button">Clear All Boards</span>';
|
||||
app.gui.options_reset_hard = document.getElementById("reset-hard-reset");
|
||||
app.gui.options_reset_soft = document.getElementById("reset-soft-reset");
|
||||
// Add functionality for resets here
|
||||
|
||||
app.gui.options_about = document.createElement("div");
|
||||
app.gui.options.body.appendChild(app.gui.options_about);
|
||||
app.gui.options_about.innerHTML = 'App licenced <a href="LICENSE.txt" target="_blank"><img src="images/ui/gplv3-or-later.svg" height="30px" /></a><label>-</label> Cards from <a href="https://assistivecards.com" target="_blank"><img src="images/ui/ac.svg" height="30px" alt="Assistive Cards" /></a><label>-</label> Project Source <a href="https://labs.murkfall.net/bluesaxman/librePECS">labs.murkfall.net</a>';
|
||||
|
||||
// Build New Pec UI
|
||||
app.gui.newpec.body.innerHTML = '<form id="new-pec-form"><label for="new-pec-name">Name</label><input id="new-pec-name" type="text" value="" /><br /><label for="new-pec-image">Picture</label><input id="new-pec-image" type="file" accept="image/png, image/jpeg, image/svg" value="" /><br /><div id="new-pec-preview"></div><br /><div id="new-pec-status">Create your new pec by naming it and providing an image.</div></form>';
|
||||
app.gui.newpec_form = document.getElementById("new-pec-form");
|
||||
app.gui.newpec_name = document.getElementById("new-pec-name");
|
||||
@@ -325,3 +538,6 @@ app.gui.newpec_preview.classList.add("pecSlot");
|
||||
app.gui.newpec_name.addEventListener("change", updatePreview);
|
||||
app.gui.newpec_image.addEventListener("change", updatePreview);
|
||||
|
||||
// initialize and load app
|
||||
initApp();
|
||||
loadApp();
|
||||
|
||||
Reference in New Issue
Block a user