From 2378592031c7bcdaaaa04eabea505660a97af0f1 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Fri, 13 Dec 2024 17:32:45 +0530 Subject: [PATCH 1/8] Offer card layout issue (https://github.com/bisq-network/bisq-mobile/issues/111#) - Handles lengthy names - Handles range prices for currencies with many digits - Star rating composable --- .../drawable/icon_language_green.png | Bin 0 -> 1428 bytes .../drawable/icon_language_grey.png | Bin 0 -> 1430 bytes .../drawable/icon_language_white.png | Bin 0 -> 1423 bytes .../drawable/icon_star_green.png | Bin 0 -> 545 bytes .../drawable/icon_star_green_hollow.png | Bin 0 -> 734 bytes .../drawable/icon_star_grey.png | Bin 0 -> 545 bytes .../drawable/icon_star_grey_hollow.png | Bin 0 -> 734 bytes .../drawable/icon_star_half_green.png | Bin 0 -> 562 bytes .../drawable/icon_star_half_hollow_green.png | Bin 0 -> 668 bytes .../drawable/icon_star_half_hollow_white.png | Bin 0 -> 663 bytes .../drawable/icon_star_half_white.png | Bin 0 -> 562 bytes .../drawable/icon_star_white.png | Bin 0 -> 545 bytes .../drawable/icon_star_white_hollow.png | Bin 0 -> 728 bytes .../drawable/icon_star_yellow.png | Bin 0 -> 558 bytes .../drawable/icon_star_yellow_hollow.png | Bin 0 -> 733 bytes .../presentation/ui/components/atoms/Gap.kt | 20 ++++ .../ui/components/atoms/StarRating.kt | 29 ++++++ .../presentation/ui/components/atoms/Text.kt | 93 ++++++++++-------- .../ui/components/atoms/icons/Icons.kt | 14 ++- .../ui/components/molecules/OfferCard.kt | 55 ++++++----- .../UserProfile.kt} | 25 +++-- .../organisms/trades/TradeHeader.kt | 13 ++- .../presentation/ui/theme/UIConstants.kt | 3 + 23 files changed, 167 insertions(+), 85 deletions(-) create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_language_green.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_language_grey.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_language_white.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_green.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_green_hollow.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey_hollow.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_green.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_hollow_green.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_hollow_white.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_white.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_white.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_white_hollow.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow_hollow.png create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/StarRating.kt rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/{atoms/ProfileRating.kt => molecules/UserProfile.kt} (66%) diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_language_green.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_language_green.png new file mode 100644 index 0000000000000000000000000000000000000000..116b02cfcc78d4dd193fc66cb80230822bcad396 GIT binary patch literal 1428 zcmaJ>eQXnD7(e#K7>-O)kPr2^$=J-U_tk5Ax0PjGS1Ga$O0!Ln*z4Wf^|IYvx!%^U z1_kC=z!-2L1{aK?%tb&L83Vxy6Bj-bU>YHWO~4p~Mje}cj2MOZc3UTZ5H7iUznLUG$e?%z(D<=Mpo_E@K+}= zRF>>m6HqjMa*qgcU7D3!^-Apa4Taqe`6`=A(9O%r6h;@ofS_ z$4rb`J2phM*{d#*Sg|I>J+b=cb& z0)z*IwR&BIR}#ohfT4Vk4-_|qZ1@UYhW8@WIW@6f0jlA4+A(-yl4OaetODx~kQC1N zX$wvU%oOftCavkkX|c`0IZ8Rw!Mf-K z)~$vOK@~wFwhUuWV6BhE@+CSD3{CfHT3wcX1CU(0rl4aY^YSAIm~DQGMX&&zr9^;BHZzS2WI({J94Fc=X2uo}1#AK@JtW?E zox&ZML@2?9hiZ``1mY6S*l>n2GdM^41GoT11&kzFBuc~xNRf!w%|msR*n-6wpH4Og zTuinWP+>pmuyI_2*#{70%4cq8u{Sz!uJWqVL}ulzNb{vwa<8oKx%=MnJM4uNH7EB2 z^nA*O)HW5Fw_WW`ulug;_xyGIhu^4Kd)jBF4c@!jAE~MAAKvl``en@lihk!K^L1^r!3eRnPPGANLA-(#_e~u4Q@O*P_TQ^j*r||rbjPN zYdq0f+`Tt&8hPc`#Z_;L*VcaW;`X#B)`dE_tRW>RrvKftZSZW{&ZIw6Dq^&>=eMJ$ zi@&~jY4ySzqa$ltl3v1+rtW<;{a*f&9h>@Qclvw_FTS>{HZSj7Z^5Zj*#26s(c;n=kF$f@MrHRR3CC$}8?>(HvMoCh~h-;95454uOP z8?wK2T>o}p`1ON__5h1mmE=l(VKFBc78Ikgo@MwZ@}y^aO{u<`$-yR_W7 I-{IT%AN*eZR{#J2 literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_language_grey.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_language_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..5fe459092438e43ac1e489d4e070bc5b8bc58e7f GIT binary patch literal 1430 zcmaJ>eM}o=7{Bs01(}-p2To<@!RB;a@2l7L4mv0lq_RSRhCwnS*Soi+gZ9eZVG9~F z5%!52Y-4e3i_^qJ&1N=1CjtT*GiTHoHnzEtEene}GI3-uT}Y;Hf#UukyX5ZudVbII zdw%cp+%9MF%gKqW6A=VSwinvU;P`CheIx;XmE>y&;qbJUU#XSL9xWs&0I^E48=!W- z;00wskeV9Kfh+`xZS}b-wMxe(UX=ZMA!4Hs`-2dTAX(Yrpdi)(4Rr&rFJQs`>L0>T zpJc%{vkuY`%mcN)!e#}OHy69a<~os+u2RWXvI0;}PvIg-(x{2kdl=RLJfexrKxvX@2#O*|4yS0IWO2UixXR?~t!L4-mfeTdP^ikF}`jw48#plKXh;A&Gq6T)~vO^bT40aa9d zLCq%z(1=IDEjMZw43b^Q!XI=vmK+DvMXjJ}L|6zCl%6E~{zz)`)~Z$p{-?35wd!gL z0-_A4a-$-`EAga7!BD=32Z|U%HhhWVgZCoT+hnoP4+5IqX2IZzUh+viWfEAohoo@E zO&f92W1w(1Loqm@8INFelcLc;M*S>@x7v((1zfJp$g&2C$}iw-6m4c%(#Yi%Sj`L< z#o7a^CImzfjqQW67qNK{#qxOy5HwkF$#Q+P5S+ELCabk_5T#i?i>}}73rKQEeKB%J z3n|-x;(HB91&ZuP=SAjy%MdV_-A1Ee1UO5H0GG@L8W%{9fSWi@G#d?!*&_L|Jei!(A^ zY7DqoYAq0e{iMLgnLBiR06}yg*=<%=_{u=V9{=0q6OOcmnmFEiEQ9O&NbD<8EYN08OMsfq)xcmI&yb#ZXolHyZzS_+!t@nxi=i{lJMapU5TG{ z?>Ms7;;MLaMS7Zd``yFN;cs(~ri`t+URCTG-(mi4pl7sovSC|%x|R}i`Mpfs+TGu^ zqV!f$bzfZ3>-%pY{ioRc%U3#rKgXOn*&DZ|^YapVD6x-i9~*hza^PP44;y!ePImnL z%wwOt!Dhx)4wrlH9cwzfYd@N7m^qO7)04fS_usL9Kh!q9_u`F|nhoL6k&e?J{GM7e z`Qg`BU!u;WU7K~~#ACrzyW4ILD@Er!T4PoxRCILjIejQsC>WTiF50Jir9GqL%%Jm+ z?ms7HKi-b0y**nHHTBl*`zy;z+p^Q!@rIn~-yBIM4=4?9y->BL=g#OaQ$JR$kG+%@ z(wTOylo}`Xx~c1_NwZI_C0$>!R|}h)C-!zaFEkz>>t?5k$93vA`_A{Y4GE?eV&=K3 zxqpk^jjhBEdM{T0^QHUMHGS*4b+x(oM{|ZR^$pJ4oPJ>#IlE&k*)ZEV75P)z^NVet I=GL_Q2P78(9RL6T literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_language_white.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_language_white.png new file mode 100644 index 0000000000000000000000000000000000000000..12c7348431a60c701e0e6923ee5d773badbd9d4b GIT binary patch literal 1423 zcmaJ>eNYr-7~c!DM6uE|Kc{WQhSdGOJ#Kfn?BEW)h698PE~$pS-FIb^yS;Yzy5nYY z9Hq%DGU*dR3QBM$6Db?0rpb^@Mu%W3KhTC|a7fHjD<`L6viE=^|6tsi-S_MHJhqg^Z@wUDK|)N}5V2qwq7fu}Z7eKGn}LZ2z$P{1z^;7p6^5#^ z11saalsB9UD%JII9hAfid{TU~#LL*)N6_q;038H@DWb7pRmc!x4s6`70OyHq5<|yL z%*_sLf|TD|gyw2GKzV}3C5mFuES^wU&I%MMi&}#+6vL7MFb!vC5@Mkst_}9+v}yCxooZ0-Yst0fnM*Ho(|$ zO0m*-fTdX+Fsvfl0+eL4Qb|A4;d8Qb+_ar@+BnWi)9yScW2c>*+f6xLypwfuNvtPi zm|{o*$=E84J&EOSixqNpAex%))3mB&Arw_=re;)XVU*zr4$Ul6L$Ve%9!}iRM9MCp ztIq*BPuGIzxX6M!4FRh?V6%xffOE72aM^BUaFJ3(Jd5WgyUohl6-mS<@$xO=P1Gse zfk}juTm+~VB|#uAGprqFX)BBKOhCa!C@NrO*(TExMnZ~YqHb=fqvRGW&ct-8G2mjV zwLl2=lMWka!N%<05X92#aXEdl!IPx}!R^$2HTzSjJL=yvQ$DxsMf*}S=hqbUE8C8w zj?V0z*}U|S^TtRUH}Hh;IB^`vU&t*FRhy%Q)kCzb18L*5i$Zd+;-h)s(ui6D`LpymKw33m@WajPI|yYx_Sr z{A<;xd}r$~qy9&2bGPq(p=Rms@`BupY46NB)c6c>#9uQ*3cS7Iz?!no1`TPqkf2$qzTKTu2@LdB)A5id9cvZIBP_*m`NzSOe8ldVIJ}Dqr0(uy)RB`oRbM znGrK06PDio^Tz$(x(^=SaPFgP`JxsdjJ4=*`pQm9vBGND6Y#@A2WI9cR(RFVf>Ka2?F4*!CaPPz6^2 literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_green.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_green.png new file mode 100644 index 0000000000000000000000000000000000000000..b3fbf60bee1932ca7a15e6d85cb6287e97e3bc7a GIT binary patch literal 545 zcmV++0^a?JP)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz!%0LzRCwCNmP;r^Q5eUK@rn=&WkZsZ zB2qFTlo$;WM#>9)87RD)X3=B79-ZAaV^ z=YR=mKWJtiGvYo_A?;U!9yi1x#aP5?aRC@tjE{jlC&fdcL@{0t{6-T+#4H%$T^Dhz zn8&@6tWaaFUGUEBXYd2Q!3)RUz$e%PYe{jGlP^(ZCi01hGR1Lm6Z2qQe$@%E3 zZG(2z9c#oLui3G>j<2{h^oDrCYdZ=^Bd9VU7Ok@04spQ5Hx4){PBAy))ITARu|)c z^rpu78$2gjZU^}{YFO-JYZM)&8{Fzh#2e5B7MLF`>H4uMYFL3T4K5|o{uaRrs7rOd jmUzozgSa5d_!VFP4eCojpH<+|00000NkvXXu0mjfxpMAf literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_green_hollow.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_green_hollow.png new file mode 100644 index 0000000000000000000000000000000000000000..06bc33bc552d5f5f1ffe2ee3a7c4639eb439a24f GIT binary patch literal 734 zcmV<40wMj0P)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!fJsC_RCwCNmrY1iQ546WEX$&@7D7a& zgb-4h2%%*3L6%~oM&t*z2p4UlaNDX{)FKEH6g4o4kST}?Qi+IGil9^!xr!j8pj;I8 zfqgms5Bvr$I=-3rW*QIt=Dl~{z4w3LdFP(_ZdNa{{-^Lku|kaCW^?y*v07C6&RnvSqLx)Jqis3& zGZ8ae$}#NB5hjb>7C&g46o17Z@s+mkWV$<|Gb-H9jcVB#CzSV@yhf&6VrKBXOCiwY_^q zJQQmkcPA}u$)JoVw^H~*>?I-8h&tR`!Mz;bak*HTjBq8HDvMNS6W`;#+tb|_Tg3ww z*-d_5M5YQXT4MADXZKPX7cL0Eu*k6C%mb Qng9R*07*qoM6N<$g1o>;!2kdN literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..1afd3272624929a03782b6de97876afb5ce4c3ba GIT binary patch literal 545 zcmV++0^a?JP)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz!%0LzRCwCNmP;r^Q5eUK@rn=&WkZsZ zB2qFTlo$3y5VIid`vXa%5ENo;a3$kE#Ugg#JpZZUoICJN| zef6t*&%O8j?&CY(cYT_sW&KBF+qkwFH2jA+0-|1veIN{`ycTzWYETQ>yc9>I?WkAc z955m6Pg-F&1@OTmZ%u<6|JtP4N&YQH+;^pxHzbF$YF?*F_vF z=5fCyE7X~57rb%%34DVu@XWDS@B#L~T1p(_Jx;prVBC^Sd8`1JDExf1Q)dN@ZCrzcNwmXV?N0il?7tBQW&3^~8Ru)y4TA zy{U8l2G2>A+d=+~nidDx8bwFx1~�@fvgijrq}%sUNGNh85_-cb%*6W&&00000NkvXXu0mjf>pt*; literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey_hollow.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_grey_hollow.png new file mode 100644 index 0000000000000000000000000000000000000000..c471eac02299283cc7282ca0ef8fc181113d78c2 GIT binary patch literal 734 zcmV<40wMj0P)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!fJsC_RCwCNmrY1iQ546WEX|_Q7D0rS zgb!2|75aa7Z+Yrfdsu6RX4;u_c?r&CYpCwuCJp4>{L|gUk~|c#l{{G`|tc zMP)XG8#&$-y+PgWS9rcS$ayc~W(^|me+usti^U*rHg`W4OGSuReM7sOsMM%xzxX*I4i3Ru{PGvPbtDRBCg5OCx485Px{4XuCP@nf-B42VK;O;m}` zFyY~e38!DJxQZA1ne$1q;QGM6>?De>h#t<9nZ>|$aS69y6uZR7RHJ&5fICXS91~A* z;Y?Oa9~<+Hw0c_n46>bWh^?%+TpaP}Yl0iad&Wf5-N!H48fN!A`o-_r6TZqs0x1(K ziR59YeZ5%cTw7B4M5$bx3E?`9_t^?I<_tnZ;uIeSw!a@t86_5w0Oq<&o-a;@iA;d%8PfgSg8g zyUFkK$W(!a>zt1}OZLYpfn!de_|u=D5QI{3x0i6PQ|kJuKs_G)yXiB)b*-}qU&0lX zMyn`0#oH7D(Q5P#aSqp)C#%Patb`2o%;(2~mA?pEt8}LEq1pQH^jClZ0H8F56TSh| QkpKVy07*qoM6N<$g5GdZ4gdfE literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_green.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_half_green.png new file mode 100644 index 0000000000000000000000000000000000000000..acd793056620906f0a085c65f194a0e04be05cc6 GIT binary patch literal 562 zcmV-20?qx2P)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz)Ja4^RCwBA{Qv(y!$1HQ5D~uKlN`MU zT9+(-0qJX`YOJrXXJDeh(UCwLMXqLYEoKA-6c9(y+hS`VmIq>GAU30?#gRztD0*28 zN{}H){4jFNA;)4DAQnU7O9HV2JuD8#A{Iq!i#dQe2#a_i5VO(JVjm#p!y+yO#2zG< zTtJWm#QsoMb3?^=q4LZ~mT}=RYZVZGgR(yX@n0bR1H_-9Vqbw6RMM>l;u$cDr$P;H zf?7llV25H55X2%6azqsn&qNMtP)*SW#O^@+ng(^kOCWXw;%=y27;(H8h>d~x1Qjhk z3N>>-p~UqVnlGnP!O}@U>RCZ)KE4di8pHyS53f?A0MP|vIT9=eRh1glu-Kc7IQFKc#s6t(F{li-#8Dvl0&xHk zzrrGK1H}B4SnPqN2;BgU_pLy@5s3AGcng{uR%l5@w#CRn1}f~6p;h2(EWS^NRs=)^ zH$ID*k*YdSv1b6p^YEyj1yutpZatx`QIajTgjS898pR%n?-7v@?*Oqa5H~>6hasW* z7#mQ8mO$r7%u1l@uMvp11F0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!K1oDDRCwCNmrqC(Q5?s2-TYUm=|Kp= zkXVof(+FgjlnSy|D%1$KUGUVQi`2c#S_eINN?6f76hy=-hy{ssh)yel5wfBu2}(ND z9)c~!N*ljF_zDl2-Pw7w?*8Dj^JeC~_kHu5-~0V$-G*VfN@2(3Cp6!yGq%H*^8dkc z!|uRnH0mmIu;?&|=nmEuc8jCHoni}L0H?tj&{<63u+okcOIQN(wsJnGGmnn&70}4` zCO8Ey6+<|rv|sAF+pcgGxTT!W@HhY}j#Bsrs8!A-d8~p45VW1SV8ft~t3JVNHN5Xp z#EzTHk&r9~X2A}xWxzhz13!6f8%U;`15<~>F;4!NLUv4q$3P_!t2gN7{(Hyoz32Qlz_1^FIeK3UrehHz+av1^aA+JR%~J-*bcsMOv33t zUgOrVvIQRH3D*meK-xfamU}*>y#l_oRJImE_*nk_-YS*Cip`1pRbx4@iNNe8*j&&WUi)B!#}>dzYts4bFl$Tx6X2y_}g!TUd3O zB>TH8foYSczsEx0&d1%kggr{BOR@qz&Cx&3K8NYHS6PHD;Q&jcRFsS0QyzgRpF-VW zgswklRgcZAg&F9h&3rB8?-93_H`{o3ss1}12rvM5-)$4ujw5{l00000000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!IY~r8RCwCNmrF<+Q51%a?+0zQ3qb@W zh){&uiXe)L3cf-WtB5fHS1#NX-MfjpNEclxDC(jG5wQh9K@k_FD~nJmMX4(hR9sjW zh4?^CHU0;F;eun5xsxUbzRaDOd+&ee%(>@GY=J-^E*6$3KYqVoXY6aQ*L#iQj@f}8 zk0&nP!lGTktvgs(*an=SJKDmPARiQfvSvWDy#sArbq23J;r#?fEZty^ zdC6kn3%KAlAGiVkz$vet1Ics?VDesgoRg1G$c%~bdyqoJvJCpkA_l>f>T0PJUeE+i zObYLFo;12#uruI%>~jnn!3SzRc*kEsDcI16_Dk@WIKU@*ah-F13l&_4+?V4T;t~Th zV1jNR19jji+^D`{!1X8r6Uqv~caAw@S{;z8tFxVELAlY24NL@Ifdh`2x4MtFxiv!B z3Xk%Hzax=AUV^+w?iDHRAK(v5<%>uNzX@`06ZG@L;1;ZgF~+iRfO~fotbts`-Ij$V z8B`ctmxRy?-qO7dU<+jO9an*8R)m`kQs^SzyFA?zCZ7&I0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz)Ja4^RCwBA{Qv(y!$1HQ5b^u>Z*ue+ zw6(SU0@Bw=)mUF&&%i{1qa%Shid@a)TFeN<;XoWgZ;P#gSRRO#f!K_m7Dpnnqv&NZ zC_#oG@x#b5ha8JtfLIKPFA2mB^sqP_i&zw`E#?5?AS~j6K+Hx_yR3f^Fg&PIoW9m5L;k#F&^*; zs%HhI`S>z4YY+=SKDEvG_h6S`iQx z-1sbJMyl#S#hw8W&%>jB7E}$axb=j#MoG5V5?VEaY7~1QzDGntyaU9xK->ULABKeL zV{AYXS^}LTF)M+pzeXV54#cXs^fL}r-w7bV00AgfTR*m(CIA2c07*qoM6N<$f`--M A>Hq)$ literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_white.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_white.png new file mode 100644 index 0000000000000000000000000000000000000000..eefaf4ecd8c8938a382582325e7aa4be349bfca3 GIT binary patch literal 545 zcmV++0^a?JP)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz!%0LzRCwCNmdz_fQ5eRJ8Ac;yiik)o zq==ME2$3d3SZO9~B%ApQtmIEnQ>-npP!w5dR?5mocA`ic%EDKQb#(+cuog%-wkg0_4JM?p+=utzb}9&iJ`L5rIn_kl*x40_xY zj_ST+ZiU(h?m;zwKY)7h>$JzCI#FS@V91S7&q~^2PKUY#q(FIE`!hY)obq@=A}TBh z!YUre!4xP4rR*!?LGtRv0>E!D*C+Vk_Y3%8p1-o~oe|js8$LEBIQbfdRLrkiRHdX} zEMf(0%Jz5!Y=bJB?}QX{KWVhbC!iag*(iF-Ig{BA*B$dRVT0&87-qrADV^rHCxILV z-@p>sv69E_;26}I6ukxG;L>UyUobVy+E+GFv%&RoQBXa75uyMVu7=b5dB; z;E+K2EZy8+@<32JPX0OVx1Px j-X^eX=Y!s|{R=PvVi9S<*IS?d00000NkvXXu0mjfJR0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!dPzht{cOLcyo)Ea-%%NgHM|nV>2~r#C{AZ{yIU z_J}xy7w`)vS2E&xPz#e_j?V|GQpjAirbSc0jv-uf}fkl;& zdV`J^;k>WhNu?eL9WV^0K!11w9~60KZ%MsUPVY%(llviLVR_=pg>8q`ieQND4b}5% zIWrrqW6t?TPF3s@eAm6t@LPHQMfbi*kt=YdD76)YU9eY<;>>36czC1hS{0M9Ogrnu zZrF#^QRx^jg$pnOK0yoIRRm@~ARjaSgLFO|>Mb&<)uG&P>uQW|!ECq#HE;?V;G@XL zM3i^lTLCBK^tQg)RxX`hDK8Hxieqp>=jF`iz-c%P1K=PmR>4V>PMhGUKG+WHG@k!6 zORvi?6TZUMl1Z2-ozB8s^|($Q>B^er^rhP5(pIj=N)5BtnD>g$3Mwk8OXduip!8{X z?oWql&b1YlcUmf^_Jrd`9j`&8Haq3$KI~8qTYg_JY11Q)TU9u2!hX$K%i9BR1I9XX zr*@oGA^54K@DVIgL0AQAByWSB)o6_8tB827PPW{glf=c6conw6dtHx$<61xh=iT*6 zFRyfJbT)TZ?6<&L$7$e1-=c*e?2g=V5m!sbtjgYIcwVNXw&OgbJhrx@r9h&H>$No6 zin6d9P6Msc3t*2rT;~&UvkJij&z-1kdnam(^iRZLU;TIbE5HCNV8GR@c_t?S0000< KMNUMnLSTYNzE*Gm literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..0b30c15f23769d52a8e30946a67236884131a277 GIT binary patch literal 558 zcmV+}0@3}6P)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz&`Cr=RCwBA{Qv(y!$1HQ5OJ|ZfgHUC zK>Q1cuaT-zzvcl069tZr1mY-iHIr*GBM^rJaRj|BwgzH(AXWxqGkRJaiNubgm&Kq2 z8G^(QBgY(aEOr56F(keu5IfMr;&3ctQM9(01BipLhz9~O8!avN0b)KZ;zB^|L2}6j z1UW$L4|O#+RE!rY&x~Xl7ap@#0r58|`x6lV1>!$I{240t6zYni>E>jZ-QDx z4q%635D>&74{}5m5YI#oYEVtl2E^__{F(-J!b>1_1LAI|T^Mn^7l@64_yiR#Jqk5* zKcU3+7@9AqQo+(mKl>BT#N@ig6dg8 zX+FLT%^Ji4kPoj?qX5wbVmT5l233_B)Ueo_j5zkDrN#egX)&k_w!~2&_yTbN5Wm7A zZv({qlvwP6r3l>sjrXlUyb*}?fOrd<8dhjYMYhGrK?W-9lc81MYb?G`hgJkc1vfs6 znUSixqtJHrJUr@WLDj&DTTf_flw^x7p;aTOMzIItdqgC}J3wp;#0}8&VMwSx#s(Cj wCD1t%vl6KKYXsu$K&*;OKjT34od5z10Ir}?TS=?bd;kCd07*qoM6N<$f*$zWr~m)} literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow_hollow.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_star_yellow_hollow.png new file mode 100644 index 0000000000000000000000000000000000000000..c51b7802b73d1825626f40b81d9c17e2f2b85b10 GIT binary patch literal 733 zcmV<30wVp1P)0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!e@R3^RCwCNmrY1iQ544=Ez_d37D7a& zgb-1g1ff`1k)>Ez5t&kpaN#Brx6vXcauEaxhA9|D$P@$xeGn0?48iD=Tt!q;P%aGn zz&@w{f#1Nz#y9icjN^gdy!Y&vEPT`$mff&Ng=I*Crk*M~axnxH~9jl&4+kEb4 zA!at0W7wG^OcuK;zSA}?{)pe=3vJ)Xbk{_8RJe=D+Y$1zzcGY6#2heN7-O6*;+Qz^ zy4otmDX~M0()O7^D#VpWE(`nMO!$_0a-Duf1l%}%K8o$)G+O_?*9qNoyM zFyY~e38!C;xPTW2nDarr;2L3Hb`izBqL1@e| zd&uvz$y9-bYn_ifOZH8az)`19^y!-^1ffLS?IoP$l)3>bP@hNt9{LP&UE?gmmvA|y z(JD%%c%48XT8-W$PT=~|c=b4z6_J4+`}|n2^4G@JDxPY5Xr}%<{S#mSniPc-Uj{=+ P00000NkvXXu0mjfb}3$S literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt index 5580167f..ee6ad905 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt @@ -9,6 +9,11 @@ import network.bisq.mobile.presentation.ui.theme.BisqUIConstants object BisqGap { + @Composable() + fun VHalf() { + Spacer(modifier = Modifier.height(BisqUIConstants.ScreenPaddingHalf)) + } + @Composable() fun V1() { Spacer(modifier = Modifier.height(BisqUIConstants.ScreenPadding)) @@ -29,6 +34,21 @@ object BisqGap { Spacer(modifier = Modifier.height(BisqUIConstants.ScreenPadding4X)) } + @Composable() + fun HQuarter() { + Spacer(modifier = Modifier.width(BisqUIConstants.ScreenPaddingQuarter)) + } + + @Composable() + fun HHalf() { + Spacer(modifier = Modifier.width(BisqUIConstants.ScreenPaddingHalf)) + } + + @Composable() + fun HHalfQuarter() { + Spacer(modifier = Modifier.width(BisqUIConstants.ScreenPaddingHalfQuarter)) + } + @Composable() fun H1() { Spacer(modifier = Modifier.width(BisqUIConstants.ScreenPadding)) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/StarRating.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/StarRating.kt new file mode 100644 index 00000000..6a31c313 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/StarRating.kt @@ -0,0 +1,29 @@ +package network.bisq.mobile.presentation.ui.components.atoms + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.components.atoms.icons.StarEmptyIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.StarFillIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.StarHalfFilledIcon + +@Composable +fun StarRating(rating: Double) { + + val fullStars = rating.toInt() + val hasHalfStar = rating - fullStars >= 0.5 + val emptyStars = 5 - fullStars - if (hasHalfStar) 1 else 0 + + Row(horizontalArrangement = Arrangement.spacedBy(2.dp)) { + repeat(fullStars) { + StarFillIcon() + } + if(hasHalfStar) { + StarHalfFilledIcon() + } + repeat(emptyStars) { + StarEmptyIcon() + } + } +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt index b5ca9957..c81ab083 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Text.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.unit.sp import org.jetbrains.compose.resources.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnitType import bisqapps.shared.presentation.generated.resources.Res @@ -46,10 +47,12 @@ object BisqText { fontWeight: FontWeight = FontWeight.REGULAR, textAlign: TextAlign = TextAlign.Start, lineHeight: TextUnit = TextUnit.Unspecified, + maxLines: Int = Int.MAX_VALUE, + overflow: TextOverflow = TextOverflow.Clip, modifier: Modifier = Modifier, ) { - val fontFamily = when(fontWeight) { + val fontFamily = when (fontWeight) { FontWeight.LIGHT -> FontFamily(Font(Res.font.ibm_plex_sans_light)) FontWeight.REGULAR -> FontFamily(Font(Res.font.ibm_plex_sans_regular)) FontWeight.MEDIUM -> FontFamily(Font(Res.font.ibm_plex_sans_medium)) @@ -63,6 +66,8 @@ object BisqText { fontFamily = fontFamily, textAlign = textAlign, lineHeight = lineHeight, + maxLines = maxLines, + overflow = overflow, modifier = modifier, ) } @@ -78,7 +83,7 @@ object BisqText { text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -95,7 +100,7 @@ object BisqText { text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -112,7 +117,7 @@ object BisqText { text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -129,7 +134,7 @@ object BisqText { text = text, fontSize = FontSize.XSMALL, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -147,7 +152,7 @@ object BisqText { text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -164,7 +169,7 @@ object BisqText { text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -181,7 +186,7 @@ object BisqText { text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -198,7 +203,7 @@ object BisqText { text = text, fontSize = FontSize.SMALL, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -216,7 +221,7 @@ object BisqText { text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, lineHeight = TextUnit(16.0f, TextUnitType.Sp), modifier = modifier, @@ -228,15 +233,18 @@ object BisqText { text: String, color: Color = BisqTheme.colors.light1, textAlign: TextAlign = TextAlign.Start, + singleLine: Boolean = false, modifier: Modifier = Modifier, ) { styledText( text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, lineHeight = TextUnit(16.0f, TextUnitType.Sp), + maxLines = if (singleLine) 1 else Int.MAX_VALUE, + overflow = if (singleLine) TextOverflow.Ellipsis else TextOverflow.Clip, modifier = modifier, ) } @@ -252,7 +260,7 @@ object BisqText { text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, lineHeight = TextUnit(16.0f, TextUnitType.Sp), modifier = modifier, @@ -270,7 +278,7 @@ object BisqText { text = text, fontSize = FontSize.BASE, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, lineHeight = TextUnit(16.0f, TextUnitType.Sp), modifier = modifier, @@ -289,7 +297,7 @@ object BisqText { text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -300,14 +308,17 @@ object BisqText { text: String, color: Color = BisqTheme.colors.light1, textAlign: TextAlign = TextAlign.Start, + singleLine: Boolean = false, modifier: Modifier = Modifier, ) { styledText( text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, + maxLines = if (singleLine) 1 else Int.MAX_VALUE, + overflow = if (singleLine) TextOverflow.Ellipsis else TextOverflow.Clip, modifier = modifier, ) } @@ -323,7 +334,7 @@ object BisqText { text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -340,7 +351,7 @@ object BisqText { text = text, fontSize = FontSize.LARGE, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -358,7 +369,7 @@ object BisqText { text = text, fontSize = FontSize.H6, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -375,7 +386,7 @@ object BisqText { text = text, fontSize = FontSize.H6, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -392,7 +403,7 @@ object BisqText { text = text, fontSize = FontSize.H6, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -409,7 +420,7 @@ object BisqText { text = text, fontSize = FontSize.H6, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -427,7 +438,7 @@ object BisqText { text = text, fontSize = FontSize.H5, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -444,7 +455,7 @@ object BisqText { text = text, fontSize = FontSize.H5, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -461,7 +472,7 @@ object BisqText { text = text, fontSize = FontSize.H5, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -478,7 +489,7 @@ object BisqText { text = text, fontSize = FontSize.H5, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -496,7 +507,7 @@ object BisqText { text = text, fontSize = FontSize.H4, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -513,7 +524,7 @@ object BisqText { text = text, fontSize = FontSize.H4, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -530,7 +541,7 @@ object BisqText { text = text, fontSize = FontSize.H4, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -547,7 +558,7 @@ object BisqText { text = text, fontSize = FontSize.H4, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -565,7 +576,7 @@ object BisqText { text = text, fontSize = FontSize.H3, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -582,7 +593,7 @@ object BisqText { text = text, fontSize = FontSize.H3, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -599,7 +610,7 @@ object BisqText { text = text, fontSize = FontSize.H3, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -616,7 +627,7 @@ object BisqText { text = text, fontSize = FontSize.H3, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -634,7 +645,7 @@ object BisqText { text = text, fontSize = FontSize.H2, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -651,7 +662,7 @@ object BisqText { text = text, fontSize = FontSize.H2, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -668,7 +679,7 @@ object BisqText { text = text, fontSize = FontSize.H2, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -685,7 +696,7 @@ object BisqText { text = text, fontSize = FontSize.H2, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -703,7 +714,7 @@ object BisqText { text = text, fontSize = FontSize.H1, fontWeight = FontWeight.LIGHT, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -720,7 +731,7 @@ object BisqText { text = text, fontSize = FontSize.H1, fontWeight = FontWeight.REGULAR, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -737,7 +748,7 @@ object BisqText { text = text, fontSize = FontSize.H1, fontWeight = FontWeight.MEDIUM, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) @@ -754,7 +765,7 @@ object BisqText { text = text, fontSize = FontSize.H1, fontWeight = FontWeight.BOLD, - color=color, + color = color, textAlign = textAlign, modifier = modifier, ) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt index 5d4f0e6c..9e147bbd 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt @@ -28,6 +28,11 @@ fun CopyIcon(modifier: Modifier = Modifier) { Image(painterResource(Res.drawable.icon_copy), "Copy icon", modifier = modifier) } +@Composable +fun LanguageIcon(modifier: Modifier = Modifier.size(16.dp)) { + Image(painterResource(Res.drawable.icon_language_grey), "Language icon", modifier = modifier) +} + @Composable fun InfoIcon(modifier: Modifier = Modifier.size(16.dp)) { Image(painterResource(Res.drawable.icon_info), "Info icon", modifier = modifier) @@ -61,12 +66,17 @@ fun SortIcon(modifier: Modifier = Modifier) { @Composable fun StarEmptyIcon(modifier: Modifier = Modifier.size(16.dp)) { // TODO: Import right resource for this - Image(painterResource(Res.drawable.icon_star), "Empty star icon", modifier = modifier) + Image(painterResource(Res.drawable.icon_star_grey_hollow), "Empty star icon", modifier = modifier) +} + +@Composable +fun StarHalfFilledIcon(modifier: Modifier = Modifier.size(16.dp)) { + Image(painterResource(Res.drawable.icon_star_half_green), "Half filled star icon", modifier = modifier) } @Composable fun StarFillIcon(modifier: Modifier = Modifier.size(16.dp)) { - Image(painterResource(Res.drawable.icon_star), "Filled star icon", modifier = modifier) + Image(painterResource(Res.drawable.icon_star_green), "Filled star icon", modifier = modifier) } @Composable diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt index 6efac1f9..05ff3304 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt @@ -1,37 +1,29 @@ package network.bisq.mobile.presentation.ui.components.molecules -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.IconButton -import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.remember 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.unit.dp -import bisqapps.shared.presentation.generated.resources.Res -import bisqapps.shared.presentation.generated.resources.icon_chat_outlined import network.bisq.mobile.domain.data.model.OfferListItem -import network.bisq.mobile.presentation.ui.components.atoms.BisqText -import network.bisq.mobile.presentation.ui.components.atoms.BisqVDivider -import network.bisq.mobile.presentation.ui.components.atoms.PaymentMethods -import network.bisq.mobile.presentation.ui.components.atoms.ProfileRating +import network.bisq.mobile.presentation.ui.components.atoms.* import network.bisq.mobile.presentation.ui.components.atoms.icons.ChatIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.LanguageIcon import network.bisq.mobile.presentation.ui.theme.BisqTheme -import org.jetbrains.compose.resources.painterResource @Composable fun OfferCard( item: OfferListItem, onClick: () -> Unit, onChatClick: () -> Unit, - ) { +) { Row( modifier = Modifier .fillMaxWidth() @@ -51,27 +43,44 @@ fun OfferCard( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { - ProfileRating(item) + Column( + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.weight(3f) + ) { + UserProfile(item) PaymentMethods(item) } Column( horizontalAlignment = Alignment.End, - verticalArrangement = Arrangement.SpaceBetween + verticalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.weight(2f) ) { BisqText.smallMedium( - // text = "\$52,000 / BTC", text = item.formattedPrice, color = BisqTheme.colors.primary ) - BisqText.largeRegular( - text = "\$98,000 / BTC", - color = BisqTheme.colors.grey1 - ) - BisqText.baseRegular( - text = item.formattedQuoteAmount, - color = BisqTheme.colors.light1 - ) + Row(verticalAlignment = Alignment.CenterVertically) { + LanguageIcon() + BisqText.largeRegular( + text = ": ${item.supportedLanguageCodes}", + color = BisqTheme.colors.grey1 + ) + } + BisqGap.H1() + // Len: 13 - "300 - 600 USD" + // Len: 17 - "3,000 - 6,000 XYZ" + // Len: 23 - "150,640 - 1,200,312 CRC" + if (item.formattedQuoteAmount.length < 18) { + BisqText.baseRegular( + text = item.formattedQuoteAmount, + color = BisqTheme.colors.light1 + ) + } else { + BisqText.smallRegular( + text = item.formattedQuoteAmount, + color = BisqTheme.colors.light1 + ) + } } } BisqVDivider() diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProfileRating.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/UserProfile.kt similarity index 66% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProfileRating.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/UserProfile.kt index e8391026..c58443f6 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/ProfileRating.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/UserProfile.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.components.atoms +package network.bisq.mobile.presentation.ui.components.molecules import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -14,31 +14,28 @@ import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.icon_star import bisqapps.shared.presentation.generated.resources.img_bot_image import network.bisq.mobile.domain.data.model.OfferListItem +import network.bisq.mobile.presentation.ui.components.atoms.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.StarRating import network.bisq.mobile.presentation.ui.components.atoms.icons.StarEmptyIcon import network.bisq.mobile.presentation.ui.components.atoms.icons.StarFillIcon import org.jetbrains.compose.resources.painterResource // TODO: Get params and render apt @Composable -fun ProfileRating(item: OfferListItem) { - val fiveSystemScore:Int = 3 // item.reputationScore.fiveSystemScore.toInt() +fun UserProfile(item: OfferListItem) { + val fiveSystemScore:Double = 3.5 // TODO: item.reputationScore.fiveSystemScore Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) { Image( painterResource(Res.drawable.img_bot_image), "", - modifier = Modifier.size(48.dp) + modifier = Modifier.size(36.dp) ) Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { - BisqText.largeRegular(text = item.userName) - Row(horizontalArrangement = Arrangement.spacedBy(2.dp)) { - // TODO: Find right icons from Bisq2 and update - repeat(fiveSystemScore) { - StarFillIcon() - } - repeat(5 - fiveSystemScore) { - StarEmptyIcon() - } - } + BisqText.baseRegular( + text = item.userName, // + " abcde fghijkl mnop qrst uvwxyz", + singleLine = true, + ) + StarRating(fiveSystemScore) } } } \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt index e907c8ad..c013a31e 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt @@ -21,8 +21,8 @@ import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ui.components.atoms.BisqButton import network.bisq.mobile.presentation.ui.components.atoms.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText -import network.bisq.mobile.presentation.ui.components.atoms.ProfileRating import network.bisq.mobile.presentation.ui.components.atoms.icons.UpIcon +import network.bisq.mobile.presentation.ui.components.molecules.UserProfile import network.bisq.mobile.presentation.ui.components.molecules.info.InfoBoxStyle import network.bisq.mobile.presentation.ui.components.molecules.info.InfoRow import network.bisq.mobile.presentation.ui.theme.BisqTheme @@ -78,13 +78,16 @@ fun TradeHeader( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - ProfileRating(offer) + Column(modifier = Modifier.weight(3f)) { + UserProfile(offer) + } Column( verticalArrangement = Arrangement.spacedBy(2.dp), - horizontalAlignment = Alignment.End + horizontalAlignment = Alignment.End, + modifier = Modifier.weight(2f) ) { - BisqText.xsmallRegular(text = "10000.02 USD") - BisqText.xsmallRegular(text = "0.00173399 BTC") + BisqText.smallRegular(text = "10000.02 USD") + BisqText.smallRegular(text = "0.00173399 BTC") } } AnimatedVisibility( diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/UIConstants.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/UIConstants.kt index 905604d4..778de33b 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/UIConstants.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/theme/UIConstants.kt @@ -3,6 +3,9 @@ package network.bisq.mobile.presentation.ui.theme import androidx.compose.ui.unit.dp object BisqUIConstants { + val ScreenPaddingQuarter = 3.dp + val ScreenPaddingHalf = 6.dp + val ScreenPaddingHalfQuarter = 9.dp val ScreenPadding = 12.dp val ScreenPadding2X = 24.dp val ScreenPadding3X = 36.dp From 8a7ff3b5c8d968b49617eee1006539e07c2650b1 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 14 Dec 2024 14:01:56 +0530 Subject: [PATCH 2/8] - Settings :: Payment methods 1/2 --- .../drawable/icon_arrow_down.png | Bin 0 -> 410 bytes .../drawable/icon_search_dimmed.png | Bin 0 -> 2338 bytes .../drawable/icon_search_green.png | Bin 0 -> 1908 bytes .../drawable/icon_search_white.png | Bin 0 -> 2001 bytes .../network/bisq/mobile/i18n/CommonStrings.kt | 3 + .../bisq/mobile/i18n/CommonStringsEn.kt | 5 +- .../bisq/mobile/i18n/CommonStringsFr.kt | 8 +- .../network/bisq/mobile/i18n/Strings.kt | 1 + .../network/bisq/mobile/i18n/StringsEn.kt | 1 + .../network/bisq/mobile/i18n/StringsFr.kt | 1 + .../network/bisq/mobile/i18n/UserStrings.kt | 105 +++++++++++ .../network/bisq/mobile/i18n/UserStringsEn.kt | 107 ++++++++++++ .../network/bisq/mobile/i18n/UserStringsFr.kt | 109 ++++++++++++ .../presentation/di/PresentationModule.kt | 8 +- .../ui/components/atoms/DropDown.kt | 68 ++++++++ .../ui/components/atoms/TextField.kt | 126 +++++++++----- .../ui/components/atoms/icons/Icons.kt | 10 ++ .../ui/components/molecules/BottomSheet.kt | 47 +++++ .../molecules/ConfirmationDialog.kt | 3 +- .../molecules/{BisqDialog.kt => Dialog.kt} | 0 .../settings/AddPaymentAccountCard.kt | 80 +++++++++ .../presentation/ui/composeModels/model.kt | 2 + .../settings/PaymentAccountPresenter.kt | 66 +++++++ .../settings/PaymentAccountSettingsScreen.kt | 164 +++++++++++++++--- 24 files changed, 835 insertions(+), 79 deletions(-) create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_arrow_down.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_search_dimmed.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_search_green.png create mode 100644 shared/presentation/src/commonMain/composeResources/drawable/icon_search_white.png create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/UserStrings.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/UserStringsEn.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/i18n/UserStringsFr.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BottomSheet.kt rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/{BisqDialog.kt => Dialog.kt} (100%) create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/settings/AddPaymentAccountCard.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_arrow_down.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_arrow_down.png new file mode 100644 index 0000000000000000000000000000000000000000..769cfd97fe771e161f2d6bdb9b3492926bfef84f GIT binary patch literal 410 zcmV;L0cHM)P)^lA*G~Fc3vA2v$`Qg+qZ#3`O8l6$PJ^<&&yF5tR=J zs#UnER#j2cr`qX*GL+23WX_)4xwEsjZ2ma6h&-|fe->s z(;!XL(f;40omdFLr_%|G#R6qn!g~*642TF-RpD~EpswrDdPb!~agrohE|>lLF!`qq z`6wOhFwb+`Zny92*0$}}E2Xr?m{v+@r|^@cop>ty2cZN!oc733aR2}S07*qoM6N<$ Ef;up-+W-In literal 0 HcmV?d00001 diff --git a/shared/presentation/src/commonMain/composeResources/drawable/icon_search_dimmed.png b/shared/presentation/src/commonMain/composeResources/drawable/icon_search_dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..1a1bd40cb8860352c5fab16816a5037068bfc4ae GIT binary patch literal 2338 zcmbVOYitx%6kbplC{!pE1T0|~3PELd9{ZeWx6Qsv7g%UZ6Dl>r>^#~{cXy^U)9&^W zFa@*^7urIg5J8{`AP}AwO8`-zJd9`rqZkZtEdCJMCL$6E-q~)~LI4Syot-=Pe&;*i zIp?0aTbDCuMqRM%S(Bc|@aYhN5jctyD2^exks>hgg<>BV_>)+k%5!GLyn!bx zT&yS}g`%NQNEg!U1gQwcNs>e{0wo9pAP~7CsL){~C{ONVaB?yu`9#Gh1R<4?_6lW+ z6$V;+g9wOm+Mpau6i68wrbQIjVQNrOAj`yYVwvQRI%gS_^K$_%sK@||$FX9upa^oY z@C@qs@?#D_ay_27kEd!01mZ4a#Z?Z%h$ZByXgR+^6mAaq7(nulh5K{bfC`k8P}TH&lPs2hRc1VZ5Xn1RA@%0Rq>nJEnG zg?a?m$5+ImdITd8oXp1w%4njD#>b#w+px4k|1X$jC|-~PGzi%jpo=(E3>LvqJdu<` z@Cy=f4AklS&$}It97*7Pey||t&9Fmmm&1gUCKE#F@TgpmhjIsHg$^>D+i8VCdUQS? zOOY7Mm>2_wa14zj27;v#(qg6&1BS6AW;XF=p6|1F3QU>03Ht0=U~i-?dYk}x0+$gn z&@6$F2Cosp8QyDP8N!PZOrQN+$p_ky_P;a_XqNv{(Z^x~5y_y+a;%l?bWv>N_hqPI zsxk?Sm++by5;5Q$55mN7#DeSf2x~SQc%I=&-hic}YTp2(-j?iVZL~W{!ss&Tjd~M~ zy9kRV%VEPXgUz00aoR{rKg%dbuLSh@TBChHW&2d^6)~UlxYD?HD7y72no(QY3Nz|n z=2$p3?R!csU#u3rw4q`SkUnRJ_rhd>S3T3Xu2bpHBY=uTD9opb4b-aE3P>T>6yM~}$P ziYxiLwfc=MudbWDHC#=-PNQp*ADWhJvwW0x>ttbJp=TQY<>-~ARQ;n0=vgqjU^>hncdXbw)#F*^N=jI*0`J(u1dcD3wgQsKcL$?e*@(nj;`h9i4tE_F3! zrjAQrd1QA&H?^edQR>;N!J9licYaN4OWpg|K3HQobA8;_>j``$w;EY7xJ1mWUE8cZ zVS${sR&nN=SxHwSb0#&(O*1x$ZyY^oyLNj|(t~wLBiqJYShjduY2weh3pZW(@I;5U zWA}!OsW;CPpVZEuxY)Vs_`Rbi{t172yraNV^;tsC?Ni!Gg_T=G>u*`zi_=G(|9r^s zhKexSlheZ-Do#w zG8Cf|#z0L#qSJ_j1%)7JScHUy!3qN-7$6A4DMUarGKLUP{`{`%8Zh|B<-Ys=p6_{o zzW05v!BI3TF=1SSMx#lzSuG`?AFH06DW=$cqT<);Dw?O4CG0yn<}x)j7kGDBkWZa zkwVd6FsKXab%NwUagroaj6ewj0SH8{2`F?33CL-K3>HpiBwkc_Apoh2v`eT~j4;r3 zzzDw>qYcPWM*)|iAzDOn9i|!;0kTXCCss?oh;WucIUnce0*VZs1dG>#vFP33tlMgYMIi}c6`lL^Rc6oh@4g3i%0ic-`#WQjhwXR zHP5wlFKy1&;kIk+;?W72JZ9Ce$WA?Z`iI7y7mtvQORn6z{l(6ceY>;ll9+T+Mid~S(QGMsk=ZY z>JHqy()Q-O4sFKIDO;+B6;wTW_EH$Fv!tHct`&~eA8s9=fW>XbOs8&++;eb4nbXsI zb4bDV;FR|H86$?Zje2eJkx|w0o}q8yQ%4*f$1JWekyJx*Yj{g~`;M`F>-dpD!b`WN5+!XL-r-7By|_GuyOLEO>tQdf`CQamx(*mqjOj z+jXSq$DVlp^y&{ztxlP~KmPdemd}#I=T^y8zNC}+O)v5@%GN$zw9>I|Ov~xoe&e`J zyZXvLES!H^H2glNH&vlq91FhL*zYWCy0Ao?+q%i#mgT*Z+?%{~DBsw*%DZso^0p1l z&W}@cuF@@A>ld{-60n88h~``0Prlso{@Rz4?p92g*bsNnx;5cO;>#y!)-#Zch~k<+dJ-V>&9>+ zGr(Zc5l|zT0AW!VM3k2aOu^@1kw*e5F^bGFP+|rMVn}%CcYTQjQE7U;@4owe|KI=j ze|2SL#q8{{kBo&NDBE4`tOEBu^%`?O_#KQ{uY%hHV)=721U)=my)xWYk6nbItX|$b zPnqYLLoq@`OS6KX(>6y$fQF!wvSyKH8aM^^b3s08MK1L1M_`_{A~gmN?hzeah%a9( zan*|}yv*VT#=;_HrEp0z1q?(ug@&6W;iybCTamb33ar&_41wbirNN5WR6=;3rxJDu z5(k^K1j^tz4x21mvxPP4Xq4Nz6iSxGkVWJN-X zB2pL@i^a4tomP;77-6wkFr36l5(NlUZiy;%Ga8i(QWl(?%t*Yb@In+;Ez*9WQL!Sx z*Mx|Om^K@glYs&u!Plh?GO(Xho2` zf)Gxnsxsv=Op;my{Dg;Q_^2wP@RlQ-lU6t@0`f+p1c{P_7uQobLFvgN+(hAc0_qW1 zKG2ee>QLN*5*9B(Ql#;AC@342R_K2PvkVmwqzDZp^AS48VPZ6h!0A9z4k0W^fEakE zyLI2~a8yb{fDeNga@A}*>~=YfgvDq?Ni7j~*W;nwQCXp*4Ci)Q5fC0N&$AS1_LF`S zV?p%<7eMtSPM~H&r$bqjNgoI>0ZTxikPFT`1*TCgg4B8Tf1aN!@t_Uq@IBiB&GJ_$ zQdVq0kqojdCtJx*2a~HXU#iMf-89&p7SiA{>I^y~LAXe>d6vV5<9eHYmf2~um`gCV zXTSkCu}T=h?#>pkWU8E3*;|sF)!d>qI~*@wie}WNv?7dJjU0<4xA}X{M#5|?!~vss zsnG;X76M9)mN;7wWbQw70hS6uLJ4-e$atV`88#_6m|*HMJv_lfdi-)xFmoj^T+f`y zy9q%VN8L`Fw|wR9Z>$Xyo}SSE>v&h>H6Jq0{^Ycdj@sT3eXMiYryV&(#Zz2G#Ut5c znv89k+r5`EHp98LDdTP9Gz)TGx|*9+uxdtG*GH#c-dWtY*0W?#9Q>j6NPFP?o}Z3D zL+uNnAGqps)^~R9>8yPJf`-V~94OLM?&^8{>tng|hYHW$c&9G!-0IWsO&mSrVsREW zNH+B>zmnIl`Tn47gRgGl$E8c$w&Qstzq6siNbMgvZ|u!54z<;mbfMNYLF4j`h3A); zW)`5epKn+-pzC|Ze~RvXP&AY zQb?mYx@Kx&=GJH59Dy@GoZHsAacTa*er;w+dE3_R;VYpRuC4pv+g;xskhs0=%broD zf3feAvpdL>tBXV3hC2JJ!z(V1`_g=JWK&ktkJTNAe8KMF$9Jzkm3!pMeWNNu`8TrW zEHw5_JG{K+09}7#+nI{hJ8oX;%_-@w*<(8N+vd!l!`Mt;&Lm>R)McX Unit, + items: List, + label: String +) { + var showDialog by remember { mutableStateOf(false) } + + BisqTextField( + value = value, + onValueChanged = onValueChanged, + label = label, + rightSuffix = { + Box( + modifier = Modifier + .padding(vertical = 12.dp, horizontal = 16.dp) + .clickable( + onClick = { showDialog = true }, + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) + ) { + ArrowDownIcon() + } + }, + ) + + if (showDialog) { + BisqDialog(onDismissRequest = { showDialog = false }) { + LazyColumn( + modifier = Modifier.padding(16.dp), + ) { + items(items) { item -> + Row( + modifier = Modifier.fillMaxWidth() + .padding(vertical = 8.dp) + .clickable { + onValueChanged(item) + showDialog = false + } + ) { + BisqText.baseBold(text = item) + } + } + } + } + } +} diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt index df60f130..7b5f77fe 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt @@ -2,41 +2,68 @@ package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.TextField -import androidx.compose.material3.TextFieldDefaults +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import network.bisq.mobile.presentation.ui.components.atoms.icons.ArrowDownIcon +import network.bisq.mobile.presentation.ui.components.atoms.icons.SearchIcon import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable fun BisqTextField( label: String, value: String, - onValueChanged: (String) -> Unit, - placeholder: String? = null, + onValueChanged: (String) -> Unit = {}, + placeholder: String = "", labelRightSuffix: (@Composable () -> Unit)? = null, - prefix: (@Composable () -> Unit)? = null, - suffix: (@Composable () -> Unit)? = null, - disabled: Boolean = false, + rightSuffix: (@Composable () -> Unit)? = null, + isSearch: Boolean = false, + helperText: String = "", indicatorColor: Color = BisqTheme.colors.primary, + isTextArea: Boolean = false, + paddingValues: PaddingValues = PaddingValues(vertical = 12.dp), + disabled: Boolean = false, modifier: Modifier = Modifier, ) { var isFocused by remember { mutableStateOf(false) } + + val focusManager = LocalFocusManager.current + + val imeAction = when { + isSearch -> ImeAction.Search + isTextArea -> ImeAction.Next + else -> ImeAction.Done + } + Column(modifier = modifier) { if (label.isNotEmpty()) { Row( @@ -56,10 +83,11 @@ fun BisqTextField( Box( modifier = Modifier .fillMaxWidth() + .padding(paddingValues) .clip(shape = RoundedCornerShape(6.dp)) .background(color = BisqTheme.colors.secondary) .drawBehind { - if (isFocused || value.isNotEmpty()) { + if (!isSearch && isFocused) { drawLine( color = indicatorColor, start = Offset(0f, size.height), @@ -69,45 +97,57 @@ fun BisqTextField( } } ) { - TextField( + BasicTextField( value = value, - singleLine = true, - modifier = Modifier.fillMaxWidth().clickable { isFocused = true } + onValueChange = onValueChanged, + modifier = Modifier + .padding(12.dp) + .fillMaxWidth() .onFocusChanged { focusState -> isFocused = focusState.isFocused }, - textStyle = TextStyle(fontSize = 22.sp), - onValueChange = onValueChanged, - prefix = prefix, - suffix = suffix, - colors = TextFieldDefaults.colors( - focusedTextColor = BisqTheme.colors.light3, - unfocusedTextColor = BisqTheme.colors.secondaryHover, - unfocusedIndicatorColor = BisqTheme.colors.secondary, - focusedIndicatorColor = Color.Transparent, - focusedContainerColor = BisqTheme.colors.secondary, - cursorColor = Color.Blue, - unfocusedContainerColor = BisqTheme.colors.secondary + singleLine = !isTextArea, + maxLines = if (isTextArea) 4 else 1, + textStyle = TextStyle( + color = Color.White, + fontSize = 18.sp, + textDecoration = TextDecoration.None ), - placeholder = { - if (placeholder != null) { - BisqText.h5Regular( - text = placeholder, - color = BisqTheme.colors.secondaryHover, - ) - } - }, + keyboardOptions = KeyboardOptions(imeAction = imeAction), + cursorBrush = SolidColor(BisqTheme.colors.primary), enabled = !disabled, + decorationBox = { innerTextField -> + Row(verticalAlignment = Alignment.CenterVertically) { + if (value.isEmpty()) { + if (isSearch) { + SearchIcon() + Spacer(modifier = Modifier.width(10.dp)) + } + BisqText.largeRegular( + text = placeholder, + color = BisqTheme.colors.secondaryHover + ) + } + } + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + innerTextField() + + if (rightSuffix != null) { + rightSuffix() + } + } + } + ) + } + if (helperText.isNotEmpty()) { + BisqText.smallRegular( + text = helperText, + color = BisqTheme.colors.grey1 ) - if (isFocused) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(2.dp) - .align(Alignment.BottomCenter) - .background(BisqTheme.colors.primary) - ) - } } } } \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt index 9e147bbd..7a3f9af4 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Icons.kt @@ -13,6 +13,11 @@ import org.jetbrains.compose.resources.painterResource expect fun rememberPlatformImagePainter(platformImage: PlatformImage): Painter +@Composable +fun ArrowDownIcon(modifier: Modifier = Modifier.size(12.dp)) { + Image(painterResource(Res.drawable.icon_arrow_down), "Down arrow icon", modifier = modifier) +} + @Composable fun BellIcon(modifier: Modifier = Modifier.size(30.dp)) { Image(painterResource(Res.drawable.icon_bell), "Bell icon", modifier = modifier) @@ -58,6 +63,11 @@ fun ScanIcon(modifier: Modifier = Modifier) { Image(painterResource(Res.drawable.icon_qr), "Scan icon", modifier = modifier) } +@Composable +fun SearchIcon(modifier: Modifier = Modifier.size(16.dp)) { + Image(painterResource(Res.drawable.icon_search_dimmed), "Search icon", modifier = modifier) +} + @Composable fun SortIcon(modifier: Modifier = Modifier) { Image(painterResource(Res.drawable.icon_sort), "Sort icon", modifier = modifier) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BottomSheet.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BottomSheet.kt new file mode 100644 index 00000000..e8d61d5a --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BottomSheet.kt @@ -0,0 +1,47 @@ +package network.bisq.mobile.presentation.ui.components.molecules + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +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.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BisqBottomSheet( + onDismissRequest:() -> Unit, + content: @Composable () -> Unit +) { + ModalBottomSheet( + onDismissRequest = onDismissRequest, + shape = RoundedCornerShape(16.dp), + sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = true, + ), + containerColor = BisqTheme.colors.dark3, + dragHandle = { + Box( + modifier = Modifier.padding(top = 20.dp) + .clip(shape = RoundedCornerShape(4.dp)) + ) { + Box( + modifier = Modifier.height(4.dp).width(60.dp) + .background(Color(0xFF6F6F6F)) + ) + } + } + ) { + content() + } +} + diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt index 057e72bc..b4df1e42 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt @@ -17,6 +17,7 @@ fun ConfirmationDialog( message: String = "Are you sure?", confirmButtonText: String = "Yes", cancelButtonText: String = "No", + onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { BisqDialog { @@ -41,7 +42,7 @@ fun ConfirmationDialog( ) BisqButton( text = confirmButtonText, - onClick = { onDismissRequest() }, + onClick = { onConfirm() }, padding = PaddingValues(horizontal = 32.dp, vertical = 4.dp) ) } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BisqDialog.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt similarity index 100% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/BisqDialog.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/settings/AddPaymentAccountCard.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/settings/AddPaymentAccountCard.kt new file mode 100644 index 00000000..4846d285 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/settings/AddPaymentAccountCard.kt @@ -0,0 +1,80 @@ +package network.bisq.mobile.presentation.ui.components.organisms.settings + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import cafe.adriel.lyricist.LocalStrings +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqText +import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants + +@Composable +fun AppPaymentAccountCard( + onConfirm: (String, String) -> Unit, + onCancel: () -> Unit, +) { + val strings = LocalStrings.current.user + val stringsCommon = LocalStrings.current.common + + var accountName by remember { mutableStateOf("") } + var accountDescription by remember { mutableStateOf("") } + + Column( + modifier = Modifier.padding( + horizontal = BisqUIConstants.ScreenPadding, + ), verticalArrangement = Arrangement.spacedBy(BisqUIConstants.ScreenPadding) + ) { + BisqText.h5Regular( + text = strings.user_paymentAccounts_createAccount_headline, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + BisqText.smallRegular( + text = strings.user_paymentAccounts_createAccount_subtitle, + color = BisqTheme.colors.grey1, + textAlign = TextAlign.Center + ) + BisqTextField( + value = accountName, + onValueChanged = { accountName = it }, + placeholder = strings.user_paymentAccounts_createAccount_accountName_prompt, + label = strings.user_userProfile_payment_account + ) + BisqTextField( + value = accountDescription, + onValueChanged = { accountDescription = it }, + placeholder = strings.user_paymentAccounts_createAccount_accountData_prompt, + label = strings.user_paymentAccounts_accountData, + isTextArea = true + ) + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + BisqButton( + text = stringsCommon.buttons_cancel, + backgroundColor = BisqTheme.colors.dark5, + onClick = onCancel, + padding = PaddingValues(horizontal = 24.dp, vertical = 12.dp) + ) + BisqButton( + text = stringsCommon.buttons_save, + onClick = { onConfirm(accountName, accountDescription) }, + padding = PaddingValues(horizontal = 64.dp, vertical = 12.dp) + ) + } + } +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt index d064d2e9..da7523bc 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/composeModels/model.kt @@ -6,3 +6,5 @@ data class BottomNavigationItem(val title: String, val route: String, val icon: data class PagerViewItem(val title: String, val image: DrawableResource, val desc: String) data class PaymentTypeData(val image: String, val title: String) + +data class PaymentAccount(val id: String, val name: String, var description: String) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt new file mode 100644 index 00000000..0222a871 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt @@ -0,0 +1,66 @@ +package network.bisq.mobile.presentation.ui.uicases.settings + +import kotlinx.coroutines.flow.MutableStateFlow +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import kotlinx.coroutines.flow.StateFlow +import network.bisq.mobile.domain.data.repository.SettingsRepository +import network.bisq.mobile.presentation.BasePresenter +import network.bisq.mobile.presentation.MainPresenter +import network.bisq.mobile.presentation.ui.composeModels.PaymentAccount + +open class PaymentAccountPresenter( + private val settingsRepository: SettingsRepository, + mainPresenter: MainPresenter +) : BasePresenter(mainPresenter), IPaymentAccountSettingsPresenter { + + private val _accounts = MutableStateFlow( + listOf( + PaymentAccount("0", "Pink account", "Acc Num: 1234566789\nBank name: Bank of America"), + PaymentAccount("1", "Yellow account", "Acc Num: 9876543210\nBank name: Chase Bank"), + PaymentAccount("2", "Red account", "Acc Num: 1122334455\nBank name: Wells Fargo"), + PaymentAccount("3", "Orange account", "Acc Num: 5566778899\nBank name: Citi Bank") + ) + ) + override val accounts: StateFlow> = _accounts + + private val _selectedAccount = MutableStateFlow(_accounts.value.first()) + override val selectedAccount: StateFlow = _selectedAccount + + override fun selectAccount(account: PaymentAccount) { + _selectedAccount.value = _accounts.value.firstOrNull { it.id == account.id } + ?: account + } + + override fun addAccount(newName: String, newDescription: String) { + val newAccount = PaymentAccount( + id = _accounts.value.count().toString(), + name = newName, + description = newDescription + ) + + val updatedAccounts = _accounts.value.toMutableList().apply { + add(newAccount) + } + _accounts.value = updatedAccounts + _selectedAccount.value = newAccount + } + + override fun saveAccount(newName: String, newDescription: String) { + val updatedAccounts = _accounts.value.map { + if (it.id == _selectedAccount.value.id) { + it.copy(name = newName, description = newDescription) + } else it + } + _accounts.value = updatedAccounts + _selectedAccount.value = updatedAccounts.first { it.id == _selectedAccount.value.id } + } + + override fun deleteCurrentAccount() { + val updatedAccounts = _accounts.value.toMutableList() + updatedAccounts.remove(_selectedAccount.value) + _accounts.value = updatedAccounts + _selectedAccount.value = updatedAccounts.firstOrNull() ?: PaymentAccount("0", "", "") + } + +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt index e9dcd2e4..d90c5dc4 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt @@ -1,24 +1,140 @@ -package network.bisq.mobile.presentation.ui.uicases.settings - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.sp -import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle -import network.bisq.mobile.presentation.ui.theme.BisqTheme - -@Composable -fun PaymentAccountSettingsScreen() { - -// RememberPresenterLifecycle() - Column(modifier = Modifier.fillMaxSize()) { - Text( - text = "PaymentAccountSettingsScreen", - style = MaterialTheme.typography.bodyLarge.copy(color = BisqTheme.colors.light1 , fontSize = 16.sp), - modifier = Modifier.weight(1f) - ) - } -} \ No newline at end of file +package network.bisq.mobile.presentation.ui.uicases.settings + +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import cafe.adriel.lyricist.LocalStrings +import kotlinx.coroutines.flow.StateFlow +import network.bisq.mobile.presentation.ViewPresenter +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqDropDown +import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField +import network.bisq.mobile.presentation.ui.components.molecules.BisqBottomSheet +import network.bisq.mobile.presentation.ui.components.molecules.ConfirmationDialog +import network.bisq.mobile.presentation.ui.components.organisms.settings.AppPaymentAccountCard +import network.bisq.mobile.presentation.ui.composeModels.PaymentAccount +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants +import org.koin.compose.koinInject + +interface IPaymentAccountSettingsPresenter : ViewPresenter { + val accounts: StateFlow> + val selectedAccount: StateFlow + + fun selectAccount(account: PaymentAccount) + + fun addAccount(newName: String, newDescription: String) + fun saveAccount(newName: String, newDescription: String) + fun deleteCurrentAccount() +} + +// TODO: Toast messages +@Composable +fun PaymentAccountSettingsScreen() { + + val strings = LocalStrings.current.user + val stringsCommon = LocalStrings.current.common + + val presenter: IPaymentAccountSettingsPresenter = koinInject() + val accounts by presenter.accounts.collectAsState() + val selectedAccount by presenter.selectedAccount.collectAsState() + + var accountName by remember { mutableStateOf(selectedAccount.name) } + var accountDescription by remember { mutableStateOf(selectedAccount.description) } + + var showConfirmationDialog by remember { mutableStateOf(false) } + var showBottomSheet by remember { mutableStateOf(false) } + + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(BisqUIConstants.ScreenPadding) + ) { + BisqButton( + text = "+ Create new payment method", + onClick = { showBottomSheet = !showBottomSheet }, + padding = PaddingValues(horizontal = 18.dp, vertical = 6.dp), + modifier = Modifier.align(Alignment.End) + ) + + BisqDropDown( + value = accountName, + onValueChanged = { name -> + var account = accounts.firstOrNull { it.name == name } + + if (account == null) { + account = accounts.firstOrNull { it.description == accountDescription } + + if (account != null) { + account = PaymentAccount(id = account.id, name = name, description = account.description) + } + } + + if (account == null) { + account = + PaymentAccount(id = accounts.count().toString(), name = name, description = accountDescription) + } + + presenter.selectAccount(account) + accountName = account.name + accountDescription = account.description + }, + items = accounts.map { it.name }, + label = strings.user_userProfile_payment_account + ) + + BisqTextField( + value = accountDescription, + onValueChanged = { accountDescription = it }, + label = strings.user_paymentAccounts_accountData, + isTextArea = true + ) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + BisqButton( + text = stringsCommon.delete_account, + backgroundColor = BisqTheme.colors.dark5, + onClick = { showConfirmationDialog = true } + ) + BisqButton( + text = stringsCommon.buttons_save, + onClick = { + presenter.saveAccount(accountName, accountDescription) + } + ) + } + } + + if (showConfirmationDialog) { + ConfirmationDialog( + onConfirm = { + presenter.deleteCurrentAccount() + accountName = presenter.selectedAccount.value.name + accountDescription = presenter.selectedAccount.value.description + showConfirmationDialog = false + }, + onDismissRequest = { + showConfirmationDialog = false + } + ) + } + + if (showBottomSheet) { + BisqBottomSheet( + onDismissRequest = { showBottomSheet = !showBottomSheet } + ) { + AppPaymentAccountCard( + onCancel = { showBottomSheet = false }, + onConfirm = { name, description -> + presenter.addAccount(name, description) + showBottomSheet = false + }, + ) + } + } +} + From 1364a0e7cf48196f39487509601e2722f729d3b1 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 14 Dec 2024 14:38:01 +0530 Subject: [PATCH 3/8] - Settings :: Payment methods 2/2 --- .../ui/components/atoms/DropDown.kt | 2 +- .../molecules/ConfirmationDialog.kt | 13 +++-- .../ui/components/molecules/Dialog.kt | 3 +- .../settings/PaymentAccountPresenter.kt | 11 +---- .../settings/PaymentAccountSettingsScreen.kt | 49 +++++++++++++------ 5 files changed, 50 insertions(+), 28 deletions(-) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt index 5a79f136..b1a5b166 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt @@ -33,7 +33,7 @@ fun BisqDropDown( rightSuffix = { Box( modifier = Modifier - .padding(vertical = 12.dp, horizontal = 16.dp) + .padding(vertical = 8.dp, horizontal = 16.dp) .clickable( onClick = { showDialog = true }, interactionSource = remember { MutableInteractionSource() }, diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt index b4df1e42..a94f63a0 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/ConfirmationDialog.kt @@ -10,6 +10,7 @@ import network.bisq.mobile.presentation.ui.components.atoms.BisqButton import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.molecules.BisqDialog import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants @Composable fun ConfirmationDialog( @@ -19,7 +20,7 @@ fun ConfirmationDialog( cancelButtonText: String = "No", onConfirm: () -> Unit, onDismissRequest: () -> Unit, - ) { +) { BisqDialog { Column( modifier = Modifier @@ -38,12 +39,18 @@ fun ConfirmationDialog( text = cancelButtonText, backgroundColor = BisqTheme.colors.dark5, onClick = { onDismissRequest() }, - padding = PaddingValues(horizontal = 42.dp, vertical = 4.dp) + padding = PaddingValues( + horizontal = BisqUIConstants.ScreenPadding4X, + vertical = BisqUIConstants.ScreenPaddingHalf + ) ) BisqButton( text = confirmButtonText, onClick = { onConfirm() }, - padding = PaddingValues(horizontal = 32.dp, vertical = 4.dp) + padding = PaddingValues( + horizontal = BisqUIConstants.ScreenPadding4X, + vertical = BisqUIConstants.ScreenPaddingHalf + ) ) } } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt index 49465224..5edb4211 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/Dialog.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable @@ -21,7 +22,7 @@ fun BisqDialog( onDismissRequest: () -> Unit = {}, content: @Composable ColumnScope.() -> Unit = {} ) { - Dialog(onDismissRequest = { onDismissRequest() }) { + Dialog(onDismissRequest = onDismissRequest, properties = DialogProperties(dismissOnClickOutside = true)) { Box( modifier = Modifier .fillMaxSize() diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt index 0222a871..385b36c9 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountPresenter.kt @@ -14,17 +14,10 @@ open class PaymentAccountPresenter( mainPresenter: MainPresenter ) : BasePresenter(mainPresenter), IPaymentAccountSettingsPresenter { - private val _accounts = MutableStateFlow( - listOf( - PaymentAccount("0", "Pink account", "Acc Num: 1234566789\nBank name: Bank of America"), - PaymentAccount("1", "Yellow account", "Acc Num: 9876543210\nBank name: Chase Bank"), - PaymentAccount("2", "Red account", "Acc Num: 1122334455\nBank name: Wells Fargo"), - PaymentAccount("3", "Orange account", "Acc Num: 5566778899\nBank name: Citi Bank") - ) - ) + private val _accounts = MutableStateFlow(listOf()) override val accounts: StateFlow> = _accounts - private val _selectedAccount = MutableStateFlow(_accounts.value.first()) + private val _selectedAccount = MutableStateFlow(_accounts.value.firstOrNull() ?: PaymentAccount(id= "0", name= "", description = "")) override val selectedAccount: StateFlow = _selectedAccount override fun selectAccount(account: PaymentAccount) { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt index d90c5dc4..f3ca41a7 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt @@ -47,12 +47,46 @@ fun PaymentAccountSettingsScreen() { var showConfirmationDialog by remember { mutableStateOf(false) } var showBottomSheet by remember { mutableStateOf(false) } + LaunchedEffect(selectedAccount) { + accountName = selectedAccount.name + accountDescription = selectedAccount.description + } + + if (showBottomSheet) { + BisqBottomSheet( + onDismissRequest = { showBottomSheet = !showBottomSheet } + ) { + AppPaymentAccountCard( + onCancel = { showBottomSheet = false }, + onConfirm = { name, description -> + presenter.addAccount(name, description) + showBottomSheet = false + }, + ) + } + } + + if (accounts.isEmpty()) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + BisqButton( + text = strings.user_paymentAccounts_createAccount, + onClick = { showBottomSheet = !showBottomSheet }, + modifier = Modifier.padding(all = 8.dp) + ) + } + return + } + Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(BisqUIConstants.ScreenPadding) ) { BisqButton( - text = "+ Create new payment method", + text = strings.user_paymentAccounts_createAccount, onClick = { showBottomSheet = !showBottomSheet }, padding = PaddingValues(horizontal = 18.dp, vertical = 6.dp), modifier = Modifier.align(Alignment.End) @@ -123,18 +157,5 @@ fun PaymentAccountSettingsScreen() { ) } - if (showBottomSheet) { - BisqBottomSheet( - onDismissRequest = { showBottomSheet = !showBottomSheet } - ) { - AppPaymentAccountCard( - onCancel = { showBottomSheet = false }, - onConfirm = { name, description -> - presenter.addAccount(name, description) - showBottomSheet = false - }, - ) - } - } } From d0aa34df9adf4aacd46832e611e931fe2e756523 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Sat, 14 Dec 2024 18:59:23 +0530 Subject: [PATCH 4/8] - Improvements: Amount Selector; BtcSats composable; --- .../ui/helpers/NumberFormatter.android.kt | 2 +- .../ui/components/atoms/BtcSatsText.kt | 66 +++++++++ .../presentation/ui/components/atoms/Gap.kt | 5 + .../ui/components/atoms/Slider.kt | 6 +- .../ui/components/atoms/icons/Logo.kt | 8 ++ .../ui/components/molecules/AmountSelector.kt | 130 ++++-------------- .../components/molecules/DirectionToggle.kt | 4 +- .../ui/components/molecules/FiatInputField.kt | 111 +++++++++++++++ .../ui/components/molecules/OfferCard.kt | 1 + .../{atoms => molecules}/PaymentMethods.kt | 3 +- .../molecules/RangeAmountSelector.kt | 16 +-- .../{RageSlider.kt => RangeSlider.kt} | 6 +- .../presentation/ui/helpers/DoubleHelper.kt | 9 ++ .../ui/helpers/NumberFormatter.kt | 1 + .../presentation/ui/helpers/StringHelper.kt | 5 +- .../createOffer/AmountSelectorScreen.kt | 6 +- .../offers/takeOffer/TradeAmountScreen.kt | 12 +- 17 files changed, 260 insertions(+), 131 deletions(-) create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BtcSatsText.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/FiatInputField.kt rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/{atoms => molecules}/PaymentMethods.kt (93%) rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/{RageSlider.kt => RangeSlider.kt} (94%) create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/DoubleHelper.kt diff --git a/shared/presentation/src/androidMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.android.kt b/shared/presentation/src/androidMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.android.kt index ff6fc095..9d58ed1b 100644 --- a/shared/presentation/src/androidMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.android.kt +++ b/shared/presentation/src/androidMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.android.kt @@ -3,6 +3,6 @@ package network.bisq.mobile.presentation.ui.helpers import java.text.DecimalFormat actual val numberFormatter: NumberFormatter = object : NumberFormatter { - private val formatter = DecimalFormat("#.########") + private val formatter = DecimalFormat("0.00000000") override fun satsFormat(value: Double): String = formatter.format(value) } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BtcSatsText.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BtcSatsText.kt new file mode 100644 index 00000000..d6dbde3a --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BtcSatsText.kt @@ -0,0 +1,66 @@ +package network.bisq.mobile.presentation.ui.components.atoms + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import network.bisq.mobile.presentation.ui.components.atoms.icons.BtcLogo +import network.bisq.mobile.presentation.ui.helpers.numberFormatter +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BtcSatsText(sats: Long) { + + val btcValue = sats.toDouble() / 100_000_000 + val formattedValue = formatSatsToDisplay(btcValue, sats) + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + BtcLogo() + Text( + text = formattedValue, + fontSize = 20.sp, + color = BisqTheme.colors.light1, + ) + } +} + +@Composable +private fun formatSatsToDisplay(btcValue: Double, sats: Long): AnnotatedString { + val btcString = numberFormatter.satsFormat(btcValue) + + return buildAnnotatedString { + val parts = btcString.split(".") + val integerPart = parts[0] + val fractionalPart = parts[1] + + val formattedFractional = fractionalPart.chunked(3).joinToString(" ") + val leadingZeros = formattedFractional.takeWhile { it == '0' || it == ' ' } + val significantDigits = formattedFractional.dropWhile { it == '0' || it == ' ' } + + val prefixColor = if(integerPart.toInt() > 0) BisqTheme.colors.light1 else BisqTheme.colors.grey2 + + withStyle(style = SpanStyle(color = prefixColor)) { + append(integerPart) + append(".") + } + + withStyle(style = SpanStyle(color = prefixColor)) { + append(leadingZeros) + } + + withStyle(style = SpanStyle(color = BisqTheme.colors.light1)) { + append(significantDigits) + append(" sats") + } + } +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt index ee6ad905..192b04ef 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt @@ -34,6 +34,11 @@ object BisqGap { Spacer(modifier = Modifier.height(BisqUIConstants.ScreenPadding4X)) } + @Composable() + fun V5() { + Spacer(modifier = Modifier.height(BisqUIConstants.ScreenPadding5X)) + } + @Composable() fun HQuarter() { Spacer(modifier = Modifier.width(BisqUIConstants.ScreenPaddingQuarter)) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Slider.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Slider.kt index 22d731ce..1692a339 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Slider.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Slider.kt @@ -18,10 +18,10 @@ import network.bisq.mobile.presentation.ui.theme.BisqTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun BisqSlider( + value: Float, + onValueChange: (Float) -> Unit, minAmount: Float, maxAmount: Float, - tradeValue: Float, - onValueChange: (Float) -> Unit ) { val colors = SliderColors( @@ -39,7 +39,7 @@ fun BisqSlider( Slider( modifier = Modifier.fillMaxWidth(), - value = tradeValue, + value = value, onValueChange = { onValueChange(it) }, valueRange = minAmount..maxAmount, thumb = { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt index fcbf0f18..afff951c 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/icons/Logo.kt @@ -1,11 +1,14 @@ package network.bisq.mobile.presentation.ui.components.atoms.icons import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.bisq_logo import bisqapps.shared.presentation.generated.resources.bisq_logo_small +import network.bisq.mobile.presentation.ui.components.atoms.DynamicImage import org.jetbrains.compose.resources.painterResource @Composable @@ -16,4 +19,9 @@ fun BisqLogo(modifier: Modifier = Modifier) { @Composable fun BisqLogoSmall(modifier: Modifier = Modifier) { Image(painterResource(Res.drawable.bisq_logo_small), "Bisq Logo small", modifier = modifier) +} + +@Composable +fun BtcLogo(modifier: Modifier = Modifier.size(16.dp)) { + DynamicImage("drawable/bitcoin.png", modifier = modifier) } \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/AmountSelector.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/AmountSelector.kt index 698992f8..cd30a007 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/AmountSelector.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/AmountSelector.kt @@ -1,140 +1,68 @@ package network.bisq.mobile.presentation.ui.components.molecules -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.unit.dp -import kotlinx.coroutines.launch import network.bisq.mobile.presentation.ui.components.atoms.* -import network.bisq.mobile.presentation.ui.components.atoms.icons.InfoIcon -import network.bisq.mobile.presentation.ui.helpers.numberFormatter +import network.bisq.mobile.presentation.ui.helpers.* import network.bisq.mobile.presentation.ui.theme.BisqTheme -import network.bisq.mobile.presentation.ui.theme.BisqUIConstants -import kotlin.math.roundToInt -@OptIn(ExperimentalMaterial3Api::class) @Composable fun BisqAmountSelector( - minAmount: Float, - maxAmount: Float, + minAmount: Double, + maxAmount: Double, exchangeRate: Double, currency: String, - onValueChange: (Float) -> Unit + onValueChange: ((Double) -> Unit)? = null ) { - var sliderPosition by remember { mutableFloatStateOf((minAmount + maxAmount) * 0.5f) } - val roundedNumber = (sliderPosition * 100).roundToInt() / 100.0 - val price = if (roundedNumber.toString().split(".").getOrNull(1)?.length == 1) - "${roundedNumber}0" // to make 3.1 to 3.10 - else - roundedNumber.toString() // if it's 3.14, keep the same + var fiatValue by remember { mutableDoubleStateOf((minAmount + maxAmount) * 0.5) } + val sats = (100_000_000L * (fiatValue.toDouble()) / exchangeRate).toLong() - val satsValue = numberFormatter.satsFormat(price.toDouble() / exchangeRate) - - val highLightedSatsZeros = satsValue.takeWhile { it == '0' || it == '.' } - val sats = satsValue.dropWhile { it == '0' || it == '.' } - var showPopup by remember { mutableStateOf(false) } - val satoshi = sats.reversed().chunked(3).joinToString(" ").reversed() - val tooltipState = rememberTooltipState(isPersistent = true) - val scope = rememberCoroutineScope() - - LaunchedEffect(sliderPosition) { - onValueChange(sliderPosition) + LaunchedEffect(fiatValue) { + onValueChange?.invoke(fiatValue) } Column( - verticalArrangement = Arrangement.Top + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { - Column( - modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.Bottom - ) { - BisqText.h1Regular( - text = price, - ) - BisqText.h5Regular( - text = currency - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - // TODO: Create a control out of this - DynamicImage( - "drawable/bitcoin.png", - modifier = Modifier.size(16.dp) - ) - Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { - BisqText.h5Regular( - text = highLightedSatsZeros, - color = BisqTheme.colors.grey2 - ) - BisqText.h5Regular( - text = "$satoshi sats", - ) - } - BisqGap.H1() - // TODO: Needs work - TooltipBox(positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(), - tooltip = { - Box( - modifier = Modifier.background(BisqTheme.colors.dark5), - contentAlignment = Alignment.Center - ){ - BisqText.h5Regular( - text = "Hi welcome" - ) - } - }, - // modifier = Modifier.offset((-20).dp, (-20).dp), - state = tooltipState - ) { - IconButton(onClick = { - scope.launch { - tooltipState.show() - } - }) { - // TODO: Make SVG Icons work! - InfoIcon() - } - } - } + FiatInputField( + text = fiatValue.toInt().toString(), + onValueChanged = { fiatValue = it.toDoubleOrNull() ?: (0.0) }, + currency = currency + ) + + if (fiatValue < minAmount || fiatValue > maxAmount) { + BisqText.baseRegular("Amount out of range", color = BisqTheme.colors.danger) } - Column(modifier = Modifier.padding(horizontal = 24.dp)) { + BtcSatsText(sats) + + Column { BisqSlider( - minAmount, - maxAmount, - sliderPosition, - onValueChange = { sliderPosition = it } + fiatValue.toFloat(), + onValueChange = { fiatValue = it.toDouble() }, + minAmount.toFloat(), + maxAmount.toFloat(), ) Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth().padding(horizontal = 6.dp) ) { - - val minString = minAmount // Do precision rounding to 2 decimals - val maxString = maxAmount // Do precision rounding to 2 decimals BisqText.smallRegular( - text = "Min $minString $currency", + text = "Min ${minAmount.toStringWith2Decimals()} $currency", color = BisqTheme.colors.grey2 ) BisqText.smallRegular( - text = "Max $maxString $currency", + text = "Max ${maxAmount.toStringWith2Decimals()} $currency", color = BisqTheme.colors.grey2 ) } } } -} \ No newline at end of file +} diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/DirectionToggle.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/DirectionToggle.kt index 21db242d..fcf409ae 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/DirectionToggle.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/DirectionToggle.kt @@ -61,7 +61,6 @@ fun DirectionToggle( .offset(x = slideOffset) .background(BisqTheme.colors.primary, RoundedCornerShape(4.dp)) ) { - BisqText.baseMedium( text = toggleText, color = BisqTheme.colors.light1, @@ -86,8 +85,9 @@ fun DirectionToggle( } ) ) { + val label = if (direction.isBuy) strings.offers_list_buy_from else strings.offers_list_sell_to BisqText.baseMedium( - text = toggleText, + text = label, color = BisqTheme.colors.light1, ) } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/FiatInputField.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/FiatInputField.kt new file mode 100644 index 00000000..23c4e5f9 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/FiatInputField.kt @@ -0,0 +1,111 @@ +package network.bisq.mobile.presentation.ui.components.molecules + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import bisqapps.shared.presentation.generated.resources.Res +import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_regular +import network.bisq.mobile.presentation.ui.components.atoms.BisqText +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import org.jetbrains.compose.resources.Font + +@Composable +fun FiatInputField( + text: String, + onValueChanged: (String) -> Unit = {}, + label: String = "", + currency: String, + paddingValues: PaddingValues = PaddingValues(all = 0.dp), + indicatorColor: Color = BisqTheme.colors.primary, +) { + var isFocused by remember { mutableStateOf(false) } + + val keyboardController = LocalSoftwareKeyboardController.current + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues) + .clip(shape = RoundedCornerShape(6.dp)) + .background(color = BisqTheme.colors.secondary) + .drawBehind { + if (isFocused) { + drawLine( + color = indicatorColor, + start = Offset(0f, size.height), + end = Offset(size.width, size.height), + strokeWidth = 4.dp.toPx() + ) + } + } + ) { + BasicTextField( + value = text, + onValueChange = onValueChanged, + modifier = Modifier + .padding(12.dp) + .fillMaxWidth() + .onFocusChanged { focusState -> + isFocused = focusState.isFocused + }, + textStyle = TextStyle( + color = Color.White, + fontSize = 32.sp, + textAlign = TextAlign.End, + textDecoration = TextDecoration.None + ), + keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number), + keyboardActions = KeyboardActions(onDone = { keyboardController?.hide() }), + cursorBrush = SolidColor(BisqTheme.colors.primary), + decorationBox = { innerTextField -> + Row( + horizontalArrangement = Arrangement.spacedBy(24.dp), + verticalAlignment = Alignment.Bottom + ) { + if (label.isNotEmpty()) { + BisqText.h5Regular( + text = label, + color = BisqTheme.colors.grey1, + modifier = Modifier.align(Alignment.CenterVertically) + ) + } + Box(modifier = Modifier.weight(1f)) { + innerTextField() + } + + BisqText.h5Regular(text = currency) + } + } + ) + } +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt index 05ff3304..3517b2b8 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt @@ -16,6 +16,7 @@ import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ui.components.atoms.* import network.bisq.mobile.presentation.ui.components.atoms.icons.ChatIcon import network.bisq.mobile.presentation.ui.components.atoms.icons.LanguageIcon +import network.bisq.mobile.presentation.ui.components.molecules.* import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/PaymentMethods.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/PaymentMethods.kt similarity index 93% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/PaymentMethods.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/PaymentMethods.kt index 30c13dd5..3867270f 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/PaymentMethods.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/PaymentMethods.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.components.atoms +package network.bisq.mobile.presentation.ui.components.molecules import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -8,6 +8,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import network.bisq.mobile.domain.data.model.OfferListItem +import network.bisq.mobile.presentation.ui.components.atoms.DynamicImage // TODO: Get params and render apt @Composable diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeAmountSelector.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeAmountSelector.kt index 3438918d..23725f24 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeAmountSelector.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeAmountSelector.kt @@ -19,10 +19,10 @@ import kotlin.math.roundToInt // TODO: This has more work to do @Composable fun RangeAmountSelector( - minAmount: Float, - maxAmount: Float, + minAmount: Double, + maxAmount: Double, ) { - var sliderPosition by remember { mutableStateOf(minAmount .. maxAmount) } + var sliderPosition by remember { mutableStateOf(minAmount..maxAmount) } var tradeValue = 873f..1200f Column { Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) { @@ -113,12 +113,12 @@ fun RangeAmountSelector( } Column { BisqRangeSlider( - minAmount, - maxAmount, - sliderPosition, + sliderPosition.start.toFloat()..sliderPosition.endInclusive.toFloat(), onValueChange = { - sliderPosition = it - } + sliderPosition = it.start.toDouble()..it.endInclusive.toDouble() + }, + minAmount.toFloat(), + maxAmount.toFloat(), ) Row( verticalAlignment = Alignment.CenterVertically, diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RageSlider.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeSlider.kt similarity index 94% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RageSlider.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeSlider.kt index 04bf1d90..40c434bb 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RageSlider.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/RangeSlider.kt @@ -18,10 +18,10 @@ import network.bisq.mobile.presentation.ui.theme.BisqTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun BisqRangeSlider( + value: ClosedFloatingPointRange, + onValueChange: (ClosedFloatingPointRange) -> Unit, minAmount: Float, maxAmount: Float, - tradeValue: ClosedFloatingPointRange, - onValueChange: (ClosedFloatingPointRange) -> Unit ){ val colors = SliderColors( thumbColor = BisqTheme.colors.primary, @@ -38,7 +38,7 @@ fun BisqRangeSlider( RangeSlider( modifier = Modifier.fillMaxWidth(), - value = tradeValue, + value = value, onValueChange = {onValueChange(it)}, valueRange = minAmount .. maxAmount, track = { rangeSliderState -> diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/DoubleHelper.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/DoubleHelper.kt new file mode 100644 index 00000000..50ba3a74 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/DoubleHelper.kt @@ -0,0 +1,9 @@ +package network.bisq.mobile.presentation.ui.helpers + +import kotlin.math.roundToInt + +fun Double.toStringWith2Decimals(): String { + val roundedNumber = (this * 100).roundToInt() / 100.0 + val isNumberHasSingleZero = roundedNumber.toString().split(".").getOrNull(1)?.length == 1 + return if (isNumberHasSingleZero) "${roundedNumber}0" else roundedNumber.toString() +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.kt index 464098c9..bc3c5258 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/NumberFormatter.kt @@ -1,6 +1,7 @@ package network.bisq.mobile.presentation.ui.helpers interface NumberFormatter { + // TODO: Should be re-named eightDecimalFormat fun satsFormat(value: Double): String } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/StringHelper.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/StringHelper.kt index e7355016..255ab6ea 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/StringHelper.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/helpers/StringHelper.kt @@ -2,11 +2,10 @@ package network.bisq.mobile.presentation.ui.helpers import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.text.TextMeasurer -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.text.* import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.sp +import network.bisq.mobile.presentation.ui.theme.BisqTheme object StringHelper { @Composable diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/AmountSelectorScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/AmountSelectorScreen.kt index c364b49b..287a0bbe 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/AmountSelectorScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/AmountSelectorScreen.kt @@ -32,8 +32,8 @@ fun CreateOfferAmountSelectorScreen() { val stringsCommon = LocalStrings.current.common val presenter: ICreateOfferPresenter = koinInject() - val offerMinFiatAmount = 800.0f - val offerMaxFiatAmount = 1500.0f + val offerMinFiatAmount = 800.0 + val offerMaxFiatAmount = 1500.0 val state by presenter.state.collectAsState() val isBuy = presenter.direction.collectAsState().value.isBuy val fixedAmount = presenter.fixedAmount.collectAsState().value @@ -96,7 +96,7 @@ fun CreateOfferAmountSelectorScreen() { maxAmount = offerMaxFiatAmount, exchangeRate = 95000.0, currency = "USD", - onValueChange = { value -> presenter.onFixedAmountChange(value) } + // onValueChanged = { value -> presenter.onFixedAmountChange(value) } ) } else { RangeAmountSelector( diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt index 1ea87d2d..365f6cf5 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt @@ -21,7 +21,7 @@ interface ITakeOfferTradeAmountPresenter : ViewPresenter { // TODO: Update later to refer to a single OfferListItem val offerListItems: StateFlow> fun amountConfirmed() - + fun onFixedAmountChange(amount: Float) } @@ -33,8 +33,8 @@ fun TakeOfferTradeAmountScreen() { val offer = presenter.offerListItems.collectAsState().value.first() // TODO: Should be from OfferListItem - val offerMinFiatAmount = 800.0f - val offerMaxFiatAmount = 1500.0f + val offerMinFiatAmount = 800.0 + val offerMaxFiatAmount = 1500.0 MultiScreenWizardScaffold( strings.bisqEasy_takeOffer_progress_amount, @@ -56,14 +56,14 @@ fun TakeOfferTradeAmountScreen() { color = BisqTheme.colors.grey2 ) - Spacer(modifier = Modifier.height(128.dp)) + BisqGap.V5() BisqAmountSelector( minAmount = offerMinFiatAmount, maxAmount = offerMaxFiatAmount, - exchangeRate = 95000.0, + exchangeRate = 100000.0, currency = "USD", - onValueChange = {value -> } + onValueChange = { println(it) } ) } } \ No newline at end of file From a516ced56fe1490b6d86798958fa310d6dff46d5 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 18 Dec 2024 00:49:18 +0530 Subject: [PATCH 5/8] - Market list - Search; Moved Gap, Dividers to atoms/layout --- .../ui/components/atoms/SearchField.kt | 60 +++++++++++++++++++ .../ui/components/atoms/TextField.kt | 13 ++-- .../atoms/{ => layout}/BisqHDivider.kt | 5 +- .../atoms/{ => layout}/BisqVDivider.kt | 8 +-- .../ui/components/atoms/{ => layout}/Gap.kt | 2 +- .../ui/components/molecules/OfferCard.kt | 2 + .../trades/TradeFlowAccountDetails.kt | 1 + .../organisms/trades/TradeFlowBtcPayment.kt | 2 +- .../organisms/trades/TradeFlowCompleted.kt | 2 +- .../organisms/trades/TradeFlowFiatPayment.kt | 1 + .../organisms/trades/TradeHeader.kt | 2 +- .../ui/uicases/offers/MarketListScreen.kt | 36 +++++++++-- .../ui/uicases/offers/OffersListScreen.kt | 6 +- .../offers/createOffer/BuySellScreen.kt | 1 + .../CreateOfferCurrencySelectorScreen.kt | 2 +- .../PaymentMethodSelectorScreen.kt | 2 +- .../offers/createOffer/ReviewOfferScreen.kt | 4 +- .../createOffer/TradePriceSelectorScreen.kt | 2 +- .../offers/takeOffer/PaymentMethodScreen.kt | 2 +- .../offers/takeOffer/ReviewTradeScreen.kt | 5 +- .../offers/takeOffer/TradeAmountScreen.kt | 6 +- .../ui/uicases/trades/TradeFlowScreen.kt | 1 + 22 files changed, 119 insertions(+), 46 deletions(-) create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SearchField.kt rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/{ => layout}/BisqHDivider.kt (66%) rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/{ => layout}/BisqVDivider.kt (65%) rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/{ => layout}/Gap.kt (95%) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SearchField.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SearchField.kt new file mode 100644 index 00000000..d471cc5d --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SearchField.kt @@ -0,0 +1,60 @@ +package network.bisq.mobile.presentation.ui.components.atoms + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import network.bisq.mobile.presentation.ui.components.atoms.icons.SearchIcon +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BisqSearchField( + label: String = "", + value: String, + onValueChanged: (String) -> Unit = {}, + placeholder: String = "", + rightSuffix: (@Composable () -> Unit)? = null, + disabled: Boolean = false, + modifier: Modifier = Modifier) { + + BisqTextField( + label = label, + value = value, + onValueChanged = onValueChanged, + placeholder = placeholder, + leftSuffix = { SearchIcon() }, + rightSuffix = rightSuffix, + isSearch= true, + disabled = disabled, + modifier = modifier, + ) + +} diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt index 7b5f77fe..398da1dd 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt @@ -1,8 +1,6 @@ package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -34,7 +32,6 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import network.bisq.mobile.presentation.ui.components.atoms.icons.ArrowDownIcon import network.bisq.mobile.presentation.ui.components.atoms.icons.SearchIcon import network.bisq.mobile.presentation.ui.theme.BisqTheme @@ -45,6 +42,7 @@ fun BisqTextField( onValueChanged: (String) -> Unit = {}, placeholder: String = "", labelRightSuffix: (@Composable () -> Unit)? = null, + leftSuffix: (@Composable () -> Unit)? = null, rightSuffix: (@Composable () -> Unit)? = null, isSearch: Boolean = false, helperText: String = "", @@ -119,10 +117,6 @@ fun BisqTextField( decorationBox = { innerTextField -> Row(verticalAlignment = Alignment.CenterVertically) { if (value.isEmpty()) { - if (isSearch) { - SearchIcon() - Spacer(modifier = Modifier.width(10.dp)) - } BisqText.largeRegular( text = placeholder, color = BisqTheme.colors.secondaryHover @@ -134,6 +128,11 @@ fun BisqTextField( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { + if (leftSuffix != null) { + leftSuffix() + Spacer(modifier = Modifier.width(10.dp)) + } + innerTextField() if (rightSuffix != null) { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqHDivider.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqHDivider.kt similarity index 66% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqHDivider.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqHDivider.kt index dea42767..406fc15c 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqHDivider.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqHDivider.kt @@ -1,14 +1,11 @@ -package network.bisq.mobile.presentation.ui.components.atoms +package network.bisq.mobile.presentation.ui.components.atoms.layout -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable fun BisqHDivider() { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqVDivider.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqVDivider.kt similarity index 65% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqVDivider.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqVDivider.kt index b57a5aa6..554a6ae4 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/BisqVDivider.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/BisqVDivider.kt @@ -1,18 +1,12 @@ -package network.bisq.mobile.presentation.ui.components.atoms +package network.bisq.mobile.presentation.ui.components.atoms.layout -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import network.bisq.mobile.presentation.ui.theme.BisqTheme - - @Composable fun BisqVDivider() { VerticalDivider( diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/Gap.kt similarity index 95% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/Gap.kt index 192b04ef..ca8ae8ee 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Gap.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/layout/Gap.kt @@ -1,4 +1,4 @@ -package network.bisq.mobile.presentation.ui.components.atoms +package network.bisq.mobile.presentation.ui.components.atoms.layout import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt index 3517b2b8..a21639c3 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/molecules/OfferCard.kt @@ -16,6 +16,8 @@ import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ui.components.atoms.* import network.bisq.mobile.presentation.ui.components.atoms.icons.ChatIcon import network.bisq.mobile.presentation.ui.components.atoms.icons.LanguageIcon +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqVDivider import network.bisq.mobile.presentation.ui.components.molecules.* import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowAccountDetails.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowAccountDetails.kt index 69681794..850fac32 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowAccountDetails.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowAccountDetails.kt @@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.atoms.* +import network.bisq.mobile.presentation.ui.components.atoms.layout.* import network.bisq.mobile.presentation.ui.theme.BisqUIConstants import network.bisq.mobile.presentation.ui.uicases.trades.ITradeFlowPresenter import org.koin.compose.koinInject diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowBtcPayment.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowBtcPayment.kt index 433cba5e..7270c5a8 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowBtcPayment.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowBtcPayment.kt @@ -11,7 +11,7 @@ import bisqapps.shared.presentation.generated.resources.img_bitcoin_payment_wait import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.delay import network.bisq.mobile.presentation.ui.components.atoms.BisqButton -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.CircularLoadingImage import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowCompleted.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowCompleted.kt index 9816aa19..7aab33b4 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowCompleted.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowCompleted.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.atoms.BisqButton -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowFiatPayment.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowFiatPayment.kt index bd3dff54..4db81545 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowFiatPayment.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeFlowFiatPayment.kt @@ -13,6 +13,7 @@ import bisqapps.shared.presentation.generated.resources.img_fiat_payment_waiting import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.delay import network.bisq.mobile.presentation.ui.components.atoms.* +import network.bisq.mobile.presentation.ui.components.atoms.layout.* import network.bisq.mobile.presentation.ui.theme.BisqTheme import network.bisq.mobile.presentation.ui.theme.BisqUIConstants import network.bisq.mobile.presentation.ui.uicases.trades.ITradeFlowPresenter diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt index c013a31e..97f1a732 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/trades/TradeHeader.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ui.components.atoms.BisqButton -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.icons.UpIcon import network.bisq.mobile.presentation.ui.components.molecules.UserProfile diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt index a54c5483..c36f9e0d 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt @@ -4,32 +4,58 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap -import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.BisqSearchField import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle -import network.bisq.mobile.presentation.ui.theme.BisqUIConstants import org.koin.compose.koinInject @Composable fun MarketListScreen() { val strings = LocalStrings.current.common val presenter: MarketListPresenter = koinInject() + var searchText by remember { mutableStateOf("") } RememberPresenterLifecycle(presenter) + val filteredMarketItems = remember(searchText, presenter.marketListItemWithNumOffers) { + if (searchText.isEmpty()) { + presenter.marketListItemWithNumOffers + } else { + presenter.marketListItemWithNumOffers.filter { item -> + item.market.quoteCurrencyCode.contains(searchText, ignoreCase = true) || + item.market.quoteCurrencyName.contains(searchText, ignoreCase = true) + } + } + } + BisqStaticLayout(padding = PaddingValues(all = 0.dp), verticalArrangement = Arrangement.Top) { - BisqTextField(label = "", placeholder = strings.common_search, value ="", onValueChanged = {}) + BisqSearchField( + value = searchText, + onValueChanged = { searchText = it }, + placeholder = strings.common_search, +// rightSuffix = { +// BisqButton( +// iconOnly = { SortIcon() }, +// onClick = { println("Sort / filterrrr") } +// ) +// } + ) BisqGap.V1() LazyColumn { - items(presenter.marketListItemWithNumOffers) { item -> + items(filteredMarketItems) { item -> CurrencyProfileCard( item, onClick = { presenter.onSelectMarket(item) } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/OffersListScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/OffersListScreen.kt index c6f78809..6736eea0 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/OffersListScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/OffersListScreen.kt @@ -1,27 +1,23 @@ package network.bisq.mobile.presentation.ui.uicases.offers import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.client.replicated_model.offer.Direction import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ViewPresenter -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.layout.BisqStaticScaffold import network.bisq.mobile.presentation.ui.components.molecules.DirectionToggle import network.bisq.mobile.presentation.ui.components.molecules.OfferCard import network.bisq.mobile.presentation.ui.components.molecules.TopBar import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle -import network.bisq.mobile.presentation.ui.theme.BisqUIConstants import org.koin.compose.koinInject interface IOffersListPresenter : ViewPresenter { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/BuySellScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/BuySellScreen.kt index fd7066e1..101a18af 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/BuySellScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/BuySellScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.atoms.* +import network.bisq.mobile.presentation.ui.components.atoms.layout.* import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt index 7c4d28cc..ba37ad42 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/PaymentMethodSelectorScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/PaymentMethodSelectorScreen.kt index bcabf84f..ce070a04 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/PaymentMethodSelectorScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/PaymentMethodSelectorScreen.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold import network.bisq.mobile.presentation.ui.components.organisms.PaymentMethodCard diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/ReviewOfferScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/ReviewOfferScreen.kt index 77ece910..45704a19 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/ReviewOfferScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/ReviewOfferScreen.kt @@ -13,8 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap -import network.bisq.mobile.presentation.ui.components.atoms.BisqHDivider +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqHDivider import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold import network.bisq.mobile.presentation.ui.components.molecules.info.InfoBox diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/TradePriceSelectorScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/TradePriceSelectorScreen.kt index 0e82a6f8..7afe1681 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/TradePriceSelectorScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/TradePriceSelectorScreen.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.unit.sp import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.ibm_plex_sans_medium import cafe.adriel.lyricist.LocalStrings -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField import network.bisq.mobile.presentation.ui.components.atoms.NoteText diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/PaymentMethodScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/PaymentMethodScreen.kt index 39a56f4e..1912e2c5 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/PaymentMethodScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/PaymentMethodScreen.kt @@ -13,7 +13,7 @@ import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ViewPresenter -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.DynamicImage import network.bisq.mobile.presentation.ui.theme.BisqTheme diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/ReviewTradeScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/ReviewTradeScreen.kt index 9b29c751..a17449ca 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/ReviewTradeScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/ReviewTradeScreen.kt @@ -4,14 +4,13 @@ import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ViewPresenter -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap -import network.bisq.mobile.presentation.ui.components.atoms.BisqHDivider +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqHDivider import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.theme.BisqTheme import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt index 365f6cf5..1cc9bb10 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/takeOffer/TradeAmountScreen.kt @@ -1,20 +1,16 @@ package network.bisq.mobile.presentation.ui.uicases.offers.takeOffer -import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ViewPresenter -import network.bisq.mobile.presentation.ui.components.atoms.BisqGap +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.layout.MultiScreenWizardScaffold import network.bisq.mobile.presentation.ui.components.molecules.BisqAmountSelector import network.bisq.mobile.presentation.ui.theme.BisqTheme -import network.bisq.mobile.presentation.ui.theme.BisqUIConstants import org.koin.compose.koinInject interface ITakeOfferTradeAmountPresenter : ViewPresenter { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/TradeFlowScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/TradeFlowScreen.kt index 75d0ff3f..a7d067f5 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/TradeFlowScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/trades/TradeFlowScreen.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.domain.data.model.OfferListItem import network.bisq.mobile.presentation.ViewPresenter import network.bisq.mobile.presentation.ui.components.atoms.* +import network.bisq.mobile.presentation.ui.components.atoms.layout.* import network.bisq.mobile.presentation.ui.components.layout.BisqStaticScaffold import network.bisq.mobile.presentation.ui.components.molecules.BisqDialog import network.bisq.mobile.presentation.ui.components.molecules.TopBar From dab7490034636d9996b29e920d995512c27429cd Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 18 Dec 2024 17:12:04 +0530 Subject: [PATCH 6/8] - Market list - Filter bottom sheet and filter functionality; CurrencyCard - Handle lengthy currency names (#121); DropDown component --- ...CurrencyProfileCard.kt => CurrencyCard.kt} | 23 +- .../ui/components/atoms/Button.kt | 43 ++- .../ui/components/atoms/DropDown.kt | 92 +++-- .../ui/components/atoms/EditableDropDown.kt | 68 ++++ .../ui/components/atoms/SegmentButton.kt | 30 ++ .../ui/components/atoms/TextField.kt | 27 +- .../organisms/market/MarketFilters.kt | 87 +++++ .../ui/uicases/offers/MarketListPresenter.kt | 91 ++++- .../ui/uicases/offers/MarketListScreen.kt | 59 ++-- .../CreateOfferCurrencySelectorScreen.kt | 4 +- .../settings/PaymentAccountSettingsScreen.kt | 322 +++++++++--------- 11 files changed, 568 insertions(+), 278 deletions(-) rename shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/{CurrencyProfileCard.kt => CurrencyCard.kt} (86%) create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/EditableDropDown.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SegmentButton.kt create mode 100644 shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/market/MarketFilters.kt diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyCard.kt similarity index 86% rename from shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt rename to shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyCard.kt index b54460e4..794119e6 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyProfileCard.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/CurrencyCard.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember @@ -21,14 +20,16 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.unit.dp import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.style.TextAlign import network.bisq.mobile.domain.data.model.MarketListItem import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.DynamicImage +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants @Composable -fun CurrencyProfileCard( +fun CurrencyCard( item: MarketListItem, isSelected: Boolean = false, onClick: () -> Unit @@ -63,18 +64,14 @@ fun CurrencyProfileCard( Modifier.background(Color.Transparent) } ) - .padding(horizontal = 4.dp, vertical = (16/LocalDensity.current.density).dp) - // .padding(vertical = 4.dp) + .padding(vertical = BisqUIConstants.ScreenPadding) .clickable( interactionSource = interactionSource, indication = null, onClick = onClick ) ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(3.0f)) { // If the image is not available we get an exception here and we cannot use try/catch // Is DynamicImage needed? If so we can pass it as DynamicImage( @@ -83,12 +80,12 @@ fun CurrencyProfileCard( .replace("-", "_")}.png", modifier = Modifier.size(36.dp) ) - - Spacer(modifier = Modifier.width(8.dp)) + BisqGap.HHalf() Column { BisqText.baseRegular( text = item.market.quoteCurrencyName, color = BisqTheme.colors.light1, + singleLine = true ) Spacer(modifier = Modifier.height(0.dp)) BisqText.baseRegular( @@ -97,9 +94,11 @@ fun CurrencyProfileCard( ) } } - BisqText.smallRegular( + BisqText.baseRegular( text = "$numOffers offers", color = BisqTheme.colors.primary, + textAlign = TextAlign.End, + modifier = Modifier.weight(1.0f), ) } } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt index 66548de0..ec3f027e 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt @@ -1,6 +1,7 @@ package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button @@ -12,11 +13,17 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import network.bisq.mobile.presentation.ui.theme.BisqTheme +enum class BisqButtonType { + Default, + Outline, + Clear +} + /** * Either pass - * - text for regular button (or) - * - iconOnly for Icon only button. - * If both are given, iconOnly takes precedence + * - iconOnly for Icon only button (or) + * - textComponent for button with custom styled text (or) + * - text for regular button */ @Composable fun BisqButton( @@ -32,20 +39,38 @@ fun BisqButton( modifier: Modifier = Modifier, cornerRadius: Dp = 8.dp, disabled: Boolean = false, - border: BorderStroke? = null + border: BorderStroke? = null, + type: BisqButtonType = BisqButtonType.Default ) { + val finalBackgroundColor = when (type) { + BisqButtonType.Default -> backgroundColor + BisqButtonType.Outline -> Color.Transparent + BisqButtonType.Clear -> Color.Transparent + } + + val finalBorder = when (type) { + BisqButtonType.Default -> border + BisqButtonType.Outline -> BorderStroke(1.dp, BisqTheme.colors.primary) + BisqButtonType.Clear -> null + } + + val finalContentColor = when (type) { + BisqButtonType.Default, BisqButtonType.Outline -> color + BisqButtonType.Clear -> color + } + Button( onClick = { onClick() }, contentPadding = if(iconOnly != null) PaddingValues(horizontal = 0.dp, vertical = 0.dp) else padding, colors = ButtonColors( - containerColor = backgroundColor, - disabledContainerColor = backgroundColor, - contentColor = color, - disabledContentColor = color), + containerColor = finalBackgroundColor, + disabledContainerColor = finalBackgroundColor, + contentColor = finalContentColor, + disabledContentColor = finalContentColor), shape = RoundedCornerShape(cornerRadius), enabled = !disabled, - border = border, + border = finalBorder, modifier = modifier ) { if (iconOnly == null && text == null && textComponent == null) { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt index b1a5b166..703d33a0 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/DropDown.kt @@ -1,67 +1,65 @@ package network.bisq.mobile.presentation.ui.components.atoms import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import network.bisq.mobile.presentation.ui.components.atoms.icons.ArrowDownIcon -import network.bisq.mobile.presentation.ui.components.molecules.BisqDialog +import androidx.compose.ui.text.style.TextAlign import network.bisq.mobile.presentation.ui.theme.BisqTheme @Composable fun BisqDropDown( + label: String = "", + items: List, value: String, onValueChanged: (String) -> Unit, - items: List, - label: String + modifier: Modifier = Modifier, + placeholder: String = "Select an item" ) { - var showDialog by remember { mutableStateOf(false) } + var expanded by remember { mutableStateOf(false) } - BisqTextField( - value = value, - onValueChanged = onValueChanged, - label = label, - rightSuffix = { - Box( - modifier = Modifier - .padding(vertical = 8.dp, horizontal = 16.dp) - .clickable( - onClick = { showDialog = true }, - interactionSource = remember { MutableInteractionSource() }, - indication = null - ) - ) { - ArrowDownIcon() - } - }, - ) + Column { + if (label.isNotEmpty()) { + BisqText.baseRegular( + text = label, + color = BisqTheme.colors.light2, + ) + } + + BisqButton( + onClick = { expanded = true }, + modifier = Modifier.fillMaxWidth(), + backgroundColor = BisqTheme.colors.grey5, + textComponent = { + BisqText.baseRegular( + text = value, + color = BisqTheme.colors.light1, + textAlign = TextAlign.Start + ) + }, + ) - if (showDialog) { - BisqDialog(onDismissRequest = { showDialog = false }) { - LazyColumn( - modifier = Modifier.padding(16.dp), - ) { - items(items) { item -> - Row( - modifier = Modifier.fillMaxWidth() - .padding(vertical = 8.dp) - .clickable { - onValueChanged(item) - showDialog = false - } - ) { - BisqText.baseBold(text = item) - } - } + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + modifier = Modifier.wrapContentSize().background(color = BisqTheme.colors.secondary) + ) { + items.forEach { item -> + DropdownMenuItem( + text = { BisqText.baseRegular(text = item) }, + onClick = { + onValueChanged.invoke(item) + expanded = false + }, + ) } } } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/EditableDropDown.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/EditableDropDown.kt new file mode 100644 index 00000000..fd6107b6 --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/EditableDropDown.kt @@ -0,0 +1,68 @@ +package network.bisq.mobile.presentation.ui.components.atoms + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.components.atoms.icons.ArrowDownIcon +import network.bisq.mobile.presentation.ui.components.molecules.BisqDialog +import network.bisq.mobile.presentation.ui.theme.BisqTheme + +@Composable +fun BisqEditableDropDown( + value: String, + onValueChanged: (String) -> Unit, + items: List, + label: String +) { + var showDialog by remember { mutableStateOf(false) } + + BisqTextField( + value = value, + onValueChanged = onValueChanged, + label = label, + rightSuffix = { + Box( + modifier = Modifier + .padding(vertical = 8.dp, horizontal = 16.dp) + .clickable( + onClick = { showDialog = true }, + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) + ) { + ArrowDownIcon() + } + }, + ) + + if (showDialog) { + BisqDialog(onDismissRequest = { showDialog = false }) { + LazyColumn( + modifier = Modifier.padding(16.dp), + ) { + items(items) { item -> + Row( + modifier = Modifier.fillMaxWidth() + .padding(vertical = 8.dp) + .clickable { + onValueChanged(item) + showDialog = false + } + ) { + BisqText.baseBold(text = item) + } + } + } + } + } +} diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SegmentButton.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SegmentButton.kt new file mode 100644 index 00000000..b9dbd3ea --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/SegmentButton.kt @@ -0,0 +1,30 @@ +package network.bisq.mobile.presentation.ui.components.atoms + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember + +// TODO: SingleChoiceSegmentedButtonRow: Not available in KMP? +@Composable +fun BisqSegmentButton() { + var selectedIndex by remember { mutableIntStateOf(0) } + val options = listOf("Day", "Month", "Week") + + /* + SingleChoiceSegmentedButtonRow { + options.forEachIndexed { index, label -> + SegmentedButton( + shape = SegmentedButtonDefaults.itemShape( + index = index, + count = options.size + ), + onClick = { selectedIndex = index }, + selected = index == selectedIndex, + label = { Text(label) } + ) + } + } + */ +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt index 398da1dd..9895cfc1 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/TextField.kt @@ -48,7 +48,7 @@ fun BisqTextField( helperText: String = "", indicatorColor: Color = BisqTheme.colors.primary, isTextArea: Boolean = false, - paddingValues: PaddingValues = PaddingValues(vertical = 12.dp), + paddingValues: PaddingValues = PaddingValues(all = 12.dp), disabled: Boolean = false, modifier: Modifier = Modifier, ) { @@ -81,7 +81,6 @@ fun BisqTextField( Box( modifier = Modifier .fillMaxWidth() - .padding(paddingValues) .clip(shape = RoundedCornerShape(6.dp)) .background(color = BisqTheme.colors.secondary) .drawBehind { @@ -99,7 +98,7 @@ fun BisqTextField( value = value, onValueChange = onValueChanged, modifier = Modifier - .padding(12.dp) + .padding(paddingValues) .fillMaxWidth() .onFocusChanged { focusState -> isFocused = focusState.isFocused @@ -115,14 +114,6 @@ fun BisqTextField( cursorBrush = SolidColor(BisqTheme.colors.primary), enabled = !disabled, decorationBox = { innerTextField -> - Row(verticalAlignment = Alignment.CenterVertically) { - if (value.isEmpty()) { - BisqText.largeRegular( - text = placeholder, - color = BisqTheme.colors.secondaryHover - ) - } - } Row( verticalAlignment = Alignment.CenterVertically, @@ -133,10 +124,20 @@ fun BisqTextField( Spacer(modifier = Modifier.width(10.dp)) } - innerTextField() + Box(modifier = Modifier.weight(1f)) { + if (value.isEmpty()) { + BisqText.largeRegular( + text = placeholder, + color = BisqTheme.colors.secondaryHover + ) + } + innerTextField() + } if (rightSuffix != null) { - rightSuffix() + Box(modifier = Modifier.width(50.dp)) { + rightSuffix() + } } } } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/market/MarketFilters.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/market/MarketFilters.kt new file mode 100644 index 00000000..74e1394e --- /dev/null +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/organisms/market/MarketFilters.kt @@ -0,0 +1,87 @@ +package network.bisq.mobile.presentation.ui.components.organisms.market + +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqDropDown +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants +import network.bisq.mobile.presentation.ui.uicases.offers.MarketListPresenter +import org.koin.compose.koinInject + +enum class MarketSortBy(val displayName: String) { + MostOffers("Most Offers"), + NameAZ("Name A-Z"), + NameZA("Name Z-A") +} + +enum class MarketFilter(val displayName: String) { + WithOffers("With Offers"), + All("All") +} + + +@Composable +fun MarketFilters( + onConfirm: () -> Unit, + onCancel: () -> Unit, +) { + + val presenter: MarketListPresenter = koinInject() + + Column(modifier = Modifier.padding(all = BisqUIConstants.ScreenPadding2X)) { + + BisqDropDown( + label = "Sort by", + value = presenter.sortBy.collectAsState().value.displayName, + items = MarketSortBy.entries.map { it.displayName }, + onValueChanged = { + val newValue = when (it) { + MarketSortBy.MostOffers.displayName -> MarketSortBy.MostOffers + MarketSortBy.NameAZ.displayName -> MarketSortBy.NameAZ + else -> MarketSortBy.NameZA + } + presenter.setSortBy(newValue) + } + ) + + BisqGap.V2() + + BisqDropDown( + label = "Show markets", + value = presenter.filter.collectAsState().value.displayName, + items = MarketFilter.entries.map { it.displayName }, + onValueChanged = { + val newValue = when (it) { + MarketFilter.All.displayName -> MarketFilter.All + else -> MarketFilter.WithOffers + } + presenter.setFilter(newValue) } + ) + +// BisqGap.V1() +// +// Row( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.SpaceBetween +// ) { +// BisqButton( +// text = "Cancel", +// onClick = onCancel, +// backgroundColor = BisqTheme.colors.dark5, +// padding = PaddingValues(horizontal = 48.dp, vertical = 4.dp), +// ) +// BisqButton( +// text = "Apply", +// onClick = onConfirm, +// padding = PaddingValues(horizontal = 48.dp, vertical = 4.dp), +// ) +// } + + } + +} \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt index 8e75defa..06b7f748 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt @@ -1,34 +1,115 @@ package network.bisq.mobile.presentation.ui.uicases.offers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.launch import network.bisq.mobile.domain.data.model.MarketListItem import network.bisq.mobile.domain.service.offerbook.OfferbookServiceFacade import network.bisq.mobile.presentation.BasePresenter import network.bisq.mobile.presentation.MainPresenter +import network.bisq.mobile.presentation.ui.components.organisms.market.MarketFilter +import network.bisq.mobile.presentation.ui.components.organisms.market.MarketSortBy import network.bisq.mobile.presentation.ui.navigation.Routes class MarketListPresenter( mainPresenter: MainPresenter, private val offerbookServiceFacade: OfferbookServiceFacade, - ) : BasePresenter(mainPresenter) { +) : BasePresenter(mainPresenter) { private var mainCurrencies = OfferbookServiceFacade.mainCurrencies - var marketListItemWithNumOffers: List = offerbookServiceFacade.offerbookMarketItems + private var _sortBy = MutableStateFlow(MarketSortBy.MostOffers) + var sortBy: StateFlow = _sortBy + fun setSortBy(newValue: MarketSortBy) { + _sortBy.value = newValue + } + + private var _filter = MutableStateFlow(MarketFilter.WithOffers) + var filter: StateFlow = _filter + fun setFilter(newValue: MarketFilter) { + _filter.value = newValue + } + + private var _searchText = MutableStateFlow("") + val searchText: StateFlow = _searchText + fun setSearchText(newValue: String) { + _searchText.value = newValue + } + + /* + var marketListItems: List = offerbookServiceFacade.offerbookMarketItems .sortedWith( - compareByDescending { it.numOffers.value } + compareByDescending { it.numOffers.value } .thenByDescending { mainCurrencies.contains(it.market.quoteCurrencyCode.lowercase()) } // [1] - .thenBy { item-> + .thenBy { item -> if (!mainCurrencies.contains(item.market.quoteCurrencyCode.lowercase())) item.market.quoteCurrencyName else null // Null values will naturally be sorted together } ) + */ // [1] thenBy doesn’t work as expected for boolean expressions because true and false are // sorted alphabetically (false before true), thus we use thenByDescending + val marketListItemWithNumOffers: StateFlow> = combine( + // offerbookServiceFacade.offerbookMarketItems, + _filter, + _searchText, + _sortBy + ) { /*items: List,*/ filter: MarketFilter, searchText: String, sortBy: MarketSortBy -> + computeMarketList(filter, searchText, sortBy) +// }.onEach { updatedList: List -> +// println("Updating main Var for Screen ${updatedList.count()}") +// marketListItemWithNumOffers = updatedList + }.stateIn( + CoroutineScope(Dispatchers.Main), + SharingStarted.Lazily, + emptyList() + ) + + private fun computeMarketList( + // items: List, + filter: MarketFilter, + searchText: String, + sortBy: MarketSortBy + ): List { + // return items + return offerbookServiceFacade.offerbookMarketItems + .filter { item -> + when (filter) { + MarketFilter.WithOffers -> item.numOffers.value > 0 + MarketFilter.All -> true + } + } + .filter { item -> + searchText.isEmpty() || + item.market.quoteCurrencyCode.contains(searchText, ignoreCase = true) || + item.market.quoteCurrencyName.contains(searchText, ignoreCase = true) + } + .sortedWith( + compareByDescending { + when (sortBy) { + MarketSortBy.MostOffers -> it.numOffers.value + else -> 0 + } + } + .thenByDescending { mainCurrencies.contains(it.market.quoteCurrencyCode.lowercase()) } + .thenBy { + when (sortBy) { + MarketSortBy.NameAZ -> it.market.quoteCurrencyName + MarketSortBy.NameZA -> it.market.quoteCurrencyName + else -> null + } + } + .let { comparator -> + if (sortBy == MarketSortBy.NameZA) comparator.reversed() else comparator + } + ) + } + fun onSelectMarket(marketListItem: MarketListItem) { offerbookServiceFacade.selectMarket(marketListItem) rootNavigator.navigate(Routes.OfferList.name) - // rootNavigator.navigate(Routes.TradeFlow.name) } override fun onViewAttached() { diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt index c36f9e0d..79eebdcd 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListScreen.kt @@ -3,20 +3,18 @@ package network.bisq.mobile.presentation.ui.uicases.offers import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier +import androidx.compose.runtime.* import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings -import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard +import network.bisq.mobile.presentation.ui.components.CurrencyCard import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqButtonType import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqSearchField import network.bisq.mobile.presentation.ui.components.atoms.icons.SortIcon import network.bisq.mobile.presentation.ui.components.layout.BisqStaticLayout +import network.bisq.mobile.presentation.ui.components.molecules.BisqBottomSheet +import network.bisq.mobile.presentation.ui.components.organisms.market.MarketFilters import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle import org.koin.compose.koinInject @@ -24,43 +22,46 @@ import org.koin.compose.koinInject fun MarketListScreen() { val strings = LocalStrings.current.common val presenter: MarketListPresenter = koinInject() - var searchText by remember { mutableStateOf("") } + var showFilterDialog by remember { mutableStateOf(false) } - RememberPresenterLifecycle(presenter) + val marketItems = presenter.marketListItemWithNumOffers.collectAsState().value - val filteredMarketItems = remember(searchText, presenter.marketListItemWithNumOffers) { - if (searchText.isEmpty()) { - presenter.marketListItemWithNumOffers - } else { - presenter.marketListItemWithNumOffers.filter { item -> - item.market.quoteCurrencyCode.contains(searchText, ignoreCase = true) || - item.market.quoteCurrencyName.contains(searchText, ignoreCase = true) - } - } - } + RememberPresenterLifecycle(presenter) BisqStaticLayout(padding = PaddingValues(all = 0.dp), verticalArrangement = Arrangement.Top) { + BisqSearchField( - value = searchText, - onValueChanged = { searchText = it }, + value = presenter.searchText.collectAsState().value, + onValueChanged = { presenter.setSearchText(it) }, placeholder = strings.common_search, -// rightSuffix = { -// BisqButton( -// iconOnly = { SortIcon() }, -// onClick = { println("Sort / filterrrr") } -// ) -// } + rightSuffix = { + // TODO: Height to be reduced with Icon only buttons + BisqButton( + iconOnly = { SortIcon() }, + onClick = { showFilterDialog = true }, + type = BisqButtonType.Clear + ) + } ) BisqGap.V1() LazyColumn { - items(filteredMarketItems) { item -> - CurrencyProfileCard( + items(marketItems) { item -> + CurrencyCard( item, onClick = { presenter.onSelectMarket(item) } ) } } + + if (showFilterDialog) { + BisqBottomSheet(onDismissRequest = { showFilterDialog = false }) { + MarketFilters( + onConfirm = {}, + onCancel = {} + ) + } + } } } \ No newline at end of file diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt index ba37ad42..11a6a071 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/createOffer/CreateOfferCurrencySelectorScreen.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cafe.adriel.lyricist.LocalStrings -import network.bisq.mobile.presentation.ui.components.CurrencyProfileCard +import network.bisq.mobile.presentation.ui.components.CurrencyCard import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField @@ -77,7 +77,7 @@ fun CreateOfferCurrencySelectorScreen() { verticalArrangement = Arrangement.spacedBy(12.dp) ) { items(presenter.marketListItemWithNumOffers) { item -> - CurrencyProfileCard( + CurrencyCard( item, isSelected = state.selectedOfferbookMarket.market.quoteCurrencyCode == item.market.quoteCurrencyCode, onClick = { presenter.onSelectMarket(item) } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt index f3ca41a7..4837197b 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/settings/PaymentAccountSettingsScreen.kt @@ -1,161 +1,161 @@ -package network.bisq.mobile.presentation.ui.uicases.settings - -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import cafe.adriel.lyricist.LocalStrings -import kotlinx.coroutines.flow.StateFlow -import network.bisq.mobile.presentation.ViewPresenter -import network.bisq.mobile.presentation.ui.components.atoms.BisqButton -import network.bisq.mobile.presentation.ui.components.atoms.BisqDropDown -import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField -import network.bisq.mobile.presentation.ui.components.molecules.BisqBottomSheet -import network.bisq.mobile.presentation.ui.components.molecules.ConfirmationDialog -import network.bisq.mobile.presentation.ui.components.organisms.settings.AppPaymentAccountCard -import network.bisq.mobile.presentation.ui.composeModels.PaymentAccount -import network.bisq.mobile.presentation.ui.theme.BisqTheme -import network.bisq.mobile.presentation.ui.theme.BisqUIConstants -import org.koin.compose.koinInject - -interface IPaymentAccountSettingsPresenter : ViewPresenter { - val accounts: StateFlow> - val selectedAccount: StateFlow - - fun selectAccount(account: PaymentAccount) - - fun addAccount(newName: String, newDescription: String) - fun saveAccount(newName: String, newDescription: String) - fun deleteCurrentAccount() -} - -// TODO: Toast messages -@Composable -fun PaymentAccountSettingsScreen() { - - val strings = LocalStrings.current.user - val stringsCommon = LocalStrings.current.common - - val presenter: IPaymentAccountSettingsPresenter = koinInject() - val accounts by presenter.accounts.collectAsState() - val selectedAccount by presenter.selectedAccount.collectAsState() - - var accountName by remember { mutableStateOf(selectedAccount.name) } - var accountDescription by remember { mutableStateOf(selectedAccount.description) } - - var showConfirmationDialog by remember { mutableStateOf(false) } - var showBottomSheet by remember { mutableStateOf(false) } - - LaunchedEffect(selectedAccount) { - accountName = selectedAccount.name - accountDescription = selectedAccount.description - } - - if (showBottomSheet) { - BisqBottomSheet( - onDismissRequest = { showBottomSheet = !showBottomSheet } - ) { - AppPaymentAccountCard( - onCancel = { showBottomSheet = false }, - onConfirm = { name, description -> - presenter.addAccount(name, description) - showBottomSheet = false - }, - ) - } - } - - if (accounts.isEmpty()) { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - BisqButton( - text = strings.user_paymentAccounts_createAccount, - onClick = { showBottomSheet = !showBottomSheet }, - modifier = Modifier.padding(all = 8.dp) - ) - } - return - } - - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(BisqUIConstants.ScreenPadding) - ) { - BisqButton( - text = strings.user_paymentAccounts_createAccount, - onClick = { showBottomSheet = !showBottomSheet }, - padding = PaddingValues(horizontal = 18.dp, vertical = 6.dp), - modifier = Modifier.align(Alignment.End) - ) - - BisqDropDown( - value = accountName, - onValueChanged = { name -> - var account = accounts.firstOrNull { it.name == name } - - if (account == null) { - account = accounts.firstOrNull { it.description == accountDescription } - - if (account != null) { - account = PaymentAccount(id = account.id, name = name, description = account.description) - } - } - - if (account == null) { - account = - PaymentAccount(id = accounts.count().toString(), name = name, description = accountDescription) - } - - presenter.selectAccount(account) - accountName = account.name - accountDescription = account.description - }, - items = accounts.map { it.name }, - label = strings.user_userProfile_payment_account - ) - - BisqTextField( - value = accountDescription, - onValueChanged = { accountDescription = it }, - label = strings.user_paymentAccounts_accountData, - isTextArea = true - ) - - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() - ) { - BisqButton( - text = stringsCommon.delete_account, - backgroundColor = BisqTheme.colors.dark5, - onClick = { showConfirmationDialog = true } - ) - BisqButton( - text = stringsCommon.buttons_save, - onClick = { - presenter.saveAccount(accountName, accountDescription) - } - ) - } - } - - if (showConfirmationDialog) { - ConfirmationDialog( - onConfirm = { - presenter.deleteCurrentAccount() - accountName = presenter.selectedAccount.value.name - accountDescription = presenter.selectedAccount.value.description - showConfirmationDialog = false - }, - onDismissRequest = { - showConfirmationDialog = false - } - ) - } - -} - +package network.bisq.mobile.presentation.ui.uicases.settings + +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import cafe.adriel.lyricist.LocalStrings +import kotlinx.coroutines.flow.StateFlow +import network.bisq.mobile.presentation.ViewPresenter +import network.bisq.mobile.presentation.ui.components.atoms.BisqButton +import network.bisq.mobile.presentation.ui.components.atoms.BisqEditableDropDown +import network.bisq.mobile.presentation.ui.components.atoms.BisqTextField +import network.bisq.mobile.presentation.ui.components.molecules.BisqBottomSheet +import network.bisq.mobile.presentation.ui.components.molecules.ConfirmationDialog +import network.bisq.mobile.presentation.ui.components.organisms.settings.AppPaymentAccountCard +import network.bisq.mobile.presentation.ui.composeModels.PaymentAccount +import network.bisq.mobile.presentation.ui.theme.BisqTheme +import network.bisq.mobile.presentation.ui.theme.BisqUIConstants +import org.koin.compose.koinInject + +interface IPaymentAccountSettingsPresenter : ViewPresenter { + val accounts: StateFlow> + val selectedAccount: StateFlow + + fun selectAccount(account: PaymentAccount) + + fun addAccount(newName: String, newDescription: String) + fun saveAccount(newName: String, newDescription: String) + fun deleteCurrentAccount() +} + +// TODO: Toast messages +@Composable +fun PaymentAccountSettingsScreen() { + + val strings = LocalStrings.current.user + val stringsCommon = LocalStrings.current.common + + val presenter: IPaymentAccountSettingsPresenter = koinInject() + val accounts by presenter.accounts.collectAsState() + val selectedAccount by presenter.selectedAccount.collectAsState() + + var accountName by remember { mutableStateOf(selectedAccount.name) } + var accountDescription by remember { mutableStateOf(selectedAccount.description) } + + var showConfirmationDialog by remember { mutableStateOf(false) } + var showBottomSheet by remember { mutableStateOf(false) } + + LaunchedEffect(selectedAccount) { + accountName = selectedAccount.name + accountDescription = selectedAccount.description + } + + if (showBottomSheet) { + BisqBottomSheet( + onDismissRequest = { showBottomSheet = !showBottomSheet } + ) { + AppPaymentAccountCard( + onCancel = { showBottomSheet = false }, + onConfirm = { name, description -> + presenter.addAccount(name, description) + showBottomSheet = false + }, + ) + } + } + + if (accounts.isEmpty()) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + BisqButton( + text = strings.user_paymentAccounts_createAccount, + onClick = { showBottomSheet = !showBottomSheet }, + modifier = Modifier.padding(all = 8.dp) + ) + } + return + } + + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(BisqUIConstants.ScreenPadding) + ) { + BisqButton( + text = strings.user_paymentAccounts_createAccount, + onClick = { showBottomSheet = !showBottomSheet }, + padding = PaddingValues(horizontal = 18.dp, vertical = 6.dp), + modifier = Modifier.align(Alignment.End) + ) + + BisqEditableDropDown( + value = accountName, + onValueChanged = { name -> + var account = accounts.firstOrNull { it.name == name } + + if (account == null) { + account = accounts.firstOrNull { it.description == accountDescription } + + if (account != null) { + account = PaymentAccount(id = account.id, name = name, description = account.description) + } + } + + if (account == null) { + account = + PaymentAccount(id = accounts.count().toString(), name = name, description = accountDescription) + } + + presenter.selectAccount(account) + accountName = account.name + accountDescription = account.description + }, + items = accounts.map { it.name }, + label = strings.user_userProfile_payment_account + ) + + BisqTextField( + value = accountDescription, + onValueChanged = { accountDescription = it }, + label = strings.user_paymentAccounts_accountData, + isTextArea = true + ) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + BisqButton( + text = stringsCommon.delete_account, + backgroundColor = BisqTheme.colors.dark5, + onClick = { showConfirmationDialog = true } + ) + BisqButton( + text = stringsCommon.buttons_save, + onClick = { + presenter.saveAccount(accountName, accountDescription) + } + ) + } + } + + if (showConfirmationDialog) { + ConfirmationDialog( + onConfirm = { + presenter.deleteCurrentAccount() + accountName = presenter.selectedAccount.value.name + accountDescription = presenter.selectedAccount.value.description + showConfirmationDialog = false + }, + onDismissRequest = { + showConfirmationDialog = false + } + ) + } + +} + From 65880e596354144f67340f9690a38c27572cc2b5 Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 18 Dec 2024 17:45:53 +0530 Subject: [PATCH 7/8] - button.isLoading (only for text buttons) --- .../ui/components/atoms/Button.kt | 40 ++++++++++++------- .../ui/uicases/offers/MarketListPresenter.kt | 8 +--- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt index ec3f027e..5a650444 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/components/atoms/Button.kt @@ -6,11 +6,14 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonColors +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import network.bisq.mobile.presentation.ui.components.atoms.layout.BisqGap import network.bisq.mobile.presentation.ui.theme.BisqTheme enum class BisqButtonType { @@ -39,10 +42,13 @@ fun BisqButton( modifier: Modifier = Modifier, cornerRadius: Dp = 8.dp, disabled: Boolean = false, + isLoading: Boolean = false, border: BorderStroke? = null, type: BisqButtonType = BisqButtonType.Default ) { + val enabled = !disabled && !isLoading + val finalBackgroundColor = when (type) { BisqButtonType.Default -> backgroundColor BisqButtonType.Outline -> Color.Transparent @@ -55,21 +61,19 @@ fun BisqButton( BisqButtonType.Clear -> null } - val finalContentColor = when (type) { - BisqButtonType.Default, BisqButtonType.Outline -> color - BisqButtonType.Clear -> color - } + val finalContentColor = color Button( onClick = { onClick() }, - contentPadding = if(iconOnly != null) PaddingValues(horizontal = 0.dp, vertical = 0.dp) else padding, + contentPadding = if (iconOnly != null) PaddingValues(horizontal = 0.dp, vertical = 0.dp) else padding, colors = ButtonColors( containerColor = finalBackgroundColor, - disabledContainerColor = finalBackgroundColor, + disabledContainerColor = finalBackgroundColor.copy(alpha = 0.5f), contentColor = finalContentColor, - disabledContentColor = finalContentColor), + disabledContentColor = finalContentColor.copy(alpha = 0.5f), + ), shape = RoundedCornerShape(cornerRadius), - enabled = !disabled, + enabled = enabled, border = finalBorder, modifier = modifier ) { @@ -80,19 +84,27 @@ fun BisqButton( if (iconOnly != null) { iconOnly() } else if (text != null) { - Row { - if(leftIcon != null) leftIcon() - if(leftIcon != null) Spacer(modifier = Modifier.width(10.dp)) + Row(verticalAlignment = Alignment.CenterVertically) { + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + color = BisqTheme.colors.light1, + strokeWidth = 2.dp + ) + BisqGap.HHalf() + } + if (leftIcon != null) leftIcon() + if (leftIcon != null) Spacer(modifier = Modifier.width(10.dp)) if (textComponent != null) { textComponent() } else { BisqText.baseMedium( text = text, color = BisqTheme.colors.light1, - ) + ) } - if(rightIcon != null) Spacer(modifier = Modifier.width(10.dp)) - if(rightIcon != null) rightIcon() + if (rightIcon != null) Spacer(modifier = Modifier.width(10.dp)) + if (rightIcon != null) rightIcon() } } } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt index 06b7f748..648407c0 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/offers/MarketListPresenter.kt @@ -52,15 +52,11 @@ class MarketListPresenter( // sorted alphabetically (false before true), thus we use thenByDescending val marketListItemWithNumOffers: StateFlow> = combine( - // offerbookServiceFacade.offerbookMarketItems, _filter, _searchText, _sortBy - ) { /*items: List,*/ filter: MarketFilter, searchText: String, sortBy: MarketSortBy -> + ) { filter: MarketFilter, searchText: String, sortBy: MarketSortBy -> computeMarketList(filter, searchText, sortBy) -// }.onEach { updatedList: List -> -// println("Updating main Var for Screen ${updatedList.count()}") -// marketListItemWithNumOffers = updatedList }.stateIn( CoroutineScope(Dispatchers.Main), SharingStarted.Lazily, @@ -68,12 +64,10 @@ class MarketListPresenter( ) private fun computeMarketList( - // items: List, filter: MarketFilter, searchText: String, sortBy: MarketSortBy ): List { - // return items return offerbookServiceFacade.offerbookMarketItems .filter { item -> when (filter) { From d05da787fc6e72847184cd3e77003301a759de9d Mon Sep 17 00:00:00 2001 From: nostrbuddha Date: Wed, 18 Dec 2024 21:12:00 +0530 Subject: [PATCH 8/8] - strings accessible in all presenters that derive from BasePresenter --- .../network/bisq/mobile/presentation/BasePresenter.kt | 10 ++++++++++ .../kotlin/network/bisq/mobile/presentation/ui/App.kt | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt index 8b3fab1c..68d7852f 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/BasePresenter.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import network.bisq.mobile.domain.data.BackgroundDispatcher import network.bisq.mobile.domain.data.model.BaseModel +import network.bisq.mobile.i18n.AppStrings import network.bisq.mobile.utils.Logging @@ -225,4 +226,13 @@ abstract class BasePresenter(private val rootPresenter: MainPresenter?): ViewPre } private fun isRoot() = rootPresenter == null + + companion object { + lateinit var strings: AppStrings + } + + fun setStrings(localStrings: AppStrings) { + BasePresenter.strings = localStrings + } + } diff --git a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt index 4313c1b8..3d7cf4f3 100644 --- a/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt +++ b/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/App.kt @@ -3,11 +3,13 @@ package network.bisq.mobile.presentation.ui import androidx.compose.runtime.* import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController +import cafe.adriel.lyricist.LocalStrings import cafe.adriel.lyricist.ProvideStrings import cafe.adriel.lyricist.rememberStrings import org.jetbrains.compose.ui.tooling.preview.Preview import kotlinx.coroutines.flow.StateFlow +import network.bisq.mobile.i18n.AppStrings import network.bisq.mobile.presentation.ViewPresenter import network.bisq.mobile.presentation.ui.components.SwipeBackIOSNavigationHandler import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle @@ -28,6 +30,8 @@ interface AppPresenter : ViewPresenter { fun toggleContentVisibility() fun isIOS(): Boolean + + fun setStrings(strings: AppStrings) } /** @@ -52,6 +56,7 @@ fun App() { BisqTheme(darkTheme = true) { ProvideStrings(lyricist) { + presenter.setStrings(LocalStrings.current) if (isNavControllerSet) { SwipeBackIOSNavigationHandler(rootNavController) { RootNavGraph(rootNavController)