tally: new app
parent
d8f65fec7b
commit
91e896bf9e
|
|
@ -0,0 +1 @@
|
|||
0.01: New app!
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Tally
|
||||
|
||||
An app that lets you keep a tally - when events happen, etc.
|
||||
|
||||
Use the clock info to add to the tally. The app can be used to review/edit/delete tallies
|
||||
|
||||
## Usage
|
||||
|
||||
Navigate to the tally clock info, then swipe up/down to select one of the tallies to enter. Tap on it to add to the tally.
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwMB/4Ai/gsDn/4Aocf+AFDh4FGDgYFU/k/Aq08n4FTAgIFtO66bKVoq5F//wj4fD+AIBAod/AojYE+IFE+YFE+4FKABQ="))
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
var storage = require("Storage");
|
||||
function readTallies() {
|
||||
var tallies = [];
|
||||
var f = storage.open("tallies.csv", "r");
|
||||
var line;
|
||||
while ((line = f.readLine()) !== undefined) {
|
||||
var parts = line.replace("\n", "").split(",");
|
||||
tallies.push({ date: new Date(parts[0]), name: parts[1] });
|
||||
}
|
||||
return tallies;
|
||||
}
|
||||
function saveTallies(tallies) {
|
||||
var f = storage.open("tallies.csv", "w");
|
||||
for (var _i = 0, tallies_1 = tallies; _i < tallies_1.length; _i++) {
|
||||
var tally = tallies_1[_i];
|
||||
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
|
||||
}
|
||||
}
|
||||
var dayEq = function (a, b) {
|
||||
return a.getFullYear() === b.getFullYear()
|
||||
&& a.getMonth() === b.getMonth()
|
||||
&& a.getDate() === b.getDate();
|
||||
};
|
||||
function showTallies(tallies) {
|
||||
var menu = {
|
||||
"": { title: "Tallies" },
|
||||
"< Back": function () { return load(); },
|
||||
};
|
||||
var today = new Date;
|
||||
var day;
|
||||
tallies.forEach(function (tally, i) {
|
||||
var td = tally.date;
|
||||
if (!dayEq(day !== null && day !== void 0 ? day : today, td)) {
|
||||
var s = "".concat(td.getFullYear(), "-").concat(pad2(td.getMonth() + 1), "-").concat(pad2(td.getDate()));
|
||||
menu[s] = function () { };
|
||||
day = td;
|
||||
}
|
||||
menu["".concat(tfmt(tally), ": ").concat(tally.name)] = function () { return editTally(tallies, i); };
|
||||
});
|
||||
E.showMenu(menu);
|
||||
}
|
||||
function editTally(tallies, i) {
|
||||
var tally = tallies[i];
|
||||
var onback = function () {
|
||||
saveTallies(tallies);
|
||||
E.removeListener("kill", onback);
|
||||
};
|
||||
E.on("kill", onback);
|
||||
var menu = {
|
||||
"": { title: "Edit ".concat(tally.name) },
|
||||
"< Back": function () {
|
||||
onback();
|
||||
showTallies(tallies);
|
||||
},
|
||||
"Name": {
|
||||
value: tally.name,
|
||||
onchange: function () {
|
||||
setTimeout(function () {
|
||||
require("textinput")
|
||||
.input({ text: tally.name })
|
||||
.then(function (text) {
|
||||
if (text) {
|
||||
tally.name = text;
|
||||
}
|
||||
editTally(tallies, i);
|
||||
});
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
"Time": {
|
||||
value: tally.date.getTime(),
|
||||
format: function (_tm) { return tfmt(tally); },
|
||||
onchange: function (v) {
|
||||
tally.date = new Date(v);
|
||||
},
|
||||
step: 60000,
|
||||
},
|
||||
"Delete": function () {
|
||||
E.showPrompt("Delete \"".concat(tally.name, "\"?"), {
|
||||
title: "Delete",
|
||||
buttons: { Yes: true, No: false },
|
||||
}).then(function (confirm) {
|
||||
if (confirm) {
|
||||
tallies.splice(i, 1);
|
||||
saveTallies(tallies);
|
||||
showTallies(tallies);
|
||||
return;
|
||||
}
|
||||
editTally(tallies, i);
|
||||
});
|
||||
},
|
||||
};
|
||||
E.showMenu(menu);
|
||||
}
|
||||
function tfmt(tally) {
|
||||
var d = tally.date;
|
||||
return "".concat(d.getHours(), ":").concat(pad2(d.getMinutes()));
|
||||
}
|
||||
var pad2 = function (s) { return ("0" + s.toFixed(0)).slice(-2); };
|
||||
showTallies(readTallies());
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 296 B |
|
|
@ -0,0 +1,120 @@
|
|||
const storage = require("Storage");
|
||||
|
||||
type Tally = {
|
||||
date: Date,
|
||||
name: string,
|
||||
};
|
||||
|
||||
function readTallies() {
|
||||
const tallies: Tally[] = [];
|
||||
const f = storage.open("tallies.csv", "r");
|
||||
let line;
|
||||
while ((line = f.readLine()) !== undefined) {
|
||||
const parts = line.replace("\n", "").split(",");
|
||||
tallies.push({ date: new Date(parts[0]), name: parts[1] });
|
||||
}
|
||||
return tallies;
|
||||
}
|
||||
|
||||
function saveTallies(tallies: Tally[]) {
|
||||
const f = storage.open("tallies.csv", "w");
|
||||
for(const tally of tallies){
|
||||
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const dayEq = (a: Date, b: Date) =>
|
||||
a.getFullYear() === b.getFullYear()
|
||||
&& a.getMonth() === b.getMonth()
|
||||
&& a.getDate() === b.getDate();
|
||||
|
||||
function showTallies(tallies: Tally[]) {
|
||||
const menu: Menu = {
|
||||
"": { title: "Tallies" },
|
||||
"< Back": () => load(),
|
||||
};
|
||||
|
||||
const today = new Date;
|
||||
let day: undefined | Date;
|
||||
|
||||
tallies.forEach((tally, i) => {
|
||||
const td = tally.date;
|
||||
if(!dayEq(day ?? today, td)){
|
||||
const s = `${td.getFullYear()}-${pad2(td.getMonth() + 1)}-${pad2(td.getDate())}`;
|
||||
menu[s] = () => {};
|
||||
day = td;
|
||||
}
|
||||
|
||||
menu[`${tfmt(tally)}: ${tally.name}`] = () => editTally(tallies, i);
|
||||
});
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function editTally(tallies: Tally[], i: number) {
|
||||
const tally = tallies[i]!;
|
||||
|
||||
const onback = () => {
|
||||
saveTallies(tallies);
|
||||
E.removeListener("kill", onback);
|
||||
};
|
||||
E.on("kill", onback);
|
||||
|
||||
const menu: Menu = {
|
||||
"": { title: `Edit ${tally.name}` },
|
||||
"< Back": () => {
|
||||
onback();
|
||||
showTallies(tallies)
|
||||
},
|
||||
"Name": {
|
||||
value: tally.name,
|
||||
onchange: () => {
|
||||
setTimeout(() => {
|
||||
require("textinput")
|
||||
.input({ text: tally.name })
|
||||
.then(text => {
|
||||
if (text) {
|
||||
tally.name = text;
|
||||
}
|
||||
editTally(tallies, i);
|
||||
});
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
"Time": {
|
||||
value: tally.date.getTime(),
|
||||
format: (_tm: number) => tfmt(tally),
|
||||
onchange: (v: number) => {
|
||||
tally.date = new Date(v);
|
||||
},
|
||||
step: 60000, // 1 min
|
||||
},
|
||||
"Delete": () => {
|
||||
E.showPrompt(`Delete "${tally.name}"?`, {
|
||||
title: "Delete",
|
||||
buttons: { Yes: true, No: false },
|
||||
}).then(confirm => {
|
||||
if (confirm) {
|
||||
tallies.splice(i, 1);
|
||||
saveTallies(tallies);
|
||||
showTallies(tallies);
|
||||
return;
|
||||
}
|
||||
|
||||
// need to regrab ui, can't `m.draw()`
|
||||
editTally(tallies, i);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function tfmt(tally: Tally) {
|
||||
const d = tally.date;
|
||||
return `${d.getHours()}:${pad2(d.getMinutes())}`;
|
||||
}
|
||||
|
||||
const pad2 = (s: number) => ("0" + s.toFixed(0)).slice(-2);
|
||||
|
||||
showTallies(readTallies());
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
(function () {
|
||||
var storage = require("Storage");
|
||||
var tallyEntries = storage.readJSON("tallycfg.json", 1) || [];
|
||||
var img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==");
|
||||
return {
|
||||
name: "Tally",
|
||||
img: img,
|
||||
items: tallyEntries.map(function (ent) { return ({
|
||||
name: ent.name,
|
||||
img: img,
|
||||
get: function () {
|
||||
return { text: this.name, img: img };
|
||||
},
|
||||
run: function () {
|
||||
var f = storage.open("tallies.csv", "a");
|
||||
f.write([
|
||||
new Date().toISOString(),
|
||||
this.name,
|
||||
].join(",") + "\n");
|
||||
},
|
||||
show: function () { },
|
||||
hide: function () { },
|
||||
}); }),
|
||||
};
|
||||
})
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
(function() {
|
||||
const storage = require("Storage");
|
||||
const tallyEntries = storage.readJSON("tallycfg.json", 1) as TallySettings || [];
|
||||
|
||||
// transparent
|
||||
const img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==")
|
||||
// non-transparent
|
||||
//const img = atob("GBgBAAAAAAAAAAAAH//4P//8MAAMMAAMMBgMMBgMMBmMMBmMMZmMMZmMMZmMMZmMMAAMMAAMP//8H//4A4AAAwAAAgAAAAAAAAAA")
|
||||
|
||||
return {
|
||||
name: "Tally",
|
||||
img,
|
||||
items: tallyEntries.map(ent => ({
|
||||
name: ent.name,
|
||||
img,
|
||||
get: function() {
|
||||
return { text: this.name, img };
|
||||
},
|
||||
run: function() {
|
||||
const f = storage.open("tallies.csv", "a");
|
||||
f.write([
|
||||
new Date().toISOString(),
|
||||
this.name,
|
||||
].join(",") + "\n");
|
||||
},
|
||||
show: function(){},
|
||||
hide: function(){},
|
||||
})),
|
||||
};
|
||||
}) satisfies ClockInfoFunc
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 760 B |
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"id": "tally",
|
||||
"name": "Tally Keeper",
|
||||
"shortName": "Tally",
|
||||
"version": "0.01",
|
||||
"description": "Add to a tally from clock info",
|
||||
"icon": "app.png",
|
||||
"tags": "clkinfo",
|
||||
"type": "clkinfo",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{ "name": "tally.settings.js", "url": "settings.js" },
|
||||
{ "name": "tally.img", "url": "app-icon.js", "evaluate": true },
|
||||
{ "name": "tally.clkinfo.js", "url": "clkinfo.js" },
|
||||
{ "name": "tally.app.js", "url": "app.js" }
|
||||
],
|
||||
"data": [
|
||||
{ "name": "tallycfg.json" },
|
||||
{ "name": "tallies.csv" }
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
(function (back) {
|
||||
var storage = require("Storage");
|
||||
var SETTINGS_FILE = "tallycfg.json";
|
||||
var tallycfg = storage.readJSON(SETTINGS_FILE, 1) || [];
|
||||
function saveSettings() {
|
||||
storage.writeJSON(SETTINGS_FILE, tallycfg);
|
||||
}
|
||||
function showMainMenu() {
|
||||
var menu = {
|
||||
"": { "title": "Tally Configs" },
|
||||
"< Back": back,
|
||||
"Add New": function () { return showEditMenu(); },
|
||||
};
|
||||
tallycfg.forEach(function (tally, index) {
|
||||
menu[tally.name] = function () { return showEditMenu(tally, index); };
|
||||
});
|
||||
E.showMenu(menu);
|
||||
}
|
||||
function showEditMenu(tally, index) {
|
||||
var isNew = tally == null;
|
||||
if (tally == null) {
|
||||
tally = { name: "" };
|
||||
index = tallycfg.length;
|
||||
tallycfg.push(tally);
|
||||
}
|
||||
var menu = {
|
||||
"": { "title": isNew ? "New Tally" : "Edit Tally" },
|
||||
"< Back": function () {
|
||||
saveSettings();
|
||||
showMainMenu();
|
||||
},
|
||||
};
|
||||
menu[tally.name || "<set name>"] = function () {
|
||||
require("textinput")
|
||||
.input({ text: tally.name })
|
||||
.then(function (text) {
|
||||
tally.name = text;
|
||||
showEditMenu(tally, index);
|
||||
});
|
||||
};
|
||||
if (!isNew) {
|
||||
menu["Delete"] = function () {
|
||||
tallycfg.splice(index, 1);
|
||||
saveSettings();
|
||||
showMainMenu();
|
||||
};
|
||||
}
|
||||
E.showMenu(menu);
|
||||
}
|
||||
showMainMenu();
|
||||
})
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
type TallySettings = TallySetting[];
|
||||
type TallySetting = { name: string };
|
||||
|
||||
(function(back) {
|
||||
const storage = require("Storage");
|
||||
const SETTINGS_FILE = "tallycfg.json";
|
||||
|
||||
const tallycfg = storage.readJSON(SETTINGS_FILE, 1) as TallySettings || [];
|
||||
|
||||
function saveSettings() {
|
||||
storage.writeJSON(SETTINGS_FILE, tallycfg);
|
||||
}
|
||||
|
||||
function showMainMenu() {
|
||||
const menu: Menu = {
|
||||
"": { "title": "Tally Configs" },
|
||||
"< Back": back,
|
||||
"Add New": () => showEditMenu(),
|
||||
};
|
||||
|
||||
tallycfg.forEach((tally, index) => {
|
||||
menu[tally.name] = () => showEditMenu(tally, index);
|
||||
});
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function showEditMenu(tally?: TallySetting, index?: number) {
|
||||
const isNew = tally == null;
|
||||
if (tally == null) {
|
||||
tally = { name: "" };
|
||||
index = tallycfg.length;
|
||||
tallycfg.push(tally);
|
||||
}
|
||||
|
||||
const menu: Menu = {
|
||||
"": { "title": isNew ? "New Tally" : "Edit Tally" },
|
||||
"< Back": () => {
|
||||
saveSettings();
|
||||
showMainMenu();
|
||||
},
|
||||
};
|
||||
|
||||
menu[tally.name || "<set name>"] = () => {
|
||||
require("textinput")
|
||||
.input({ text: tally.name })
|
||||
.then(text => {
|
||||
tally.name = text;
|
||||
|
||||
showEditMenu(tally, index);
|
||||
});
|
||||
};
|
||||
|
||||
if (!isNew) {
|
||||
menu["Delete"] = () => {
|
||||
tallycfg.splice(index!, 1);
|
||||
saveSettings();
|
||||
showMainMenu();
|
||||
};
|
||||
}
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
showMainMenu();
|
||||
}) satisfies SettingsFunc;
|
||||
Loading…
Reference in New Issue