From ee20b4740f22cf0aef0f0c52c296ba3ae224d97a Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Tue, 4 Oct 2022 09:33:18 +0200 Subject: [PATCH] Continue group plan work --- Habitica/res/drawable-hdpi/assign.png | Bin 0 -> 1012 bytes Habitica/res/drawable-mdpi/assign.png | Bin 0 -> 691 bytes Habitica/res/drawable-night-hdpi/assign.png | Bin 0 -> 1043 bytes Habitica/res/drawable-night-mdpi/assign.png | Bin 0 -> 695 bytes Habitica/res/drawable-night-xhdpi/assign.png | Bin 0 -> 1340 bytes Habitica/res/drawable-night-xxhdpi/assign.png | Bin 0 -> 1928 bytes Habitica/res/drawable-xhdpi/assign.png | Bin 0 -> 1342 bytes Habitica/res/drawable-xxhdpi/assign.png | Bin 0 -> 1927 bytes Habitica/res/layout/reward_item_card.xml | 2 +- Habitica/res/layout/task_main_content.xml | 3 + Habitica/res/values/dimens.xml | 2 +- .../RealmTaskLocalRepository.kt | 15 ++- .../habitica/helpers/AssignedTextProvider.kt | 7 -- .../habitica/helpers/GroupPlanInfoProvider.kt | 10 ++ .../tasks/RewardsRecyclerViewAdapter.kt | 6 +- .../tasks/RewardsRecyclerviewFragment.kt | 5 +- .../tasks/TaskRecyclerViewFragment.kt | 1 - .../viewHolders/tasks/BaseTaskViewHolder.kt | 6 +- .../tasks/ChecklistedViewHolder.kt | 4 +- .../ui/viewHolders/tasks/DailyViewHolder.kt | 4 +- .../ui/viewHolders/tasks/HabitViewHolder.kt | 5 +- .../ui/viewHolders/tasks/RewardViewHolder.kt | 66 +++++++--- .../ui/viewHolders/tasks/TodoViewHolder.kt | 4 +- .../ui/viewmodels/MainUserViewModel.kt | 5 +- .../habitica/ui/viewmodels/TasksViewModel.kt | 25 ++-- .../habitica/ui/views/AppHeaderView.kt | 7 +- .../HabiticaBottomNavigationView.kt | 18 --- .../habitica/ui/views/stats/StatsView.kt | 115 +++++++++++++++++- common/src/main/res/values/colors.xml | 2 + version.properties | 2 +- 30 files changed, 234 insertions(+), 80 deletions(-) create mode 100644 Habitica/res/drawable-hdpi/assign.png create mode 100644 Habitica/res/drawable-mdpi/assign.png create mode 100644 Habitica/res/drawable-night-hdpi/assign.png create mode 100644 Habitica/res/drawable-night-mdpi/assign.png create mode 100644 Habitica/res/drawable-night-xhdpi/assign.png create mode 100644 Habitica/res/drawable-night-xxhdpi/assign.png create mode 100644 Habitica/res/drawable-xhdpi/assign.png create mode 100644 Habitica/res/drawable-xxhdpi/assign.png delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt diff --git a/Habitica/res/drawable-hdpi/assign.png b/Habitica/res/drawable-hdpi/assign.png new file mode 100644 index 0000000000000000000000000000000000000000..7350842d7ca172327ce2360daa4c69fc27902cda GIT binary patch literal 1012 zcmVP(r;CD$3ZGj2JjCX`|(*AWsgB;%4Ag$9YlxXi;mP=<0pXD{E{ z|M`#q{5WLQ|L?um`qo-|-8NH%_H1n&{5_N2L@bjqa+*ahp>MGZ-?u?izc;v7&QJ0z{Bu9y)cbKnxh8IvC-pB9=g}xd;vVY%sNc7F)OIJxRlA81>7~o3rmx)A6P5A#scv- z`)!R7^+ib6t2e}FYGheiXCjfjO<(Dub3pW>wzj+jvW`?Lb@kIbxq=H#Q+@C%1ADrj zXg;&liX4W`R|^-<9Tv!Pk&@6v#}sJ{IdrU=nu^!hoYw=3o$i?U#pCg>!hG1B1N}f) zV9iBJOnu;(JY(Mf7SH^i&_OJwBrHch-e^kj^$qyPo6auLJu)!W=W$8EGltrKIu*JD z!03$79ITgpu>WsqX(@jGxNC+xd4e>D$toTh6xDYmWRGOGS%&S0OF15{y*Za&F{at2 zRcv`f{l4;`Qxl1UeL9|WHR0YPU?FY9+)zuct*x;{eX40ZRy7NY0M}2ZXa0U;DT?$*6yqZfRcw%j(K(08fu7UX{XdYaX~ULet+jT$!!zANDlQ_LrwA8O zNl$BKj2gznF-S4YW;;rjMCWR#ui)y@oBRO02t7&v>!%RqIx_ z=WFMm3>>P0*7kJG#){p)bEqnq$q!Uiv=}w+0)A}UjR)DTWl=rVS37D?@r6jccZvc$ z!$)*2M0knbA-Vn|!8{?1Wise+N6ubY7Tu$!GC-LbOA8WpNq-ijsPI{2l;$2$%>zF7 zP@uNi$HBK3R*CN6l+VEgx>lC_QphMe@2pKkI=c~4dxa^6hFEs{=KV{kWvR8O*nbk9 iHv})wVejPMO#A?xP0000S literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-mdpi/assign.png b/Habitica/res/drawable-mdpi/assign.png new file mode 100644 index 0000000000000000000000000000000000000000..20b6a498eeb94d3f6b88474492c75f9181376f3e GIT binary patch literal 691 zcmeAS@N?(olHy`uVBq!ia0vp^!a&T;!3HGfUfpH|q*&4&eH|GXHuiJ>Nn{1`Em9*q z(|mmyw18|52FCVG1{NTT5s0OLn1O+50TWzAcmXq<%?*+aHeYuis6@@v#W6%fG&acB zBP3A7?)ko%oJAAF^0v4-ZPPGlW(v;~*3(|}!o52qwELiB;j%Or_ryt8E@`B8M7p+m z1?4{@$|x<^0}WU(*x2<|<6& zOVl#HD6GqQ(Nc^{=(G2|G@+Ft-^KSYm%8XY<@D1-`=_1e&M5fsBqC=m$8iNwGZ*2M z9U9Ztah!C^joqLs)w?c?JCjE*u<+>K181x)U2^c zXTNWcqcs^9?iE;Z@L6Bt1wjrAEjF9Rsbv|wANQGmZdIAEOK)yfE|2bt^(zeTOU-*z z5^K%8@nOJ@hiUomZ`ylF$e+KSyKd^c!?t-dW-*(7oqxSM{&(TWy5oki*V&UcpSqoO zY?oQ*`u!Jpe>r)1sIAw_zkg7?@U1G3#k#Hg7XD}`iq-C1tF%vE;E~#&74O|QO`iUD zN&o)(s(a;0mancGzA#n#X7=iH4bOvpLYD-LO+(XNH};`Y^Ppf*=!@D?T8jEmLF$9h?2@0lHi?q5&?-iSLJL(= zLZFDPO+$&0V16E~F?Z+mJ9l?BceiOH4(y(pbH493lHULvNa zMd){C`ilH@UsCYzAtKoa$~F?35augpjd!%Y{ng2`G>=?zG}@Ow-z-EuNVp;D*Eut` zAyR@5F-!|^CJrQ9hs!w+TN@Y1WQMmOXIcdzaMAa8ms#uA5Sun8zO8~7fnoC|`CRLH zUJMoZQSm~YQohTzn)MwZSX_D+rK>{XpW0u4Z4WFyIvkUk^zhXsS{#Eg1n7@=eD5tp zZe_FCALeH6eGmVxJfFG>oY0&+_SqXG_AJUYapZ${o^i3_my*a1bz;|_M+8G$TeA5M z3jD1u5PKzb;x879Ewb?0a9!ZL*rROmONC^k0zJd?D-n#)ybS|V8I23uY3x)-mGhrE ze!3%^TiK}`CaH8ju{>H7#g4B*c)R3mGjNw&0=1dU_}bu~8@t2g!eh}G=8D(QHRrcE z>2`CqxB*W{!DkG8R4gwWlh(3YlFq)=K&R`}Oy;|d5KLiRhj`$#|Fb3<85!~W(gW`! z;UVRr*}B!Q1KoT(|C5=#M*`===H@V89=+-FXRzhN>Oo){{W^)#Jd4B?%P6u4j+1aL zzTvUZ&-6t++4@!l6HZrcr2h2a+Ym}PB6hSHb*V2C)Ud(EwigBAP@eJ~cQqTHDav%j zian7B^JP@)f+6#pWs5%WDj@zm&N~77lwu6=36%5~OSTTzw+W@+DP&J0PvwE+-jhxg zcX>1y$Wh?uoKG!hdWT*Na`sm}Lu1T)`x7mn>KR2rI?wiGH_Y0M}l(H5XBg#RDSL9MWdy2Us#^h zONMu}tuHmWyEOdZ3SaXagwedz3ViXQz?p`RLzwSDT8YQU=?y_MfeYF}xDEexK)ep( z_!UNhs`;GjVb-s%dHmqi-MNc+7HZL}=>GpV@X}~2-mKnIb#Ao`_W^h}fP9A~qpkn| N002ovPDHLkV1g*K-hBW7 literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-night-mdpi/assign.png b/Habitica/res/drawable-night-mdpi/assign.png new file mode 100644 index 0000000000000000000000000000000000000000..dd618cb069c3c1d9380136f1e045987d0d692813 GIT binary patch literal 695 zcmeAS@N?(olHy`uVBq!ia0vp^!a&T;!3HGfUfpH|q*&4&eH|GXHuiJ>Nn{1`Em9*q z(|mmyw18|52FCVG1{NTT5s0OLn1O+50TWzAcmXq<%?*+aHeYuis6@-t#W6%fG&jgQ zBREiC?#`2!n-)41CTcHA(AJp3Rrb_veo5wPq1st2!Qtz+aEJzW>4k)}bZIE9Yq_B! z!SgYAvrtswMPC+C5uL7$UfMz0t{V;KThH@Uo^he^^vs#X@9tC@_peMl`Q)&f=G1n< zZybT0o$oYR|1;FEzY8w=)4cG)yUertsTTy71|>HJCB74lk?+1E@+@tNq{C7MX=9zR zI-$#gA6%EOTzdNRo%pKt7yr!C_&>9I!v!gO{o60Te)r4NliO|2Sm89yXyU&IE?VC* zmZ%*4zRLCAwk*B5`!_b{r1tcjx2=74W5-1ms}~1O&)@SRNzs=z%<8=8%%!mxyT8?@ zJX*O*?Bmqp>)SVPjXkBA6{FjBzN)uNI!Kw{YHG-D+xUBnPlWQ#J!Tx;n(}wiv=vHa zG9OK^YGlRCjntc7takrN@ryj!yyGXmj6W>skVu%tX{^k(sAOMhuJ`uWyHejC>B_n2 z^y0^k#Jb40IiGUt1fp-VeB=_j(b}!o$A3IwTJ3|XtUJ$Up1<#};IDq3&qg@8By-6M zL-luQPD$FFB?SjFv-ZBIye$?o!NVrbb?GDB9eW>5_dA~XJ4mlaR%oMhPR+v)3-@|n z{hKe-zcl_qbo!x-3(7*$Z|0Q!?7!JsUQul#bhkX@q>GNNmecBu58qiCGX0Udq<2Jq z(#9_j-HPhA-FjkvCgr*Py(IG^moBcjdZYhf?A9ZOgN24od8c`TY8U Y{;H(sjtf3n=z&s?r>mdKI;Vst04Gi;;s5{u literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-night-xhdpi/assign.png b/Habitica/res/drawable-night-xhdpi/assign.png new file mode 100644 index 0000000000000000000000000000000000000000..5210407785c37271bce9a2fe578b8434170e98b6 GIT binary patch literal 1340 zcmV-C1;hG@P)cN=3F!^i^!!H7EI zLIP&d#FuRbh}JC7v0Q1lmM57n&Nrg)z?LDxq7O?Xnew1^U5AaOkeVh$6EVa@i5fKs z{*4L?FPpeOb+q)}d;ER(_FUV}%Wm~cZoj|h_kI1&ch0?>xzN;9`hHe44++6`GA=eU z!Dks~R~hH;`Rju*T4vl%A26BO3ws-9Y#m~zIcFa+RT&M1g1@;ydolyBl7tXE5l=nO z1sg?CO_g3-+f58tgEXlPr%9exkq$UKaEa4K{^V#&HU`qaJbj%U?!7kT>P^z2+s&Q??*^c_4^*v z`hs6md@V$a9YRsBK~YPFBjISzsN;m7_3yo!&1RpRn_2o2`_qO3S23ME0GCx*cX#&^ zJ{`gAc!a^hM}4DN;x#KW;(?IxU^^=}@GHid;s4 zK%k&74Ztx(&v>sh3Wbq8_|K%%!$j`O4AL*RMpR<4`<~; zDN9akaX>yNoiGVo`n+;yE0N$1oimGEPNM|H_%)Rx?KzWVib%kK(Mv}ox8*p->}KmuYA7ZJx0;k zjobYdRKB*9C9iO0(AQ9(VXQG{6y|pbVI0OEdP@3LMct-F_WUfXD&H>Z5Os=t$aN93 zd68tIio(c{m`Du>Q;d`Rze(W(eUW`{x#4)aE@<)O#MwS(iV-)UTJ78v$1KcR7b4!7 zu|zC&oS9}Ehh&|^K|61ush^_7pOl_&;9E8?xEgMd--@-?*a#LDFfD8e>XBPpITbtm zoGDDFh@4*&rQ;4R?UKO9EEA5 z6JZt);^IARYb*cqY&_dMXD(f*lW2vnFc%V%ZgV|<>jMmM2iZ_uJba)xBK^cCCsGG7 z8gG(};ht|%8aD;{1N6FDk(4=OX}~E8-&%JY)^apW>&p3AT@)2riO`*JY9h71Jch8S z`(&dWl&jo-H(9|q%hNKz$M~?6y>KnseVq&C?NY2#U|e1k&T?$wkW|WZNt+v2@Q)v| zoqX}xNbm=@KsP&HCG?qOlVA@^QF0rTFIu{jOM2ZoPsHAzv$m46zi_&~a1V9!h-R$c zL0+uCiJzaUBk`r%j<>~XnzL}U*LovV$5iWhSMu|ifG8~lfHla~L0)yN-vFEq?(vk% y8!7&V=0O~pcj(`ETT*+Jg^e67%BmNIBmM|+ zx}OufMVy~w3hif{g7r-``$Tj8ww?1i)0TiXk1?7^oQ>eb|Ay@E#P}Y%$Mt<(UG<-$ z&Ygg1D5HM=?r~i0e~%cg;GDaY$`c)CF6A{tM%6xJjF%>pCnA+IzJ=Vm>+0(l^(K?e zhL<$SKx@Yn8bx+7&K^p`i8d&!q^v{itip3%u3J`hBxRj61QRCtUE9u?QO*xwH44+P zmxU-@cM+8@ZK^q*g^{?bag*%a+Bx#F)_0U~USiV4{B1`7G(*oR*tfgXjqZfcAd^Qg8+Bj$zuB1wnnOp%g5tFoc;nnceMiMz+HXyImi zf(UlM!f82X`lQWgPcV35OSJ#Dw>f9c;=YAW@6_ofPnMOHMFgE=fcJ)cq4&d#+TiCo zi-$=yd^6T;(S`wVtYk3wb<$wFSQ3+3(G(5vO`J*OyJkMVhXmP=f>p$+sB+a*&MEjcGd1HZv z4+4(n5Di~@5xiJ}dIxm7mJOAlZm+JfW)l&^K8_8pv4L(IBUzAP)6JVeFq@Um%NvZr zlFJrwB#Dx%uo>O!^;RFU(c+>gPYpk5C9z6Lj}fnT@hKSlK{OaA29cdM>`0Oknz=_ zw5i$pe*{_=Rr`$U=u z!!`xlc2YF;8g6WCF%dRh8?JJw)}w3`M|D*22e2e-9`HcXpQ z(qg;8us%`r-Jkbz6f6`T&g*yTWvKm4sbd@#^p=R!emOg}MF&ZAirqP5HgtxVrr zcG(zChrsN?d*@B2X~m!~gzYgg{vbr;^ETBsIp_%psor=TD{0yrONFoYvK!B$ob;fq zf#4i}Hmg-FzxUE9#nRzc%qqpGK0#d8Mj{;7DBAFr2J}6JNT< zL)$_nVU_QKo?P<8HhY^Eua0LAliY|&*3Zm5laEPNncH1jUte|9q-F9P*psUIp_m|M zJ&NusnrH_rGg-v# zup0l z(vOS__)Rudxfb2dtyW=DhxdtQvKfCKZBE0g9%IG>-;3GajJ5BQVzx2j%YE)!*fRsy zt-BO-T5j~%^cb@kir4$nW#-D8gWJvLXhMHvVQY9*5sMKMVl!gQ!utQH*_Vh0u}cyF O0000P))&n>SM?6BZ;M7D8^4 zLi|laoFSsax7@j5f`?6?{bMHy<7pvjvmkkc5HusCI4*s@@vg2Hek}oAkr{KjNlHm$ zL$5zC4LOd4u6KKtMrSQa-lZ&VPIIJDxN}d(0W1V-T041)htztTdXUsBu>05t;4FT> zBf(tMvkkP~{@5>x#E%euLmc~goKHyk_^HXM?D0=OnS{P(a#d`6II+dZ=cZ7#Dj?-B z(b$d6^+WCL?P*5dKN7z?mz4*lkPotsgciMC&%L|5JIo3ulgZl4f2MVeAB5Y>i_$#a z`@=oKuQ`4#LhZe5LFQpWl@zof4<5onNi3I|I z1<28{f!AgYDH4pun6RNwm(zRi9O*;5yli=>fBVj-pj)IVA(2RMKlxe5w#{_*>I}Gy zbX~uyk%%aVVaO+xta!LL#J%;4t@~|k<*tZ3i7lp#O<1ATb0nt#Y?MOKYHCh9KBC(k z*%s`vpR>xCj9nbFn(l06mOL3D@@BjgRN^#RaM`Tk_;KVGSDr*(r|cHCrM>^|5qs;* zq+8JrCgBXV7W$mTT3Xi6On?9T9A6PQ5f4P8$%aTIkW%0-p3Q7iI%3WKQabZ}`zGr0 z3zz&X>sMxHE8E)IG64CA9SCTUSJT|Qu2ajtXf)Q$ zjAe^xLP?6}7cR$8h(_Cg6o-PZnl+JY;_<R z$qpm)b=EAD#zm@Y)t-;*>crgq#r)R1klpY#Sd1%Fmq6>b+-h%3cD6y*eZ z^90LGuEf|79gGL0VH{xjnu#dTwKw!uDV&O~3m!Z+6yJ_j@a6b_(GX+)7ci&CM*CwU zxGWE08}JxggmPX&O;4iEpYexMe}iv%zmPa@#fX#U7zF?<#$;?|s+5~siS2t1+vk)V zlYgKQb%%TP>0%(<{MG4{@kn0M8(73mrl069tyAw^o0WC+kEz7?iiA5Wg8ZA2v69v%FldsAhrwsB+KxpY8$B; zFUKtFtC2RJ5&(_@69MCySBH}u3S$_HtIsx`gXb#rmylX;uA7u7pP-p>ybkx9wOhW2EhCVrevyw@+z>b17RXuHhf&?d;?mI=tt_A4&z5 zw3C=pKHN!nC|PmFWNcHn=Tg3MoT3ABoe^}e7g(`*m7f_h#O?;(_K>z>%07*qoM6N<$g6_v_ AQUCw| literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-xxhdpi/assign.png b/Habitica/res/drawable-xxhdpi/assign.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0578c8c8522b7ab4135586d181bf26f3105e73 GIT binary patch literal 1927 zcmV;22YC32P)mu?G%7Lh|aJrhJk zONc=O7)^*6qlTdI!jKXwwAo^XZr2`!c1ycZX}cA$25p3d#0t^GL;^9PBn0`RfB}pN zR|GK>!%@MO-S)jV{$}ah&b+sGK_`Lvj^B68%s0o|Qj%n=tJ^k}X#GnlV=og%9wwBG zV}$gA{sZ(OmC*LmD)&Lr-Nx#`e1owi(9Z*QA|)gX_$%PgF-rFmhx1#ncjfP*&Ap%z zH-2kqXdTnv8>}IWEeFyO4-IF>sH&{w7{g#&VUrgR51mFR-R{hCRjyf6a5VuoZFSs1 z)>Q|d#>#!q2%DTj1Y-cJBx^$ny@-{4-CN~8o~%tOxR`_7RNFj5*V$plNOmd?)5TIs zZmBArySBXeRJuN5*+m^>AP^YY)6Gtx+@{EeG^h}|g%GxvD9%fS>eum&d96q@h<%5ny7G3>4o7rbf(+wzA4Fv$VA;^z1_@f9Uw~T zkkhH=fBZ?&X-mw`_V)Je=YG3ffyBMgMSNlgujY<-JyTFn&@b4W1iinpwsk{L5AHym zmm)e$YHv5;KKQ@8)@&^I zcq-kyMVU#XVlsMfunz3`XH6L)G)OaCo%5bCBYfJ5GLz;$6@@GXZyr|M!bQS4n5d!m zwn1WPUy$5Vy5Cz>d{mOfU@(&gRTOC@u`+S5kEF$c8_LL~&d^DVGkht&8$cAJQj7xd4qC6HI()w`+3XPFJOG@6nEl4C1zNx<^ zut=O(YYyB1vIUZ1bS5Vn&Q`7}RezA}*>t}z;Fe|4IlsT<0m5jdsAZJ=DDqYs1AGeu zeN>d&a}c$u)3!mbtt>i>Rg+c|(^$vfvGLruwY9m7kkJOL^opTG4aBnBRNFKYYxISz zr>BvFba=`7)Hz$Z^0M^TwBSM_myBi-o_2^JzUh|@!&xYIAG<5Yo#`A0g;Y@4Dip5jFvl?2E^?lBQoZGxtO7_VpJrkO`)Y_jrPh$A5!^N45!1Bz#u_ zlgCewJ3hjl{2wKk9htc?Uq>=HHO{stxw+rhGF$Jxe#kn&)Lf^C#$@uCJa&qf3E{Ru z)~#=6Y(vic$U(=Lt7-YNE z5t7+Q6zcPoyZO~(JM~2TX5Y34`;5>EoIxd+tP!FPw#Ua!8aa2_vSmS2jsYqD+Q3|5 zunJ7TLQ`(`_(ECksa*Y~$*0?g2g&a%O(XnELs(h-3ZRk|o{Hj~sXA})eKtkYHT*Ut zmpoRxv20y2CcxhOzUKE0o#4(K{Eh`mb2v!e+Va&W>=wyO!h2HJ$wrt&28dbLRfQ~0 zXMjBPnu?+e)RjFCpIP$nHI%IS)VBq1TYKZNcuXE!&^iWk6GW+#ioa&-b>tX_ z6iC#kLYH_8&*I_mxoCrX_BD~W(mXcLL6lo_6m`ka3J#X%ExiF7X z{LtpQEst1a5q2Q;zflnj;b3-R)c{NjL_oq-r5u-7d18K@R=uVEY;0fgl{syr>A?kky3^hlEIGtrE2lKi0 zKM%(qKAanJv}=-=C|>WX8*G?!7MyK^+4X{3&xz;8a~w*ve*r4wkgC1&;*bCU N002ovPDHLkV1llZl;Z#Z literal 0 HcmV?d00001 diff --git a/Habitica/res/layout/reward_item_card.xml b/Habitica/res/layout/reward_item_card.xml index af9d3a58e..ddfeb32f9 100644 --- a/Habitica/res/layout/reward_item_card.xml +++ b/Habitica/res/layout/reward_item_card.xml @@ -49,7 +49,7 @@ android:paddingBottom="2dp"/> 24dp 20dp - 10dp + 8dp 8dp 8dp 6dp diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt index 57bf84801..d7b66a56c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt @@ -45,7 +45,15 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), .beginGroup() .equalTo("userId", ownerID) .or() + .beginGroup() .`in`("group.groupID", includedGroupIDs) + .and() + .beginGroup() + .contains("group.assignedUsers", ownerID) + .or() + .isEmpty("group.assignedUsers") + .endGroup() + .endGroup() .or() .equalTo("group.groupID", ownerID) .endGroup() @@ -129,14 +137,13 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), return taskList } - private fun removeOldTasks(userID: String, onlineTaskList: List) { - val groupIDs = onlineTaskList.map { it.group?.groupID }.distinct().toTypedArray() + private fun removeOldTasks(ownerID: String, onlineTaskList: List) { if (realm.isClosed) return val localTasks = realm.where(Task::class.java) .beginGroup() - .equalTo("userId", userID) + .equalTo("userId", ownerID) .or() - .`in`("group.groupID", groupIDs) + .equalTo("group.groupID", ownerID) .endGroup() .beginGroup() .beginGroup() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt deleted file mode 100644 index 4d97ad970..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.habitrpg.android.habitica.helpers - -import android.content.res.Resources - -interface AssignedTextProvider { - fun textForTask(resources: Resources, assignedUsers: List): String -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt new file mode 100644 index 000000000..60d608130 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt @@ -0,0 +1,10 @@ +package com.habitrpg.android.habitica.helpers + +import android.content.res.Resources +import com.habitrpg.android.habitica.models.tasks.Task + +interface GroupPlanInfoProvider { + fun assignedTextForTask(resources: Resources, assignedUsers: List): String + fun canScoreTask(task: Task): Boolean + fun canEditTask(task: Task): Boolean +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt index 7983d1261..cdd5ee55f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt @@ -96,7 +96,7 @@ class RewardsRecyclerViewAdapter( if (customRewards != null && position < customRewardCount) { val reward = customRewards?.get(position) ?: return val gold = user?.stats?.gp ?: 0.0 - (holder as? RewardViewHolder)?.isLocked = false + (holder as? RewardViewHolder)?.isLocked = !viewModel.canScoreTask(reward) (holder as? RewardViewHolder)?.bind(reward, position, reward.value <= gold, taskDisplayMode, viewModel.ownerID.value) } else if (inAppRewards != null) { val item = inAppRewards?.get(position - customRewardCount) ?: return @@ -122,7 +122,9 @@ class RewardsRecyclerViewAdapter( override fun getItemCount(): Int { var rewardCount = customRewardCount - rewardCount += inAppRewardCount + if (viewModel.isPersonalBoard) { + rewardCount += inAppRewardCount + } return rewardCount } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt index ac7d3c293..82854c32a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt @@ -16,15 +16,14 @@ import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler import com.habitrpg.android.habitica.helpers.ExceptionHandler import com.habitrpg.android.habitica.models.shops.ShopItem -import com.habitrpg.shared.habitica.models.tasks.TaskType import com.habitrpg.android.habitica.ui.activities.MainActivity import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar +import com.habitrpg.shared.habitica.models.tasks.TaskType import io.reactivex.rxjava3.functions.Consumer import kotlinx.coroutines.launch -import java.util.* class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() { @@ -45,7 +44,7 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() { (layoutManager as? GridLayoutManager)?.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int { - return if (recyclerAdapter?.getItemViewType(position) ?: 0 < 2) { + return if ((recyclerAdapter?.getItemViewType(position) ?: 0) < 2) { (layoutManager as? GridLayoutManager)?.spanCount ?: 1 } else { 1 diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt index f4552970b..6cf2c14f1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt @@ -214,7 +214,6 @@ open class TaskRecyclerViewFragment : BaseFragment Unit), var openTaskFunc: ((Pair) -> Unit), var brokenTaskFunc: ((Task) -> Unit), - var assignedTextProvider: AssignedTextProvider? + var assignedTextProvider: GroupPlanInfoProvider? ) : BindableViewHolder(itemView), View.OnTouchListener { private val scope = MainScope() @@ -254,7 +254,7 @@ abstract class BaseTaskViewHolder constructor( } if (data.group?.assignedUsers?.isNotEmpty() == true) { - assignedTextView.text = assignedTextProvider?.textForTask(context.resources, data.group?.assignedUsers ?: emptyList()) + assignedTextView.text = assignedTextProvider?.assignedTextForTask(context.resources, data.group?.assignedUsers ?: emptyList()) assignedTextView.visibility = View.VISIBLE } else { assignedTextView.visibility = View.GONE diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt index 211c293df..58b3a27ad 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt @@ -12,7 +12,7 @@ import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.habitrpg.android.habitica.R -import com.habitrpg.android.habitica.helpers.AssignedTextProvider +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.helpers.ExceptionHandler import com.habitrpg.android.habitica.models.tasks.ChecklistItem import com.habitrpg.android.habitica.models.tasks.Task @@ -32,7 +32,7 @@ abstract class ChecklistedViewHolder( var scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit), openTaskFunc: ((Pair) -> Unit), brokenTaskFunc: ((Task) -> Unit), - assignedTextProvider: AssignedTextProvider? + assignedTextProvider: GroupPlanInfoProvider? ) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) { private val checkboxHolder: ViewGroup = itemView.findViewById(R.id.checkBoxHolder) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt index 26ab150a7..04a2147aa 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt @@ -1,7 +1,7 @@ package com.habitrpg.android.habitica.ui.viewHolders.tasks import android.view.View -import com.habitrpg.android.habitica.helpers.AssignedTextProvider +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.models.tasks.ChecklistItem import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.shared.habitica.models.responses.TaskDirection @@ -15,7 +15,7 @@ class DailyViewHolder( scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit), openTaskFunc: ((Pair) -> Unit), brokenTaskFunc: ((Task) -> Unit), - assignedTextProvider: AssignedTextProvider? + assignedTextProvider: GroupPlanInfoProvider? ) : ChecklistedViewHolder(itemView, scoreTaskFunc, scoreChecklistItemFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) { override val taskIconWrapperIsVisible: Boolean diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt index e31f0337d..b56939f23 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt @@ -6,9 +6,8 @@ import android.widget.Button import android.widget.FrameLayout import android.widget.ImageView import androidx.core.content.ContextCompat -import androidx.lifecycle.MutableLiveData import com.habitrpg.android.habitica.R -import com.habitrpg.android.habitica.helpers.AssignedTextProvider +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.shared.habitica.models.responses.TaskDirection @@ -17,7 +16,7 @@ class HabitViewHolder( scoreTaskFunc: ((Task, TaskDirection) -> Unit), openTaskFunc: ((Pair) -> Unit), brokenTaskFunc: ((Task) -> Unit), - assignedTextProvider: AssignedTextProvider? + assignedTextProvider: GroupPlanInfoProvider? ) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) { private val btnPlusWrapper: FrameLayout = itemView.findViewById(R.id.btnPlusWrapper) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt index 06f778ecb..c083240b7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt @@ -4,12 +4,14 @@ import android.view.MotionEvent import android.view.View import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils +import androidx.core.graphics.drawable.toDrawable import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.RewardItemCardBinding -import com.habitrpg.android.habitica.helpers.AssignedTextProvider +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.ui.ItemDetailDialog import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import com.habitrpg.common.habitica.extensions.dpToPx import com.habitrpg.common.habitica.helpers.NumberAbbreviator import com.habitrpg.shared.habitica.models.responses.TaskDirection @@ -18,8 +20,14 @@ class RewardViewHolder( scoreTaskFunc: ((Task, TaskDirection) -> Unit), openTaskFunc: ((Pair) -> Unit), brokenTaskFunc: ((Task) -> Unit), - assignedTextProvider: AssignedTextProvider? -) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) { + assignedTextProvider: GroupPlanInfoProvider? +) : BaseTaskViewHolder( + itemView, + scoreTaskFunc, + openTaskFunc, + brokenTaskFunc, + assignedTextProvider +) { private val binding = RewardItemCardBinding.bind(itemView) private val isItem: Boolean @@ -29,6 +37,7 @@ class RewardViewHolder( binding.buyButton.setOnClickListener { buyReward() } + binding.goldIcon.setImageBitmap(HabiticaIconsHelper.imageOfGold()) } override fun canContainMarkdown(): Boolean { @@ -67,25 +76,44 @@ class RewardViewHolder( this.task = reward streakTextView.visibility = View.GONE super.bind(reward, position, displayMode, ownerID) - binding.priceLabel.text = NumberAbbreviator.abbreviate(itemView.context, this.task?.value ?: 0.0) + binding.priceLabel.text = + NumberAbbreviator.abbreviate(itemView.context, this.task?.value ?: 0.0) if (isLocked) { - binding.goldIcon.setImageResource(R.drawable.task_lock) - binding.goldIcon.drawable.setTint(ContextCompat.getColor(context, R.color.reward_buy_button_text)) - binding.goldIcon.alpha = 1.0f - binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.reward_buy_button_text)) - binding.buyButton.setBackgroundColor(ContextCompat.getColor(context, R.color.reward_buy_button_bg)) + binding.priceLabel.setCompoundDrawablesWithIntrinsicBounds( + HabiticaIconsHelper.imageOfLocked( + ContextCompat.getColor(context, R.color.gray_1_30), 10, 12 + ).toDrawable(context.resources), null, null, null + ) + binding.priceLabel.compoundDrawablePadding = 2.dpToPx(context) } else { - binding.goldIcon.setImageBitmap(HabiticaIconsHelper.imageOfGold()) - if (canBuy) { - binding.goldIcon.alpha = 1.0f - binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.reward_buy_button_text)) - binding.buyButton.setBackgroundColor(ContextCompat.getColor(context, R.color.reward_buy_button_bg)) - } else { - binding.goldIcon.alpha = 0.6f - binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.text_quad)) - binding.buyButton.setBackgroundColor(ColorUtils.setAlphaComponent(ContextCompat.getColor(context, R.color.offset_background), 127)) - } + binding.priceLabel.setCompoundDrawables(null, null, null, null) + } + if (canBuy && !isLocked) { + binding.goldIcon.alpha = 1.0f + binding.priceLabel.setTextColor( + ContextCompat.getColor( + context, + R.color.reward_buy_button_text + ) + ) + binding.buyButton.setBackgroundColor( + ContextCompat.getColor( + context, + R.color.reward_buy_button_bg + ) + ) + } else { + binding.goldIcon.alpha = 0.6f + binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.text_quad)) + binding.buyButton.setBackgroundColor( + ColorUtils.setAlphaComponent( + ContextCompat.getColor( + context, + R.color.offset_background + ), 127 + ) + ) } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt index b7bf10b2a..2370a4ad4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt @@ -1,7 +1,7 @@ package com.habitrpg.android.habitica.ui.viewHolders.tasks import android.view.View -import com.habitrpg.android.habitica.helpers.AssignedTextProvider +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.models.tasks.ChecklistItem import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.shared.habitica.models.responses.TaskDirection @@ -13,7 +13,7 @@ class TodoViewHolder( scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit), openTaskFunc: ((Pair) -> Unit), brokenTaskFunc: ((Task) -> Unit), - assignedTextProvider: AssignedTextProvider? + assignedTextProvider: GroupPlanInfoProvider? ) : ChecklistedViewHolder(itemView, scoreTaskFunc, scoreChecklistItemFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) { private val dateFormatter: DateFormat = android.text.format.DateFormat.getDateFormat(context) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt index dcf766b42..c86726f30 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt @@ -7,6 +7,7 @@ import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.helpers.ExceptionHandler import com.habitrpg.android.habitica.models.TeamPlan import com.habitrpg.android.habitica.models.invitations.PartyInvite +import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.user.User import io.reactivex.rxjava3.disposables.CompositeDisposable import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -43,10 +44,12 @@ class MainUserViewModel(private val providedUserID: String, val userRepository: .filterNotNull() .distinctUntilChanged { old, new -> old.id == new.id } .flatMapLatest { socialRepository.getGroup(it.id) } - var currentTeamPlanMembers = currentTeamPlan + @OptIn(ExperimentalCoroutinesApi::class) + var currentTeamPlanMembers: LiveData> = currentTeamPlan .filterNotNull() .distinctUntilChanged { old, new -> old.id == new.id } .flatMapLatest { socialRepository.getGroupMembers(it.id) } + .asLiveData() fun onCleared() { userRepository.close() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt index fd8850c0c..85a5af08b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt @@ -12,8 +12,8 @@ import com.habitrpg.android.habitica.data.TagRepository import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.helpers.AmplitudeManager import com.habitrpg.android.habitica.helpers.AppConfigManager -import com.habitrpg.android.habitica.helpers.AssignedTextProvider import com.habitrpg.android.habitica.helpers.ExceptionHandler +import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider import com.habitrpg.android.habitica.models.TeamPlan import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.shared.habitica.models.responses.TaskDirection @@ -28,7 +28,7 @@ import kotlinx.coroutines.launch import java.util.Date import javax.inject.Inject -class TasksViewModel : BaseViewModel(), AssignedTextProvider { +class TasksViewModel : BaseViewModel(), GroupPlanInfoProvider { private var compositeSubscription: CompositeDisposable = CompositeDisposable() override fun inject(component: UserComponent) { @@ -305,14 +305,21 @@ class TasksViewModel : BaseViewModel(), AssignedTextProvider { return query } - fun canScoreTask(item: Task): Boolean { - if (!item.isGroupTask) { + override fun canScoreTask(task: Task): Boolean { + if (!task.isGroupTask) { return true } - return item.isAssignedToUser(userViewModel.userID) || item.group?.assignedUsers?.isEmpty() != false + return task.isAssignedToUser(userViewModel.userID) || task.group?.assignedUsers?.isEmpty() != false } - override fun textForTask(resources: Resources, assignedUsers: List): String { + override fun canEditTask(task: Task): Boolean { + if (!task.isGroupTask) { + return true + } + return false + } + + override fun assignedTextForTask(resources: Resources, assignedUsers: List): String { return if (assignedUsers.contains(userViewModel.userID)) { if (assignedUsers.size == 1) { resources.getString(R.string.you) @@ -320,7 +327,11 @@ class TasksViewModel : BaseViewModel(), AssignedTextProvider { resources.getQuantityString(R.plurals.you_x_others, assignedUsers.size - 1, assignedUsers.size - 1) } } else { - resources.getQuantityString(R.plurals.people, assignedUsers.size, assignedUsers.size) + if (assignedUsers.size == 1) { + userViewModel.currentTeamPlanMembers.value?.firstOrNull { it.id == assignedUsers.first() }?.displayName ?: "" + } else { + resources.getQuantityString(R.plurals.people, assignedUsers.size, assignedUsers.size) + } } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt index efcd3b6aa..6d7a86ca8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt @@ -112,7 +112,7 @@ fun AppHeaderView( ) { val user by viewModel.user.observeAsState(null) val teamPlan by viewModel.currentTeamPlan.collectAsState(null) - val teamPlanMembers by viewModel.currentTeamPlanMembers.collectAsState(null) + val teamPlanMembers by viewModel.currentTeamPlanMembers.observeAsState() Column { Row { ComposableAvatarView( @@ -207,7 +207,10 @@ fun AppHeaderView( } ) { for (member in teamPlanMembers?.filter { it.id != user?.id }?.take(6) ?: emptyList()) { - Box(modifier = Modifier.clip(CircleShape).size(26.dp).padding(end = 6.dp, top = 4.dp)) { + Box(modifier = Modifier + .clip(CircleShape) + .size(26.dp) + .padding(end = 6.dp, top = 4.dp)) { ComposableAvatarView( avatar = member, Modifier diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt index d7e94af1f..03e3d67fd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt @@ -5,7 +5,6 @@ import android.content.Context import android.graphics.PorterDuff import android.util.AttributeSet import android.view.MotionEvent -import android.view.View import android.view.animation.Animation import android.view.animation.BounceInterpolator import android.view.animation.LinearInterpolator @@ -68,28 +67,11 @@ class HabiticaBottomNavigationView @JvmOverloads constructor( field = value val animator = ObjectAnimator.ofFloat(0f, 1.0f) if (field) { - val params = binding.cutoutFill.layoutParams - // add some additional height because otherwise there is a weird white line - params.height = binding.cutoutBackground.height + 10 - binding.cutoutFill.layoutParams = params - animator.addUpdateListener { - val reversed = 1.0f - it.animatedFraction - binding.cutoutFill.translationY = -(reversed) * binding.cutoutBackground.height - } - binding.cutoutSpace.visibility = View.VISIBLE binding.addButtonBackground.animate() .translationY(0f) .alpha(1f) .setDuration(200) } else { - val params = binding.cutoutFill.layoutParams - // add some additional height because otherwise there is a weird white line - params.height = binding.cutoutBackground.height + 10 - binding.cutoutFill.layoutParams = params - animator.addUpdateListener { - binding.cutoutFill.translationY = -it.animatedFraction * (binding.cutoutBackground.height) - } - binding.cutoutSpace.visibility = View.INVISIBLE binding.addButtonBackground.animate() .translationY(-binding.addButtonBackground.height.toFloat() / 2) .alpha(0.0f) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt index 8a3455f0d..d6624df74 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt @@ -5,13 +5,126 @@ import android.graphics.PorterDuff import android.util.AttributeSet import android.view.View import android.widget.LinearLayout +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.core.content.ContextCompat import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.StatsViewBinding -import com.habitrpg.common.habitica.extensions.layoutInflater import com.habitrpg.android.habitica.extensions.setTintWith import com.habitrpg.android.habitica.helpers.HapticFeedbackManager import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import com.habitrpg.common.habitica.extensions.layoutInflater + +@Composable +fun StatsViewComposable( + statText: String, + statColor: Color, + levelValue: Int, + equipmentValue: Int, + buffValue: Int, + allocatedValue: Int, + canAllocate: Boolean, + allocateAction: () -> Unit +) { + Column( + Modifier + .background(colorResource(R.color.window_background)) + .clip(RoundedCornerShape(12.dp))) { + Row( + Modifier + .height(43.dp) + .fillMaxWidth() + .background(statColor) + .padding(horizontal = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically) { + Text(statText, color = colorResource(R.color.white)) + Text("${levelValue + equipmentValue + buffValue + allocatedValue}", color = colorResource(R.color.white)) + } + Row(Modifier.height(61.dp), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically ) { + Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) { + Text(text = "$levelValue", fontSize = 20.sp) + Text(text = stringResource(R.string.level), color = colorResource(R.color.text_quad), fontSize = 12.sp) + } + Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) { + Text(text = "$equipmentValue", fontSize = 20.sp) + Text(text = stringResource(R.string.sidebar_equipment), color = colorResource(R.color.text_quad), fontSize = 12.sp) + } + Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) { + Text(text = "$buffValue", fontSize = 20.sp) + Text(text = stringResource(R.string.buffs), color = colorResource(R.color.text_quad), fontSize = 12.sp) + } + Column(modifier = Modifier + .weight(1f) + .fillMaxHeight() + .background(colorResource(if (canAllocate) R.color.offset_background_30 else R.color.window_background)), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) { + Text(text = "$allocatedValue", fontSize = 20.sp, color = if (canAllocate) statColor else colorResource(R.color.text_primary)) + Text(text = stringResource(R.string.allocated), color = if (canAllocate) statColor else colorResource(R.color.text_quad), fontSize = 12.sp) + } + AnimatedVisibility(visible = canAllocate) { + TextButton(onClick = allocateAction, + Modifier + .width(48.dp) + .fillMaxHeight() + .background( + colorResource(id = R.color.offset_background_30) + )) { + Image(HabiticaIconsHelper.imageOfAttributeAllocateButton().asImageBitmap(), null) + } + } + } + } +} + +@Preview +@Composable +fun StatsViewPreview() { + Column(Modifier.background(colorResource(id = R.color.content_background))) { + StatsViewComposable( + statText = "Strength", + statColor = colorResource(id = R.color.red_50), + levelValue = 10, + equipmentValue = 5, + buffValue = 4, + allocatedValue = 8, + canAllocate = false + ) {} + StatsViewComposable( + statText = "Intelligence", + statColor = colorResource(id = R.color.blue_50), + levelValue = 10, + equipmentValue = 5, + buffValue = 4, + allocatedValue = 8, + canAllocate = true + ) {} + } +} class StatsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { private val binding = StatsViewBinding.inflate(context.layoutInflater, this, true) diff --git a/common/src/main/res/values/colors.xml b/common/src/main/res/values/colors.xml index 994f82a89..1488f6ea8 100644 --- a/common/src/main/res/values/colors.xml +++ b/common/src/main/res/values/colors.xml @@ -73,6 +73,8 @@ #edecee #f9f9f9 + #4D1A181D + #033f5e #005158 #005737 diff --git a/version.properties b/version.properties index ce8608982..be277252e 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ NAME=4.0.3 -CODE=4571 \ No newline at end of file +CODE=4581 \ No newline at end of file