From fa3bb69d744c085e05066873da16ca451743aa40 Mon Sep 17 00:00:00 2001 From: maximal Date: Fri, 11 Jul 2025 18:02:44 +0300 Subject: [PATCH 01/13] =?UTF-8?q?Optimize=20PNG=20images=20losslessly:=201?= =?UTF-8?q?2.4=20=E2=86=92=2010.2=20KiB=20(=E2=88=9218%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 628 -> 575 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 628 -> 575 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 765 -> 661 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 765 -> 661 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 848 -> 726 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 848 -> 726 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1423 -> 1115 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 1423 -> 1115 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 2709 -> 2162 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 2709 -> 2162 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index fdc2d7a9e0d7007f833c9b38fa108ed7aec50963..096a00946c109c45ddd88b93da5ecdacf6fa2383 100644 GIT binary patch delta 346 zcmV-g0j2)*1iu83P=5z>Nliru=?4N3B0KLX_yqs}00Lr5M??VshmXv^0003aNklW4*RA(ENweLd+Orj4?*nD{t9=)|GKQWRubXqWlh~<^TWy delta 400 zcmV;B0dM}l1oQ-uP=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?mSUV<67G@2NLWDg8d<)BAjTp6Bg-UVjim2qDCOlTu14r5epMj|6ROH|#dNPz)7Lh-neTSL7NdG#_Y}G_RQz*zQK^;h4=yN`uuu0oSMQf#*!4DR#3(?kwpa+Rb;Sa!u_E=ntl)W1by0&?_ zLtso-j5Fxb7ArxEwpbIqXp2SRN>^-Z60&Y%wl84B4|T!*F4(#N%w-?~Q3FVn-K0}r ucl&GF0Q*1SgY)HRI5nT|in&bf`&bAegb?CSya5T8e+B17D~cJDodKc?$-CYF diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index fdc2d7a9e0d7007f833c9b38fa108ed7aec50963..096a00946c109c45ddd88b93da5ecdacf6fa2383 100644 GIT binary patch delta 346 zcmV-g0j2)*1iu83P=5z>Nliru=?4N3B0KLX_yqs}00Lr5M??VshmXv^0003aNklW4*RA(ENweLd+Orj4?*nD{t9=)|GKQWRubXqWlh~<^TWy delta 400 zcmV;B0dM}l1oQ-uP=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?mSUV<67G@2NLWDg8d<)BAjTp6Bg-UVjim2qDCOlTu14r5epMj|6ROH|#dNPz)7Lh-neTSL7NdG#_Y}G_RQz*zQK^;h4=yN`uuu0oSMQf#*!4DR#3(?kwpa+Rb;Sa!u_E=ntl)W1by0&?_ zLtso-j5Fxb7ArxEwpbIqXp2SRN>^-Z60&Y%wl84B4|T!*F4(#N%w-?~Q3FVn-K0}r ucl&GF0Q*1SgY)HRI5nT|in&bf`&bAegb?CSya5T8e+B17D~cJDodKc?$-CYF diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index fe8d9352db79512494670aef1ee40e5f1dc20b92..eb98d48bdff23efdbd4c1135ad622121c87600b4 100644 GIT binary patch delta 433 zcmV;i0Z#t?1(gMmP=5z>Nliru=?4N3B0KLX_yqs}00Lr5M??VshmXv^0004bNkl>G|^>o^QXW-{YK!h=_=Yh<}KPi2SN1-aO^fI}1IL z^0Nbc)asmb?vhH5z8o$(iyMVuGwLn;5QbqGW*=T|-HG@LufH5L4s8H1{{E^v;JDHw zLLm6waIKe)lK^K1VRrz~ZV;XU7%>Qs0VEB=(*SY*;YbRg#eaAnVAJ3=zmIbY#2xvkM^XA!>NOGHh=K)T!c9j>bS&crUjW1qoVJ&*^k8w^&i zL4ak0uuB0qQG@U-K(9f#A7IKL+ySs;5N-xoH3+u>tXaL|MT77Hz@-0hZ5ANrJzTd3 zaN>F8s_B}~0MPF#T--Zdz3!b#qg8qD^cUab!kn`R7bdnlo#${Ne{r}n(fGMP0zVFm bh=_=Yh=_=Yi2OItf7;U~c_P$(lUo9!YQ)N~ delta 538 zcmV+#0_FXc1^oq(P=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?_gm7L}oUBxG-?f%xu9qoaP=sehIX79C9E3 zAWU0u3E;tg=i_a!7%n12bN>0%DycL1F^gd>2nIfQ=! zH0BVl2k?D*r3;4ut2u>5sd18MB&z0(RX=-NF{XlAw^ zMNt&3uJ0U-k9J1m|1DNYJ|tpST-@_$u8a&huP$+`0V*>O=A64p;Yzu@GWUMst9MpJ cL_|bHL=QwnMC54L0&_|=`sj_l|C93pqTqe{s{jB1 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index fe8d9352db79512494670aef1ee40e5f1dc20b92..eb98d48bdff23efdbd4c1135ad622121c87600b4 100644 GIT binary patch delta 433 zcmV;i0Z#t?1(gMmP=5z>Nliru=?4N3B0KLX_yqs}00Lr5M??VshmXv^0004bNkl>G|^>o^QXW-{YK!h=_=Yh<}KPi2SN1-aO^fI}1IL z^0Nbc)asmb?vhH5z8o$(iyMVuGwLn;5QbqGW*=T|-HG@LufH5L4s8H1{{E^v;JDHw zLLm6waIKe)lK^K1VRrz~ZV;XU7%>Qs0VEB=(*SY*;YbRg#eaAnVAJ3=zmIbY#2xvkM^XA!>NOGHh=K)T!c9j>bS&crUjW1qoVJ&*^k8w^&i zL4ak0uuB0qQG@U-K(9f#A7IKL+ySs;5N-xoH3+u>tXaL|MT77Hz@-0hZ5ANrJzTd3 zaN>F8s_B}~0MPF#T--Zdz3!b#qg8qD^cUab!kn`R7bdnlo#${Ne{r}n(fGMP0zVFm bh=_=Yh=_=Yi2OItf7;U~c_P$(lUo9!YQ)N~ delta 538 zcmV+#0_FXc1^oq(P=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?_gm7L}oUBxG-?f%xu9qoaP=sehIX79C9E3 zAWU0u3E;tg=i_a!7%n12bN>0%DycL1F^gd>2nIfQ=! zH0BVl2k?D*r3;4ut2u>5sd18MB&z0(RX=-NF{XlAw^ zMNt&3uJ0U-k9J1m|1DNYJ|tpST-@_$u8a&huP$+`0V*>O=A64p;Yzu@GWUMst9MpJ cL_|bHL=QwnMC54L0&_|=`sj_l|C93pqTqe{s{jB1 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index f85ced2c5e541beabda19fe19341006ded6b82d5..fa1711674f51554e85eff38e6f8d4deaebaf17cb 100644 GIT binary patch delta 498 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 L0E36flkEheNa1+v delta 1151 zcmV-_1c3Y72#*VpP=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?-x;^vgq?2h*|S%^pR3=x zp0hqr+U}g5b7~Bekpmo&@C1JdMM*JtPG0(7x1Pyn|M;yht_PTI7~_I#vi=`TX6T&$ zJhWxStySk=d~hhDblyT+qAoPtCDAfX@zhNsnY_>R?cTOyz<=+tD)qUt#FA}CS4>q$ z5*A>LnX|g<# z*OlkSV`JFG3%-Dow{ElZ>oFXcnCu1Ae$Zy;!*8gQMda(ih%tY&A6Qv!e>i=AAWr}v z1(Z*lUfpR>S!uwldbetWX@Gj*=W;`mhf!^Uv(dwdT#tAG2t&()!H z1$^CcAahb3Nm)R$vZ`-?7&}2Ze%}Miu6=6v&o5rA4y7x=7-MF?(*1}!m9zk3YSwR` zq0SZA7~ca{ee8eclFCHw<@HVTE8IX6JCHZ=HM-B?7XOL94iX705kZ^T05@}<8yJ}{{@yG$xXAKP-l}A zkX>oVC*wK&W|9|RcG-htSKh1+Cn>;ew$mbYI86cj?bLs)4yP&LpgmD&Ue$Qk6Knwk zKjx+>A)F!*!#j1io$A%;GzI)>r#b3$ngUMPsaBm%Q-C`p62hkfF%;lVmaJ5#(-hz? zE%W}Fdl&_{BZPmc(`gE*u~Tdp6He{|n(P$9X+r)BXmlrvjegyOp8o<`+!(?!a_L00p`^pj+6V_S}jYp zK9qmSZ0AOGwm1uDxZTYqKZZ&JgwhJr^)EknKO-+tb~3q;ulFMCgZ?bJH&q_BR2Okpmo&@C6G% R=U)gQwvVMdnst-81ES3oJvsmY diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index 6516c53c5bbd14b44292208b8d0b0252f24ab07a..7c81e83c76f9a47ea4c6ce3985357f92e210b2b9 100644 GIT binary patch delta 833 zcmV-H1HSx^3)={gP=5z>Nliru=?4N3B0KLX_yqs}00Lr5M??VshmXv^0009&NklaP!uU-Mc9J~%Cdz)DTReeP*9QdfY6AF z3d$COMbTpu5!j}p5-o8Nge@v86?%x`tCLZlb4?wGA*Js3{|qhVyYu)nIA`veJ4%zl z1R;M{3M?K;R(fD|?6}=$Zb_JYcj^4RiS2` zS9E{@?@ME32hjT6df@@Iu9_q~fPOMVcmVx8PIv%)%k2U39e<7VC#2>SUuzk1_XQ&y zzGvu4<+>Se`eO}~6vFz*99%zvE5VTi40eB5cHa@8b@G_ER%nLrhOt2W_W}&q)ME>j zNerM?_nL_}5fTHaO8XK>7a3rBhZ!jq89?1OBR6FR*l9)@Wd_JLBVS|&m}f@%Wd=yL zZv!5Y0kX_UyUbTWf%JcZ_sqxzkpWWdr-3|)0U~Sd*-@Xs01=n%d%$jip9T}`DGq<# z;1d@hv83HT|E@VoP5|$;S!o-OJ?wX!59(T>Tpl2}&r6l)05yq9aDdLL%n)zQjR9Vq z$cqp8*4!ANudy=6BRRlN9}dLJ4xn}0HsJxZzA?q^0rsa@scDPW>^k$f+gYG)rl6JJ zZ?PMkdxLc%_XZa{)uC?-xbl2JRE2*nuvO+Mv9o5RB~D}j-zzh-S7ZRkBWsQn89==@ zLzyxI95h2GWd_JFL(gOe@S3fGUcblys>w{vl^NiUnOZ9|z(q4vBs0KqGj&8}fWv00 zLS_KF5I8S0z-cpeNoIhnW~x$V0Q)78a+v|_g#*PR1EkuMLMufED7FETBnE$oervxb zB=XbX4*LSQA~C>1d%=Lt78oGVW}knvM_hoIvM$Hw&~_y&fG6Wrt8;s>KFZAj${oKT zv1IwG{C($YzYX0W?nxVVxSKAV9NU)Rhlh3P?Ee~|M2Qa2y;+G4@G_tz2l!MJtpo>X zC>-@Sh1?&Y^HEu_Z;87#!1omHuOFLgtB>Z-_Xa=wZw5#{G^kLMzyu-;fcyOb9+WX1 L0E36flkEheNa1+v delta 1151 zcmV-_1c3Y72#*VpP=5kqOGiWi|A&vvzW@LL2XskIMF;5z0uUlQ?-x;^vgq?2h*|S%^pR3=x zp0hqr+U}g5b7~Bekpmo&@C1JdMM*JtPG0(7x1Pyn|M;yht_PTI7~_I#vi=`TX6T&$ zJhWxStySk=d~hhDblyT+qAoPtCDAfX@zhNsnY_>R?cTOyz<=+tD)qUt#FA}CS4>q$ z5*A>LnX|g<# z*OlkSV`JFG3%-Dow{ElZ>oFXcnCu1Ae$Zy;!*8gQMda(ih%tY&A6Qv!e>i=AAWr}v z1(Z*lUfpR>S!uwldbetWX@Gj*=W;`mhf!^Uv(dwdT#tAG2t&()!H z1$^CcAahb3Nm)R$vZ`-?7&}2Ze%}Miu6=6v&o5rA4y7x=7-MF?(*1}!m9zk3YSwR` zq0SZA7~ca{ee8eclFCHw<@HVTE8IX6JCHZ=HM-B?7XOL94iX705kZ^T05@}<8yJ}{{@yG$xXAKP-l}A zkX>oVC*wK&W|9|RcG-htSKh1+Cn>;ew$mbYI86cj?bLs)4yP&LpgmD&Ue$Qk6Knwk zKjx+>A)F!*!#j1io$A%;GzI)>r#b3$ngUMPsaBm%Q-C`p62hkfF%;lVmaJ5#(-hz? zE%W}Fdl&_{BZPmc(`gE*u~Tdp6He{|n(P$9X+r)BXmlrvjegyOp8o<`+!(?!a_L00p`^pj+6V_S}jYp zK9qmSZ0AOGwm1uDxZTYqKZZ&JgwhJr^)EknKO-+tb~3q;ulFMCgZ?bJH&q_BR2Okpmo&@C6G% R=U)gQwvVMdnst-81ES3oJvsmY diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 5c73d4e63b78ddcbbbb7ab7a59dae287ceea3a1c..335769ff8b0ad99eb694df82ff65e208cb7d21df 100644 GIT binary patch delta 1779 zcmW-id0Z1&631UR2}uZ7L97knQ%bs!x4>Rqws7Z&hD5o;55v zh*DB~{Jba=6xh((b;fRy3;=-t=Igx|X!44?g#b_jefI7NNFSLJqXomM8{3u6!(nOG z(QfALCh zK}P;?+^(wMlh?42N=8y5Z{geC>AaW#(rBl&C5hH1;6#I9M&nl zKnp|x^6T|9sZ3nIDz~p|iCeoftt?!;8ooHtx2uuCyD~l)G$~fzJZ92UmiVFH;E1ZJ zX()hRb8~9oqn-rKwFqzI-UGARigF6)?KZ3%GJl}{Gm2cY8>{~LOH&oxW!~P=qm_2R z1o;T6V|!AcQ>~K05!LNrc>hL3waN@fH{nSEgG1Y)3Vr_1nfc%l<)C}=EyAd?atSka z-3A+g0t^b7h#XYc>F{r8wFsXHPfo}tUB+vf+XXRMGiwaZ?Ee-D{<*w%!N1D1;B=bl z(k6TP{L?#nx7Gq$!oG8G?`syD59ISrhQ6rL%Bn!ir6JXL=JYS!T| zX|ZK(Z98F6+C{K~bTH)ZD3e*g57@!B~nB1WKp3d=GqJ+vF!RXS3k0 zb;txQ0v@%&9H0kk4;{WY2!?Gf&%rJJAO_}U?JynZoFr6BhvwI@yzv;@Stqgzye9RU zs9ETPLwLm2fYkZU9&>~4&~q~aKnDD;BJz|8!UG-~bmtPF4>ZYp+0*(Yc)wBmO8HE- zlw9&HMlT0NOr#7vNxmClhdDu^7P^iy&qy8!Bz3L^<24q2SluU}3K~DvpVhq;cOv8G zzfr8i9m%7phf$`|yb<>%SW#?aqskx}#diM8M!Ns-Of7^Kjwd_bMpn4EZ&ffRvn z-PTQMI%421MtjZaDY>K@`hlj=9DQ`a5XlD~^F8Sqn3orz!R$G~2Kw2|n^gXU7WY{F z!y%nLSsP*QENK1its?ZLarv_Uc9{DNgt!!4V@uzWUj(8FBkr%aWkgq%`<_ebTl zHTD#Wb7`PjB>=6Xh4yflS-V)Q61zZ7hd?KXcX+1O2$7N$^HYv;VJgfm0J$siuEOz3 z5w1W$ap=O@-K(*mNxjrMaLO{Mjei(CX=>&e7lH#(&FRxXu z-uoqvFn1b+J543G?W6};V;>D9{QjBhB#r3C65M5o*p*IaZgPkm`vIz;@-I0r{6cmc z*-l_olzJRWqgtUppfc2mx8p+9vHF4TX`wLo1A$N=R#JXPgl{b{J^-l&$s<8 z(e~LFG8YC;L}VbVcdnF#M-rpAF>q9_kTW_7GGZ%ei5qW91K=$)2_A zami?~W~Y?gyB|u?C10hdQt`s*xIsryGz}MVsLxvW;`uGRO+RZB2gI<3_Tkp5HCvHD zD)|fcrXvU?sGmV=^)+?NsiTC*f7FW|QUd13Y{;$HlU zq^r4j@}x16quq-}=|wzF9UKpxQtfG$F6G{uL1Xv+7}Zm>ik29|?Ds%^JUykx zQ*SWqeIuM6OiJ`);0sd_O2QZEWhtqIjWIp`DxVpu7Tv- zOjfMpi0C#G(W2CA8Z7U&ELLp377p}`+a;suqpwguSj~TUI7H4;zi`GfI+hIS cbmG5p5z^Kjc#A^OoaY_8rCY;F=V;~s2Q1VNQUCw| delta 2333 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 DiM@wL diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index 5c73d4e63b78ddcbbbb7ab7a59dae287ceea3a1c..335769ff8b0ad99eb694df82ff65e208cb7d21df 100644 GIT binary patch delta 1779 zcmW-id0Z1&631UR2}uZ7L97knQ%bs!x4>Rqws7Z&hD5o;55v zh*DB~{Jba=6xh((b;fRy3;=-t=Igx|X!44?g#b_jefI7NNFSLJqXomM8{3u6!(nOG z(QfALCh zK}P;?+^(wMlh?42N=8y5Z{geC>AaW#(rBl&C5hH1;6#I9M&nl zKnp|x^6T|9sZ3nIDz~p|iCeoftt?!;8ooHtx2uuCyD~l)G$~fzJZ92UmiVFH;E1ZJ zX()hRb8~9oqn-rKwFqzI-UGARigF6)?KZ3%GJl}{Gm2cY8>{~LOH&oxW!~P=qm_2R z1o;T6V|!AcQ>~K05!LNrc>hL3waN@fH{nSEgG1Y)3Vr_1nfc%l<)C}=EyAd?atSka z-3A+g0t^b7h#XYc>F{r8wFsXHPfo}tUB+vf+XXRMGiwaZ?Ee-D{<*w%!N1D1;B=bl z(k6TP{L?#nx7Gq$!oG8G?`syD59ISrhQ6rL%Bn!ir6JXL=JYS!T| zX|ZK(Z98F6+C{K~bTH)ZD3e*g57@!B~nB1WKp3d=GqJ+vF!RXS3k0 zb;txQ0v@%&9H0kk4;{WY2!?Gf&%rJJAO_}U?JynZoFr6BhvwI@yzv;@Stqgzye9RU zs9ETPLwLm2fYkZU9&>~4&~q~aKnDD;BJz|8!UG-~bmtPF4>ZYp+0*(Yc)wBmO8HE- zlw9&HMlT0NOr#7vNxmClhdDu^7P^iy&qy8!Bz3L^<24q2SluU}3K~DvpVhq;cOv8G zzfr8i9m%7phf$`|yb<>%SW#?aqskx}#diM8M!Ns-Of7^Kjwd_bMpn4EZ&ffRvn z-PTQMI%421MtjZaDY>K@`hlj=9DQ`a5XlD~^F8Sqn3orz!R$G~2Kw2|n^gXU7WY{F z!y%nLSsP*QENK1its?ZLarv_Uc9{DNgt!!4V@uzWUj(8FBkr%aWkgq%`<_ebTl zHTD#Wb7`PjB>=6Xh4yflS-V)Q61zZ7hd?KXcX+1O2$7N$^HYv;VJgfm0J$siuEOz3 z5w1W$ap=O@-K(*mNxjrMaLO{Mjei(CX=>&e7lH#(&FRxXu z-uoqvFn1b+J543G?W6};V;>D9{QjBhB#r3C65M5o*p*IaZgPkm`vIz;@-I0r{6cmc z*-l_olzJRWqgtUppfc2mx8p+9vHF4TX`wLo1A$N=R#JXPgl{b{J^-l&$s<8 z(e~LFG8YC;L}VbVcdnF#M-rpAF>q9_kTW_7GGZ%ei5qW91K=$)2_A zami?~W~Y?gyB|u?C10hdQt`s*xIsryGz}MVsLxvW;`uGRO+RZB2gI<3_Tkp5HCvHD zD)|fcrXvU?sGmV=^)+?NsiTC*f7FW|QUd13Y{;$HlU zq^r4j@}x16quq-}=|wzF9UKpxQtfG$F6G{uL1Xv+7}Zm>ik29|?Ds%^JUykx zQ*SWqeIuM6OiJ`);0sd_O2QZEWhtqIjWIp`DxVpu7Tv- zOjfMpi0C#G(W2CA8Z7U&ELLp377p}`+a;suqpwguSj~TUI7H4;zi`GfI+hIS cbmG5p5z^Kjc#A^OoaY_8rCY;F=V;~s2Q1VNQUCw| delta 2333 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 DiM@wL From a345d0a021a56a41164d544f3a2629e55d25bfc4 Mon Sep 17 00:00:00 2001 From: prudhvir3ddy Date: Sat, 12 Jul 2025 10:06:56 +0530 Subject: [PATCH 02/13] Refactor: Update permission handling to use PermissionType enum --- .../onboarding/PermissionExplanationScreen.kt | 32 +++++++++---------- .../android/onboarding/PermissionManager.kt | 17 +++++++--- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt index f09d9783..14470a1d 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt @@ -190,14 +190,14 @@ private fun PermissionCategoryCard( horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Text( - text = getPermissionEmoji(category.name), + text = getPermissionEmoji(category.type), style = MaterialTheme.typography.titleLarge, - color = getPermissionIconColor(category.name), + color = getPermissionIconColor(category.type), modifier = Modifier.size(24.dp) ) Text( - text = category.name, + text = category.type.nameValue, style = MaterialTheme.typography.titleSmall.copy( fontWeight = FontWeight.Bold, color = colorScheme.onSurface @@ -214,7 +214,7 @@ private fun PermissionCategoryCard( ) ) - if (category.name == "Precise Location") { + if (category.type == PermissionType.PRECISE_LOCATION) { // Extra emphasis for location permission Row( verticalAlignment = Alignment.CenterVertically, @@ -239,20 +239,20 @@ private fun PermissionCategoryCard( } } -private fun getPermissionEmoji(categoryName: String): String { - return when (categoryName) { - "Nearby Devices" -> "📱" - "Precise Location" -> "📍" - "Notifications" -> "🔔" - else -> "🔧" +private fun getPermissionEmoji(permissionType: PermissionType): String { + return when (permissionType) { + PermissionType.NEARBY_DEVICES -> "📱" + PermissionType.PRECISE_LOCATION -> "📍" + PermissionType.NOTIFICATIONS -> "🔔" + PermissionType.OTHER -> "🔧" } } -private fun getPermissionIconColor(categoryName: String): Color { - return when (categoryName) { - "Nearby Devices" -> Color(0xFF2196F3) // Blue - "Precise Location" -> Color(0xFFFF9800) // Orange - "Notifications" -> Color(0xFF4CAF50) // Green - else -> Color(0xFF9C27B0) // Purple +private fun getPermissionIconColor(permissionType: PermissionType): Color { + return when (permissionType) { + PermissionType.NEARBY_DEVICES -> Color(0xFF2196F3) // Blue + PermissionType.PRECISE_LOCATION -> Color(0xFFFF9800) // Orange + PermissionType.NOTIFICATIONS -> Color(0xFF4CAF50) // Green + PermissionType.OTHER -> Color(0xFF9C27B0) // Purple } } diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt index 7060fb1c..6ef3fc2b 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt @@ -115,7 +115,7 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( - name = "Nearby Devices", + type = PermissionType.NEARBY_DEVICES, description = "Required to discover and connect to other bitchat users via Bluetooth", permissions = bluetoothPermissions, isGranted = bluetoothPermissions.all { isPermissionGranted(it) }, @@ -131,7 +131,7 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( - name = "Precise Location", + type = PermissionType.PRECISE_LOCATION, description = "Required by Android for Bluetooth scanning.", permissions = locationPermissions, isGranted = locationPermissions.all { isPermissionGranted(it) }, @@ -143,7 +143,7 @@ class PermissionManager(private val context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { categories.add( PermissionCategory( - name = "Notifications", + type = PermissionType.NOTIFICATIONS, description = "Show notifications when you receive private messages while the app is in background", permissions = listOf(Manifest.permission.POST_NOTIFICATIONS), isGranted = isPermissionGranted(Manifest.permission.POST_NOTIFICATIONS), @@ -167,7 +167,7 @@ class PermissionManager(private val context: Context) { appendLine() getCategorizedPermissions().forEach { category -> - appendLine("${category.name}: ${if (category.isGranted) "✅ GRANTED" else "❌ MISSING"}") + appendLine("${category.type.nameValue}: ${if (category.isGranted) "✅ GRANTED" else "❌ MISSING"}") category.permissions.forEach { permission -> val granted = isPermissionGranted(permission) appendLine(" - ${permission.substringAfterLast(".")}: ${if (granted) "✅" else "❌"}") @@ -197,9 +197,16 @@ class PermissionManager(private val context: Context) { * Data class representing a category of related permissions */ data class PermissionCategory( - val name: String, + val type: PermissionType, val description: String, val permissions: List, val isGranted: Boolean, val systemDescription: String ) + +enum class PermissionType(val nameValue: String) { + NEARBY_DEVICES("Nearby Devices"), + PRECISE_LOCATION("Precise Location"), + NOTIFICATIONS("Notifications"), + OTHER("Other") +} From 035273011fbf1bf14ce75edc70d0c99ce32da51b Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 15:42:37 +0200 Subject: [PATCH 03/13] fix startup --- .../java/com/bitchat/android/MainActivity.kt | 54 ++++- .../mesh/BluetoothConnectionManager.kt | 83 ++++--- .../android/mesh/BluetoothMeshService.kt | 14 +- .../services/MessageRetentionService.kt | 219 ++++++++++++++++++ .../com/bitchat/android/ui/ChatViewModel.kt | 37 +-- 5 files changed, 325 insertions(+), 82 deletions(-) create mode 100644 app/src/main/java/com/bitchat/android/services/MessageRetentionService.kt diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index a1f5390c..e07873e8 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -17,6 +17,8 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.ViewModelProvider +import com.bitchat.android.mesh.BluetoothMeshService import com.bitchat.android.onboarding.* import com.bitchat.android.ui.ChatScreen import com.bitchat.android.ui.ChatViewModel @@ -29,7 +31,17 @@ class MainActivity : ComponentActivity() { private lateinit var permissionManager: PermissionManager private lateinit var onboardingCoordinator: OnboardingCoordinator private lateinit var bluetoothStatusManager: BluetoothStatusManager - private val chatViewModel: ChatViewModel by viewModels() + + // Core mesh service - managed at app level + private lateinit var meshService: BluetoothMeshService + private val chatViewModel: ChatViewModel by viewModels { + object : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + @Suppress("UNCHECKED_CAST") + return ChatViewModel(application, meshService) as T + } + } + } // UI state for onboarding flow private var onboardingState by mutableStateOf(OnboardingState.CHECKING) @@ -50,6 +62,9 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // Initialize core mesh service first + meshService = BluetoothMeshService(this) + // Initialize permission management permissionManager = PermissionManager(this) bluetoothStatusManager = BluetoothStatusManager( @@ -289,7 +304,7 @@ class MainActivity : ComponentActivity() { // This solves the issue where app needs restart to work on first install delay(1000) // Give the system time to process permission grants - android.util.Log.d("MainActivity", "Permissions verified, starting mesh service") + android.util.Log.d("MainActivity", "Permissions verified, initializing chat system") // Ensure all permissions are still granted (user might have revoked in settings) if (!permissionManager.areAllPermissionsGranted()) { @@ -299,8 +314,11 @@ class MainActivity : ComponentActivity() { return@launch } - // Initialize chat view model - this will start the mesh service - chatViewModel.meshService.startServices() + // Set up mesh service delegate and start services + meshService.delegate = chatViewModel + meshService.startServices() + + android.util.Log.d("MainActivity", "Mesh service started successfully") // Handle any notification intent handleNotificationIntent(intent) @@ -330,6 +348,8 @@ class MainActivity : ComponentActivity() { super.onResume() // Check Bluetooth status on resume and handle accordingly if (onboardingState == OnboardingState.COMPLETE) { + // Set app foreground state + meshService.connectionManager.setAppBackgroundState(false) chatViewModel.setAppBackgroundState(false) // Check if Bluetooth was disabled while app was backgrounded @@ -347,6 +367,8 @@ class MainActivity : ComponentActivity() { super.onPause() // Only set background state if app is fully initialized if (onboardingState == OnboardingState.COMPLETE) { + // Set app background state + meshService.connectionManager.setAppBackgroundState(true) chatViewModel.setAppBackgroundState(true) } } @@ -376,12 +398,32 @@ class MainActivity : ComponentActivity() { } } + /** + * Restart mesh services (for debugging/troubleshooting) + */ + fun restartMeshServices() { + if (onboardingState == OnboardingState.COMPLETE) { + lifecycleScope.launch { + try { + android.util.Log.d("MainActivity", "Restarting mesh services") + meshService.stopServices() + delay(1000) + meshService.startServices() + android.util.Log.d("MainActivity", "Mesh services restarted successfully") + } catch (e: Exception) { + android.util.Log.e("MainActivity", "Error restarting mesh services: ${e.message}") + } + } + } + } + override fun onDestroy() { super.onDestroy() - // Only stop mesh services if they were started + // Stop mesh services if app was fully initialized if (onboardingState == OnboardingState.COMPLETE) { try { - chatViewModel.meshService.stopServices() + meshService.stopServices() + android.util.Log.d("MainActivity", "Mesh services stopped successfully") } catch (e: Exception) { android.util.Log.w("MainActivity", "Error stopping mesh services in onDestroy: ${e.message}") } diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt index 83673d1f..060bef86 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt @@ -129,16 +129,16 @@ class BluetoothConnectionManager( try { isActive = true + // Setup GATT server first + setupGattServer() + // Start power manager and services connectionScope.launch { powerManager.start() - - // Setup GATT server after power manager is ready - setupGattServer() - delay(500) // Ensure GATT server is ready + delay(300) // Brief delay to ensure GATT server is ready startAdvertising() - delay(200) + delay(100) if (powerManager.shouldUseDutyCycle()) { Log.i(TAG, "Using power-aware duty cycling") @@ -458,48 +458,47 @@ class BluetoothConnectionManager( // Proper cleanup sequencing to prevent race conditions gattServer?.let { server -> Log.d(TAG, "Cleaning up existing GATT server") - connectionScope.launch { - // Give time for pending callbacks to complete - delay(100) + try { server.close() + } catch (e: Exception) { + Log.w(TAG, "Error closing existing GATT server: ${e.message}") } } - // Create new server after cleanup delay - connectionScope.launch { - delay(200) // Allow previous server to fully close - - if (!isActive) { - Log.d(TAG, "Service inactive, skipping GATT server creation") - return@launch - } - - gattServer = bluetoothManager.openGattServer(context, serverCallback) - - // Create characteristic with notification support - characteristic = BluetoothGattCharacteristic( - CHARACTERISTIC_UUID, - BluetoothGattCharacteristic.PROPERTY_READ or - BluetoothGattCharacteristic.PROPERTY_WRITE or - BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or - BluetoothGattCharacteristic.PROPERTY_NOTIFY, - BluetoothGattCharacteristic.PERMISSION_READ or - BluetoothGattCharacteristic.PERMISSION_WRITE - ) - - val descriptor = BluetoothGattDescriptor( - UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), - BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE - ) - characteristic?.addDescriptor(descriptor) - - val service = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY) - service.addCharacteristic(characteristic) - - gattServer?.addService(service) - - Log.i(TAG, "GATT server setup complete") + // Small delay to ensure cleanup is complete + Thread.sleep(100) + + if (!isActive) { + Log.d(TAG, "Service inactive, skipping GATT server creation") + return } + + // Create new server + gattServer = bluetoothManager.openGattServer(context, serverCallback) + + // Create characteristic with notification support + characteristic = BluetoothGattCharacteristic( + CHARACTERISTIC_UUID, + BluetoothGattCharacteristic.PROPERTY_READ or + BluetoothGattCharacteristic.PROPERTY_WRITE or + BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or + BluetoothGattCharacteristic.PROPERTY_NOTIFY, + BluetoothGattCharacteristic.PERMISSION_READ or + BluetoothGattCharacteristic.PERMISSION_WRITE + ) + + val descriptor = BluetoothGattDescriptor( + UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), + BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE + ) + characteristic?.addDescriptor(descriptor) + + val service = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY) + service.addCharacteristic(characteristic) + + gattServer?.addService(service) + + Log.i(TAG, "GATT server setup complete") } @Suppress("DEPRECATION") diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index e92a6dfc..7732fd0f 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -69,10 +69,10 @@ class BluetoothMeshService(private val context: Context) { while (isActive) { try { delay(10000) // 10 seconds - val debugInfo = getDebugStatus() - Log.d(TAG, "=== PERIODIC DEBUG STATUS ===") - Log.d(TAG, debugInfo) - Log.d(TAG, "=== END DEBUG STATUS ===") + if (isActive) { // Double-check before logging + val debugInfo = getDebugStatus() + Log.d(TAG, "=== PERIODIC DEBUG STATUS ===\n$debugInfo\n=== END DEBUG STATUS ===") + } } catch (e: Exception) { Log.e(TAG, "Error in periodic debug logging: ${e.message}") } @@ -282,7 +282,7 @@ class BluetoothMeshService(private val context: Context) { * Start the mesh service */ fun startServices() { - // Prevent double starts + // Prevent double starts (defensive programming) if (isActive) { Log.w(TAG, "Mesh service already active, ignoring duplicate start request") return @@ -297,9 +297,7 @@ class BluetoothMeshService(private val context: Context) { // Send initial announcements after services are ready serviceScope.launch { delay(1000) - if (isActive) { // Check if still active - sendBroadcastAnnounce() - } + sendBroadcastAnnounce() } } else { Log.e(TAG, "Failed to start Bluetooth services") diff --git a/app/src/main/java/com/bitchat/android/services/MessageRetentionService.kt b/app/src/main/java/com/bitchat/android/services/MessageRetentionService.kt new file mode 100644 index 00000000..a0651850 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/services/MessageRetentionService.kt @@ -0,0 +1,219 @@ +package com.bitchat.android.services + +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import com.bitchat.android.model.BitchatMessage +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import java.util.* + +/** + * Message retention service for saving channel messages locally + * Matches iOS MessageRetentionService functionality + */ +class MessageRetentionService private constructor(private val context: Context) { + + companion object { + private const val TAG = "MessageRetentionService" + private const val PREF_NAME = "message_retention" + private const val KEY_FAVORITE_CHANNELS = "favorite_channels" + + @Volatile + private var INSTANCE: MessageRetentionService? = null + + fun getInstance(context: Context): MessageRetentionService { + return INSTANCE ?: synchronized(this) { + INSTANCE ?: MessageRetentionService(context.applicationContext).also { INSTANCE = it } + } + } + } + + private val prefs: SharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + private val retentionDir = File(context.filesDir, "retained_messages") + + init { + if (!retentionDir.exists()) { + retentionDir.mkdirs() + } + } + + // MARK: - Channel Bookmarking (Favorites) + + fun getFavoriteChannels(): Set { + return prefs.getStringSet(KEY_FAVORITE_CHANNELS, emptySet()) ?: emptySet() + } + + fun toggleFavoriteChannel(channel: String): Boolean { + val currentFavorites = getFavoriteChannels().toMutableSet() + val wasAdded = if (currentFavorites.contains(channel)) { + currentFavorites.remove(channel) + false + } else { + currentFavorites.add(channel) + true + } + + prefs.edit().putStringSet(KEY_FAVORITE_CHANNELS, currentFavorites).apply() + + if (!wasAdded) { + // Channel removed from favorites - delete saved messages in background + Thread { + try { + val channelFile = getChannelFile(channel) + if (channelFile.exists()) { + channelFile.delete() + Log.d(TAG, "Deleted saved messages for channel $channel") + } + } catch (e: Exception) { + Log.e(TAG, "Failed to delete messages for channel $channel", e) + } + }.start() + } + + Log.d(TAG, "Channel $channel ${if (wasAdded) "bookmarked" else "unbookmarked"}") + return wasAdded + } + + fun isChannelBookmarked(channel: String): Boolean { + return getFavoriteChannels().contains(channel) + } + + // MARK: - Message Storage + + suspend fun saveMessage(message: BitchatMessage, forChannel: String) = withContext(Dispatchers.IO) { + if (!isChannelBookmarked(forChannel)) { + Log.w(TAG, "Attempted to save message for non-bookmarked channel: $forChannel") + return@withContext + } + + try { + val channelFile = getChannelFile(forChannel) + val existingMessages = loadMessagesFromFile(channelFile).toMutableList() + + // Check if message already exists (by ID) + if (existingMessages.any { it.id == message.id }) { + Log.d(TAG, "Message ${message.id} already saved for channel $forChannel") + return@withContext + } + + // Add new message + existingMessages.add(message) + + // Sort by timestamp + existingMessages.sortBy { it.timestamp } + + // Save back to file + saveMessagesToFile(channelFile, existingMessages) + + Log.d(TAG, "Saved message ${message.id} for channel $forChannel") + + } catch (e: Exception) { + Log.e(TAG, "Failed to save message for channel $forChannel", e) + } + } + + suspend fun loadMessagesForChannel(channel: String): List = withContext(Dispatchers.IO) { + if (!isChannelBookmarked(channel)) { + Log.d(TAG, "Channel $channel not bookmarked, returning empty list") + return@withContext emptyList() + } + + try { + val channelFile = getChannelFile(channel) + val messages = loadMessagesFromFile(channelFile) + Log.d(TAG, "Loaded ${messages.size} messages for channel $channel") + return@withContext messages + } catch (e: Exception) { + Log.e(TAG, "Failed to load messages for channel $channel", e) + return@withContext emptyList() + } + } + + suspend fun deleteMessagesForChannel(channel: String): Unit = withContext(Dispatchers.IO) { + try { + val channelFile = getChannelFile(channel) + if (channelFile.exists()) { + channelFile.delete() + Log.d(TAG, "Deleted saved messages for channel $channel") + } + } catch (e: Exception) { + Log.e(TAG, "Failed to delete messages for channel $channel", e) + } + } + + suspend fun deleteAllStoredMessages(): Unit = withContext(Dispatchers.IO) { + try { + if (retentionDir.exists()) { + retentionDir.listFiles()?.forEach { file -> + file.delete() + } + Log.d(TAG, "Deleted all stored messages") + } + } catch (e: Exception) { + Log.e(TAG, "Failed to delete all stored messages", e) + } + } + + // MARK: - File Operations + + private fun getChannelFile(channel: String): File { + // Sanitize channel name for filename + val sanitizedChannel = channel.replace("[^a-zA-Z0-9_-]".toRegex(), "_") + return File(retentionDir, "channel_${sanitizedChannel}.dat") + } + + private fun loadMessagesFromFile(file: File): List { + if (!file.exists()) { + return emptyList() + } + + return try { + FileInputStream(file).use { fis -> + ObjectInputStream(fis).use { ois -> + @Suppress("UNCHECKED_CAST") + ois.readObject() as List + } + } + } catch (e: Exception) { + Log.w(TAG, "Failed to load messages from ${file.name}, returning empty list", e) + emptyList() + } + } + + private fun saveMessagesToFile(file: File, messages: List) { + FileOutputStream(file).use { fos -> + ObjectOutputStream(fos).use { oos -> + oos.writeObject(messages) + } + } + } + + // MARK: - Statistics + + fun getBookmarkedChannelsCount(): Int { + return getFavoriteChannels().size + } + + suspend fun getTotalStoredMessagesCount(): Int = withContext(Dispatchers.IO) { + var totalCount = 0 + + try { + retentionDir.listFiles()?.forEach { file -> + if (file.name.startsWith("channel_") && file.name.endsWith(".dat")) { + val messages = loadMessagesFromFile(file) + totalCount += messages.size + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to count stored messages", e) + } + + totalCount + } +} diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 4240c1cf..66502fd6 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -19,13 +19,13 @@ import kotlin.random.Random * Refactored ChatViewModel - Main coordinator for bitchat functionality * Delegates specific responsibilities to specialized managers while maintaining 100% iOS compatibility */ -class ChatViewModel(application: Application) : AndroidViewModel(application), BluetoothMeshDelegate { +class ChatViewModel( + application: Application, + val meshService: BluetoothMeshService +) : AndroidViewModel(application), BluetoothMeshDelegate { private val context: Context = application.applicationContext - // Core services - val meshService = BluetoothMeshService(context) - // State management private val state = ChatState() @@ -72,7 +72,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B val favoritePeers: LiveData> = state.favoritePeers init { - meshService.delegate = this + // Note: Mesh service delegate is now set by MainActivity loadAndInitialize() } @@ -100,8 +100,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B state.setFavoritePeers(dataManager.favoritePeers) dataManager.loadBlockedUsers() - // Start mesh service - meshService.startServices() + // Note: Mesh service is now started by MainActivity // Show welcome message if no peers after delay viewModelScope.launch { @@ -120,7 +119,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B override fun onCleared() { super.onCleared() - meshService.stopServices() + // Note: Mesh service lifecycle is now managed by MainActivity } // MARK: - Nickname Management @@ -259,18 +258,10 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B return meshService.getDebugStatus() } - fun restartMeshServices() { - viewModelScope.launch { - meshService.stopServices() - delay(1000) - meshService.startServices() - } - } + // Note: Mesh service restart is now handled by MainActivity + // This function is no longer needed fun setAppBackgroundState(inBackground: Boolean) { - // Forward to connection manager for power optimization - meshService.connectionManager.setAppBackgroundState(inBackground) - // Forward to notification manager for notification logic notificationManager.setAppBackgroundState(inBackground) } @@ -355,13 +346,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B state.setNickname(newNickname) dataManager.saveNickname(newNickname) - // Disconnect from mesh - meshService.stopServices() - - // Restart services with new identity - viewModelScope.launch { - delay(500) - meshService.startServices() - } + // Note: Mesh service restart is now handled by MainActivity + // This method now only clears data, not mesh service lifecycle } } From d54d470614290b5c9ed5dd3b83c1cb6fd3181149 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 16:36:00 +0200 Subject: [PATCH 04/13] more logging --- .../bitchat/android/mesh/BluetoothConnectionManager.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt index 060bef86..7fb2ce14 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothConnectionManager.kt @@ -410,10 +410,15 @@ class BluetoothConnectionManager( } if (characteristic.uuid == CHARACTERISTIC_UUID) { + Log.d(TAG, "Server: Received packet from ${device.address}, size: ${value.size} bytes") val packet = BitchatPacket.fromBinaryData(value) if (packet != null) { val peerID = String(packet.senderID).replace("\u0000", "") + Log.d(TAG, "Server: Parsed packet type ${packet.type} from $peerID") delegate?.onPacketReceived(packet, peerID, device) + } else { + Log.w(TAG, "Server: Failed to parse packet from ${device.address}, size: ${value.size} bytes") + Log.w(TAG, "Server: Packet data: ${value.joinToString(" ") { "%02x".format(it) }}") } if (responseNeeded) { @@ -835,10 +840,15 @@ class BluetoothConnectionManager( override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { val value = characteristic.value + Log.d(TAG, "Client: Received packet from ${gatt.device.address}, size: ${value.size} bytes") val packet = BitchatPacket.fromBinaryData(value) if (packet != null) { val peerID = String(packet.senderID).replace("\u0000", "") + Log.d(TAG, "Client: Parsed packet type ${packet.type} from $peerID") delegate?.onPacketReceived(packet, peerID, gatt.device) + } else { + Log.w(TAG, "Client: Failed to parse packet from ${gatt.device.address}, size: ${value.size} bytes") + Log.w(TAG, "Client: Packet data: ${value.joinToString(" ") { "%02x".format(it) }}") } } } From ea25b71d6f06fad5f3a74b6818a08e91276249b4 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 16:55:50 +0200 Subject: [PATCH 05/13] fix favorites --- .../java/com/bitchat/android/ui/ChatHeader.kt | 6 +++- .../java/com/bitchat/android/ui/ChatState.kt | 2 ++ .../com/bitchat/android/ui/ChatViewModel.kt | 17 +++++++++ .../com/bitchat/android/ui/DataManager.kt | 28 +++++++++++++-- .../bitchat/android/ui/PrivateChatManager.kt | 35 +++++++++++++++---- .../bitchat/android/ui/SidebarComponents.kt | 11 ++++-- 6 files changed, 87 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt index d4372157..2916d8a3 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt @@ -1,5 +1,6 @@ package com.bitchat.android.ui +import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.BasicTextField @@ -253,7 +254,10 @@ private fun PrivateChatHeader( // Favorite button - positioned on the right IconButton( - onClick = onToggleFavorite, + onClick = { + Log.d("ChatHeader", "Header toggle favorite: peerID=$peerID, currentFavorite=$isFavorite") + onToggleFavorite() + }, modifier = Modifier.align(Alignment.CenterEnd) ) { Icon( diff --git a/app/src/main/java/com/bitchat/android/ui/ChatState.kt b/app/src/main/java/com/bitchat/android/ui/ChatState.kt index 9dc16cf6..7309d2fc 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatState.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatState.kt @@ -1,5 +1,6 @@ package com.bitchat.android.ui +import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData @@ -188,6 +189,7 @@ class ChatState { } fun setFavoritePeers(favorites: Set) { + Log.d("ChatState", "setFavoritePeers called with ${favorites.size} favorites: $favorites") _favoritePeers.value = favorites } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 66502fd6..e8ad9c8d 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -2,6 +2,7 @@ package com.bitchat.android.ui import android.app.Application import android.content.Context +import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope @@ -100,6 +101,10 @@ class ChatViewModel( state.setFavoritePeers(dataManager.favoritePeers) dataManager.loadBlockedUsers() + // Log all favorites at startup + dataManager.logAllFavorites() + logCurrentFavoriteState() + // Note: Mesh service is now started by MainActivity // Show welcome message if no peers after delay @@ -249,7 +254,19 @@ class ChatViewModel( } fun toggleFavorite(peerID: String) { + Log.d("ChatViewModel", "toggleFavorite called for peerID: $peerID") privateChatManager.toggleFavorite(peerID) + + // Log current state after toggle + logCurrentFavoriteState() + } + + private fun logCurrentFavoriteState() { + Log.i("ChatViewModel", "=== CURRENT FAVORITE STATE ===") + Log.i("ChatViewModel", "LiveData favorite peers: ${favoritePeers.value}") + Log.i("ChatViewModel", "DataManager favorite peers: ${dataManager.favoritePeers}") + Log.i("ChatViewModel", "Peer fingerprints: ${privateChatManager.getAllPeerFingerprints()}") + Log.i("ChatViewModel", "==============================") } // MARK: - Debug and Troubleshooting diff --git a/app/src/main/java/com/bitchat/android/ui/DataManager.kt b/app/src/main/java/com/bitchat/android/ui/DataManager.kt index 73ffbcfe..0f16a1e0 100644 --- a/app/src/main/java/com/bitchat/android/ui/DataManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/DataManager.kt @@ -2,6 +2,7 @@ package com.bitchat.android.ui import android.content.Context import android.content.SharedPreferences +import android.util.Log import com.google.gson.Gson import kotlin.random.Random @@ -10,6 +11,10 @@ import kotlin.random.Random */ class DataManager(private val context: Context) { + companion object { + private const val TAG = "DataManager" + } + private val prefs: SharedPreferences = context.getSharedPreferences("bitchat_prefs", Context.MODE_PRIVATE) private val gson = Gson() @@ -126,24 +131,41 @@ class DataManager(private val context: Context) { fun loadFavorites() { val savedFavorites = prefs.getStringSet("favorites", emptySet()) ?: emptySet() _favoritePeers.addAll(savedFavorites) + Log.d(TAG, "Loaded ${savedFavorites.size} favorite users from storage: $savedFavorites") } fun saveFavorites() { prefs.edit().putStringSet("favorites", _favoritePeers).apply() + Log.d(TAG, "Saved ${_favoritePeers.size} favorite users to storage: $_favoritePeers") } fun addFavorite(fingerprint: String) { - _favoritePeers.add(fingerprint) + val wasAdded = _favoritePeers.add(fingerprint) + Log.d(TAG, "addFavorite: fingerprint=$fingerprint, wasAdded=$wasAdded") saveFavorites() + logAllFavorites() } fun removeFavorite(fingerprint: String) { - _favoritePeers.remove(fingerprint) + val wasRemoved = _favoritePeers.remove(fingerprint) + Log.d(TAG, "removeFavorite: fingerprint=$fingerprint, wasRemoved=$wasRemoved") saveFavorites() + logAllFavorites() } fun isFavorite(fingerprint: String): Boolean { - return _favoritePeers.contains(fingerprint) + val result = _favoritePeers.contains(fingerprint) + Log.d(TAG, "isFavorite check: fingerprint=$fingerprint, result=$result") + return result + } + + fun logAllFavorites() { + Log.i(TAG, "=== ALL FAVORITE USERS ===") + Log.i(TAG, "Total favorites: ${_favoritePeers.size}") + _favoritePeers.forEach { fingerprint -> + Log.i(TAG, "Favorite fingerprint: $fingerprint") + } + Log.i(TAG, "========================") } // MARK: - Blocked Users Management diff --git a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt index cb94ab4e..ceead27f 100644 --- a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt @@ -3,6 +3,7 @@ package com.bitchat.android.ui import com.bitchat.android.model.BitchatMessage import com.bitchat.android.model.DeliveryStatus import java.util.* +import android.util.Log /** * Handles private chat functionality including peer management and blocking @@ -13,6 +14,10 @@ class PrivateChatManager( private val dataManager: DataManager ) { + companion object { + private const val TAG = "PrivateChatManager" + } + // Peer identification mapping private val peerIDToPublicKeyFingerprint = mutableMapOf() @@ -99,17 +104,39 @@ class PrivateChatManager( fun toggleFavorite(peerID: String) { val fingerprint = peerIDToPublicKeyFingerprint[peerID] ?: return - if (dataManager.isFavorite(fingerprint)) { + Log.d(TAG, "toggleFavorite called for peerID: $peerID, fingerprint: $fingerprint") + + val wasFavorite = dataManager.isFavorite(fingerprint) + Log.d(TAG, "Current favorite status: $wasFavorite") + + if (wasFavorite) { dataManager.removeFavorite(fingerprint) + Log.d(TAG, "Removed from favorites: $fingerprint") } else { dataManager.addFavorite(fingerprint) + Log.d(TAG, "Added to favorites: $fingerprint") } + + // Update state to trigger UI refresh state.setFavoritePeers(dataManager.favoritePeers) + + Log.d(TAG, "Updated favorite peers state. New favorites: ${dataManager.favoritePeers}") + Log.d(TAG, "All peer fingerprints: $peerIDToPublicKeyFingerprint") } fun isFavorite(peerID: String): Boolean { val fingerprint = peerIDToPublicKeyFingerprint[peerID] ?: return false - return dataManager.isFavorite(fingerprint) + val isFav = dataManager.isFavorite(fingerprint) + Log.d(TAG, "isFavorite check: peerID=$peerID, fingerprint=$fingerprint, result=$isFav") + return isFav + } + + fun getPeerFingerprint(peerID: String): String? { + return peerIDToPublicKeyFingerprint[peerID] + } + + fun getPeerFingerprints(): Map { + return peerIDToPublicKeyFingerprint.toMap() } // MARK: - Block/Unblock Operations @@ -262,10 +289,6 @@ class PrivateChatManager( // MARK: - Public Getters - fun getPeerFingerprint(peerID: String): String? { - return peerIDToPublicKeyFingerprint[peerID] - } - fun getAllPeerFingerprints(): Map { return peerIDToPublicKeyFingerprint.toMap() } diff --git a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt index a7ee2c4f..2bc7750d 100644 --- a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt +++ b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt @@ -1,5 +1,6 @@ package com.bitchat.android.ui +import android.util.Log import androidx.compose.animation.* import androidx.compose.animation.core.* import androidx.compose.foundation.* @@ -275,16 +276,22 @@ fun PeopleSection( ) sortedPeers.forEach { peerID -> + val fingerprint = viewModel.privateChatManager.getPeerFingerprint(peerID) + val isFavorite = favoritePeers.contains(fingerprint) + PeerItem( peerID = peerID, displayName = if (peerID == nickname) "You" else (peerNicknames[peerID] ?: peerID), signalStrength = peerRSSI[peerID] ?: 0, isSelected = peerID == selectedPrivatePeer, - isFavorite = favoritePeers.contains(viewModel.privateChatManager.getPeerFingerprint(peerID)), + isFavorite = isFavorite, hasUnreadDM = hasUnreadPrivateMessages.contains(peerID), colorScheme = colorScheme, onItemClick = { onPrivateChatStart(peerID) }, - onToggleFavorite = { viewModel.toggleFavorite(peerID) } + onToggleFavorite = { + Log.d("SidebarComponents", "Sidebar toggle favorite: peerID=$peerID, fingerprint=$fingerprint, currentFavorite=$isFavorite") + viewModel.toggleFavorite(peerID) + } ) } } From a97e2549b8adf9abb340bca0c6b19a4716000d81 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:11:19 +0200 Subject: [PATCH 06/13] fix fav updates --- .../java/com/bitchat/android/ui/ChatHeader.kt | 10 ++++++++-- .../java/com/bitchat/android/ui/ChatState.kt | 9 +++++++++ .../bitchat/android/ui/PrivateChatManager.kt | 10 +++++++--- .../bitchat/android/ui/SidebarComponents.kt | 20 ++++++++++++------- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt index 2916d8a3..65e2ee8e 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt @@ -152,11 +152,17 @@ fun ChatHeaderContent( when { selectedPrivatePeer != null -> { - // Private chat header + // Private chat header - ensure state synchronization + val favoritePeers by viewModel.favoritePeers.observeAsState(emptySet()) + val fingerprint = viewModel.privateChatManager.getPeerFingerprint(selectedPrivatePeer) + val isFavorite = favoritePeers.contains(fingerprint) + + Log.d("ChatHeader", "Header recomposing: peer=$selectedPrivatePeer, fingerprint=$fingerprint, isFav=$isFavorite") + PrivateChatHeader( peerID = selectedPrivatePeer, peerNicknames = viewModel.meshService.getPeerNicknames(), - isFavorite = viewModel.isFavorite(selectedPrivatePeer), + isFavorite = isFavorite, onBackClick = onBackClick, onToggleFavorite = { viewModel.toggleFavorite(selectedPrivatePeer) } ) diff --git a/app/src/main/java/com/bitchat/android/ui/ChatState.kt b/app/src/main/java/com/bitchat/android/ui/ChatState.kt index 7309d2fc..748062b1 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatState.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatState.kt @@ -189,8 +189,17 @@ class ChatState { } fun setFavoritePeers(favorites: Set) { + val currentValue = _favoritePeers.value ?: emptySet() Log.d("ChatState", "setFavoritePeers called with ${favorites.size} favorites: $favorites") + Log.d("ChatState", "Current value: $currentValue") + Log.d("ChatState", "Values equal: ${currentValue == favorites}") + Log.d("ChatState", "Setting on thread: ${Thread.currentThread().name}") + + // Always set the value - even if equal, this ensures observers are triggered _favoritePeers.value = favorites + + Log.d("ChatState", "LiveData value after set: ${_favoritePeers.value}") + Log.d("ChatState", "LiveData has active observers: ${_favoritePeers.hasActiveObservers()}") } } diff --git a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt index ceead27f..6c70241e 100644 --- a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt @@ -109,6 +109,9 @@ class PrivateChatManager( val wasFavorite = dataManager.isFavorite(fingerprint) Log.d(TAG, "Current favorite status: $wasFavorite") + val currentFavorites = state.getFavoritePeersValue() + Log.d(TAG, "Current UI state favorites: $currentFavorites") + if (wasFavorite) { dataManager.removeFavorite(fingerprint) Log.d(TAG, "Removed from favorites: $fingerprint") @@ -117,10 +120,11 @@ class PrivateChatManager( Log.d(TAG, "Added to favorites: $fingerprint") } - // Update state to trigger UI refresh - state.setFavoritePeers(dataManager.favoritePeers) + // Always update state to trigger UI refresh - create new set to ensure change detection + val newFavorites = dataManager.favoritePeers.toSet() + state.setFavoritePeers(newFavorites) - Log.d(TAG, "Updated favorite peers state. New favorites: ${dataManager.favoritePeers}") + Log.d(TAG, "Force updated favorite peers state. New favorites: $newFavorites") Log.d(TAG, "All peer fingerprints: $peerIDToPublicKeyFingerprint") } diff --git a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt index 2bc7750d..4186a76f 100644 --- a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt +++ b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt @@ -264,20 +264,26 @@ fun PeopleSection( val privateChats by viewModel.privateChats.observeAsState(emptyMap()) val favoritePeers by viewModel.favoritePeers.observeAsState(emptySet()) + // Pre-calculate all favorite states to ensure proper state synchronization + val peerFavoriteStates = remember(favoritePeers, connectedPeers) { + connectedPeers.associateWith { peerID -> + val fingerprint = viewModel.privateChatManager.getPeerFingerprint(peerID) + favoritePeers.contains(fingerprint) + } + } + + Log.d("SidebarComponents", "Recomposing with ${favoritePeers.size} favorites, peer states: $peerFavoriteStates") + // Smart sorting: unread DMs first, then by most recent DM, then favorites, then alphabetical val sortedPeers = connectedPeers.sortedWith( compareBy { !hasUnreadPrivateMessages.contains(it) } // Unread DM senders first .thenByDescending { privateChats[it]?.maxByOrNull { msg -> msg.timestamp }?.timestamp?.time ?: 0L } // Most recent DM (convert Date to Long) - .thenBy { - val fingerprint = viewModel.privateChatManager.getPeerFingerprint(it) - fingerprint == null || !favoritePeers.contains(fingerprint) - } // Favorites + .thenBy { !(peerFavoriteStates[it] ?: false) } // Favorites first .thenBy { (if (it == nickname) "You" else (peerNicknames[it] ?: it)).lowercase() } // Alphabetical ) sortedPeers.forEach { peerID -> - val fingerprint = viewModel.privateChatManager.getPeerFingerprint(peerID) - val isFavorite = favoritePeers.contains(fingerprint) + val isFavorite = peerFavoriteStates[peerID] ?: false PeerItem( peerID = peerID, @@ -289,7 +295,7 @@ fun PeopleSection( colorScheme = colorScheme, onItemClick = { onPrivateChatStart(peerID) }, onToggleFavorite = { - Log.d("SidebarComponents", "Sidebar toggle favorite: peerID=$peerID, fingerprint=$fingerprint, currentFavorite=$isFavorite") + Log.d("SidebarComponents", "Sidebar toggle favorite: peerID=$peerID, currentFavorite=$isFavorite") viewModel.toggleFavorite(peerID) } ) From 8eab430022e58c83df93db3412de6dfa92a5aa82 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:24:11 +0200 Subject: [PATCH 07/13] bump to 0.6 --- CHANGELOG.md | 31 +++++++++++- CHAT_REFACTORING_PLAN.md | 64 ----------------------- REFACTORING_PROGRESS.md | 103 -------------------------------------- RSSI_COLOR_FIX_SUMMARY.md | 80 ----------------------------- app/build.gradle.kts | 4 +- demo_colors.md | 62 ----------------------- refactoring_plan.md | 73 --------------------------- 7 files changed, 32 insertions(+), 385 deletions(-) delete mode 100644 CHAT_REFACTORING_PLAN.md delete mode 100644 REFACTORING_PROGRESS.md delete mode 100644 RSSI_COLOR_FIX_SUMMARY.md delete mode 100644 demo_colors.md delete mode 100644 refactoring_plan.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c586165d..4a5ca76b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.6] + +### Added +- Channel password management with `/pass` command for channel owners +- Monochrome/themed launcher icon for Android 12+ dynamic theming support +- Unit tests package with initial testing infrastructure +- Production build optimization with code minification and shrinking ### Fixed +- Favorite peer functionality completely restored and improved + - Enhanced favorite system with fallback mechanism for peers without key exchange + - Fixed UI state updates for favorite stars in both header and sidebar + - Improved favorite persistence across app sessions - `/w` command now displays user nicknames instead of peer IDs +- Button styling and layout improvements across the app + - Enhanced back button positioning and styling + - Improved private chat and channel header button layouts + - Fixed button padding and alignment issues +- Color scheme consistency updates + - Updated orange color throughout the app to match iOS version + - Consistent color usage for private messages and UI elements +- App startup reliability improvements + - Better initialization sequence handling + - Fixed null pointer exceptions during startup + - Enhanced error handling and logging +- Input field styling and behavior improvements +- Sidebar user interaction enhancements +- Permission explanation screen layout fixes with proper vertical padding + +### Changed +- Updated GitHub organization references in project files +- Improved README documentation with updated clone URLs +- Enhanced logging throughout the application for better debugging ## [0.5.1] - 2025-07-10 diff --git a/CHAT_REFACTORING_PLAN.md b/CHAT_REFACTORING_PLAN.md deleted file mode 100644 index 934366cb..00000000 --- a/CHAT_REFACTORING_PLAN.md +++ /dev/null @@ -1,64 +0,0 @@ -# ChatScreen.kt Refactoring Plan - -## Current State -- Single file: `ChatScreen.kt` (~1,100+ lines) -- Multiple UI responsibilities mixed together -- Hard to maintain and test individual components - -## Proposed Component Structure - -### 1. Main Screen (ChatScreen.kt) -**Responsibilities:** -- Main layout orchestration -- State management delegation -- Window insets handling -- Component coordination - -### 2. Header Components (ChatHeader.kt) -**Responsibilities:** -- TopAppBar with different states (main, private, channel) -- Nickname editor -- Peer counter with status indicators -- Navigation controls - -### 3. Message Components (MessageComponents.kt) -**Responsibilities:** -- MessagesList composable -- MessageItem with formatting -- Message text parsing and styling -- Delivery status indicators -- RSSI-based coloring - -### 4. Input Components (InputComponents.kt) -**Responsibilities:** -- MessageInput with different modes -- Command suggestions box -- Command suggestion items -- Input validation and handling - -### 5. Sidebar Components (SidebarComponents.kt) -**Responsibilities:** -- SidebarOverlay with navigation -- ChannelsSection for channel management -- PeopleSection for peer list -- Sidebar state management - -### 6. Dialog Components (DialogComponents.kt) -**Responsibilities:** -- Password prompt dialog -- App info dialog -- Other modal dialogs - -### 7. UI Utils (ChatUIUtils.kt) -**Responsibilities:** -- RSSI color mapping -- Text formatting utilities -- Common styling constants -- Helper functions - -## Benefits -- Each file has a single, clear responsibility -- Components are easier to test in isolation -- Better code organization and navigation -- Simplified debugging -- Easier to add new UI features diff --git a/REFACTORING_PROGRESS.md b/REFACTORING_PROGRESS.md deleted file mode 100644 index 147a91d0..00000000 --- a/REFACTORING_PROGRESS.md +++ /dev/null @@ -1,103 +0,0 @@ -# BluetoothMeshService Refactoring - Progress Report - -## ✅ COMPLETED: Extracted Components (All compile successfully) - -### 1. PeerManager.kt (161 lines) -**Responsibilities:** -- Active peer tracking and lifecycle management -- Peer nickname management and stale peer cleanup -- RSSI tracking and peer list updates -- **Interface:** `PeerManagerDelegate` - -### 2. FragmentManager.kt (194 lines) -**Responsibilities:** -- Message fragmentation for large messages (>500 bytes) -- Fragment reassembly and cleanup -- Fragment timeout management (30 seconds) -- **Interface:** `FragmentManagerDelegate` - -### 3. SecurityManager.kt (236 lines) -**Responsibilities:** -- Duplicate detection and replay attack protection -- Key exchange handling and validation -- Message encryption/decryption operations -- Packet signature verification -- **Interface:** `SecurityManagerDelegate` - -### 4. StoreForwardManager.kt (295 lines) -**Responsibilities:** -- Message caching for offline peers (12 hours regular, unlimited favorites) -- Store-and-forward delivery when peers come online -- Cache cleanup and management -- **Interface:** `StoreForwardManagerDelegate` - -### 5. MessageHandler.kt (284 lines) -**Responsibilities:** -- Processing different message types (ANNOUNCE, MESSAGE, LEAVE, etc.) -- Broadcast vs private message handling -- Message relay logic with adaptive probability -- Delivery acknowledgment sending -- **Interface:** `MessageHandlerDelegate` - -### 6. BluetoothConnectionManager.kt (611 lines) -**Responsibilities:** -- BLE advertising and scanning -- GATT server/client setup and management -- Device connection tracking (both server and client modes) -- Packet broadcasting to all connected devices -- **Interface:** `BluetoothConnectionManagerDelegate` - -## 📊 Size Reduction Analysis - -| Component | Lines | Responsibility | -|-----------|--------|----------------| -| **PeerManager** | 161 | Peer lifecycle & tracking | -| **FragmentManager** | 194 | Message fragmentation | -| **SecurityManager** | 236 | Security & encryption | -| **StoreForwardManager** | 295 | Offline message caching | -| **MessageHandler** | 284 | Message type processing | -| **BluetoothConnectionManager** | 611 | BLE connection management | -| **Original File** | ~1000+ | All responsibilities mixed | - -**Total Extracted:** ~1781 lines (distributed across 6 focused files) -**Reduction Factor:** Original single file → 6 smaller, focused components - -## 🏗️ Next Steps for Integration - -### Phase 1: Refactor Existing BluetoothMeshService -1. **Update BluetoothMeshService.kt** to use the new components -2. **Wire up all delegate interfaces** -3. **Maintain exact same public API** so ChatViewModel doesn't change -4. **Test compilation and functionality** - -### Phase 2: Integration Testing -1. **Verify all existing functionality works** -2. **Test key scenarios:** - - Peer discovery and connection - - Message sending/receiving - - Fragment handling - - Store-and-forward delivery - - Security validation - -### Phase 3: Benefits Validation -1. **Easier unit testing** (each component can be tested independently) -2. **Better code maintainability** (clear separation of concerns) -3. **Improved debugging** (isolated component logs) -4. **Future extensibility** (easier to add new features) - -## 🔧 Current Build Status -✅ **All 6 extracted components compile successfully** -✅ **No breaking changes to existing interfaces** -✅ **Original BluetoothMeshService.kt still intact** -✅ **Ready for integration phase** - -## 💡 Key Design Decisions Made - -1. **Delegate Pattern:** Each component uses a delegate interface for clean separation -2. **Coroutine Scope per Component:** Isolated lifecycle management -3. **Thread-Safe Collections:** Maintained from original implementation -4. **Same UUIDs and Constants:** No protocol changes -5. **Preserved iOS Compatibility:** All timing and logic matches iOS exactly -6. **Error Handling:** Maintained original defensive programming patterns - -The refactoring successfully breaks down a monolithic 1000+ line service into 6 focused, maintainable components while preserving 100% compatibility with the iOS implementation. diff --git a/RSSI_COLOR_FIX_SUMMARY.md b/RSSI_COLOR_FIX_SUMMARY.md deleted file mode 100644 index 78c616c5..00000000 --- a/RSSI_COLOR_FIX_SUMMARY.md +++ /dev/null @@ -1,80 +0,0 @@ -# RSSI Color Change Fix - Implementation Summary - -## Problem Identified -The username colors in the chat were not changing based on RSSI signal strength even though RSSI values were being logged as changing. Investigation revealed that: - -1. **RSSI values were only captured once** during the initial BLE scan discovery -2. **No mechanism existed** to continuously update RSSI values from connected devices -3. **UI was not being notified** of RSSI changes to trigger recomposition -4. **Chat rendering was using stale RSSI values** that never changed after initial connection - -## Root Cause -The `BluetoothMeshService` was only recording RSSI during the scan phase (`handleScanResult`) but never updating it during the connection lifetime. Bluetooth GATT provides `readRemoteRssi()` for connected devices, but this wasn't being used. - -## Solution Implemented - -### 1. Device-to-Peer ID Mapping -- Added `deviceToPeerIDMapping` to link Bluetooth devices to peer IDs -- This allows RSSI updates to be associated with the correct peer ID - -### 2. GATT RSSI Reading Callback -- Added `onReadRemoteRssi()` callback in the GATT client callback -- Updates `peerRSSI` map when new RSSI values are read -- Maps device addresses to peer IDs for proper tracking - -### 3. Periodic RSSI Monitoring -- Added background coroutine that runs every 5 seconds -- Calls `readRemoteRssi()` on all active GATT connections -- Provides continuous RSSI updates during connection lifetime - -### 4. UI Notification System -- Added `didUpdateRSSI()` delegate method to notify UI of RSSI changes -- When RSSI changes, the delegate is called to potentially trigger UI updates -- Chat screen automatically recomposes when RSSI values change - -### 5. Key Exchange Enhancement -- Modified `handleKeyExchange()` to map devices to peer IDs -- Transfers any existing peripheral RSSI data to peer-based tracking -- Ensures proper RSSI association after peer identification - -## Code Changes Made - -### BluetoothMeshService.kt -1. **Added device mapping**: `deviceToPeerIDMapping` concurrent hash map -2. **RSSI callback**: `onReadRemoteRssi()` implementation in GATT callback -3. **Periodic monitoring**: `monitorRSSI()` function called every 5 seconds -4. **Key exchange update**: Links devices to peer IDs for RSSI tracking -5. **Delegate method**: `didUpdateRSSI()` interface method for UI notifications - -### ChatViewModel.kt -1. **Delegate implementation**: Added `didUpdateRSSI()` method -2. **Logging**: Debug output when RSSI values change - -### ChatScreen.kt -- **No changes needed** - existing `getRSSIColor(rssi)` function already works -- UI automatically recomposes when `meshService.getPeerRSSI()` returns updated values - -## How It Works Now - -1. **Initial Discovery**: RSSI captured during BLE scan (as before) -2. **Connection**: Device mapped to peer ID during key exchange -3. **Monitoring**: Every 5 seconds, `readRemoteRssi()` called on connected devices -4. **Update**: RSSI callback updates `peerRSSI` map with new values -5. **Notification**: Delegate notified of RSSI change -6. **Rendering**: Chat screen uses updated RSSI values for color calculation -7. **Recomposition**: UI automatically updates with new colors - -## Expected Behavior -- Username colors now change dynamically as users move closer/farther away -- Colors reflect real-time signal strength: green (strong) → yellow (medium) → red (weak) -- Updates occur every 5 seconds while devices are connected -- Your own username remains green regardless of signal strength -- Works for both client and server GATT connections - -## Testing -- Build successful with `./gradlew assembleDebug` -- No compilation errors -- All existing functionality preserved -- Ready for testing with actual devices - -The fix addresses the core issue where RSSI values were static after connection. Now they continuously update, providing the dynamic color feedback based on signal strength that was originally intended. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ce8717bd..be7f1b23 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "com.bitchat.android" minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 1 - versionName = "1.0" + versionCode = 2 + versionName = "0.6" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/demo_colors.md b/demo_colors.md deleted file mode 100644 index c463b41c..00000000 --- a/demo_colors.md +++ /dev/null @@ -1,62 +0,0 @@ -# Username Color Feature Demo - -The bitchat Android app already has the username color feature fully implemented! Here's how it works: - -## How It Works - -1. **Your username remains green** - Uses `colorScheme.primary` (bright green in dark mode, dark green in light mode) -2. **Other users get unique colors** - Based on their peer ID using the `getUsernameColor()` function -3. **Colors are consistent** - Same user always gets the same color across sessions -4. **Terminal-friendly palette** - 16 colors that work on both black and white backgrounds - -## Color Palette - -The system uses these 16 terminal-friendly colors for other users: - -- 🟢 Bright Green (#00FF00) -- 🔵 Cyan (#00FFFF) -- 🟡 Yellow (#FFFF00) -- 🔴 Magenta (#FF00FF) -- 🟦 Bright Blue (#0080FF) -- 🟠 Orange (#FF8000) -- 🔶 Lime Green (#80FF00) -- 🟣 Purple (#8000FF) -- 🩷 Pink (#FF0080) -- 💚 Spring Green (#00FF80) -- 🟦 Light Cyan (#80FFFF) -- 🩷 Light Red (#FF8080) -- 🟦 Light Blue (#8080FF) -- 🟡 Light Yellow (#FFFF80) -- 🩷 Light Magenta (#FF80FF) -- 🟢 Light Green (#80FF80) - -## Example Chat Display - -``` -[14:23:45] <@you> hello everyone! ← Your message (green) -[14:23:47] <@alice> hey there! ← Alice (cyan) -[14:23:50] <@bob> how's it going? ← Bob (yellow) -[14:23:52] <@charlie> great to see you all ← Charlie (magenta) -[14:23:55] <@you> having a great time ← Your message (green) -[14:23:58] <@alice> same here @you! ← Alice (cyan again) -``` - -## Code Implementation - -The feature is implemented in `/app/src/main/java/com/bitchat/android/ui/ChatScreen.kt`: - -- Line 342-350: Color assignment logic in `formatMessageAsAnnotatedString()` -- Line 820-855: `getUsernameColor()` function that generates consistent colors -- Uses peer ID for consistency (falls back to nickname if no peer ID available) -- Integrates perfectly with the existing IRC-style chat format - -## Testing - -The feature is already working in the app. When you chat with multiple users, you'll see: -- Your messages in green -- Each other user in their own unique color -- Same user always has the same color -- Colors remain consistent across app restarts -- Works in both light and dark themes - -The feature is **complete and ready to use**! 🎉 diff --git a/refactoring_plan.md b/refactoring_plan.md deleted file mode 100644 index fe61e413..00000000 --- a/refactoring_plan.md +++ /dev/null @@ -1,73 +0,0 @@ -# BluetoothMeshService Refactoring Plan - -## Current State -- Single file: `BluetoothMeshService.kt` (~1000+ lines) -- Multiple responsibilities mixed together -- Hard to test and maintain - -## Proposed Structure - -### 1. Core Service (BluetoothMeshService.kt) -**Responsibilities:** -- Service lifecycle management -- Coordination between components -- Public API for sending messages -- Delegate management - -### 2. Connection Management (BluetoothConnectionManager.kt) -**Responsibilities:** -- BLE scanning and advertising -- GATT server/client setup and management -- Device connection tracking -- Peer discovery and RSSI tracking - -### 3. Packet Processing (PacketProcessor.kt) -**Responsibilities:** -- Incoming packet handling -- Message type routing -- TTL and duplicate detection -- Timestamp validation - -### 4. Message Handler (MessageHandler.kt) -**Responsibilities:** -- Processing specific message types (ANNOUNCE, MESSAGE, LEAVE, etc.) -- Message parsing and validation -- Relay logic - -### 5. Fragment Manager (FragmentManager.kt) -**Responsibilities:** -- Message fragmentation for large messages -- Fragment reassembly -- Fragment cleanup and timeouts - -### 6. Store-and-Forward Manager (StoreForwardManager.kt) -**Responsibilities:** -- Message caching for offline peers -- Delivering cached messages when peers come online -- Cache cleanup and management - -### 7. Peer Manager (PeerManager.kt) -**Responsibilities:** -- Active peer tracking -- Peer nickname management -- Stale peer cleanup -- Peer list updates - -### 8. Security Manager (SecurityManager.kt) -**Responsibilities:** -- Key exchange handling -- Message signing and verification -- Duplicate detection tracking - -## Refactoring Strategy -1. Extract each component while maintaining exact functionality -2. Use dependency injection for component communication -3. Ensure all existing tests pass -4. Maintain the same public API - -## Benefits -- Easier to test individual components -- Better separation of concerns -- More maintainable code -- Easier to add new features -- Better code reuse From d490393de6590cf2aab9371a44f97c4c0ccc2891 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:32:08 +0200 Subject: [PATCH 08/13] back gesture works --- .../java/com/bitchat/android/MainActivity.kt | 20 +++++++ .../java/com/bitchat/android/ui/ChatScreen.kt | 12 ++-- .../java/com/bitchat/android/ui/ChatState.kt | 9 +++ .../com/bitchat/android/ui/ChatViewModel.kt | 56 +++++++++++++++++++ 4 files changed, 91 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index e07873e8..2323c7fd 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -18,6 +18,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.lifecycleScope import androidx.lifecycle.ViewModelProvider +import androidx.activity.OnBackPressedCallback +import androidx.activity.addCallback import com.bitchat.android.mesh.BluetoothMeshService import com.bitchat.android.onboarding.* import com.bitchat.android.ui.ChatScreen @@ -138,6 +140,24 @@ class MainActivity : ComponentActivity() { } OnboardingState.COMPLETE -> { + // Set up back navigation handling for the chat screen + val backCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // Let ChatViewModel handle navigation state + val handled = chatViewModel.handleBackPressed() + if (!handled) { + // If ChatViewModel doesn't handle it, disable this callback + // and let the system handle it (which will exit the app) + this.isEnabled = false + onBackPressedDispatcher.onBackPressed() + this.isEnabled = true + } + } + } + + // Add the callback - this will be automatically removed when the activity is destroyed + onBackPressedDispatcher.addCallback(this, backCallback) + ChatScreen(viewModel = chatViewModel) } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatScreen.kt b/app/src/main/java/com/bitchat/android/ui/ChatScreen.kt index 4fe40704..4c9e30dc 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatScreen.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatScreen.kt @@ -60,15 +60,15 @@ fun ChatScreen(viewModel: ChatViewModel) { val hasUnreadPrivateMessages by viewModel.unreadPrivateMessages.observeAsState(emptySet()) val privateChats by viewModel.privateChats.observeAsState(emptyMap()) val channelMessages by viewModel.channelMessages.observeAsState(emptyMap()) - var showSidebar by remember { mutableStateOf(false) } + val showSidebar by viewModel.showSidebar.observeAsState(false) val showCommandSuggestions by viewModel.showCommandSuggestions.observeAsState(false) val commandSuggestions by viewModel.commandSuggestions.observeAsState(emptyList()) + val showAppInfo by viewModel.showAppInfo.observeAsState(false) var messageText by remember { mutableStateOf("") } var showPasswordPrompt by remember { mutableStateOf(false) } var showPasswordDialog by remember { mutableStateOf(false) } var passwordInput by remember { mutableStateOf("") } - var showAppInfo by remember { mutableStateOf(false) } // Show password dialog when needed LaunchedEffect(showPasswordPrompt) { @@ -142,8 +142,8 @@ fun ChatScreen(viewModel: ChatViewModel) { nickname = nickname, viewModel = viewModel, colorScheme = colorScheme, - onSidebarToggle = { showSidebar = true }, - onShowAppInfo = { showAppInfo = true }, + onSidebarToggle = { viewModel.showSidebar() }, + onShowAppInfo = { viewModel.showAppInfo() }, onPanicClear = { viewModel.panicClearAllData() } ) @@ -162,7 +162,7 @@ fun ChatScreen(viewModel: ChatViewModel) { ) { SidebarOverlay( viewModel = viewModel, - onDismiss = { showSidebar = false }, + onDismiss = { viewModel.hideSidebar() }, modifier = Modifier.fillMaxSize() ) } @@ -188,7 +188,7 @@ fun ChatScreen(viewModel: ChatViewModel) { passwordInput = "" }, showAppInfo = showAppInfo, - onAppInfoDismiss = { showAppInfo = false } + onAppInfoDismiss = { viewModel.hideAppInfo() } ) } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatState.kt b/app/src/main/java/com/bitchat/android/ui/ChatState.kt index 748062b1..4a2e9bda 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatState.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatState.kt @@ -85,6 +85,10 @@ class ChatState { val peerIDToPublicKeyFingerprint = mutableMapOf() + // Navigation state + private val _showAppInfo = MutableLiveData(false) + val showAppInfo: LiveData = _showAppInfo + // Unread state computed properties val hasUnreadChannels: MediatorLiveData = MediatorLiveData() val hasUnreadPrivateMessages: MediatorLiveData = MediatorLiveData() @@ -118,6 +122,7 @@ class ChatState { fun getShowCommandSuggestionsValue() = _showCommandSuggestions.value ?: false fun getCommandSuggestionsValue() = _commandSuggestions.value ?: emptyList() fun getFavoritePeersValue() = _favoritePeers.value ?: emptySet() + fun getShowAppInfoValue() = _showAppInfo.value ?: false // Setters for state updates fun setMessages(messages: List) { @@ -201,5 +206,9 @@ class ChatState { Log.d("ChatState", "LiveData value after set: ${_favoritePeers.value}") Log.d("ChatState", "LiveData has active observers: ${_favoritePeers.hasActiveObservers()}") } + + fun setShowAppInfo(show: Boolean) { + _showAppInfo.value = show + } } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index e8ad9c8d..190f696d 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -71,6 +71,7 @@ class ChatViewModel( val showCommandSuggestions: LiveData = state.showCommandSuggestions val commandSuggestions: LiveData> = state.commandSuggestions val favoritePeers: LiveData> = state.favoritePeers + val showAppInfo: LiveData = state.showAppInfo init { // Note: Mesh service delegate is now set by MainActivity @@ -366,4 +367,59 @@ class ChatViewModel( // Note: Mesh service restart is now handled by MainActivity // This method now only clears data, not mesh service lifecycle } + + // MARK: - Navigation Management + + fun showAppInfo() { + state.setShowAppInfo(true) + } + + fun hideAppInfo() { + state.setShowAppInfo(false) + } + + fun showSidebar() { + state.setShowSidebar(true) + } + + fun hideSidebar() { + state.setShowSidebar(false) + } + + /** + * Handle Android back navigation + * Returns true if the back press was handled, false if it should be passed to the system + */ + fun handleBackPressed(): Boolean { + return when { + // Close app info dialog + state.getShowAppInfoValue() -> { + hideAppInfo() + true + } + // Close sidebar + state.getShowSidebarValue() -> { + hideSidebar() + true + } + // Close password dialog + state.getShowPasswordPromptValue() -> { + state.setShowPasswordPrompt(false) + state.setPasswordPromptChannel(null) + true + } + // Exit private chat + state.getSelectedPrivateChatPeerValue() != null -> { + endPrivateChat() + true + } + // Exit channel view + state.getCurrentChannelValue() != null -> { + switchToChannel(null) + true + } + // No special navigation state - let system handle (usually exits app) + else -> false + } + } } From bc344879e71486e968fe8c83126d0fbd25a63710 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:33:11 +0200 Subject: [PATCH 09/13] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a5ca76b..8accb389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Monochrome/themed launcher icon for Android 12+ dynamic theming support - Unit tests package with initial testing infrastructure - Production build optimization with code minification and shrinking +- Native back gesture/button handling for all app views ### Fixed - Favorite peer functionality completely restored and improved From ad6dc3680b9a7a6469f38a110481707c1acbe77f Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:40:25 +0200 Subject: [PATCH 10/13] permissions layout --- CHANGELOG.md | 5 + .../java/com/bitchat/android/MainActivity.kt | 3 - .../onboarding/PermissionExplanationScreen.kt | 213 +++++++++--------- .../android/onboarding/PermissionManager.kt | 8 +- 4 files changed, 112 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8accb389..6e8bd3aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed +- Permission onboarding screen UX: removed "Exit App" button and fixed "Grant Permissions" button positioning to always be visible + ## [0.6] ### Added diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index 2323c7fd..5997a9f1 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -124,9 +124,6 @@ class MainActivity : ComponentActivity() { onContinue = { onboardingState = OnboardingState.PERMISSION_REQUESTING onboardingCoordinator.requestPermissions() - }, - onCancel = { - finish() } ) } diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt index f09d9783..b352dc1f 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionExplanationScreen.kt @@ -21,120 +21,130 @@ import androidx.compose.ui.unit.sp @Composable fun PermissionExplanationScreen( permissionCategories: List, - onContinue: () -> Unit, - onCancel: () -> Unit + onContinue: () -> Unit ) { val colorScheme = MaterialTheme.colorScheme val scrollState = rememberScrollState() - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 24.dp) - .verticalScroll(scrollState), - verticalArrangement = Arrangement.spacedBy(16.dp) + Box( + modifier = Modifier.fillMaxSize() ) { - Spacer(modifier = Modifier.height(24.dp)) - // Header + // Scrollable content Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = "Welcome to bitchat*", - style = MaterialTheme.typography.headlineMedium.copy( - fontFamily = FontFamily.Monospace, - fontWeight = FontWeight.Bold, - color = colorScheme.primary - ), - textAlign = TextAlign.Center - ) - - Spacer(modifier = Modifier.height(8.dp)) - - Text( - text = "Decentralized mesh messaging over Bluetooth", - style = MaterialTheme.typography.bodyMedium.copy( - fontFamily = FontFamily.Monospace, - color = colorScheme.onSurface.copy(alpha = 0.7f) - ), - textAlign = TextAlign.Center - ) - } - - Spacer(modifier = Modifier.height(16.dp)) - - // Privacy assurance section - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = colorScheme.surfaceVariant.copy(alpha = 0.3f) - ), - elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 24.dp) + .padding(bottom = 88.dp) // Leave space for the fixed button + .verticalScroll(scrollState), + verticalArrangement = Arrangement.spacedBy(16.dp) ) { + Spacer(modifier = Modifier.height(24.dp)) + // Header Column( - modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + Text( + text = "Welcome to bitchat*", + style = MaterialTheme.typography.headlineMedium.copy( + fontFamily = FontFamily.Monospace, + fontWeight = FontWeight.Bold, + color = colorScheme.primary + ), + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "Decentralized mesh messaging over Bluetooth", + style = MaterialTheme.typography.bodyMedium.copy( + fontFamily = FontFamily.Monospace, + color = colorScheme.onSurface.copy(alpha = 0.7f) + ), + textAlign = TextAlign.Center + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + // Privacy assurance section + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = colorScheme.surfaceVariant.copy(alpha = 0.3f) + ), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "🔒", + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.size(20.dp) + ) + Text( + text = "Your Privacy is Protected", + style = MaterialTheme.typography.titleSmall.copy( + fontWeight = FontWeight.Bold, + color = colorScheme.onSurface + ) + ) + } + Text( - text = "🔒", - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.size(20.dp) - ) - Text( - text = "Your Privacy is Protected", - style = MaterialTheme.typography.titleSmall.copy( - fontWeight = FontWeight.Bold, - color = colorScheme.onSurface + text = "• bitchat doesn't track you or collect personal data\n" + + "• No servers, no internet required, no data logging\n" + + "• Location permission is only used by Android for Bluetooth scanning\n" + + "• Your messages stay on your device and peer devices only", + style = MaterialTheme.typography.bodySmall.copy( + fontFamily = FontFamily.Monospace, + color = colorScheme.onSurface.copy(alpha = 0.8f) ) ) } - - Text( - text = "• bitchat doesn't track you or collect personal data\n" + - "• No servers, no internet required, no data logging\n" + - "• Location permission is only used by Android for Bluetooth scanning\n" + - "• Your messages stay on your device and peer devices only", - style = MaterialTheme.typography.bodySmall.copy( - fontFamily = FontFamily.Monospace, - color = colorScheme.onSurface.copy(alpha = 0.8f) - ) + } + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "To work properly, bitchat needs these permissions:", + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium, + color = colorScheme.onSurface + ) + ) + + // Permission categories + permissionCategories.forEach { category -> + PermissionCategoryCard( + category = category, + colorScheme = colorScheme ) } + + Spacer(modifier = Modifier.height(24.dp)) } - Spacer(modifier = Modifier.height(8.dp)) - - Text( - text = "To work properly, bitchat needs these permissions:", - style = MaterialTheme.typography.bodyMedium.copy( - fontWeight = FontWeight.Medium, - color = colorScheme.onSurface - ) - ) - - // Permission categories - permissionCategories.forEach { category -> - PermissionCategoryCard( - category = category, - colorScheme = colorScheme - ) - } - - Spacer(modifier = Modifier.height(16.dp)) - - // Action buttons - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(12.dp) + // Fixed button at bottom + Surface( + modifier = Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth(), + color = colorScheme.surface, + shadowElevation = 8.dp ) { Button( onClick = onContinue, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp, vertical = 16.dp), colors = ButtonDefaults.buttonColors( containerColor = colorScheme.primary ) @@ -148,24 +158,7 @@ fun PermissionExplanationScreen( modifier = Modifier.padding(vertical = 4.dp) ) } - - OutlinedButton( - onClick = onCancel, - modifier = Modifier.fillMaxWidth(), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = colorScheme.onSurface.copy(alpha = 0.7f) - ) - ) { - Text( - text = "Exit App", - style = MaterialTheme.typography.bodyMedium.copy( - fontFamily = FontFamily.Monospace - ), - modifier = Modifier.padding(vertical = 4.dp) - ) - } } - Spacer(modifier = Modifier.height(24.dp)) } } diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt index 7060fb1c..38ea0d6f 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt @@ -116,7 +116,7 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( name = "Nearby Devices", - description = "Required to discover and connect to other bitchat users via Bluetooth", + description = "Required to discover bitchat users via Bluetooth", permissions = bluetoothPermissions, isGranted = bluetoothPermissions.all { isPermissionGranted(it) }, systemDescription = "Allow bitchat to connect to nearby devices" @@ -132,10 +132,10 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( name = "Precise Location", - description = "Required by Android for Bluetooth scanning.", + description = "Required by Android to discover nearby bitchat users via Bluetooth", permissions = locationPermissions, isGranted = locationPermissions.all { isPermissionGranted(it) }, - systemDescription = "Allow bitchat to access this device's location" + systemDescription = "bitchat needs this to scan for nearby devices" ) ) @@ -144,7 +144,7 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( name = "Notifications", - description = "Show notifications when you receive private messages while the app is in background", + description = "Notifications to keep you updated", permissions = listOf(Manifest.permission.POST_NOTIFICATIONS), isGranted = isPermissionGranted(Manifest.permission.POST_NOTIFICATIONS), systemDescription = "Allow bitchat to send you notifications" From ee70073324395b10046c0c9be7d2c2b0f2993b9a Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 17:43:13 +0200 Subject: [PATCH 11/13] notifications description --- .../java/com/bitchat/android/onboarding/PermissionManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt index 5db01a2d..7d293324 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt @@ -144,7 +144,7 @@ class PermissionManager(private val context: Context) { categories.add( PermissionCategory( type = PermissionType.NOTIFICATIONS, - description = "Notifications to keep you updated", + description = "Receive notifications when you receive private messages", permissions = listOf(Manifest.permission.POST_NOTIFICATIONS), isGranted = isPermissionGranted(Manifest.permission.POST_NOTIFICATIONS), systemDescription = "Allow bitchat to send you notifications" From ce93900ef6c45c6ed9721c404caf57ae55391b6f Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 18:43:35 +0200 Subject: [PATCH 12/13] icons --- .../res/drawable/ic_launcher_background.xml | 10 +-- .../res/drawable/ic_launcher_foreground.xml | 60 +++------------ .../res/drawable/ic_launcher_monochrome.xml | 70 ++++-------------- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 575 -> 2265 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 575 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 661 -> 1295 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 661 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 726 -> 3009 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 726 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1115 -> 4975 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 1115 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 2162 -> 7449 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 2162 -> 0 bytes 13 files changed, 30 insertions(+), 110 deletions(-) delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index faef2e6f..b63113ef 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,10 +1,10 @@ + android:height="108dp"> + android:pathData="M-0.2617076 -0.1145289H135.7284V135.5812H-0.2617076V-0.1145289Z" + android:fillColor="#000000" /> diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 91e2961e..dbc4ad64 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,51 +1,15 @@ - - - - - - - - - - - - - - - - - - - - - - + android:height="108dp"> + + + diff --git a/app/src/main/res/drawable/ic_launcher_monochrome.xml b/app/src/main/res/drawable/ic_launcher_monochrome.xml index c531b643..a9e8c8af 100644 --- a/app/src/main/res/drawable/ic_launcher_monochrome.xml +++ b/app/src/main/res/drawable/ic_launcher_monochrome.xml @@ -1,60 +1,16 @@ - - - - - - - - - - + android:height="108dp"> + + + diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index 096a00946c109c45ddd88b93da5ecdacf6fa2383..d12842543e4f9506daa47b4b7b38459fb7e9e157 100644 GIT binary patch literal 2265 zcmV;~2qyQ5P)Px-lSxEDRCr$PoNH_pRTRh1w%tNo+Dh8S4}LM>1EGrzNlke5{g9Rd1&q-IW1=DP z1Jt0=M1qAxHz_84&=;lpL6SzJ5y8|31q63%ACw5TE;W2Ap-F)dYK)e)l(uWmxObfn zbLXBrcea4pO*ZZBeat<-`#ZwD`}gmMhZ79`hr#au`gYos zhWe!Rr{`kU&a6MI7at!F$;rtdkBp2Q0)Pj6oB&pU5RN-5E9;~2@$vU&W@i4?BmoMq z9;L0_In5q*b}EZ@Y5#=nnueYvyh|K&YN2FM9{Q7aB|7u>vAfCNs-2bt%f`_2=FFlFXu zR)CgmJJ9d#Yu~!p4j{^`I#q`o000xV0T~A&6L%;^M!Jrb!aT)QErD~5HUaJL_x66Wh3sNfLn#VV zQHD(ao}xW1fgkNE$N=a`SCZKTs=3(yes52E#R3J1VveZXDwfFxTb@#6`cYPp8KD1@ zk{nZz85B{lb}}YW`x3=2WBID0JuSm3F^DOMq8ckBL@;ICLS~UFI{8&n&=w5R$2MDL zF;UDBl~dPOB4rqlL#?l*ASxiLks?@BH=@>~s8T6NBcPtPa&i`Pxm?O;{Zu7T>xq<< zS-jVN43YsPiZQa~l-YMeNsa-+0aFx0aU;q~SJaP48Pq`T2q0dHH&cbIQe-k8PgN>P zQUmmUzxU_1GFw?pqyTCRak`#yvL7iRmFz}6B~eiiwp9XDfeJdh$ux^m6cQU73keAc zT2(Yye{EY2VCmAO5EmC0u7_n46L@(Bfc3!xHZ?T`v$M0@>?xY0hykLUdK45Cz=;zl z;QICJnz4zAiO}8M4b|1vaOch)#u!>#TVdV0b+BT^3K$(7h4Jxm$j{H$$~SD-05vr= z+W!c0_3G6yJUk4OlXw9TVBfxdaQX7(FkEVIW|QVAsj{EuQ9<3UFYGnTUOWZqzehl| zwY5-KSg09^n<)c|2XO-)U(a^*@W zFE7`OW3Tk|bm;HzhaEe1Kp+q>RRjV;hzNdga4_7K8n4WsN9tLED&j6wOF$Kx4hm7?j0%(C{ zx(~*KBcM~KPQmTlx54dpLrO{tw6(Rt!Gi}MatlI2DdnDv@mALC zdj!N>3~ya$XJ>1leLkNC3A2yh#q@y8j731by}eoh*Si=c*6?Dc5}v1(msn;ot8AuM5Cc?N zS_Q&QUd6+3kw9aAWyhP&&Af8f0sh$DCzbwsn zc6MqhyrQB4*e^yfjbobc>+9397y{C}A2W^t%FD|W25FI!*w`Hd#5qRr zc@joOMzr-zYHBKUb#=kv!-rvPY%I(j1NZv%>$QdAjT<+#g(AA3F?-@75n~Vn;>952 zq=}X&jsfDWcZ^2pKjY~Gu72?~KR+LiL&m;v0f~!6y>WP|VKfdQY((eAD1#9Ut^K*Y@WKZX2w#k zOo|MZE$2<95}-|ZvMK;1icJ*Nh*UyxHxaN!10>1{l*=Gifn8*%Y`JKO;+TR&U=~YB zj~yWYkwU4ndDSdNaVM%viqwPU$_g?95-CL%5U)R3rBD=Z222@{uc5%vEG7$378FG_ zj-`3bViZ7DgOUl_l#C|=w&;L*%&$zO3qCGi;T$^dLmp&1}&6>?ktI$@1q)s%-7mz#WH)IjAWVDxk+r n4U0COC?EmqD4-}HHE;X}gcJDRqM+P$00000NkvXXu0mjf)9M|} literal 575 zcmeAS@N?(olHy`uVBq!ia0vp^J|N5iBp4q3;rkAx6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!u;#M9T6{Utk-fRgol%^$2lA*Lj6cNd2L?fqx= zGcYhJd%8G=L>zv5b)&Xxpv-}f_Y*#RnsP5itoxH#ebdR=JR+$RRGJ_5EuS*aC?--z zVxG%P9kIvWm%2kwDa}6WogZZM;Psqp)h~yN>nGREe>%r+`}=}-w$HmHl6wrF?T=Lc zSWs*+**kpKj|I^wE&9vqx>&Efw%%wgUbm;3{i{<%X8+#g6|IK)m*mw~6-+zFw!izV z>g0395moVJ0ssCauzb}2rqk=m>3210Z{77PNrwZjc8TgG8dc}mcPVYZ+faH^uDaMr zrOI%f*P_koJNNyJo_GApy|nYTy?kqDge1i1nsKkr+8B5vu-o_Ww5S|@u`Nl${sCuX zxTimUbgcD%j`qo?JKo6t6c#-8C*J?S>9pw0*}K2qNZz~6=)#}&OHOA%zHqy)oqx08 z+SEdu6ky<~mbgZgq$HN4S|t~y0x1R~10z#i19M#iqYy(gD`OKYQ%h|F11kfAUjjX~ yC>nC}Q!>*kack)IH8}{>paHj`Br`X)xFj*R0Joky5u$QHJq(_%elF{r5}E+^I^4nl diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 096a00946c109c45ddd88b93da5ecdacf6fa2383..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 575 zcmeAS@N?(olHy`uVBq!ia0vp^J|N5iBp4q3;rkAx6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!u;#M9T6{Utk-fRgol%^$2lA*Lj6cNd2L?fqx= zGcYhJd%8G=L>zv5b)&Xxpv-}f_Y*#RnsP5itoxH#ebdR=JR+$RRGJ_5EuS*aC?--z zVxG%P9kIvWm%2kwDa}6WogZZM;Psqp)h~yN>nGREe>%r+`}=}-w$HmHl6wrF?T=Lc zSWs*+**kpKj|I^wE&9vqx>&Efw%%wgUbm;3{i{<%X8+#g6|IK)m*mw~6-+zFw!izV z>g0395moVJ0ssCauzb}2rqk=m>3210Z{77PNrwZjc8TgG8dc}mcPVYZ+faH^uDaMr zrOI%f*P_koJNNyJo_GApy|nYTy?kqDge1i1nsKkr+8B5vu-o_Ww5S|@u`Nl${sCuX zxTimUbgcD%j`qo?JKo6t6c#-8C*J?S>9pw0*}K2qNZz~6=)#}&OHOA%zHqy)oqx08 z+SEdu6ky<~mbgZgq$HN4S|t~y0x1R~10z#i19M#iqYy(gD`OKYQ%h|F11kfAUjjX~ yC>nC}Q!>*kack)IH8}{>paHj`Br`X)xFj*R0Joky5u$QHJq(_%elF{r5}E+^I^4nl diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index eb98d48bdff23efdbd4c1135ad622121c87600b4..c7771a9e4f9d2f709b4fa24d834710da3898f4b1 100644 GIT binary patch literal 1295 zcmV+q1@QWbP)Px($w@>(RA@u(noCG4XB5Z(sgF1@(M%>(R8(-Ii)8E4mAG@GZd7z36zaaxMK4P6 z7QCPhy=Itu9jWoXcb|sC*m;sRCCE;-R=jZ3=AE`q!`AbC%H0lbP7AOIy83|{LyJ29B+eeQF5r>Lr01>nXOKv5J8zzD$| z^lLqrGl1DFa57!Af1EdBjR8BYo&>L%Ka5moOdfl*I@RC@T zW!n(4gK}!1ofGJN$z+lT;P?Ak0Ct1gttFiPSt-B;$X8BqLD&jZR#v7JFk27I47XeO z@)T0M5YhvPl35fU+2#gQ1s*^}MTMmTsljAfMt^@lR8>VJ62Z>S4sLI6QB+if&dyHM z)YRbh^%W~CE4aG4LQhW*s;bC_&uwvW5jQtC++DA80HXqWPc=0)VQOj$6B83?Z*Rxt zk3Z(a_L<+1Xhwru7PJZEdCdrvTR0)-n{Zo5kM71j=cwzf7p z@@WZue}AtfaaUItj*pMAu&|)z1vPF6nT2jv09H8=2m~-NFn~lNfz#7dY;SKP8jWhx zXm@uvs;jHDd&|qq+B8Z{k|cyeA)K9^;rjZspG32dL4BSA9*>8W1NxUcS)DnHmN9G{ z<$w`Dlmlkl3{f(2S7?*C*ALHAK$0X@4u}*G8EXe&V?5n<1|Ucz(A0^llO75Ach4n6M-!0mSDGz*!OD1fwKW;HU2w(YVke|UO&`p(H>md8-Z;FTol zw`er_5x}1So~%kt)R9ym2&zZGN7 zWTP4})x_wc&l%0`Uk&W;{~KUm6u0$*{ud0)$qDZs;BN(tNsD2;iShsd002ovPDHLk FV1h++RRaJ3 literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^6(Gz3Bp77)Gx>m&Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZOo!c>21szhq|;P_lln`GXZG#FXUi?!xfDz5mR9 z1_s7TPZ!6KjC*fy*lV;D${hcAU$j)%bEAaDVbzVnUY=fFlK#sk&lVA0on&}pild~j zS0`ul(W#C`c6uj2#Jrp1G-dVnhXvxXKY#z0vRnW5<sHK+L9B(J`GGJ00s(yfWcuXO(iv?WTU$;aj0?fk*De!q+fUoL~e zzkjQ&AMCiK?4nJ#?9&@c%;(t_4TyE94R` ze-F9N`<^*vR!wVuvjRuc=a|Bmmc5qo4~=%Ny_l6QxbMEVi|-+aUAKSAu3Po%+!4J4 z$@33J*-l_zC(RSK&aol2d4o5jd0_Jg9f$RfJLD5iDcoV)kRp)B7GcVcbBJ%V zp8LE&vA%GJ(ZwG-?V0TPx?zFR@yGmp{jJMtl}cA?fl;Db;u=wsl30>zm0Xkxq!^40 zj7)V6%ykWnLJZBUj7_XeEwv2{tPBi(3G|?9$jwj5OsmALq1)HwAkYR4xD6$lxv9k^ ZiMa*1_1uXNl>_Qw@O1TaS?83{1OT>l{^0-s diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index eb98d48bdff23efdbd4c1135ad622121c87600b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^6(Gz3Bp77)Gx>m&Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZOo!c>21szhq|;P_lln`GXZG#FXUi?!xfDz5mR9 z1_s7TPZ!6KjC*fy*lV;D${hcAU$j)%bEAaDVbzVnUY=fFlK#sk&lVA0on&}pild~j zS0`ul(W#C`c6uj2#Jrp1G-dVnhXvxXKY#z0vRnW5<sHK+L9B(J`GGJ00s(yfWcuXO(iv?WTU$;aj0?fk*De!q+fUoL~e zzkjQ&AMCiK?4nJ#?9&@c%;(t_4TyE94R` ze-F9N`<^*vR!wVuvjRuc=a|Bmmc5qo4~=%Ny_l6QxbMEVi|-+aUAKSAu3Po%+!4J4 z$@33J*-l_zC(RSK&aol2d4o5jd0_Jg9f$RfJLD5iDcoV)kRp)B7GcVcbBJ%V zp8LE&vA%GJ(ZwG-?V0TPx?zFR@yGmp{jJMtl}cA?fl;Db;u=wsl30>zm0Xkxq!^40 zj7)V6%ykWnLJZBUj7_XeEwv2{tPBi(3G|?9$jwj5OsmALq1)HwAkYR4xD6$lxv9k^ ZiMa*1_1uXNl>_Qw@O1TaS?83{1OT>l{^0-s diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index fa1711674f51554e85eff38e6f8d4deaebaf17cb..c8d2b212df7033c9a9e78eb99ef86f493ce2a50e 100644 GIT binary patch literal 3009 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 D4YGYM literal 726 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 literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5890C>L#5>RT|i19*(1o8fuTx`fuW&=f#DZW zsNn?zL#Y7+!>a@a2CEqi4B`cIb_Lo1CD=&O7eDhVff$P ze`Y@e1GBxSi(^Q|t+#i)JwgH{4t!kv*djSfZ0ZBG6RjG8${}pa0z@=ZTyHdUoZ8gt zsM*@;84xh>OT&eZF0NBzO|BP{g#~XcTO_1gDA=N_r6XF^@o4qrzMM%(+gjShdlGx6NGlFU8DlV?HL_gS6hfN;=#%Q#Ma! zyOHT8mCAO)OgTPPQ*;QRv&g45qtAINK*&nEmvlke^WVR40xOYYkJUuWs%$MAkjWTte#?VIvB{I8-G z#>gq`IPX361%qj)S3$$MRc8e9&-OCL%{kG{|MS`%i3RI78XZ@*Jm4?ScjPqRg3{Y& zz|h!dc=Rpfx8)HlGrO<7vHHB@cI1M*WecW0$loYEr@FaR={uXa&DDkZ+&eziIE1w7 zZU}v*xp8ya5>>wxhWpyao5NEWjw@&PiAXx^HFKV6#4KattPb?0f%Ewkwhyz`HpcBg z!LaJ2&)KPx5Bg?CX&WDKH4arVK2T^}>XO!QIBk_v8pCb@3w`4QnZ~7_X$`B>Rt2Ro z{8pV4Phq{7xwm%U$2<b7bsy^6oPE11K zLfZWL&F(P`GdAfRe|DivRl7m`amec8>J4_M&N7~o-LJ4Q<>#tDwa>Hm^WIf>=P6yb zW47KLncLGIwzrqQeDhywflDXfg}srTd>@P!sIdPC5n0Q^o}nT0)x7nN{DRMcksIQmqBidp)5ml`w3vmRxNRjC`m~y zNwrEYN(E93Mg~Tvx(4RD21X%&@~R;HHP1_o9J2EPP)YEd-g=BH$)RpQpr?Q3!n js6hj6LrG?CYH>+oZUJsRcOpdPK>5wn)z4*}Q$iB}=J=@T diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 7c81e83c76f9a47ea4c6ce3985357f92e210b2b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5890C>L#5>RT|i19*(1o8fuTx`fuW&=f#DZW zsNn?zL#Y7+!>a@a2CEqi4B`cIb_Lo1CD=&O7eDhVff$P ze`Y@e1GBxSi(^Q|t+#i)JwgH{4t!kv*djSfZ0ZBG6RjG8${}pa0z@=ZTyHdUoZ8gt zsM*@;84xh>OT&eZF0NBzO|BP{g#~XcTO_1gDA=N_r6XF^@o4qrzMM%(+gjShdlGx6NGlFU8DlV?HL_gS6hfN;=#%Q#Ma! zyOHT8mCAO)OgTPPQ*;QRv&g45qtAINK*&nEmvlke^WVR40xOYYkJUuWs%$MAkjWTte#?VIvB{I8-G z#>gq`IPX361%qj)S3$$MRc8e9&-OCL%{kG{|MS`%i3RI78XZ@*Jm4?ScjPqRg3{Y& zz|h!dc=Rpfx8)HlGrO<7vHHB@cI1M*WecW0$loYEr@FaR={uXa&DDkZ+&eziIE1w7 zZU}v*xp8ya5>>wxhWpyao5NEWjw@&PiAXx^HFKV6#4KattPb?0f%Ewkwhyz`HpcBg z!LaJ2&)KPx5Bg?CX&WDKH4arVK2T^}>XO!QIBk_v8pCb@3w`4QnZ~7_X$`B>Rt2Ro z{8pV4Phq{7xwm%U$2<b7bsy^6oPE11K zLfZWL&F(P`GdAfRe|DivRl7m`amec8>J4_M&N7~o-LJ4Q<>#tDwa>Hm^WIf>=P6yb zW47KLncLGIwzrqQeDhywflDXfg}srTd>@P!sIdPC5n0Q^o}nT0)x7nN{DRMcksIQmqBidp)5ml`w3vmRxNRjC`m~y zNwrEYN(E93Mg~Tvx(4RD21X%&@~R;HHP1_o9J2EPP)YEd-g=BH$)RpQpr?Q3!n js6hj6LrG?CYH>+oZUJsRcOpdPK>5wn)z4*}Q$iB}=J=@T diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 335769ff8b0ad99eb694df82ff65e208cb7d21df..10fa135ec530ee1d5ad76611cc6087fc6778da90 100644 GIT binary patch literal 7449 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 literal 2162 zcmcJQdpK148pnTYnPC{$#MlUl4xv5Ub&ShQ2VvVNNyzo6498_;928m7=D6F{u6@+D zCs7BvRW2!pbjsN&GkkDUWx1BNgG00~q8gdqUXe*%EQ zzS?ro7JiW8xVk$@%}Ak&x;6`jYeX1A|KjHC2*g>1-8}f+$JKG4chczGcv{|Y!jASO ztKq;z-Ebk%*N1H|l6j-tglXjVtEr?~^z*3vnX@N;s2J?JQ*kBV(4Qm%cdAFuejCmh z$~k|jH!nG7ILfl(pYdCmf4Nc|yJR){B}25dq4i|x$8}MgRv~Y_ZSt4RGbJf$DQ&;> zY#zdw_(wd)@|@Xa}7 zOx(;})x!o5Z-smcQwS<+Ww_TQnt6|T(KCWs`gApAZ(Bs_!j_Ww!+%!u{uXiz95__g|5Wq%6K!T6x)$l~K<~=9H)*nlIwCPuHD5 znq;`^5;Q?;s|7lecpjJ%4*1thP$+f#fgx%zeU+DqX#Qk?X(AVA(#YiIZ-Fan5dU!D zTq@eNjX5J7j85ob#>icfy$shG_@M^c*=VyTh(KAXrfSoSXgq7(Yk3>h8OCTvO!fxJ=-&&7bE?b|V6QIwF&23v&3`R;R2PT3D7SBx zE~HNpi*{q=Qcyr)7K4ZJHNl3MITD~HYbJ0ADFHr&&d+|Z#+oa&`vg)Z%}wy6cJF~s zNX+tAi`$^Xzuyz< zz;4@ZbK;H&v`eYI>dc&w-;I1HEfycS@1e-d0rty1Ny(U#6Ocw}AKTQ)=TfedxHA&0 zqjmR&WcH=*Kv^F^%h#_K1D>grZg}oRS&xA~z2FLMYK-{QCwA2C#h�Hz|lY2ROf7 zn%Bi1AyM>tl1?m;IFfIKc4@SakFSi=5pyrl$tXFrP_4|IA}lV?nF)CbC@T+SZpPT~ zrprfQ1``wptZvm@j(kt(CDnq{+P`o#Mm&rJJ;-bQ0_NNys zHqI`5Gn6$Cg3RaQTP?`Gy4YIO_=Zcv90uueizAdbTdTd7#Op^;hxS9O(~`azODOsi z_Oin_4KLD?QNN`RF?~R%8VcbH^7JM6@r3$tY^XdTT=NePQYEA`BdY1@a>pQepgfB zY_tk9L$Wt5OfL9A!r*Y*$2${0OI12(Bu%kyETly`9t`U#_*|rd(q02$XcDK&L2fYh zbpx8@M_{`v!CSH|fBl^Zjc|t8dk&ek&eL#)b3#W<8@_bMa3iEuE@W+f zCd;Z76z{>Fz0;guMp-35lE=u*WfFRg5!*hqWaEA^*APvL`q%8GdiSrfOa*@SLTcpb z$W01ULaI(&uU*r;R<`R(5Rg-8=TD@~3MZF(J%=aTKIhy!1O713u_}P zl}@E@DCVX9pCCH+Sj36s-xuV%n|DBg!T(0!L_{Bt=Y&SHe_u1^tD=R^)YZwuvF6Vq GXMY2+7CI6D diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 335769ff8b0ad99eb694df82ff65e208cb7d21df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2162 zcmcJQdpK148pnTYnPC{$#MlUl4xv5Ub&ShQ2VvVNNyzo6498_;928m7=D6F{u6@+D zCs7BvRW2!pbjsN&GkkDUWx1BNgG00~q8gdqUXe*%EQ zzS?ro7JiW8xVk$@%}Ak&x;6`jYeX1A|KjHC2*g>1-8}f+$JKG4chczGcv{|Y!jASO ztKq;z-Ebk%*N1H|l6j-tglXjVtEr?~^z*3vnX@N;s2J?JQ*kBV(4Qm%cdAFuejCmh z$~k|jH!nG7ILfl(pYdCmf4Nc|yJR){B}25dq4i|x$8}MgRv~Y_ZSt4RGbJf$DQ&;> zY#zdw_(wd)@|@Xa}7 zOx(;})x!o5Z-smcQwS<+Ww_TQnt6|T(KCWs`gApAZ(Bs_!j_Ww!+%!u{uXiz95__g|5Wq%6K!T6x)$l~K<~=9H)*nlIwCPuHD5 znq;`^5;Q?;s|7lecpjJ%4*1thP$+f#fgx%zeU+DqX#Qk?X(AVA(#YiIZ-Fan5dU!D zTq@eNjX5J7j85ob#>icfy$shG_@M^c*=VyTh(KAXrfSoSXgq7(Yk3>h8OCTvO!fxJ=-&&7bE?b|V6QIwF&23v&3`R;R2PT3D7SBx zE~HNpi*{q=Qcyr)7K4ZJHNl3MITD~HYbJ0ADFHr&&d+|Z#+oa&`vg)Z%}wy6cJF~s zNX+tAi`$^Xzuyz< zz;4@ZbK;H&v`eYI>dc&w-;I1HEfycS@1e-d0rty1Ny(U#6Ocw}AKTQ)=TfedxHA&0 zqjmR&WcH=*Kv^F^%h#_K1D>grZg}oRS&xA~z2FLMYK-{QCwA2C#h�Hz|lY2ROf7 zn%Bi1AyM>tl1?m;IFfIKc4@SakFSi=5pyrl$tXFrP_4|IA}lV?nF)CbC@T+SZpPT~ zrprfQ1``wptZvm@j(kt(CDnq{+P`o#Mm&rJJ;-bQ0_NNys zHqI`5Gn6$Cg3RaQTP?`Gy4YIO_=Zcv90uueizAdbTdTd7#Op^;hxS9O(~`azODOsi z_Oin_4KLD?QNN`RF?~R%8VcbH^7JM6@r3$tY^XdTT=NePQYEA`BdY1@a>pQepgfB zY_tk9L$Wt5OfL9A!r*Y*$2${0OI12(Bu%kyETly`9t`U#_*|rd(q02$XcDK&L2fYh zbpx8@M_{`v!CSH|fBl^Zjc|t8dk&ek&eL#)b3#W<8@_bMa3iEuE@W+f zCd;Z76z{>Fz0;guMp-35lE=u*WfFRg5!*hqWaEA^*APvL`q%8GdiSrfOa*@SLTcpb z$W01ULaI(&uU*r;R<`R(5Rg-8=TD@~3MZF(J%=aTKIhy!1O713u_}P zl}@E@DCVX9pCCH+Sj36s-xuV%n|DBg!T(0!L_{Bt=Y&SHe_u1^tD=R^)YZwuvF6Vq GXMY2+7CI6D From 679c458d70c4edd4b59dc82fb57704dd8233a965 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sat, 12 Jul 2025 18:44:40 +0200 Subject: [PATCH 13/13] all icons like svg --- .../mipmap-hdpi/ic_launcher_adaptive_back.png | Bin 0 -> 5621 bytes .../mipmap-hdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 4096 bytes .../mipmap-mdpi/ic_launcher_adaptive_back.png | Bin 0 -> 3103 bytes .../mipmap-mdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 2559 bytes .../mipmap-xhdpi/ic_launcher_adaptive_back.png | Bin 0 -> 8717 bytes .../mipmap-xhdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 6409 bytes .../mipmap-xxhdpi/ic_launcher_adaptive_back.png | Bin 0 -> 16004 bytes .../mipmap-xxhdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 10377 bytes .../ic_launcher_adaptive_back.png | Bin 0 -> 25168 bytes .../ic_launcher_adaptive_fore.png | Bin 0 -> 15977 bytes 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..a44d618bf304e5c963d59e33186c4c4e97754d2e GIT binary patch literal 5621 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 P00000NkvXXu0mjfWvGXM literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..8d671b3c0a7799f4c643286c2dd693990500837b GIT binary patch literal 4096 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 Xr~48XL@#om^n9lfPH=|ph4}vfr1i=U literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..43aaf7449ffaca4b165dbc159da2d9916c9282b5 GIT binary patch literal 3103 zcmV+)4B+#LP)Px=*-1n}RCr$PUFn+JHVj<7Thk`#m8MPlPHpa{eO>1>EpaIjzzj&rmfZEftat(# z%n+iT>FvL#(=Ns^L6Dmk#$LwupS`-xU%HM5_piWCms3Dk2?( zz#s)ko!%}8Gu+k`sbsXm#fx!Nlm@bb(R3Y@jH>_7 zILsIp&j&e75gn!qF%(jT3?w|}P#?kt0S+_M;(?Uy^ycg7l+F*DI-8N8sjJ+)GeX18 zHq@ay4!eFYeWUq0_iw383!&2+AnP-sI%(xr{FPJMDu*lQq(a(@rsejkj%o&A)bxhD z`-rg8rG(nq6k){tA?`sOW+a$W{av-v;i*IuVIWG%NX<HGpdz{Z#p|NYj-$& z)ty0fq62Y&miT4a ziX6i$glSP~ot&x(c*ERf5Suy$qwEf%5YOA5ewQk-;E2o>j(jxz01#%W zLqjZP_xEx@6xn7ivrO{>Vb*&$_YJu~hGkb3VOFGC;>1-gZ2eK7Cdyrw%5qhv^6(b? z#VW)L!u|=WME&Xpf2U#TPoBH1s=TElhrYLC-zpT5te%nBafk{}N{JP62%!&~M36#MPyg}B~6s#GRHA`nCRABB3a=Q`8^qcHbbyBsvfw z7h#aJE;EtM9@~Nr=3|h)R%;3HmiMN?LWH;P)Q6ovSV5Y8{aoLzU!Ai8-p?KhR`Zc+ zLzNNlcGngv(^7?zTTzO3p)7q79pr~@D8{oQPEOl{tfQhUnxPWHNPkhy(A|6JBteR3 zam>wR6A?=0syJCJpoP1t`R92VRW0o`++i!IBWol6BRH!WSg2|{EORq)ZOaBFmBgpujHuP*V{A=XDT>LMo8CPnn${=0o34YxD!%4LS^}DS9ef zHAEtmRi(_BO~@)B$IQ`do=SAQ{IF3iQHxBXQsGftde*Bdfo!ZEE1VU{44XJ?^q}T= z0e+&ys1o8#)E^O9Sr@*1Pn^Rxc*ATW32;=U60PW%$3c?HMN~sZ*gE*9b4naONh6X> zDGeSl8$hUX)#N+@GtY2aiUB8tu(A@6@7Q;Izp0g@Xk^U|Q3b<{fg7K*ki%mLD?)5! zw7Fv$583(e1zDNHUYt2>!%sy?BuByYC?FR>l=(huhn!W(`mG(Nr9d}6IuVt*2!tVn z>P;iL5hT-Shd}^=2C%=_X!k9wopaXJ5Jp9((}?O{?1tegMhUuY8c{K_+w}ZBsB|oE zl(la@I_ER%`(RPECo3ClEw4IX855iBMp}8`SWPK08vV=#jPRJ?7q?3r9hI*%KTpr! z8UItd7LgXBvgY(Jt+dqOv~!>ruq?7@6*>?dBZf*Tal}9jihB8hPb_9c5 z5Z3XDs=8__F#vm>GP#gYp&i@3dDm`-Sv%;8f_cygqV5@0rH!W_-d$8;gt9_!oIy-R zISQ&w4Y31jpSOls2w@{o<03LR0c?I?uCnZu5Y`nnOGFzGZADNBNk)d~+Sg7y_d6`O zu^b%@VM2AeLsV597P7fOl={9b@Qb8!Zm2qq21lz{glt|k-UMMiC@MD+MHEzutybDm zzv=tGPbc|nZCM3w@GW@AO`cq}FHP;pq}wh9B20~PD)eIur-u{`>3*^0?6!46*p{o) zD95cS-g%{>*VdamOcNEMMgPwcC2a*A298KdYJ-ckGM*(Pr#Sh?7d zF^;g5loE$76pS`@vY{(K#9$o4maPC)H}XB%A*^?UMP3{>=re4fLF>84VW#f}I_w?| tw6{GyIc#qp0qc2k*ptH!W`Tn(_ZyliKobD^Z|VR5002ovPDHLkV1kj2zgYkP literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..3a361855002add0a706c66c951016404800a6679 GIT binary patch literal 2559 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..45a6a5a60cdc6ca662329680cff9ebfed114cb45 GIT binary patch literal 6409 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 O4p33hL{`BqL;nxBgPNBB literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..dba13791e06bfe57a3e8ee5125d1f0fbde0b7cd4 GIT binary patch literal 10377 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..49a37c8e3e944d11f2eb15df56c0d62dbc0fcce7 GIT binary patch literal 25168 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�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