From 06aca259cbb84c41a002e5a93735b289cc2aa93a Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 22 Nov 2023 14:38:52 +1100 Subject: [PATCH] Add basic lua browser screen --- lib/lvgl/src/extra/widgets/list/lv_list.c | 2 +- lua/assets/audio.png | Bin 623 -> 4318 bytes lua/assets/battery_20.png | Bin 617 -> 4337 bytes lua/assets/battery_40.png | Bin 617 -> 4338 bytes lua/assets/battery_60.png | Bin 618 -> 4338 bytes lua/assets/battery_80.png | Bin 622 -> 4340 bytes lua/assets/battery_empty.png | Bin 614 -> 4332 bytes lua/assets/battery_full.png | Bin 618 -> 4339 bytes lua/assets/bt.png | Bin 8502 -> 4595 bytes lua/assets/bt_conn.png | Bin 654 -> 4363 bytes lua/assets/pause.png | Bin 608 -> 4286 bytes lua/assets/play.png | Bin 616 -> 4309 bytes lua/browser.lua | 113 ++++++++++++++++++++++ lua/main_menu.lua | 8 ++ lua/widgets.lua | 13 +-- src/database/database.cpp | 12 ++- src/database/include/database.hpp | 1 + src/lua/lua_database.cpp | 77 ++++++++++----- src/ui/ui_fsm.cpp | 15 ++- 19 files changed, 199 insertions(+), 42 deletions(-) create mode 100644 lua/browser.lua diff --git a/lib/lvgl/src/extra/widgets/list/lv_list.c b/lib/lvgl/src/extra/widgets/list/lv_list.c index 29355fd3..1d58615f 100644 --- a/lib/lvgl/src/extra/widgets/list/lv_list.c +++ b/lib/lvgl/src/extra/widgets/list/lv_list.c @@ -91,7 +91,7 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) if(txt) { lv_obj_t * label = lv_label_create(obj); lv_label_set_text(label, txt); - lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_label_set_long_mode(label, LV_LABEL_LONG_DOT); lv_obj_set_flex_grow(label, 1); } diff --git a/lua/assets/audio.png b/lua/assets/audio.png index b8ad90717d7f7ddf66b217d4507c9e4614216320..6151307fa7ae71cbc1eb19119919f802c85b17e9 100644 GIT binary patch literal 4318 zcmeHKe{dAl9Y4~NABVY=A4!0bX5CaFmA(COw|BQYxt!tdAV)Ynk`ogP)9jCTmu+%C z*xTeT!J;6hxyEQHWEd?i3P{?f#3B`_IBU*eZHUf{eIr}y?HO`Te&P#KVPrY=`uYft}^&Gs84z-{Ld@F-hr>njs6Oy zjEf^tITDa+0irZS0Rj?IK&MNbX~ zr8T7)zPxlj-O*99rHb6{FGrgn=sa09Xa0-IU&Xaqr*97|{9)ieT|sz3xcx@k%>4SE z#@R=%2Jf9}D}L?xe94cG_cisfyZxmbo;bMg+BP}w z-Ngm>98V1`VLJ4O(<^(64sE@-fBEIdKd!j=edFNr?C7u7R%SeODz()9)X%>#L1Iu46 zE<8|4+diB9i;7jNlP8i3y{{nu%6~6=`-isNJ983&z7-tB zd}ig1CB2~i-#Nj3YlMC4ujZ!4ZoW;uCq0R7bT2O6ls=u_=3AOQ^P#%3#e1q9SI*_F zyEW_OIdc17`u0DnH}^f6cPnc{yyn90@^BepP#_bw(9Gp=>L z{Mt)jth=e(^ZU+EGNaM-Cvq39KYRYH{Wq`OUcdL$hgoMnko(WR>6;DMnoM&`oaVY2|_^OkVL399Agu9RO4mgw`#^wM1v?bcC^ClL!1#AAZDZ4NMP=S zR8OHrdZbVm18kXV=`aOs+0kl6iLy8zkH?L1lQAL(agt#eoS<-u!XN^RHG~x|frVrF zD#Z|o3&aFjiYihhjHsL(AE{I9C<^VYS?C{7v)JQTvmd&CrX zJtP?p=o>v^ez>0TG7yW@$pUcKgRqi6oEHJz6^B1A*?Nyc5tPxocpE@_JcUM5t54^SJD&IzB5# z1W9DIPnr|Wq>VITfHGS#Ghi5up$Q5j8QN;0NQ=oLFyp8^;h4gO1)x$va-#%!I6zP$ z;AqT7^CD)Z86M+F-i8INHVe-QCXq7p<0$TzC0LbQ?f9rvDiKnNG(~bIp2ldB3}9xf zMZjznAz-|TGn;J;#f!FpMkNaD(uf@5;B-nME(q{wIH+}~g0sawj~%6q#F)ib%P9fq zU`JO-;kv|FhhGYTa)ndXB&`GiQzmJ%m82PqWel_$$T3)nDkn)8O=hh}ofZ}*1BK<( zI)wz99p=J1Wxy#B*&m72+EFzmMD-l)_QK^Pati0-6aYyH%EXc+OHqE(#F}ZAHs1@I z#5jCJlmZRkhE^93QaCi_B~lEI-=LX>R#Z7yH`E$x)=Jt^LJ)0Hu$(ZILX4{iq82CQ z8tM|Nxo{A`-D9|1N9@u!lmbH#LO?W`FNfpi+ofO*nsUK$SI1W!2lM77J;Y!^^5HWnI<{0l UbA}i_3Q2Sx_exjSlB!Mr11IGQh5!Hn delta 537 zcmV+!0_OeRA@2l`BYy#eX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmKpe$i(~3n}9PA*{ zAz*c~AS&XhRVYG*P%E_RU~=gfG-*guTpR`0f`cE6RR`&;D3Vyj5+sOF zP(v9N*of1rlYe3%P5TKC|4_>>kxL<08H^kYs6vC>@`L}u?{2Na*OOt32C~jFvL_t(2&%IJP4!|%7i!J{D<3OfLsG$ik)Dr^CWngAD z8jw>Ez~+1UNS2W97;WGSay0QjQ8G! diff --git a/lua/assets/battery_20.png b/lua/assets/battery_20.png index 9012376f49e7db949b9e8520c09efa4e30e89c32..3a70239760c259551e5786154dc3837573923f17 100644 GIT binary patch literal 4337 zcmeHKdvp_38c)kYYox6RrBz`WQ(fw@lX+y4X2yhAl0bumrVrX8aO`B}CYf!L37Kh= zw!1113q7r@2%KHPl@+PW(zS{%$V-ZLfx3HkK|BbHa>}#l>H;bcVOhI(CT(etp5y5` z`d@RB%-nl_-|v3k@B8jO_cnRv%uLhXtJP>UX|6&?34D%KeyL;Ne|gP<3-EEVzN}I% zVPi-nD*A*VK;*gzKtNpZX*BT@&lb-M@5fVbU4N+lXC`dY!MgWX*Dw8f$N2lEx?5*C z$wp!^`~1q+55;bp-RmCs`?gH%nW~ZFe#5d1XI89#ZtkZ$H#oYnFF(jFD!{7Fx0UU4rGp3KbJyoxwQQMe?rfel z{r-$Ds?&eW$57zUkO>Sa)FQ*(dkxzP_U&CG}bI!#}rY|KYQ_hP5l2 zU-)86cHB9o5vfWpeqr8$7aw@=G`;uY>9e0NT;{La@L%al8{M2VZI$`J*tcfwDX_dX z&uG3hetBhadDEe$sqS6KmpR8Wf7@-&nlv%)>ze(?o+kTWy)Q3ao9=U#=DhTa^tN?# zZcIM_)_y(F|JnlXwT7><#z;5+MjjJZ>J~fm3YMgfHm>o^$Q<{0O-bISfbHVxDT{91 zy>miz?Y^$9Piv{Jl~ZnIJQ=G#|4M1N1W%Vcj$b>Neb@2P>uNs!cG~v;^xSdksWI(W zws#!S_-wA%-`;k49R5byf(36ILB@_xk{UOR{nwhw?-!MJU08hGaP!qXJbveu_MPu+ zySC`2X49YA&ZR{nsV!N#4JXf@wEq5`|24dNv^(R(C(*+v_j^Xe3XKb}5-Z)a8BPr8 zSzh!4eLNI_C92U_Z1D)oRRbCE0>2Qp>Mrf>&>;eE)m0eXxI1D80im!y3QFtelyUXd z9L?)&)3la20|`PvW|4R(7?zm0Rj2YY@LlP~bchO(tF5|9w+FF{QGif-N{^$?xKK;# zrfCsNl=m?ujv0Lvuw~T+WI4iMSS%LP#|(Ng>clJHct4;^Uk$(R|5x0AQJ}mXA0QJD)Yy>0pI2H02QWku-#Tw$9GNOhv*b!(xz&ixpAG->MD7Tw&h+K{0p37m?Df2VD$O$~7 zz7ibgB`A=O5(bV%DI-Opw21&H4!j&;%Fm|^27C~eD=f)um;(wGB-aa&$43za&l?S> zk0p&LMH2ZaZ8nf7@R0;>!YP_0`9Ty#Q2|yZ8yxJFLd8QWn&yr0YeG3d(kSIM8&Dc2 z3DiUyz4<1ZC44?krQ$heh8PX8Fr7k(^#d#t_NxPm;7ozXWz~`TgyU+DC&21C>J$>F z7BCjZ9tEr{M$1GoXw@kWAd2O{up2HXo|Rb#D+5T1lLm$$7?La_3=CytjP%2>i4Vey zyx^<*A+)l15KAKEg@Od&JWct`stN<_lIW9TY!npu zp^i{1Se~j@NUoZwhlZkK0ia|73WgE{`dz`WzJM`h&*+cXf_+C5iwYRD$w0eAAKbj) zUWg5BhJBhre}BqPUoL*iDG+32l40pPBG-sq!%|>a;F0PYk!x5A3=2F`T|b&!+S}JD z5Qe9q7`!aKxAMLayl9Q_J~q>#Ub!?k?7N?WZ+Aor=SdokK1cZ_#anH)uroz=xt%E& z?wpv6K2q^~w_AfdA`&$E!-&+1=@%gQ}Gm?6Hdk=b+SB%<~J$_VEmE)IH1zB&HH#gqhGIetJ?6J$e kmqL3?ceMzCVCT^!P0PmFoF>Hq)$ delta 541 zcmV+&0^wkN+e{}DVt+QbD)zo2h$sRGV_0UE zF(*kWc#f}o`1pDk=ULw8{v2U7Z!y3p63;Tjw23!}r#Eeb^FDEem1LFpoOsNn3lcwa zU2*x1bFsw&&y1Lv^gMBdSS)t2(#5P~YQ$5-F;&wkU&y+wa^B*sRcfq#PyWJCUSC<} zI?X7OSi}+}h<{K}Lm3s=h|{W*Vj)fY2@n5J%P)~jAy*lU91EyIgWU3i|H1EWt-|Dl zn-od_Jui;)F#`1N0?oSPd>=bb^91le16O*-Uu^(0pQP72TI>ku-v%zOJDRcwTt+~Cm_i_3FWT>mu4I6N92#gjfd)?#R!S3GvJ=5;* z2Ti_mm_%RHXp=z@9|;H?1UCSBBr24XX%HxAQ%OWYR2b7^{QK`O0}QY*v;6=6pMima zk&*Gw-#>71CS(;5X+}my1_lOZCT4^b0}?>i4bg*c5*{#Q6`=%y^lZE00000NkvXXu0mjf*|qKG diff --git a/lua/assets/battery_40.png b/lua/assets/battery_40.png index 88a0b448840e7e34806d8cb94c7578bbd41d0096..ae7e3d7bed00ac6d9a3ab36690c17a8e85449ed2 100644 GIT binary patch literal 4338 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 FV1k;x`APr) diff --git a/lua/assets/battery_60.png b/lua/assets/battery_60.png index d86c997ade94b64ee3bfdfd1ae6ed46a3f9a51b3..44ba795403ebd316bc21b15a79a62bdd9af40cdb 100644 GIT binary patch literal 4338 zcmeHKeNYtV8DB)cPQj##Tui7ti&|~i+mHL;ZikbQyHl=udK?7NlGOdWV*_`4+%DV! zsS$Kk24xy5)0ojFTC_1VB*rNCk&x7iv@=G>)M`>}v_@?wO|+>+p(uTKkIzYFI?Ocx zaWi|n@AE#-?|Giz^Stl8Z-aZ)@?_0C4Fo~S&OEyZyk{y;Vm$aSsw}w$Ubkxsi)9ZT zhJzu|E0puFTpi?LJ|cJ_DDvr!{2w=+!V?GYEvcFQ+@Z4-yBD?e#n%q*xoj4G_{_Qm ztai3`kudb2djA>Pv+xto^L@LMya8Qu?tZ%L-pW5cc-zSYtp4IIv&-uno8$yQePR``V-TRb_B$Hm?tb{)MB&pS9hqw#Ege&4!4n_oI2{F^%9 z_`3O+_GD5^b9zPUJJYNkoBsC2lD|BT+Ro2@xj!>C*!=9;q~|Wiudp^fAN$drea-Hk zbn@(-)?+hP-*0&hy7~Q0^Y$?Bmr26i(+>|94aD~9!pX1Kcdmz^n9YLC=62d_BdLRg zcmMPyYu>4+o;dxJg8lna6B@Ufxz|&ev?u>s+~(e_*;`b4@x#wAV5Jv+_HL(H(;kkUB?ZZhc~$ai@D(>Z9u_J(;bgIbU6yUorT- zV{<|+AM_mBs4?_3%^#e#AzXIjR|NqNo+5W$?mMG>i=WNLlk;|+|vC9qH#1Ib~bOs%cIwC?9i7eH? z*&)tLdF;!EA;8Frl*)3D!mw~StPAUPV#tRP7K;VLNsJ^>pn*!&0hx}V0VzX)h+^1z zi46%sSr7xTf=M%CrEEnIFb|K!=MTDEqwoP~m<7NG7NLU}p~Er19~*BW$&M-jG91vi zT1bUpMPnXb5-US2@2KJfa>jTFjvciRR))&ebT}5{%XvRgm4H`bg3IMjmwVJgp};5j zgQ^uEdxEAcc*n?^5SucirZYYeU_OdFL3<>3RT*fxT$Ej8E0yq^b}ORzr#O)nI7jZ$qup~_w*(}t^ zTa2hd&sk8~Xkk&tZ1L(XX41lC5#u0MhXl}-bouzG6etcr(FCDqEP4ZK$YMCuU;-#+ zBg3Gy2{)Q~qmk5GqS0_HwM-28X;4nVPy2W*81Sh+6vC-ox6_J{I($sxE~jNLFt8#k zg+OIwY@$%`^93@kut{X$xQQePlLWoqr3M2!FrIkJf z0ID41LfJw*EsLQ-Q7pG2N=UF`IXdkE%Za09+D^+n0L4i?MGzE877}{OV4`r-lVFIC z(-%3xTm8SZmBj;RM@yb3NWg!!DvGYC0=^Qd5x(h8?Nw{Y<}cKuVa z+qZ8YdQ7W*sK@cat?%UDIJ9_K%+S!#8TZyTvB$NuV;eU1%_}}1mzna$-p>BkQ(x9q oT^Q=>I9L|@;mcdPO(p4&_sX2U-)?BW3Sc3pW0k%A>Gk#h1r7Wi1^@s6 delta 568 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 delta 546 zcmV+-0^R-eA?^f_8Gix*007w+%dh|d0fcEoLr_UWLm+T+Z)Rz1WdHyuk$sUpNW(xJ z#b48kMOqx}AkraVb+RBT;;2<9LWNK(wCZ4T=@&FwkN+e{}DVt+QbD)zo2h$sRGV_0UE zF(*kWc#f}o`1pDk=ULw8{v2U7Z!y3p63;Tjw23!}r#Eeb^FDEem1LFpoOsNn3lcwa zU2*x1bFsw&&y1Lv^gMBdSS)t2(#5P~YQ$5-F;&wkU&y+wa^B*sRcfq#PyWJCUSC<} zI?X7OSi}+}h<{K}Lm3s=h|{W*Vj)fY2@n5J%P)~jAy*lU91EyIgWU3i|H1EWt-|Dl zn-od_Jui;)F#`1N0?oSPd>=bb^91le16O*-Uu^(0pQP72TI>ku-v%zOJDRcwTt+~Cm_i_3FWT>mu4I6N92#gjfd)?#R!S3GvJ=5;* z2Ti_mm_%RHXp=z@9|;H?1U3)zfCfa9X%HxFSV=@dR2b7^{QK`O0}QY*v;6=6pMima zk&*Gw-#>71CS(;5X+}my1_lOZCT4^b0}?>i4bg*c5*~nJlJ#Lttcr*-iOz~p9RC0B kZSqZGghvZ<=%Ixz08lv=B%$qnZvX%Q07*qoM6N<$f>eR?{{R30 diff --git a/lua/assets/battery_empty.png b/lua/assets/battery_empty.png index c9176e8c7e739612ac63fdac98fd6b0bf4d1ad41..5f3bfdbc1422ae38a327986027bb02911ce5e563 100644 GIT binary patch literal 4332 zcmeHKYj6|S6_z1>32X=yY!Vo@YoHKV?L+UaWnm;4t3^bX9WcZ#UhUqMHny~~c5TUa zngrtkTmwT=+!V%1O29OU8xx>_!6dYk2GdT{P$&%~&_D^$PEw#LF@&19cUOK+GSl%) z^Us=D?cVeF&N<&b_s+dd-sMX(v=3=D8cl|~(CLHkiOQ3f0{>T3mtBXi8+9e6vX6-& zk*LTEl>m`zBLD$$f!Ao_A8amqe9PNJTJN0&br1Y--@8?<^ICdR>U&=}XAvHGZ1o&A zcXIYTq3?ceTQ}pId*1g%Pis0K)@9_kF%@@~{pJ1}feTM|pV>Zn@sA(xJ~Q{$EQ^23 z;qJ*VejeDB*7@z#9nOlidt*;-UhlI%oIL(2x&6>xXA!xy7o^w_FBeI>t>!!X}#>4 zyL0PzxgGUOx^6YDN!OO&AYb{@f@@u-=L^<+YOiRse^?Nku;$`hH#M51M#16mx*d*z z%3-~&KYG?y`1azN@2n|qdwE)F^F|BzN~S++;onNzy^Y$PD}rZ#^YLjsczWxvIxX6c z1)|>*X;F3`M9F(t4_4enS0s#){Vt*cg^`B*>NcVnEy)SG**SZ$vH>4#Sw|NVuJ-E8sw`h0Je&h1& zs@^F_z7=ix^~rtDXbmT~%*>y(d@gxM^@m^P9s1|B^h-~t zblg64{IrI*yZ0VGcH%>!<5Re%p9;ysWblirjxHSA$#5jtmCUS)hE%kU2hZqHjL1)krm@6*S zP-vbO$&GS6?Q<6NL%@*@4a#za#_?DzriFs4A(y&6-a!wA zf`AZ;s9uol5tg#R50Nz@H$|hCGdvOKK8QQQdZ2dI7+QHev{PiOmGs+;oIgu4O zTKzN|4Xl;Wa~NYZkeI;)Sj@t4R?N&8d9#USIHT1v49XprWG2i41qy=e1c*cN3}N6I z3r3p#9A*F}GsgH0ddy2Yl+qDH5^p6V^U%SD zE)&Al@gYTt5CX+Aqp(Su3Bp8?q*-q!DZ*$NGFkzm66{0;lO%NdghrVb8WsbIWt2XJ z0ICP9g?2;%Ba6`zQLMC~N=k_0IjHu)<-{>E<78w2K?zDvlO#=1C8VA<~lBsa&HT76FIE1UZN(hsBj^Gqa#kf!mp1GXFiceDU~A zn>O{$$j<&!PY}Hu_7`2iZ hhm-~~V{@pJ*0gV(GOI3FmIo0vZr5^W$CC1f{{myf6nX#v delta 538 zcmV+#0_FYeA?5^-8Gix*007w+%dh|d0fcEoLr_UWLm+T+Z)Rz1WdHyuk$sUpNW(xJ z#b48kMOqx}AkraVb+RBT;;2<9LWNK(wCZ4T=@&FwkN+e{}DVt+QbD)zo2h$sRGV_0UE zF(*kWc#f}o`1pDk=ULw8{v2U7Z!y3p63;Tjw23!}r#Eeb^FDEem1LFpoOsNn3lcwa zU2*x1bFsw&&y1Lv^gMBdSS)t2(#5P~YQ$5-F;&wkU&y+wa^B*sRcfq#PyWJCUSC<} zI?X7OSi}+}h<{K}Lm3s=h|{W*Vj)fY2@n5J%P)~jAy*lU91EyIgWU3i|H1EWt-|Dl zn-od_Jui;)F#`1N0?oSPd>=bb^91le16O*-Uu^(0pQP72TI>ku-v%zOJDRcwTt+~Cm_i_3FWT>mu4I6N92#gjfd)?#R!S3GvJ=5;* z2Ti_mm_%RHXp=z@9|;H?1T`dd5v<3PX%Hx7P)S5VR2b96kt-H}Fbo7|n_dRR{qNQg zL?3OaK!9Ln_9G_p!?{$gMg$B^m!0-y6^i>|=ewZ^Jyse*|k z;Ydgj{Q!{~!TUsIJMVvlw;Z&}0 zY<8a5d#_M#G7k&OwTCZ%+%hVbMoF>-m^dL`f$V8nLmH3YkS#+ABW$c zd_Bi5pWL)ocVU%p&-iW0`#-&5%qhF$pOC)3i$C+(3Say9)&kS$lEqK#-?sBFC$_d- zeNnh^#QMm-QJ24*SU2vSbla{Kf4e$uhk4y2{Ilu~&r0p)`Mwi}K0l86jz9PN-4<nEPGiM((MJzdCQpnmkDsy63$9#Txtj?B*41nS!%2_t$xu z9WTwjGwUd5``0Azwnf~wrhjIoMDPBIJSDEvEq4|aH>V{V*LzAPj$0V3C}{T;UAs7? zu4nw736Zvg-ES|`Qr+vO^o)5XUVHhq%3uYaDIGX{t1El#>ExGUpL{)I=Rdv}bzx~r z=gpl5j%$P>*Y9@i_-Y*fR>q=5yNqDW?z2g&Hl=^O{)c~jvamto){Pm(JN))VK)oH-jgcJ7EL8CIw)!b+@m&!M?c zK+o_Y7U<Ax=)G3Sg zq;7^5DU9#}UEwI{qkw-lolla&G=|0FaedsN4@JBfVYON@oWw{Hg$Oj-5R@1h4MuYn ziUfxPM7f9v`+=72PQLNjL_p)Ab<__h)T|S zNYWS3w|YdY;Dp91Kr|GKaKKp)f>Q2a3Z5JA562>YH65PAfFA@PGzxnqhIBdG<@OAC zC=z(ZKv?yHVh=$|qHtfVA+aefYC3}hf$jsmL(u)Xt6+$7yJ<&=iz(r`95$WOKh1|Y zk*C#9ilYR0@hD-k;wWV@3Mgx#2$Zq1JfJKl6J@~%QMrOqi3xH*p@QUk5%K_mpn#F! zQJyrgC}kxHlm&2Xfe8p^tAR8MfE+~eWJH8j$@m9HrBLw-6>DYG!Ts9r4PXw-7Jbp$Jpo2{} zM-0Z~`_L*e04gO$QIjy^xQQePv&n2UP?X_5Xg-KUVI?Y@1gZG6r zaXu#K1#tD~E7yLz_${SivXW+2AV`#B0fSOz+=5y-_+TxBku^}P84%1+_Gn0u;!Fe- zd!dd{D_EYYR!F`&P}7E@<36B_0u&4-2=tqRVSNc>%9_!iaUu2%O$t@OphX7yC2Vl< zf@>i*uo(7frYt+(Kc)2SPBdaJW^f%H@UR; zk5eEBcR_J@SW4ejvH>2nQrIVEJJchW=8k>uQusA0Tv`*=X!NnyY zUKu^<0sYux55}%R)5DUpTC#@%%C20aZWaNL#6`)6D4WFv%QLee$nA0zSLJ`eEt&aX zYin!o!`azi8*sem*>}n>znx!_)Z5!TyS%Hp^I*@i>Du1*!+{s`Qj{w%W&EMlA1xdA nW^eDOTRSrz;&O663CA?{_6gThfARV$NUU)==Q=uPEouHA`1cwa delta 542 zcmV+(0^$AhA?gH>8Gix*007w+%dh|d0fcEoLr_UWLm+T+Z)Rz1WdHyuk$sUpNW(xJ z#b48kMOqx}AkraVb+RBT;;2<9LWNK(wCZ4T=@&FwkN+e{}DVt+QbD)zo2h$sRGV_0UE zF(*kWc#f}o`1pDk=ULw8{v2U7Z!y3p63;Tjw23!}r#Eeb^FDEem1LFpoOsNn3lcwa zU2*x1bFsw&&y1Lv^gMBdSS)t2(#5P~YQ$5-F;&wkU&y+wa^B*sRcfq#PyWJCUSC<} zI?X7OSi}+}h<{K}Lm3s=h|{W*Vj)fY2@n5J%P)~jAy*lU91EyIgWU3i|H1EWt-|Dl zn-od_Jui;)F#`1N0?oSPd>=bb^91le16O*-Uu^(0pQP72TI>ku-v%zOJDRcwTt+~Cm_i_3FWT>mu4I6N92#gjfd)?#R!S3GvJ=5;* z2Ti_mm_%RHXp=z@9|;H?1T{4tp^P71CS(;5X+}my1_lOZCT4^b0}?PlpbBT7bhwShBs^fqDnbc@|9@|jZxSOs gS|A~g4B#;X0P>d<`z9c}z5oCK07*qoM6N<$g6uKw(*OVf diff --git a/lua/assets/bt.png b/lua/assets/bt.png index 180e6b3a64257ee98e22fcb148beb174089ec3ae..73f3179f552c5a8e157fe3f31575d92a7f95e1a9 100644 GIT binary patch delta 1072 zcmdny^jUd=ay`S_s*s41pu}>8f};Gi%$!t(lFEWqh1817GzNx>TfKqNc}Em@{yZ14 zZHi~Ck@*y{()`Bb_bf7(LRN)%OH}8aFRt4KTHv;0}7^O2;5 z%~Sc(T!WS8sqw9z<@eL+SnAZzV(DvRlGj#$5@##^b;{^^W}i}{tBzw62dn9n05?&= zsL~*vB^mbb9?BQ~5!xwIH1)uVjSXBTC;H_7@YmOsXFpvWoEK!kSF-=cx8o85H&|zt z-u`E|?d>zp2lZ_0zHHlni6PD2bN%+M9|R3H@W#Y!H%;Z=afh*OKF`f5vM2q6Pdsn@ zZv1PRjzII!F?$H2N z1_r*EOkmoJ*sLzx%A{hEm}s7Cn4GGcmS}9IYm$~|qHCF&YOZT$YLQ}|mS$*fVV*eo zf@l}3Pi9_e#pDDrF->y=12ZE-Lvu@W6H`kg10^m61qF9c-vFzy)S}|d{5)GFBRxX{ zJ!6x}^TjM;K(ZCN1y;VPC5b7CC5bMHC8PcD^^$qfn`^;w=Sjv*T7 z=LQAxIT*6sj+vQUkoLRkWOD5EGv}8Cixis#Uwsqda;EQO=aY9PGdK9VO>;bRhHIu! zpu!=wti|lJZklOWZteK9`dIzZ$;XULL(iVMbMO3e(ZFnu#jgv#?{+H*%b1latH1qM Z4)@Y3KcW6aB^>EX>4U6ba`-PAZ2)IW&i+q+O3-DmE$@N zh5s{(34!|(4%c%gg9(2=kdn);z5Bg#wND_ur-d!(T`)D<4vhB}UDk zFTU8yN!I7D?RTU7em{TnI-1w(>hXo;lH=&k$6_BpG<>Jc^?$islbHMd$3WMKshowk zFKWH6x7X|K8qntV16>k0b7t1#`oT4jvzJ8veD0S-vE=l!w9&7b{dFn7{r4`}7@|p@ zcW-q{v2dQP_6dCs5p;E1_CVn%^l{<-eBWx3$xdgS=H0nVN+1m^I11H%gZdATyeu?z|l8`yt5Bk%$~OF>AJ~!C_N0fTEk$1r@wxw-`=>E_>wU?KXip$ zR=g7_w88vx;5KYv)}_?26@0(m|A}2477Sa>nFUte)ES}$^9C-r4ehuwa6CpfXmLJlR==%RRDj44WZuE`~zLW(J+tWrreyX6<1O#ud?dHYL{6*y#Byy=CYdImXaIO z!)jbj=^nyJI0<4iEM~pI;0dc?F@P;L)7f}$#d2aZ@)2GUEJ6k`&M;yzEa<1PVVQ^R zE`Q4@TmK!qsg$?f>_4@f64U+Cav$yXnbn45iM}m%+)$LN9p1Onsy6eF^!wFuk=GVV zUr5m^!$}C8eymkZsVi|wzus_t&2PDZna4er`e8EH!phOfPciN2GE`}4O>`YtT$lm$ z^|aK)3a#upmWx{^J!~6cez%m5NA=kkwtvKCT*nx=_!`~Y(PGGTRA3QNB)O~l?D}fR zC&A1nRVMd}Jh~vT*Q60XWi%A>rJWXzc1l0mA!{$P4Ad#h=gFMQD2eCVx3we}i@%Jh zL-)&$5qfXQ5R7I4k#^33&TRM7m+8g?RZpu>8iAKC0Ji}&vI`h<4KaGp76Y~7l79(( z8k6(%32f=wLq(X5xC{Cbw}#b@5!~gHI1NaBo@NG z+nSxBU?V*Q9LCEqeR4E%YOZ4#!>$n9Br8q?vFLT#O;BVF79;qglj$luI9nat@YydM z1$}vA<#W%*$Z-+hJAi@I4ZLwp=YO#S-qVO55!4VcFn@_NI((RkoGHP=8pxKbhJ*|$ z+m(|nF9zVXW?R-AwDpkMcnGiFR`Js@hS^%3*d{0RjTPr~1p}s{y;uC##zFJSM5#oy zI@3Xi#2l9CW~<1A{rtXeF<34eQPz%tyWoFzDZEDGF@7=LB%svPy&u-{yMNpUZvqd3 zoa?9xHF)2(?bYkP`WO!2IxA38LcQhW>DVyx&f)}}nuLICS%!&2bdHIq-f$>ppmsTH zQ2~K!M+LK^#%ri$!F~?WRp8RsIFKVQ9UJDn;S};DG!WW?%!Wi`^`jMgoL)xaY9NS~ z<>T-(Lb)*es3EtAhE1`7P=D#oq%KI2xLz^8gM_8C4AE(G*D{(c;|ZBkOLxvmrYNEgJt4aikz-OEYyI8tr|>a-)?h_b%RwD{VKb+K)$ z2-T`@vl+5_%h~BXQywt{J#g7bHY+Q!-YKCtwWW{K?syZ@jyLW&s(<{$w|*BM9TI^n z^&VIcT!CXativmOs4bpg+{1AXGg~h&!C1YY<_Vd?rj>{2zUZxCZ}J%kRu`08J+^K(5NC5ew3^18 zwMnq-4KJvDvSd4mmw%;kF%i%`IlxMqj}R829A2g2VH?}n)~&iDpIKoG-*w#5pd75B z&52P^g?)8<4lJFtZU!+s;R6Y~ff(YECOS=sejT9pP!1CzNvlSWOAs7t`P2;RYdc&J z*;2e9r0!(z-!LQ)QvU{qHX#2E3~^j4wxO4IgtCa7gf>fx2QMp=Q<{ zCg8a8Jb$IfwirySPQqO1_>ls#xDV?he&(1mplB8bLU~q$7vvP_Sxi_hCappc3vu)V zkx;@UE+WxdIGGmqaAjKNJeiiDvcJpRRsG7w;Txs}qV}4DIaDW@0{Z5Oq;*pRX4lm< z>7`Li-2|m{PKCsOF_n6n>*6XWmkV3jsl4x0E`Pr4zjI}UFJpd4#RRs^_e`D{6dl5q zM9`i+Ndc*WIKb-Uj6=#;PDijQhD!}L!X-@Xau8mQ-911mCfnLmgWeLeS}qTkvYA)C z(^@7o00L!H?cfgdQ`r?%@ zs}o*1$KjPqC^!y2j@B~uzT{enVh+~((z_QXo(++yCQ7AF;A8OmKAxyYu7f`GR8HX} z(1?AVstFOU=nsS4vEOqXTcRn71@%t@eScDdgT7rCOYrVj1@3nGDkqC#X;^`=lRTtc z%!CQFJH{%`!etw)k^&N!3&G=l1oG^5VGz9JCSgbzOguSD9b2^ZQbJ(YK61(}k#GrP z(d{B~QX5e45%^rMl7Y10vvp7y@t#p%m!Ni#rRZ8hv6!^LqOr{kE0yFrNFmV&*MFk) z>tU>5NVm3}LJzG_ zL$`@U(|Fr(Y3YMo$p-OTE1V>{yAxBrn4z8a#1`l3PV}ogVRnDRe?^qK`e*3*hG+jR z-&P+9O8Fr6Z=_bg5&JioSMxh7>Sv66 zAk{BaPPDpH_9vwJ)h&LBZS_0Bf0kRh?fI}hGiwshpS;Kl1l5A)FKSm5D-B=ituf=n z^PzRy^YtkqAo$z!gA_~B*paGNDENrPJqdeybckC`C+yWKjUIEtUWPnT!GC2KkxK0k zbR+~85@&>FQI1nsSmGj%le}sqJ5Sz#QTXg^4+JT~D4Abe;@eV78l$ABvqp8;+K`sY zUZXI(&<(MuOiOne6VfCm@@NK#@CRu*s5X-7qB2S$g1ZrXxWf`dQ+p zpQK+D>e6HWt9vHfBeH$7yMJe*Y|<`T;+i38m%2siyp~;09mHP!qlKu2nZhjWOQ=yF zVhtpt`LP)+>bB!bKGHY6laJ77^6iU!>Q%tE_THQ#XG5IfQKpHBtWxX&SX;?W5&?Q| z0Ipy6LW(-jz&niwajo)v$j`ltt~HB!@K0l-5Q`x-*a|Q-9|vO5iz7E_;p7LO4shq_WD>+NT5dC{&`v$ z2dL^Rr2Z*T)mKRU6sV9g_^gYvSKWkqz*MJ)r_G>xg*Ko;0|JtGAU^=c^^>;ZyCY$3 z+H}ZgJdG&y){c6id4ENyUQgeYSI;fW;n2d$xhNougP0f&SEaDG5IwuOY5{@NBaZOY zY9dy|u)EdFbBZ15FyU9y+flpPDOa_V4CR>_DGnrZl^Rwy)lKh&CNKNCR?0OYm`CwtLBecmv=%be0bHs#;-0g!Wj|GRlKk`;yOvYCA7{VYpX!VLr+cz2Sl(v6jVkJn zlZXTL_qj>2x}rKID~|3LNqm>APM!`ahx<#%xA*$mPMZJZw_YKl6xRtioruceEWjaN3+g4(oympTr*BM?0!t$rhL*%L3 z9sN$?S#~lBxS2Y@4(dZY$O==M-)(B@N@`?Ef<~cPf{M5n$wIT*5yu(Oo4aom-Q71T zyKiK~Yd^N+hl%Ry$b*d2$l#ZhA=q~}=oWQe2Zhu#xqtRR_6HX58EIS9&FODwsP~P~ zuX;y6K}7vkBlHu9sBb%PUp3(F_S@BblU1nGef!XR`{UM|`lmp=ai~749NNL6)d!1& zqK!pK@~2lXPaeh7+mU`f1YE+17HZJr>7sm7a}Xbrabx&CUdEd*kbFv*^gFGs=pQ{lpJK1QisvUpYI}XOgEqK;Ywz)&E z9(QMMhu_ng+uPN7Cn$4m6M2;&MF(``rR|lw6CHC;WDZBb<7jsqh*V4Yj<6KkvaN|j zxO%TZ{g6)YBNXnrr6YyaZtC1Eouz~}gHxhz2Y-TS5F+77Suqc3gP znUoEV=kA*{qGXG&2pB_qyK^_k(!JBiz1+A^dXQOrlh#o48P2db*``x`F+4i4a0uCC zLtEw10sXeGPQ^z4Dy~*f+EcM6$jfN8!?h>{n-mSk5+kZl4&(0j-+nHl^?L2i?Y+m@ zu74ey)y^K|-g*78hsJI7qah|9X$JPJinXVZVCQyDUy3E==`MX=SO}P_u4UJgjZLP# z8<2PV@u5B0@q@J7!K#-U?k6>ZJgI?xlbCB#ZW$?;Vn_p0o1~Ap84#CHXP>x;?3DVL zpw&`FgeJp#O1D@&;bHuCulspZeALoB^ncUumL(yeZ8E#N$`I|t?aCDsVzNIC z5>*QQdOw%3TWj~z4A#j5C}i-HHDS?kd_q7I5;}L`vc>3^7~f)s6 zA|>9J6k5c1;qgAsyXWxUeSp7SW~$jS0jQc~q!MuBDYVx~SPib;6Z z*FAMo-9>qpci*4YtK>|72KWTxS*9Bn@dokCrloVYciDr?@8zc7^3R+hO=YZwVE zVhJJy$f%-(GAu-C*GMsuqVu?if5`ERNFNQM2vuW7}?=0D))VN^AKmbs+Xhdab2Jj)4Ac;NrTa$$P-%4lwwnONQh~ z0b2fi9(X^aZ^{A#w?OxrJGbUJP9K0Y%_?~V92^2;1bh zgTb%>01X^zR9JMgvI2$zBsOF=VK_2jWi4ScF)%GOGdD6VVP<7!Ej2h~F*0Q_F*GtV zFq2#biYrZFV<1mcA_^cNAV*0}P&!m;ZDmt*VQp|dA~7~OIXN;lG&M3fIWsplHSzy=Eev#tnW2n4wfOQ(|(5i$r40Uk7@t!CwuOc5x5c}YY;R4C7lQArK} zAqYdh4Dk`hH`}?)LJ$~x5s^xpHUJ<4RV9x(=howlWQU{A_;izhXDXnoq0EpN4Mx2N z0A7Y4jJ$IuvGSf0?Z(U_;f9DnMBdt-z6JoUWFF<1N&fX1d9kE1#vaFWS!+@6{X9oY etib#^y8vuDaPis?Lz&6|0000)iF<{-zeIrJ=1r6VtS9`4aefN zD&iKgtMA^uMXUE(oB752&WaDc+}TM_Y~I+`t1iC%LBp9lwRR>A3U1=(dxq8JChUYYIOYTNzT-He=BOWZ&2=7;W_pG#U9+#^WxhbI%RuY zLQYC+lIr7knGR+3=Lt2fb(?qAHT}D5*GcsFbA9WM9KPLAm5^9Z{pGjqX|MkMF?DlI z-PSMPNDEssHX>_cmv1dT-tx1bU(g@DcA@VdPi}BmZvR%i*{ZLL$=;+pKIOooBe{kH z#Two9nZGVtzM}S%+J|lLBHv`5PJZdUE;T(R?CM^!_j0Z2L+6g?nv-0X!pz@1l+^ml z(mM-|gXVvxxZ758ZB;i?S+ieR?iwI!UM zM{}~3hA;yGyg*`+u(#AFGGQYc!DZmLEXGkJVj`6o(IT52G5Lc4p;fesz${^*f z5V@cbkOaREkuh1Pzg#k+DAXf^`FR62+Yr1@9AE+Rfrr@uPO1pp>%~WUh?1oOf(#_| zy&j?iu4lXei2m{*2P_r9CuNR=;JG3HKzXn&QgK@oPMj7btIbyOoy3j>RR#IkaqLV$<| ztc5WJ0W0}~4!^(Dh{`D;vgeT62A31hO01cc00bo{HA9jNML9?{LubK{d2mRKu=n$V ztMY$Y%ZmpwM5jDo5Mlhvh$ynbXmO9<>W9;7O%r-3O<}9Phn2@^FbF<7wy{|+aHh{1?W2Kq&1aPxwD zAwIMj4sZtZ{ULt?bMZrlK#=huW8!z5u5r4?#K4%0$GdBst}!t%Cgbt$`oGbo9KKEg zA3Ozx;AIKl{{Exzq80C4ywEJ)xD<*zro+#`*Q7vxv8Yg}GUb0vcy~?(6edVkn&!Ff*$xM-L_@P{9ZKGw!0_Rqh~tV)E9TWp5Jo+K;VUj^b-^F&|mCa*=ze0g@lm5djhZ4T|}vh**%C_C3QJ@@U)57Naj OqQYufYHnY!rux5`_9s37 delta 568 zcmV-80>}M}B8~-+BYy#eX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmKpe$i(~3n}9PA*{ zAz*c~AS&XhRVYG*P%E_RU~=gfG-*guTpR`0f`cE6RR`&;D3Vyj5+sOF zP(v9N*of1rlYe3%P5TKC|4_>>kxL<08H^kYs6vC>@`L}u?{2NaVw4!&DM|J+`ozdPGKrP#%Vg?O4v!m1VN^I+|DZa&eNXU$?(6(jsF?Gt~dGv zY89VC6G=HFMFFZdBmfH1QV2oP=eDkVH1Cf2xwi*q+a?i3^Nw#Q>9PNOb8l z-{NMOQp=Thj`WrmDxcZ&H}C8?cVX^VuWa0v|F^5VQ?p*`oc|DlWHn0;htK1145bZ| zZQron=KlSU=DoMNdhZMQIjvh*@uj?A!GgaBx_r%s-8GTZ?_BLABE3(&c91o6XXjMR z>B=*H@FsWA&~!OxOIPdDFSPFX;%Mh7?AQ~1kH2+z;Nbe4+^zIqe%oF6tB)TtwQXsA z<{!T)OuLFUqiZIud}h_L_IpaMSdV;irSJNWo5KwqUn>1w*4C^=+u38&_Ah_U zXm+yg?Gvy5#9%(Lt?2fQ$5U%R+*2K|BJw6N zZyfDKLKU9h9eDlIndB?eYikcMV8+1W4{#TrG1 z!wD22DJ4`%j-whUAC&7<8-_tUIuu_l;q?yF$CW`9pdLh;PY{%mBw{gQw1=X)>LJNs zK;P=2_~B|Ms(>QbB?aKB2XVD{G=(S(`zPv>Q9T_|AV3tvAXI^)Qe%c(;_>>1Jv0fz zQY@i+L9xdmRVg$g)|l8di=NKtK%o0D?-=w@?m8Hvyk5>J3w2s}9;Xe{#^*#?kVH=Z z1QtF-Stt{3v4{+AW?2i)QUZySVwsgEY1+*2p;1(xxT5lL0ccc^+$cewpuh?i-pb%s zv%uqKa~Y%{%_2^TEJHH_#Q>HaMX@3&!K&n=qodNOL`Y?2Eux9xEqJI*gj6gO!mS|0 z;DSgAf|X~=Xp2Rs5(TbOPR4jRol=Ys10oR*>jq75&hGQrFxp6t^!TE@8iEcsY?&0V zOOF`*QVdk9yrw2qMv@kqqFBaiVyv`z1XKf(3amtplOm0#j76Ik4kiPI<+VD61iA;z zg>xhUugXckEJtma780s?4x7DjIf=Z=J9!mAQj#`t6vffBpE7Y~3r8~xV3Qn$mqjVm z@W0U7;z7$ZQ|^`&IDUiPm03~MU|pt_X+|Y|DWRyoC^%loq@eKiK-A-eTp5!P;p1Td zcaOnx9qO09r4-6&Mg$@m!p$@v#LXs_#rdFU!3CNmO(JUwiDqUjyCR3w6rTk4Fw_xh z1b|k)R0L?V00qM-3jd~H#9+dNwr31wTuyvLlX4v}YLkI}nLfCA!M%_e z-V6sd)3%-O@HaRY-{A<5dSZ}q={q6Ugk0lNU|isd>Y9*iTndZ}JW*Z$H@OTW*C`N( zr=S$PEG^#P?12}p$-xJgIQ1(Ra?^2mBmA0@aIaDj#8|97S?RqM^{_KX^>|%5A5EPz z$#~bxm;SUAcHO1A0;)rfX{T~TKP&Jsjt@bWI-6>aV>XtFJ9C1U!!C9_5c6? delta 522 zcmV+l0`>jAA>ag%BYy#eX+uL$Nkc;*aB^>EX>4Tx04R}tkv&MmKpe$i(~3n}9PA*{ zAz*c~AS&XhRVYG*P%E_RU~=gfG-*guTpR`0f`cE6RR`&;D3Vyj5+sOF zP(v9N*of1rlYe3%P5TKC|4_>>kxL<08H^kYs6vC>@`L}u?{2Naaeq&3{ET%kcCV7gf2s6#xJL M07*qoM6N<$g0HLSrT_o{ diff --git a/lua/assets/play.png b/lua/assets/play.png index 0d0bb34dfbacced5decb456d89b215b587f2074f..81927a8a1eb5c3f01216814b75e5b1fd4bee3f44 100644 GIT binary patch literal 4309 zcmeHKe{d639^Y2l(f|dN{!r<#rl;b;W`AUpY<3cQHA!iNU}z(@cO0;M*ln>#@fL4G;D-L$10ow@1E z`Cl`$*?r&l{eHgR@8^BrciwCEFPcBaaGL=^kSX30cPV^lY0t!T_&=)z`xw5yTp1`= zO1T6Yi%TJ~8lXyj44^<2LkOaN+Pe5R(Ra|v*G|uHHZD(jc;@-?9kwF_=O)bT3%ndy zkk>$5B(@G*zkc8H?cR1_!H%QyUBB<{rYE$o-PLcdxb*hABbS@E*Q1Zl*thNzuuRxI zeg0W;%_~=q&Q6UsJ$?20J#QVp`^{q4j-K1oZu)}Uc(H3*YoM{M_2EgyN2}@`kz;4X zZnt7dW4J=%x?9 z+Opo?n@@d^f8OLcF{dcyeP_C5Q}FvwPW|)D)T;+~_hp=_P2`;1DZPgvDQiTR%kOo$ zh7yPAZvI`Hv*hhx&3t!x*-KlpGg_J$;g4Ct+&Q0@clg&BURY9j=&vXH@XEd?|I)=6 zI@2-=b2_q2AMRzl42{P#nmSsZ+S0P&yPmBd84o-*uxkIlOI-~a6I-c&?Ci{Y{@)Ln z+nZW8{`ciP)iY}?x*~P)#)<=*e{tst`H&G#_lf+qW0}y5Mm3Gsl?RnK^2xcj5L^&8~NXFFe+s74no7{Nb*w zj!la$-+KVGf0Gm5wUpo0a6UI(zVaS*SX^gZ?U`HDI5Ew#!C#y`{nxdnbGKF&o;@+E z=Gx8OGve)U_5S%$1KqoB*0rgt5>;QkSQafMvXq`97yp(w?MT|D+JAjN@3k*aWgdSd zz4O9rJ$*>1(EG~kd%l`Z{AtS4rLSAS)UMA`);>4+=!X2i-(S{ydi5pqm2Gngb<%~- z?l<;aths`0-O+J!N-Q?Xz>xgmjB`f2gY~`W= zzp{$A3&z5E28YT*fCx}HRE<bzByHYhv7p>MBZ=(^&5Fqb?~9P})SB2+X63 zb(C?Q0d>TM5L@al9)y4+r?FB|Vl0j)5(!hnY?9((oV45RI6>hQg+UEWu8%65ibdrD z4I+u*1~MNPV~Qw6Q4Ny|O0|m9XoU0VP<)Y?&o>Mol?PdXeBdehRt2h|_~Rb}Xv9OZJp*XJL$ z&?pFtk(h1;$sVPth@l%~jfzd1(bE|j2s9tY9i=^#yRHnid_LAK@wHlbUboYz`DX=* z7X?=Tv~!HbY9Y-SLo#NJCI}nG1+5m$N(mgn+sroFOpk!_MrDPI@<4-v;3g5`SgpWj zA!r^WEEI#$B!sXNf*rFE6yOMkrb(M+1jPMu5mqHvJu)f{N`O#+G&79NYQ=!XEMT<7 zPGdom)S{tiUSK$2wkM+zc(z!IM>x2gVuT9=JQfY>J~YDFBEQ#Zq)fyOiNBgtLeRiz zTqs6s)f*E5F#^gIPGgg_5rmZ@NybhvR>qo)S;t!f;xep64U;5HgM?_y!op-Av7AHOWzOSS{*X2}Siy!E$^u1(~Y@f*vQtN>1^W zTr><|_ZTeKA-VVyr4S77AG@j0R*7;{Y&Yl%1h~4FH-0+-P)J3MmOL4vNB% zN5~Z{Pn|1tw!TpJjMh$60&Nu_VHinbKPC(xOc>XC#!$u%{70NPbcGR32HGWMuzA5= zhz~czLC&>;FcV;l_0e zMBynY0WV7*Y|FX>UbNDK3+B7^D;ILvweJ!5l^H9kkP*aGpgk$-ONDh%n4x%mo{ZCz za#BtCov&t=LD8*>r(AJK5$#lt=!Zohpb1f_M76`>gR8T0p%USB7X@Y?EX>4Tx04R}tkv&MmKpe$i(~3n}9PA*{ zAz*c~AS&XhRVYG*P%E_RU~=gfG-*guTpR`0f`cE6RR`&;D3Vyj5+sOF zP(v9N*of1rlYe3%P5TKC|4_>>kxL<08H^kYs6vC>@`L}u?{2Na IndexKey::Header { + return ::database::ExpandHeader(key_.header, key_.item); +} + Iterator::Iterator(std::weak_ptr db, const IndexInfo& idx) : db_(db), pos_mutex_(), current_pos_(), prev_pos_() { std::string prefix = EncodeIndexPrefix( @@ -887,6 +890,11 @@ auto Iterator::Next(Callback cb) -> void { db->dbGetPage(*current_pos_)}; prev_pos_ = current_pos_; current_pos_ = res->next_page(); + if (!res || res->values().empty() || !res->values()[0]) { + ESP_LOGI(kTag, "dropping empty result"); + InvokeNull(cb); + return; + } std::invoke(cb, *res->values()[0]); }); } diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp index 63014bed..e18701eb 100644 --- a/src/database/include/database.hpp +++ b/src/database/include/database.hpp @@ -80,6 +80,7 @@ class IndexRecord { auto track() const -> std::optional; auto Expand(std::size_t) const -> std::optional; + auto ExpandHeader() const -> IndexKey::Header; private: IndexKey key_; diff --git a/src/lua/lua_database.cpp b/src/lua/lua_database.cpp index d8ae86f6..79916115 100644 --- a/src/lua/lua_database.cpp +++ b/src/lua/lua_database.cpp @@ -20,7 +20,9 @@ #include "event_queue.hpp" #include "index.hpp" #include "property.hpp" +#include "records.hpp" #include "service_locator.hpp" +#include "track.hpp" #include "ui_events.hpp" namespace lua { @@ -55,6 +57,42 @@ static auto indexes(lua_State* state) -> int { static const struct luaL_Reg kDatabaseFuncs[] = {{"indexes", indexes}, {NULL, NULL}}; +/* + * Struct to be used as userdata for the Lua representation of database records. + * In order to push these large values into PSRAM as much as possible, memory + * for these is allocated and managed by Lua. This struct must therefore be + * trivially copyable. + */ +struct LuaRecord { + database::TrackId id_or_zero; + database::IndexKey::Header header_at_next_depth; + size_t text_size; + char text[]; +}; + +static_assert(std::is_trivially_copyable_v == true); + +static auto push_lua_record(lua_State* L, const database::IndexRecord& r) + -> void { + // Bake out the text into something concrete. + auto text = r.text().value_or(""); + + // Create and init the userdata. + LuaRecord* record = reinterpret_cast( + lua_newuserdata(L, sizeof(LuaRecord) + text.size())); + luaL_setmetatable(L, kDbRecordMetatable); + + // Init all the fields + *record = { + .id_or_zero = r.track().value_or(0), + .header_at_next_depth = r.ExpandHeader(), + .text_size = text.size(), + }; + + // Copy the string data across. + std::memcpy(record->text, text.data(), text.size()); +} + static auto db_iterate(lua_State* state) -> int { luaL_checktype(state, 1, LUA_TFUNCTION); int callback_ref = luaL_ref(state, LUA_REGISTRYINDEX); @@ -66,11 +104,7 @@ static auto db_iterate(lua_State* state) -> int { events::Ui().RunOnTask([=]() { lua_rawgeti(state, LUA_REGISTRYINDEX, callback_ref); if (res) { - database::IndexRecord** record = - reinterpret_cast( - lua_newuserdata(state, sizeof(uintptr_t))); - *record = new database::IndexRecord(*res); - luaL_setmetatable(state, kDbRecordMetatable); + push_lua_record(state, *res); } else { lua_pushnil(state); } @@ -105,40 +139,37 @@ static auto push_iterator( lua_pushcclosure(state, db_iterate, 1); } + static auto record_text(lua_State* state) -> int { - database::IndexRecord* data = *reinterpret_cast( + LuaRecord* data = reinterpret_cast( luaL_checkudata(state, 1, kDbRecordMetatable)); - lua_pushstring(state, - data->text().value_or("[tell jacqueline u saw this]").c_str()); + lua_pushlstring(state, data->text, data->text_size); return 1; } static auto record_contents(lua_State* state) -> int { - database::IndexRecord* data = *reinterpret_cast( + LuaRecord* data = reinterpret_cast( luaL_checkudata(state, 1, kDbRecordMetatable)); - if (data->track()) { - lua_pushinteger(state, *data->track()); + if (data->id_or_zero) { + lua_pushinteger(state, data->id_or_zero); } else { - push_iterator(state, data->Expand(1).value()); + std::string p = database::EncodeIndexPrefix(data->header_at_next_depth); + push_iterator(state, database::Continuation{ + .prefix = {p.data(), p.size()}, + .start_key = {p.data(), p.size()}, + .forward = true, + .was_prev_forward = true, + .page_size = 1, + }); } return 1; } -static auto record_gc(lua_State* state) -> int { - database::IndexRecord** data = reinterpret_cast( - luaL_checkudata(state, 1, kDbRecordMetatable)); - if (data != NULL) { - delete *data; - } - return 0; -} - static const struct luaL_Reg kDbRecordFuncs[] = {{"title", record_text}, {"contents", record_contents}, {"__tostring", record_text}, - {"__gc", record_gc}, {NULL, NULL}}; static auto index_name(lua_State* state) -> int { @@ -207,4 +238,4 @@ auto RegisterDatabaseModule(lua_State* s) -> void { lua_pop(s, 1); } -} // namespace lua \ No newline at end of file +} // namespace lua diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp index d5de53f0..ed0624df 100644 --- a/src/ui/ui_fsm.cpp +++ b/src/ui/ui_fsm.cpp @@ -219,6 +219,7 @@ void Lua::entry() { {"pop", [&](lua_State* s) { return PopLuaScreen(s); }}, }); + sCurrentScreen.reset(); sLua->RunScript("/lua/main.lua"); } } @@ -243,12 +244,6 @@ auto Lua::PushLuaScreen(lua_State* s) -> int { // Store the reference for the table the constructor returned. new_screen->SetObjRef(s); - // Ensure that we don't pollute the new screen's group. We leave the luavgl - // root alone. - // FIXME: maybe we should set the luavgl root to some catch-all that throws - // when anything is added to it? this may help catch bugs! - lv_group_set_default(NULL); - // Finally, push the now-initialised screen as if it were a regular C++ // screen. PushScreen(new_screen); @@ -256,12 +251,16 @@ auto Lua::PushLuaScreen(lua_State* s) -> int { return 0; } -auto Lua::PopLuaScreen(lua_State*) -> int { +auto Lua::PopLuaScreen(lua_State* s) -> int { PopScreen(); + luavgl_set_root(s, sCurrentScreen->root()); + lv_group_set_default(sCurrentScreen->group()); return 0; } -void Lua::exit() {} +void Lua::exit() { + lv_group_set_default(NULL); +} void Lua::react(const internal::IndexSelected& ev) { auto db = sServices->database().lock();