Skip to content

Commit 46795ed

Browse files
authored
Merge pull request espruino#3831 from bobrippling/feat/tally-app
New app/clkinfo: tally
2 parents f7be785 + cc2978f commit 46795ed

File tree

14 files changed

+428
-0
lines changed

14 files changed

+428
-0
lines changed

apps/tally/ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.01: New app!

apps/tally/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Tally
2+
3+
An app that lets you keep a tally - when events happen, etc.
4+
5+
Use the clock info to add to the tally. The app can be used to review/edit/delete tallies
6+
7+
## Usage
8+
9+
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.

apps/tally/app-icon.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require("heatshrink").decompress(atob("mEwwInkgf/AAXAg4FD8EPAofwAowcDAqkD4AFW4fAAqYEBAtp3XTZStFXIsAh/gD4cPBAIFDwAFEbAkOAokMAokIApQAKA=="))

apps/tally/app.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
var storage = require("Storage");
2+
function readTallies() {
3+
var tallies = [];
4+
var f = storage.open("tallies.csv", "r");
5+
var line;
6+
while ((line = f.readLine()) !== undefined) {
7+
var parts = line.replace("\n", "").split(",");
8+
tallies.push({ date: new Date(parts[0]), name: parts[1] });
9+
}
10+
return tallies;
11+
}
12+
function saveTallies(tallies) {
13+
var f = storage.open("tallies.csv", "w");
14+
for (var _i = 0, tallies_1 = tallies; _i < tallies_1.length; _i++) {
15+
var tally = tallies_1[_i];
16+
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
17+
}
18+
}
19+
var dayEq = function (a, b) {
20+
return a.getFullYear() === b.getFullYear()
21+
&& a.getMonth() === b.getMonth()
22+
&& a.getDate() === b.getDate();
23+
};
24+
function showTallies(tallies) {
25+
var menu = {
26+
"": { title: "Tallies" },
27+
"< Back": function () { return load(); },
28+
};
29+
var today = new Date;
30+
var day;
31+
tallies.forEach(function (tally, i) {
32+
var td = tally.date;
33+
if (!dayEq(day !== null && day !== void 0 ? day : today, td)) {
34+
var s = "".concat(td.getFullYear(), "-").concat(pad2(td.getMonth() + 1), "-").concat(pad2(td.getDate()));
35+
menu[s] = function () { };
36+
day = td;
37+
}
38+
menu["".concat(tfmt(tally), ": ").concat(tally.name)] = function () { return editTally(tallies, i); };
39+
});
40+
E.showMenu(menu);
41+
}
42+
function editTally(tallies, i) {
43+
var tally = tallies[i];
44+
var onback = function () {
45+
saveTallies(tallies);
46+
E.removeListener("kill", onback);
47+
};
48+
E.on("kill", onback);
49+
var menu = {
50+
"": { title: "Edit ".concat(tally.name) },
51+
"< Back": function () {
52+
onback();
53+
showTallies(tallies);
54+
},
55+
"Name": {
56+
value: tally.name,
57+
onchange: function () {
58+
setTimeout(function () {
59+
require("textinput")
60+
.input({ text: tally.name })
61+
.then(function (text) {
62+
if (text) {
63+
tally.name = text;
64+
}
65+
editTally(tallies, i);
66+
});
67+
}, 0);
68+
},
69+
},
70+
"Time": {
71+
value: tally.date.getTime(),
72+
format: function (_tm) { return tfmt(tally); },
73+
onchange: function (v) {
74+
tally.date = new Date(v);
75+
},
76+
step: 60000,
77+
},
78+
"Delete": function () {
79+
E.showPrompt("Delete \"".concat(tally.name, "\"?"), {
80+
title: "Delete",
81+
buttons: { Yes: true, No: false },
82+
}).then(function (confirm) {
83+
if (confirm) {
84+
tallies.splice(i, 1);
85+
saveTallies(tallies);
86+
showTallies(tallies);
87+
return;
88+
}
89+
editTally(tallies, i);
90+
});
91+
},
92+
};
93+
E.showMenu(menu);
94+
}
95+
function tfmt(tally) {
96+
var d = tally.date;
97+
return "".concat(d.getHours(), ":").concat(pad2(d.getMinutes()));
98+
}
99+
var pad2 = function (s) { return ("0" + s.toFixed(0)).slice(-2); };
100+
showTallies(readTallies());

apps/tally/app.png

296 Bytes
Loading

