forked from cory/tildefriends
Cory McWilliams
fb94e1cde9
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3233 ed5197a5-7fde-0310-b194-c3ffbd925b24
264 lines
7.1 KiB
JavaScript
264 lines
7.1 KiB
JavaScript
"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();
|