"use strict"; var kUnchecked = "☐"; var kChecked = "☑"; let activeList = null; let confirmRemove; let showHidden = false; terminal.setPrompt("Add Item>"); core.register("onInput", function(command) { if (typeof command == "string" && command.substring(0, "action:".length) == "action:") { command = JSON.parse(command.substring("action:".length)); if (confirmRemove && command.action != "reallyRemoveList" && command.action != "reallyRemove") { confirmRemove = false; } if (command.action == "set") { setItem(command.key, command.item, command.value).then(notifyChanged).then(redisplay); } else if (command.action == "setHidden") { setItemHidden(command.key, command.item, command.hidden).then(notifyChanged).then(redisplay); } else if (command.action == "setShowHidden") { showHidden = !showHidden; redisplay(); } else if (command.action == "makePublic") { let key = JSON.parse(command.key); delete key.user; key.public = true; let newKey = JSON.stringify(key); readList(command.key).then(function(data) { return writeList(newKey, data); }).then(function() { activeList = newKey; return database.remove(command.key); }).then(redisplay); } else if (command.action == "remove") { confirmRemove = command; redisplay(); } else if (command.action == "reallyRemove") { confirmRemove = false; removeItem(command.key, command.item).then(notifyChanged).then(redisplay); } else if (command.action == "editList") { activeList = command.key; terminal.setHash(activeList); redisplay(); } else if (command.action == "lists") { activeList = null; redisplay(); } else if (command.action == "removeList") { confirmRemove = true; redisplay(); } else if (command.action == "reallyRemoveList") { confirmRemove = false; activeList = null; database.remove(command.key).then(notifyChanged).then(redisplay).catch(function(error) { terminal.print(JSON.stringify(error)); terminal.print(command.key); }); } } else if (typeof command == "string") { if (activeList) { addItem(activeList, command).then(notifyChanged).then(redisplay); } else { activeList = makePrivateKey(command); writeList(activeList, {name: command, items: []}).then(notifyChanged).then(redisplay); } } }); core.register("hashChange", function(event) { activeList = event.hash; if (activeList && activeList.charAt(0) == "#") { activeList = activeList.substring(1); } redisplay(); }); core.register("onMessage", function(message) { return redisplay(); }); function notifyChanged() { return core.broadcast({changed: true}); } function readList(key) { return database.get(key).catch(function(error) { return null; }).then(function(todo) { try { todo = JSON.parse(todo); } catch (error) { todo = {name: "TODO", items: []}; } return todo; }); } function writeList(key, todo) { return database.set(key, JSON.stringify(todo)); } function addItem(key, name) { return readList(key).then(function(todo) { todo.items.push({name: name, value: false}); return writeList(key, todo); }); } function setItem(key, name, value) { return readList(key).then(function(todo) { for (var i = 0; i < todo.items.length; i++) { if (todo.items[i].name == name) { todo.items[i].value = value; } } return writeList(key, todo); }); } function setItemHidden(key, name, hidden) { return readList(key).then(function(todo) { for (var i = 0; i < todo.items.length; i++) { if (todo.items[i].name == name) { todo.items[i].hidden = hidden; } } return writeList(key, todo); }); } function removeItem(key, name) { return readList(key).then(function(todo) { todo.items = todo.items.filter(function(item) { return item.name != name; }); return writeList(key, todo); }); } function printList(name, key, items) { terminal.cork(); terminal.clear(); terminal.print(name, " - ", {command: "action:" + JSON.stringify({action: "setShowHidden", value: !showHidden}), value: showHidden ? "stop showing hidden" : "show hidden"}, " - ", {command: "action:" + JSON.stringify({action: "lists"}), value: "back"}, " - ", {command: "action:" + JSON.stringify({action: (confirmRemove === true ? "reallyRemoveList" : "removeList"), key: key}), value: (confirmRemove === true ? "confirm remove" : "remove list")}, JSON.parse(key).public ? "" : [" - ", {command: "action:" + JSON.stringify({action: "makePublic", key: key}), value: "make public"}]); terminal.print("=".repeat(name.length)); for (var i = 0; i < items.length; i++) { var visible = !items[i].hidden; if (showHidden || visible) { var isChecked = items[i].value; var style = ["", "text-decoration: line-through"]; terminal.print( {command: "action:" + JSON.stringify({action: "set", key: key, item: items[i].name, value: !isChecked}), value: isChecked ? kChecked : kUnchecked}, " ", {style: style[isChecked ? 1 : 0], value: items[i].name}, " (", {command: "action:" + JSON.stringify({ action: "setHidden", key: key, item: items[i].name, hidden: visible, }), value: visible ? "hide" : "unhide"}, " ", {command: "action:" + JSON.stringify({ action: (confirmRemove && confirmRemove.item == items[i].name ? "reallyRemove" : "remove"), key: key, item: items[i].name}), value: (confirmRemove && confirmRemove.item == items[i].name ? "confirm remove" : "remove")}, ")"); } } terminal.uncork(); } function redisplay() { terminal.cork(); terminal.clear(); terminal.setEcho(false); if (activeList) { readList(activeList).then(function(data) { printList(getName(activeList), activeList, data.items); }).catch(function(error) { terminal.print("error: " + error); }); } else { printListOfLists(); } terminal.uncork(); } function makeId() { var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var result = ""; for (var i = 0; i < 32; i++) { result += alphabet.charAt(Math.floor(Math.random() * alphabet.length)); } return result; } function makePublicKey(name) { return JSON.stringify({public: true, id: makeId(), name: name}); } function makePrivateKey(name) { return JSON.stringify({public: false, id: makeId(), name: name, user: core.user.name}); } function hasPermission(key) { let result = false; try { let data = JSON.parse(key); result = data.public || data.user == core.user.name || !data.user; } catch (error) { result = true; } return result; } function getName(key) { let name = "TODO"; try { name = JSON.parse(key).name || name; } catch (error) { } return name; } function isPrivate(key) { let isPrivate = false; try { isPrivate = !JSON.parse(key).public; } catch (error) { } return isPrivate; } function getVisibleLists() { return database.getAll().then(function(data) { return data.filter(hasPermission); }); } function printListOfLists() { getVisibleLists().then(function(keys) { terminal.cork(); terminal.print("TODO Lists:"); for (var i = 0; i < keys.length; i++) { let key = keys[i]; terminal.print({ command: "action:" + JSON.stringify({action: "editList", key: key}), value: getName(key), }, " ", isPrivate(key) ? "(private)" : "(public)"); } terminal.uncork(); }); } redisplay();