tildefriends/packages/cory/todo/todo.js

261 lines
7.1 KiB
JavaScript
Raw Normal View History

"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});
}
async function readList(key) {
let todo = null;
try {
todo = JSON.parse(await database.get(key));
} 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();