From a438fe0a65962f688a3c1af104a2eff8e098c86b Mon Sep 17 00:00:00 2001 From: Francois Lancelot <16709438+francoislanc@users.noreply.github.com> Date: Sun, 13 Mar 2022 16:52:39 +0100 Subject: [PATCH] Create Todo List app --- apps/todolist/ChangeLog | 1 + apps/todolist/README.md | 40 +++++++++++ apps/todolist/app-icon.js | 1 + apps/todolist/app.js | 129 ++++++++++++++++++++++++++++++++++ apps/todolist/app.png | Bin 0 -> 1833 bytes apps/todolist/metadata.json | 23 ++++++ apps/todolist/screenshot1.png | Bin 0 -> 1671 bytes apps/todolist/screenshot2.png | Bin 0 -> 2510 bytes apps/todolist/screenshot3.png | Bin 0 -> 2286 bytes 9 files changed, 194 insertions(+) create mode 100644 apps/todolist/ChangeLog create mode 100644 apps/todolist/README.md create mode 100644 apps/todolist/app-icon.js create mode 100644 apps/todolist/app.js create mode 100644 apps/todolist/app.png create mode 100644 apps/todolist/metadata.json create mode 100644 apps/todolist/screenshot1.png create mode 100644 apps/todolist/screenshot2.png create mode 100644 apps/todolist/screenshot3.png diff --git a/apps/todolist/ChangeLog b/apps/todolist/ChangeLog new file mode 100644 index 000000000..2e979ec12 --- /dev/null +++ b/apps/todolist/ChangeLog @@ -0,0 +1 @@ +0.01: Initial release \ No newline at end of file diff --git a/apps/todolist/README.md b/apps/todolist/README.md new file mode 100644 index 000000000..27c7cfb63 --- /dev/null +++ b/apps/todolist/README.md @@ -0,0 +1,40 @@ +Todo List +======== + +This is a simple Todo List application. + +![](screenshot2.png) + +The content is loaded from a JSON file. +You can mark a task as completed. + +JSON file content example: +```javascript +[ + { + name: "Pro", + children: [ + { + name: "Read doc", + done: true, + children: [], + } + ], + }, + { + name: "Pers", + children: [ + { + name: "Grocery", + children: [ + { name: "Milk", done: false, children: [] }, + { name: "Eggs", done: false, children: [] }, + { name: "Cheese", done: false, children: [] }, + ], + }, + { name: "Workout", done: false, children: [] }, + { name: "Learn Rust", done: false, children: [] }, + ], + }, +] +``` \ No newline at end of file diff --git a/apps/todolist/app-icon.js b/apps/todolist/app-icon.js new file mode 100644 index 000000000..9d9019c70 --- /dev/null +++ b/apps/todolist/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("AEURiMQCycBC6gVDDKAPBAAYXDA4gWMiUhAgUiDBYmBiUiCAMjmQQBiczBQkRFw0T/4ABC4MzkUSmYXBl4KB+QXHBYQXDAAYLFJAsRn4LDIYIXIkIXGBQQLBRYojEmIXKmIWFiQLEC5X/IwkzFwYXNABQX/C6kxXIYXR+cRj4XTkUyaIPzbYcSVIQXJFoLRC+LZEGwQvKFQIPBDgQACF5gTBkLpEX/6/Z/6/VmfyX4UiAAa/kC4UT/4yBAAZmCX5bPDX/4MEmRIJX8sv+czAAa/PAoK/rmQPDI4h3OB4bX/aJIAFkIXGOQQALTgIXGiQwNmMRCwkAgK3EABQuFGAQAOCwwAU") \ No newline at end of file diff --git a/apps/todolist/app.js b/apps/todolist/app.js new file mode 100644 index 000000000..58cd3783c --- /dev/null +++ b/apps/todolist/app.js @@ -0,0 +1,129 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// Const +let TODOLIST_FILE = "todolist.json"; +let MAX_DESCRIPTION_LEN = 14; + +// Clear todolist file +// require("Storage").erase(TODOLIST_FILE); + +let DEFAULT_TODOLIST = [ + { + name: "Pro", + children: [ + { + name: "Read doc", + done: true, + children: [], + }, + ], + }, + { + name: "Pers", + children: [ + { + name: "Grocery", + children: [ + { name: "Milk", done: false, children: [] }, + { name: "Eggs", done: false, children: [] }, + { name: "Cheese", done: false, children: [] }, + ], + }, + { name: "Workout", done: false, children: [] }, + { name: "Learn Rust", done: false, children: [] }, + ], + }, +]; + +// Load todolist +let todolist = + require("Storage").readJSON(TODOLIST_FILE, true) || DEFAULT_TODOLIST; +let menus = {}; + +function writeData() { + require("Storage").writeJSON(TODOLIST_FILE, todolist); +} + +function getChild(todolist, indexes) { + let childData = todolist; + for (let i = 0; i < indexes.length; i++) { + childData = childData[indexes[i]]; + childData = childData.children; + } + + return childData; +} + +function getName(item) { + let title = item.name.substr(0, MAX_DESCRIPTION_LEN); + return title; +} +function getParentTitle(todolist, indexes) { + let parentIndexes = indexes.slice(0, indexes.length - 1); + let lastIndex = indexes[indexes.length - 1]; + let item = getItem(todolist, parentIndexes, lastIndex); + return getName(item); +} + +function getItem(todolist, parentIndexes, index) { + let childData = getChild(todolist, parentIndexes, index); + return childData[index]; +} + +function toggleableStatus(todolist, indexes, index) { + const reminder = getItem(todolist, indexes, index); + return { + value: !!reminder.done, // !! converts undefined to false + format: (val) => (val ? "[X]" : "[-]"), + onchange: (val) => { + reminder.done = val; + writeData(); + }, + }; +} + +function showSubMenu(key) { + const sub_menu = menus[key]; + return E.showMenu(sub_menu); +} + +function createListItem(todolist, indexes, index) { + let reminder = getItem(todolist, indexes, index); + if (reminder.children.length > 0) { + let childIndexes = []; + for (let i = 0; i < indexes.length; i++) { + childIndexes.push(indexes[i]); + } + childIndexes.push(index); + createMenus(todolist, childIndexes); + return () => showSubMenu(childIndexes); + } else { + return toggleableStatus(todolist, indexes, index); + } +} + +function showMainMenu() { + const mainmenu = menus[""]; + return E.showMenu(mainmenu); +} + +function createMenus(todolist, indexes) { + const menuItem = {}; + if (indexes.length == 0) { + menuItem[""] = { title: "todolist" }; + } else { + menuItem[""] = { title: getParentTitle(todolist, indexes) }; + menuItem["< Back"] = () => + showSubMenu(indexes.slice(0, indexes.length - 1)); + } + for (let i = 0; i < getChild(todolist, indexes).length; i++) { + const item = getItem(todolist, indexes, i); + const name = getName(item); + menuItem[name] = createListItem(todolist, indexes, i); + } + menus[indexes] = menuItem; +} + +createMenus(todolist, []); +showMainMenu(); diff --git a/apps/todolist/app.png b/apps/todolist/app.png new file mode 100644 index 0000000000000000000000000000000000000000..a93fc14ad2bcf0a5d8f9686ba0203e985089c20e GIT binary patch literal 1833 zcmV+^2iEwBP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H12DV8= zK~!jg?V4*)l-C``e`oKk5)oMiq+ApeEg~(*O{ljf6LWEfQ6{Y^p{D7Sc818LmvjQn z*p5l3Hj`*=E_PxxF_Oemjb=>JO2!)PAlQ+{L~1}}xk;p4gar|I***P0K*44A<=vO~ zCC{gK&-?uU=Xv&A_nZ|>9Yknsdb)r)ZlV9A$6nDiC6!D?(pgcNbA?{M2PA)4d-t8V{bLuBOw+0;$}uf#A7mvn&Q(frQmSBnb0ZhBN_D-eNsEd2hG9 z>S$O@Mk(;H7m5=^tCvUzLevS5EbC~lI)IOE=hJ{KHgk=X@-1MdFCM`Bh4G}X$^ziS zvLjsS?80gda?Y7!b2K)#gh?q$&Prq9l0~?jE)JLe4dJ(smV$iZT<0C3{NW3;zjCN(vQrAw2>RkWEd^ zEsiHNpp)W7z#JMH!nSRjiI0!-$~%1cC=N&en6d>4cd_Yrzv9fls_5_OBWhkW$yrM= zna#JvCoWk;Uf#M}%B7T)mcGj?uj~a$s;w`$pacG_$UtaxY66e~P*n8TgyMa{7H(rr z?t_z#8-Wmlyu5W(SD&M*sv0RoK3)vyyanrZ`o#b`osP`R6rUBD%|-zFdL4?z4LMz0 z8yFalAJ-+vBRf0w%O|-QFJsng3rI;YfW=~F+BB=r3KA0+VYjzXQGSw&@{@kWk4Msy zMLyq$g^kY477`MS`fW|bN#>I~@hI-YpqCv5nB4tw7`KyB?sN=i0iG>lERVtEEDmS?CErW66K#NiRM zdGg7hX{ALKzFr4L(9qCKVc~BmSFxoI1e$E-Tth=_{_XQLTpT`pyXT(oXpvSCR2w+{ z@hOZ3Bg>Yh@cN#=j*8!~A!n4+*w{)%#lP`*d>_W?^*XY$(uj_ZoU{&A23lG!QBu4W zfO&DzG__m;;Qsqok(IS{l=sXt+c|%}UQy2DA6N31oqw3L7F7mpwlI>u^-a!x@?RS4 z&A{+azfDCy9>ZI?av2UsKhn=>s7@zXxkBA^tIB}IV&>(Seotj(HG6jN=R&=ml9I;> z4xToKmzTHB>ye3;2xt&zWF(W3k&N5zL9f3(GqNVN-Y)T=;X2UW-NTL@yE#`=t5r%x z(8Pe0k}X^Q#Qy#7vGe7k?@Gw969n4r%(R}fbZUY<6fix>Q!n# zzvy=z(CGvV7smTNMDqq!2HOAE$q)03@JJ7Pi1c(_e*&WMQFYNV)Z zff+M`dHb!GC_C^z@4S78-rhb63m+vSa?TiDaq;666+Nb?3#sWo5WpA+vRcT0WIYe% zKEUPnPGV!d-ZH5crW66sLY5%QgyO#ncr_q|bOX5EZlu4B%oM}pc8@$tYHXhI@4dHx zq#fY;bti3Y?NcUB3F;e0FZes*_$}u%UJbZJPzB%w*thTCl!^0)-rhbAA38exLGVv+ z9IrR^gFTIdK{KOl0@Ca18tCf0!uMqdeG1ClzPSGf X`~f40OX#!|00000NkvXXu0mjf51oTh literal 0 HcmV?d00001 diff --git a/apps/todolist/metadata.json b/apps/todolist/metadata.json new file mode 100644 index 000000000..0833a86bd --- /dev/null +++ b/apps/todolist/metadata.json @@ -0,0 +1,23 @@ +{ + "id": "todolist", + "name": "TodoList", + "shortName": "TodoList", + "version": "0.01", + "type": "app", + "description": "Simple Todo List", + "icon": "app.png", + "allow_emulator": true, + "tags": "tool,todo", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "storage": [ + { "name": "todolist.app.js", "url": "app.js" }, + { "name": "todolist.img", "url": "app-icon.js", "evaluate": true } + ], + "data": [{ "name": "todolist.json" }], + "screenshots": [ + { "url": "screenshot1.png" }, + { "url": "screenshot2.png" }, + { "url": "screenshot3.png" } + ] +} diff --git a/apps/todolist/screenshot1.png b/apps/todolist/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..523d60307e3e9805676205a6a9d34688ce7a3e4b GIT binary patch literal 1671 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfz8p=#WAEJ z?(N*SMYA0QSQdY;&seJC9y)`ex;p7P&*h(z2k&0EY$yNg)8n5tcK<){Gc96~#{EUmvyJD=WHdUd`y%e;(d!G?Y3{+GOY`gD%v zHI`-5f(0s=J}*yF_`vdIE|A@ny7Yi>VVVC=ljk!dR~?%qUa@z5OmozGvE{c9XXlj%$?6`yvF1SF%*{b*$6OzLp6m9Y-be69 z%}y&fmjuSf>A&wxls+|a>OSXneU<_dE)SF?HSecSuQcH4}bjPH_tTfAHP<;`|_71x7Y9@Ka)JC z&8Dp<>auzNIw&|Rh*(4w_J>{c`0(Q6nbv|e>WyD6XPnk`-oo0!(ku6UP0Q+Y0vzEF zz9vY%T$H@{xUu-5jq_LpZfyR3JI0jh{xYxg+>Qz7@8uU?<*1phWvjm=x+HV2_Y_6zlP`0uTNkFur2(+=xZshf%0NN*e>y`GCiBP763ZI340R zL6WK8-iFuUaBs1m6GNkZ5R2h6jvDSiKYm5)v;Uv>M|Otgo;jhu50)Q@UbOG2+oM-{ z67@|EIv>7k3*L8D{>YN#w^F6yz|<1S-E$7?IZ*xk*;B2(aXS|m-{_t$Ubmg|8Oy!f zL2o#JtCnuz{rTnNZqvhGc?3IH?IsmvcRl_1TJ&oMzbvOsiKWaFH--NuQ7X6Q9k|Gw zV6raSIOe@TV+Cs*zi{U^)dCg$^Cdh}k2?Mro*{0r$a2&ByT2dakgk5hu6XL`7tETFVdQ&MBb@0G(G0>Hq)$ literal 0 HcmV?d00001 diff --git a/apps/todolist/screenshot2.png b/apps/todolist/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..0337f9000378268ccf6e771ce0c46a7c5b1875f4 GIT binary patch literal 2510 zcmeHJS5%V=5)QwC1QbXVrC%U`s31taQY3&C3amhaVCX0vqM}HZ7A`F)Vhe-- zDU=9A_acY^L?H-Las@+|q7)-#vk&{WPy4)c&dhgaUcPhYoNvCl?}V}y7n2hMfk5K+ zb{AX(*zoU!iU=yDdB#@&LeVa^R-pQRg?SK2G{gRa<>ffv<;uSkrcWIbZeH1c-|p8o za-{^YeQl9jIGXDHj|a8^*^1piw|4~bPb74_hy?+rXi+u0)*!qR%-p=qB%)yboEL0c zE#lJ9`7pK3A{l%-%kSBXeQdDWW}yuJz%4{WRg0|+)a*n==tL6n$;Gu{qq?r|5HUa! zI$oCV{o1?+P2C=j>-a%w6b3YOzUWmK>xYDklljTw6TB6{DE#rs!TvQWYXNZDFzx(7 z8B_%z1lX*L=3oe*8Q=O*H|31V>O+=TeBgxl<}2%pYQAYM>o%}LbQ@+@>FkDH$FrbG zp@nc6Jbar2E&yr|*1JhZYN;#`bPq^ElL#$$H$0TEPo@#t$fJk|qO7+J+`|9y)dvnl z5HMTXm=4ExyTi9p70#A+>b7aJXS=gF7%=QpopMc~Y8uPfmu4gYjIc_jf)KcWt(qPmJiXAdBsUvEypAlf zaOGyhNaW0cPfrvB*gb{jyu;7MDvB-X?rXA4T0pjJ{D*EIpcDKX+!E*dCNY#ZDM>D3 zPA1CpTgkoQ+Aay7?YZ|@kJE{Ck@}5~3(Q!jA_!~Fd|3+!$T_loY}?@xb~3%^Wtly_ zy~%OfZZt{*uY;!?OW+*Z`4p)hbPyF|Gbviq$T{+-$${p{($C&Up=Zp}Hbji_So z6oUyA{5wzj<~~Q*oyT_44nXKU^c5v^Y{5RINL$$(n-u1THAD0t*C85q%~vJx!&;qU z$9KPJH0&0(lmfM$?m2X&-&OmMuNGld^lqMRku+n@P==>I5^dg%n}*T97PgEOL-TY6B&qF2!(!pAl-&E3AiD&hD5dcznFK&l-@#~aE z=K*R4a>7?_)scIC(uKpB(ve{EV1HV2DJ%z-@p;K}6OVeJjcvzqOe~ika1avvlBm&ZVS-_{4)|=X(eB-w@W%WFXR5&^m?2+$meG+hPQmaqO~s zN$N4HD;68ypeH;r;}C6~bXZm&0_`mYp5ZTo=sI%juG-ge;JJ|A8+ z7aq8DVlG#=`fEh5dKuM~Ip=Mi>UV2MBNvkj_0cf}{7e<}DDThN$c>2zBwI#`Pf?|Q zFOZF!X>V`GHQ91|w%c9Nyvi=k%sq!>lD>!R0Ars>x5aYjoNH1fl@4QT*fg?e9qObQ3X=r(jdltOkush(T)eEU;?<>8Y_$y4UzNiXCu&KFF|E%D za!3M>p(@nethRjXbPWP?+w!0WEq++ZK)mr1^f&sgH7zzAKw|0etqy4d;Z$9bEoz%!PUHRETVo_!8nmZ5; zJ$NS)(cbFWnFIZaTXEFyI={->kx(BPI?XMK0b+KSSMD!^b5pWEdxvhCM}6Bs2JDjV z7m-yiBYG-f)C z6{C!i;*4uao1<|vX^NhkCwQpHF0Jy#82s?Hl&>$`UpcRNg_Rnv9sN16xB4M@`xE>_O*7w7a`wZQ$szbK~x2so_Lu;}5b-#k09d>L2&6*P4VTgD2x<|H9? z&JcUUgYLGrWF9zH+gOV4mZ*8aA}#hvn5f00F%8)D<_Py$P`&S)_d0yDHF-<|}Zbx?To@iZ3atBSGU w1vskmg(J{^o0-}(fz2T<{GaT9SR)td07g`e?B&e~9yE}>HR?jWmH(}O0Ylf7a{vGU literal 0 HcmV?d00001 diff --git a/apps/todolist/screenshot3.png b/apps/todolist/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..e5a4a85acd3d4298f930359725df1de07f21175a GIT binary patch literal 2286 zcmeHJ`BT$*68+@Ma2O696jm{Eh&qHIDu>(<7$phO2mv7k0&zSz0)leHEQBEn!w6!; zXjnkdaI@wDIcC8?R2CUAtbl||E-#22i6DoA$}&H1ZPoq(`$PAu_o}<9tLs%)U-czm zbm2yD0DvwIdxW@w;y*)6VW;D0syUQ+!4=!OJQ@xlg(w8I!CLN z>n|jCi)-_rz-~qc=*zzp{g`n^xp#Nt@={vc_|L0Zkf*^VSiJ8PcC8F;nI0|*>I<~C zVMLu!Q|ZO&(v(WZe#-s2Z2*76XO0$Ja-R&k-%VZYw}QnhqTP1V z)<@)Tl;JQJsPN@fgmPg#Is8Cl(oZo@am+_li!Yu8k1T>8k?X9l_z?-6iu zM(5<4x|2XvC!exFq$jNY7GnS&@|T?8niB|j>kxHtfX2N380MJ8?h1rSyU2IT;z9TS z-eLyvKbs~hQ>ZO}r>AP-Ia77kKUk+~i4C*;?liI=7>(O^54k#x1+lE9hNk7Dn$fay zmkw1Y$34{`5{k+6%+4Qn^JzYpeYHfdV@#C;RRaa$MFuw$-8d%NF+w#x5P6VZ)s_RO{XPB}@j>UcOWioWnFt!9zm z6J{IFu(`u@m>()c@B0N3+KS)b{@h|!7(4>;>~=mCU$GLvLt8b35&iP@u5$Ke(%mg| zSJ&F?;}6@QCZ!kl!H3{<0e#J<{9YSY1lyDmrB$*eQ#PxF|I&bA+!=ux+uTB^}ahm7H*ZGf6X zZYNX$a3W&Urr`fVrJ575MYzQwmh<^fpGPIcxxj(MXE$CT)yX5}g-^c-vi#5Pwyz3L zZ@Tw=yEzFnUJ54s5gBf)(^vM+T<`$%o}nej$)*BnR#J9*5u8-gIKKA9Rte`GUsli>F0!Pc|B|C&m&`B*Jeyyh_jy9>oJo|`$CtWXI4}i*HOu&7?v5l6*oUQSOZ={g z8E1niFn^(!h?8i{<7RcmjnX8mf1Rx97#G`$lQ8D_4YUArSd7HTR!#IsW_PkubFl7P zL5G39A4)aouAqdmV$1sJ?03ftDv!6s z&6e&db}dEcTk{>8ue8`%Dx$Pc88 zdTxis5vhMouSiN@C|-0#zd653bKb>uf zm{m9GdzT5vj)i0e!d}hPHz1}*DUi6o@XklK^op~uh2FA!I90~YN<0UPCzuLO;_f&u zMT~oM^j+Zbaf>Zh0ST9bGtIsksqZ21%LpE7cy)&M?p(~8llsH2&_qI7e7zqG2)|o2 zY@gPg^xhCJ7O}b-qLqXTIYT3M^skMjFLB!SKr$#mfSQsej)FIZQCbY$8y&KwxXI}q$bep4wDpKIwTzmg$ zgYc^1p-h`4xJqzF5_p7Az2WIdI8tG-3R6u>&ZXq{ri3s3xV0ddHP+H&Wl#HK72-2d zrXa+Mw3@ zOTwDhn+EMXX3i+`NfHR~2R;P7?cq$f-$0O&@hIuLLSpk8NB_a>ka4cWMicwV553Uo z{7kh^7?ve3&iBP%Z5YNl5G7kHPf}6rk}a6E1~@)7gvFgIOySAv>b{H|2ycqDJBDUe zZ`gXdx;t+L0|OcvFW?|Pat&*oe#*2S0*GPvo0`<^S^@yF8rg4Q+cmsUK+2mlXMkT= g|1bT|4XkfIp&ff88rdGY@xTDwQNj_S7xnVL0pPJ6_5c6? literal 0 HcmV?d00001