apps/tally/app.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
const storage = require("Storage");
2+
3+
type Tally = {
4+
date: Date,
5+
name: string,
6+
};
7+
8+
function readTallies() {
9+
const tallies: Tally[] = [];
10+
const f = storage.open("tallies.csv", "r");
11+
let line;
12+
while ((line = f.readLine()) !== undefined) {
13+
const parts = line.replace("\n", "").split(",");
14+
tallies.push({ date: new Date(parts[0]), name: parts[1] });
15+
}
16+
return tallies;
17+
}
18+
19+
function saveTallies(tallies: Tally[]) {
20+
const f = storage.open("tallies.csv", "w");
21+
for(const tally of tallies){
22+
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
23+
}
24+
}
25+
26+
const dayEq = (a: Date, b: Date) =>
27+
a.getFullYear() === b.getFullYear()
28+
&& a.getMonth() === b.getMonth()
29+
&& a.getDate() === b.getDate();
30+
31+
function showTallies(tallies: Tally[]) {
32+
const menu: Menu = {
33+
"": { title: "Tallies" },
34+
"< Back": () => load(),
35+
};
36+
37+
const today = new Date;
38+
let day: undefined | Date;
39+
40+
tallies.forEach((tally, i) => {
41+
const td = tally.date;
42+
if(!dayEq(day ?? today, td)){
43+
const s = `${td.getFullYear()}-${pad2(td.getMonth() + 1)}-${pad2(td.getDate())}`;
44+
menu[s] = () => {};
45+
day = td;
46+
}
47+
48+
menu[`${tfmt(tally)}: ${tally.name}`] = () => editTally(tallies, i);
49+
});
50+
51+
E.showMenu(menu);
52+
}
53+
54+
function editTally(tallies: Tally[], i: number) {
55+
const tally = tallies[i]!;
56+
57+
const onback = () => {
58+
saveTallies(tallies);
59+
E.removeListener("kill", onback);
60+
};
61+
E.on("kill", onback);
62+
63+
const menu: Menu = {
64+
"": { title: `Edit ${tally.name}` },
65+
"< Back": () => {
66+
onback();
67+
showTallies(tallies)
68+
},
69+
"Name": {
70+
value: tally.name,
71+
onchange: () => {
72+
setTimeout(() => {
73+
require("textinput")
74+
.input({ text: tally.name })
75+
.then(text => {
76+
if (text) {
77+
tally.name = text;
78+
}
79+
editTally(tallies, i);
80+
});
81+
}, 0);
82+
},
83+
},
84+
"Time": {
85+
value: tally.date.getTime(),
86+
format: (_tm: number) => tfmt(tally),
87+
onchange: (v: number) => {
88+
tally.date = new Date(v);
89+
},
90+
step: 60000, // 1 min
91+
},
92+
"Delete": () => {
93+
E.showPrompt(`Delete "${tally.name}"?`, {
94+
title: "Delete",
95+
buttons: { Yes: true, No: false },
96+
}).then(confirm => {
97+
if (confirm) {
98+
tallies.splice(i, 1);
99+
saveTallies(tallies);
100+
showTallies(tallies);
101+
return;
102+
}
103+
104+
// need to regrab ui, can't `m.draw()`
105+
editTally(tallies, i);
106+
});
107+
},
108+
};
109+
110+
E.showMenu(menu);
111+
}
112+
113+
function tfmt(tally: Tally) {
114+
const d = tally.date;
115+
return `${d.getHours()}:${pad2(d.getMinutes())}`;
116+
}
117+
118+
const pad2 = (s: number) => ("0" + s.toFixed(0)).slice(-2);
119+
120+
showTallies(readTallies());

apps/tally/clkinfo.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
(function () {
2+
var storage = require("Storage");
3+
var tallyEntries = storage.readJSON("tallycfg.json", 1) || [];
4+
var img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==");
5+
return {
6+
name: "Tally",
7+
img: img,
8+
items: tallyEntries.map(function (ent) { return ({
9+
name: ent.name,
10+
img: img,
11+
get: function () {
12+
return { text: this.name, img: img };
13+
},
14+
run: function () {
15+
var f = storage.open("tallies.csv", "a");
16+
f.write([
17+
new Date().toISOString(),
18+
this.name,
19+
].join(",") + "\n");
20+
},
21+
show: function () { },
22+
hide: function () { },
23+
}); }),
24+
};
25+
})

apps/tally/clkinfo.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
(function() {
2+
const storage = require("Storage");
3+
const tallyEntries = storage.readJSON("tallycfg.json", 1) as TallySettings || [];
4+
5+
// transparent
6+
const img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==")
7+
// non-transparent
8+
//const img = atob("GBgBAAAAAAAAAAAAH//4P//8MAAMMAAMMBgMMBgMMBmMMBmMMZmMMZmMMZmMMZmMMAAMMAAMP//8H//4A4AAAwAAAgAAAAAAAAAA")
9+
10+
return {
11+
name: "Tally",
12+
img,
13+
items: tallyEntries.map(ent => ({
14+
name: ent.name,
15+
img,
16+
get: function() {
17+
return { text: this.name, img };
18+
},
19+
run: function() {
20+
const f = storage.open("tallies.csv", "a");
21+
f.write([
22+
new Date().toISOString(),
23+
this.name,
24+
].join(",") + "\n");
25+
},
26+
show: function(){},
27+
hide: function(){},
28+
})),
29+
};
30+
}) satisfies ClockInfoFunc

apps/tally/icon.png

760 Bytes
Loading

apps/tally/metadata.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"id": "tally",
3+
"name": "Tally Keeper",
4+
"shortName": "Tally",
5+
"version": "0.01",
6+
"description": "Add to a tally from clock info",
7+
"icon": "app.png",
8+
"tags": "clkinfo",
9+
"supports": ["BANGLEJS2"],
10+
"readme": "README.md",
11+
"storage": [
12+
{ "name": "tally.settings.js", "url": "settings.js" },
13+
{ "name": "tally.img", "url": "app-icon.js", "evaluate": true },
14+
{ "name": "tally.clkinfo.js", "url": "clkinfo.js" },
15+
{ "name": "tally.app.js", "url": "app.js" }
16+
],
17+
"data": [
18+
{ "name": "tallycfg.json" },
19+
{ "name": "tallies.csv" }
20+
]
21+
}

0 commit comments

Comments
 (0)