From ad6edd9a058bab260c1fb55ab58bfce268a684c5 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Mon, 14 Aug 2023 16:57:47 +0300 Subject: [PATCH 01/18] V4.8.1 v1.5.1 (#1038) * Revert "Cw 397 chatwoot live support (#1011)" This reverts commit af9b5ff10ce2a6a59afa94e17658c25d65a20c99. * Add Version 4.8.1 configs * Update macos build version [skip ci] --- .github/workflows/pr_test_build.yml | 1 - assets/images/live_support.png | Bin 1776 -> 0 bytes assets/images/more_links.png | Bin 1889 -> 0 bytes assets/images/wallet_guides.png | Bin 1760 -> 0 bytes assets/text/Monerocom_Release_Notes.txt | 10 +- assets/text/Release_Notes.txt | 11 +- cw_core/lib/cake_hive.dart | 4 - cw_core/lib/erc20_token.dart | 3 +- cw_core/lib/hive_type_ids.dart | 13 --- cw_core/lib/node.dart | 3 +- cw_core/lib/unspent_coins_info.dart | 5 +- cw_core/lib/wallet_info.dart | 8 +- cw_core/lib/wallet_type.dart | 4 +- cw_ethereum/lib/ethereum_wallet.dart | 7 +- lib/anonpay/anonpay_invoice_info.dart | 3 +- lib/buy/order.dart | 7 +- lib/core/backup_service.dart | 13 ++- lib/di.dart | 8 -- lib/entities/contact.dart | 9 +- lib/entities/get_encryption_key.dart | 17 +-- lib/entities/template.dart | 3 +- lib/entities/transaction_description.dart | 3 +- lib/exchange/exchange_template.dart | 3 +- lib/exchange/trade.dart | 5 +- lib/main.dart | 70 ++++++------- lib/router.dart | 13 +-- lib/routes.dart | 2 - .../screens/restore/restore_options_page.dart | 2 + .../restore/widgets/restore_button.dart | 20 ++-- .../widgets/settings_cell_with_arrow.dart | 7 +- lib/src/screens/support/support_page.dart | 99 +++++++----------- .../support/widgets/support_tiles.dart | 69 ------------ .../support_chat/support_chat_page.dart | 38 ------- .../support_chat/widgets/chatwoot_widget.dart | 62 ----------- .../support_other_links_page.dart | 58 ---------- lib/view_model/support_view_model.dart | 29 ++--- pubspec_base.yaml | 1 - res/values/strings_ar.arb | 26 ++--- res/values/strings_bg.arb | 8 +- res/values/strings_cs.arb | 8 +- res/values/strings_de.arb | 10 +- res/values/strings_en.arb | 8 +- res/values/strings_es.arb | 8 +- res/values/strings_fr.arb | 8 +- res/values/strings_ha.arb | 8 +- res/values/strings_hi.arb | 8 +- res/values/strings_hr.arb | 8 +- res/values/strings_id.arb | 8 +- res/values/strings_it.arb | 8 +- res/values/strings_ja.arb | 26 ++--- res/values/strings_ko.arb | 26 ++--- res/values/strings_my.arb | 26 ++--- res/values/strings_nl.arb | 8 +- res/values/strings_pl.arb | 8 +- res/values/strings_pt.arb | 8 +- res/values/strings_ru.arb | 27 ++--- res/values/strings_th.arb | 26 ++--- res/values/strings_tr.arb | 8 +- res/values/strings_uk.arb | 8 +- res/values/strings_ur.arb | 26 ++--- res/values/strings_yo.arb | 26 ++--- res/values/strings_zh.arb | 26 ++--- scripts/android/app_env.sh | 8 +- scripts/ios/app_env.sh | 8 +- scripts/macos/app_env.sh | 4 +- tool/append_translation.dart | 66 ------------ tool/update_secrets.dart | 3 +- tool/utils/secret_key.dart | 1 - 68 files changed, 275 insertions(+), 790 deletions(-) delete mode 100644 assets/images/live_support.png delete mode 100644 assets/images/more_links.png delete mode 100644 assets/images/wallet_guides.png delete mode 100644 cw_core/lib/cake_hive.dart delete mode 100644 cw_core/lib/hive_type_ids.dart delete mode 100644 lib/src/screens/support/widgets/support_tiles.dart delete mode 100644 lib/src/screens/support_chat/support_chat_page.dart delete mode 100644 lib/src/screens/support_chat/widgets/chatwoot_widget.dart delete mode 100644 lib/src/screens/support_other_links/support_other_links_page.dart delete mode 100644 tool/append_translation.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 47378eef5..e2b932202 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -127,7 +127,6 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart - echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties diff --git a/assets/images/live_support.png b/assets/images/live_support.png deleted file mode 100644 index 89ad61f458cddcb9ee9c17f751c1d545137d6d95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1776 zcmV<M1`qj(P)<h;3K|Lk000e1NJLTq001HY001Hg1^@s6I!6n_00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH28BsPK~#7FtyoWQ z8$}d<GrQ~5DYVWfs8h};2@(?Gj}l)B5)w^7NR2>>jZj5TaV4(M<j4V9IM5q)52$b` zbwt$$gcRq<0Z2YU%_oQ}A)MIWdA#>#-tM~4G*lU9y|cTsGrxK7_j~U-29B{^U+h<t z#GH@ORuhCuf(VH-Js1tQ;jhWgQiuAFX$Fp=eYK49u^X;ghYJJ%V?+}pFbIqRO_Bme zbS^n)MJcS;Hp|^(1+un?mDA<X6#}p-3zG%tY+?r<fCKP=JP<w;$cJ=q{nh)E*NSsl zc*@2g%9Fz_n!5?Kh@nF^Mquc|Sh9@nG&@kv6?*o?ujl$#js?iXGox9Wbcc=(t=pr6 zCNqSF4q1?{1&qH4Ak+oM8eIGB^}m}s-?4Cn+w}|mg=A<~Vgq${33DZK$Y+R%GkjJz zu?r({A@*Q6n49ZNb)VWIkG4zSl{+8ao@n66P19w|yDPVXMYa@s3&o4{C2mUMWEJ2D z7HQV8LNm^n&@B?t77~Z2={yyaB50?(blojs)HZ|R_N8{NhFc`%34|@OL^Wm$(Y@G{ zRY)A6w-)vH4${F{a~Obub*l-HktV3HsS`FQD}z-KBwAvViwj7q4sJr4t~UapI~-S> zxkJxqlc1#Fo+1#Q>x2JvO}##t?MLnpCKQpZB4{yup_tV0ixKO<iJ>vLVkNfr!S`<; zh$5B<(9rg47H~%h3t=REJh7$mdo%w6(zu8#aT5PdPpc-3^8Q3nH3%5?I9bK;e0=sm zS;oB5mD`K^S3Q`iUJ@VF=y{jl<HHIg&_JdnQyByD-X&Ziv^O%DA!Li20-ub@7cK0} zFM^qMns?71+~C_a0%P2$!DB7kMaF6131rqeE_{Slo8mPiyOSeZS^J*-ApG|)TU5+6 z5%NNe%Y+S}bM<>~`dCrhe6~Y(z67-@_}IeW$-fUXAhf$JdQvetA;2$LK%N1@5INC6 z4%m#DJ4DvVM4#S&qhICzuz#>leCZYE6gN4uBS4nPCA3Jj5Qc?T)}YB;f?oYlbP>u# zXhC`8O|0?44|G$d$b2JK>5z*MTVV1SBVb|J5g-n+o^b*KCvZG0TQ;TfI}Ic@-g3bT zm~({(8b3fSSle3ItH?u(8^WVpg`H`RtjrC%T2L#PZ1+KD!U=y<Kxp3Z)=-eh%F$~G zzV{sPW25p!ogcl(T%ioiuC*xk-Vl7F2xbb%#pl*|VeqbOW=4^%QHuoE1dyD>9(9+W z#Hz_CDyvJau|BRC>B|h(I#>wu3?$>}QOUVY({xoW)=T0c&Dy5PyW{!9^oWRU>UNoZ z!GhjXLRvGUKoHVDMPVXi570{FltAP6XZ#;JaF;)C#kJ3F#?$nqqgYdC8z0}ASaSQN zIlAsCkWuR9F8pv}iHfnBfWlA`<f~URi_qqRD>1i{pbwJt6p)D{M~mk!=%`Bu{YdU# zZkt{Vehj_T)%>zdXWCd#izQW}HREY5SicKya9M!pSFV;&VcBT4S?^arc^_wp0CkO| zCnraew!eNC=V|1k@ZVwe+jj<Xe`9ffm0mxSsVj>sxTheV|K;Qwrgr+dt;w^j7y-6? zF>OW$u4aWx$fm`<FK&FlB*n3$bdYSC)ur+dKQp0r^<zSorT)%KKTXcTW15Yu+sS1{ zUru+Tnbu^rXYi?yT^h<mAPdPzRF&tbkc&{5y90+b8}G*yUWr^GgsOBQBbxWKhV(#A zm8}nCLB>kXOy1#r?mCxl915h>;=&hOYL#5N*&>jq_+UA$Ey8*^De)2DS<vgg{PU^y zp+Mx@xebuqlBItPKMx=e>-tf!#Z<0Y$V*Z!Vna-#&rNtj^FZR5B<GA8Tzsv$0`sf~ zSsjsE!)gT5h1DYd9iH>SE1M_RjszqgjjDcOAIvnr*bo)9%(Gb^vjho&GDY|0E~8!? zEx{359Ppgi&~C-N>hHX^;9{w8oh7#r`h&`}*a_nt)L*+-+C2&o8?euEgtcCAIbp+M z00rL%by&;_4zUQ|w4pqv8+)mR#{6daiQE_iVlmwgzf@7HCat&wSv?p@-8qrR>dw4& z*>*9!aPG%)3;stF*9=DSwQ`gaPw)(d>s<<nZFey0QkbuhDVhXkMT&LFO9ilAt_q-& zrnvsr-Es$>qM4%%;$Qx!%A*-lR;`5Q42Sbbe&3p2<kH;%oM<=NkN+pkQQALJ%Zw-4 S$a=g00000<MNUMnLSTY`lS)zm diff --git a/assets/images/more_links.png b/assets/images/more_links.png deleted file mode 100644 index 97891f3ad5a8a68d7c6be3fe11a7fcaa06ed429d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1889 zcmV-n2cGzeP)<h;3K|Lk000e1NJLTq001Ze001Zm1^@s6jQ+T700009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH2KGrrK~#7F?N~o= z97Pm=Z+7qEiyU$(5s_kl0^1bS4vIvQCKrVGBamW4kwA)^J37Z5ogINt8qgV01c|~8 z6$oF1M2BL30l0huUlb{Ea^88oKQps?7oWqWBpGSFd%H99e((4Gjsaec|M@_8fzfJH z^R-8CsR4ezQ9yI*fMDvt!*K$bDgcgqx$`@@d+PJ^&beP2oA3f-Vt}n{G;<7S`<SPh zh8Hjb&cHA*(q|$(UhuPmBy1Sq-qcfEeDn9l{Ym6Gm~=Q;=f7uUp(7w*PzbgW5&<Hh zK8MTkTafnzGcKbJOgJV2c%IoqpcVsz00JEfrT|WUGiFB$3L|K_XZ*z97XN;m&P*b6 zB7k{*zyO&sWYQRdz(8iu05br6BcLLqK?#!844A(U@ZrKFGA9Cvn9n#BsBEBKiNO*C zg2!lfaRUr@)6F#}5DEDtlc7lL2oPb1eb7uOKr;nH7yv0?WgG&NF!>m}=Dq8*{=w&d z@8heq9^YjU!ruIixiS{zF7M>CDxfUdUCpniCR5I56!+V{_;~e?i;wpHyzpp!B7m(g zXqAPw`D(Jc+MiuF$BurLsc;Jd@jc-(21I6z#Yjdd85OXUxk7c^KL2=zzun~hnhd%9 z*E@%Ud<Nj<t2D>j-c)B-!NaLi!+@gMlqu9m72)QI7}<&u9Q;s$a#|V^t}FDS_Puit z7oQ8z=g^KhEP{#OG7rh$P|ZgQrplHp1(Sg@C4!kTs|ur-D=iJ>kgXmGP)ZoDS~Be= zQZ=s)QE1>|BDS0tnFwr!^kSw(jcf*s;rod2=+mkk(%ikpz2;beMFDe(Jur6Uc`7m} zVeBd7J;DTpf*E5l=*Ae5x8@;vt;%GTATc6Jrg_e(X`GrH3y`PG2X-_QTQWv^hQVM~ z7lK1KR|YT&t@vN*k20qSK>~>g!yki*wVxjg5WJraFVUIq%FwV97PV1(3yWCROlT%% z4`PiWO3Ku$44T<V^C`uEDQ3q4bm*EGf+8}2LzA;;TB^E1s?A{yNF`C`%)Hgo7l*hF zdJ`4vw)(1fC&vN=b7o8+M>fsaNzK0uWH4`<H*!&Cxvxy_Nr5O_6FFHfRe?BKZbp5u zj8O9%Emg3eASR!35a*UmmjPnmqhD!q$B<KL@IZHRMKk&yl!3;T<_LgMkV}=o1bQg6 z1IcQGow8~`NG}#fym_D1-(UqgJf~;hvFvQTbwB%A(UZLjpEWJP8;dGSeDWv;1xlG_ zLaLDDN)}n2Z|ge@pj%cFGq-%I59+f^Ki5~@-)bz^9G&HtKbV3gtE~0i)7?`$Dwyb! zS`9-flv(VP{wM~^>OrXlS;EE}?IqF#iU)&b_R~#Xc-MLCc!y`(ck0W_TiB2LT-a*# z_zbdCJMat4PKTN5@^xz;2AAU;-nxacRWo<d$R90jL+w_^WLuwSZXKdjHfcKNSNYw_ z?M|b|_vMj&V7*1n6Scv*M5ZhJ+A@QD>(}X>!{$o&B1Zt3TUI5|K*~mH{}4ce0<A?z zizo&To232am4hZc8LWMEM?ofFdHvu<27@+vIGOR1+_~0I?>^b^-fw=iRnC<TCPTl@ zf?8Ez`i#~H0}U%P1oy*hMTb+vm7FKmID&I_?3(zX+!<(1qLH=E33lp4efG_n8sQB8 zhMeEm^bVBs+M2BqMs{o7_jz5jPB_Pmpw9Ku{pdVi$BlySt9x(0ad&$8PzD)oKjpbZ zdn*31`;h3>pwS#CK5AWcNZ^DRtYAj~nv*y&w<%2usg}#|mIh7W{VJxBQdjiQjzW|U zJYe-V)m<phAhDWMgkhNvOC>8=A?zL^J7$AQrQv2`Z!Ey<SZ!Ov-XT>4VHw#`Sa^oe z#e_<bqCbL92PLSmX6|NdQW*^ON@lxacPzjkzs6mj+OIZ}21ZYsrM6^8OfyNU7-(ri z`$MXlF_pA3e^yzK%80z)>)jLGu>h4t@V8QDQZ0MtUKVGu<qFNJi)<!PIGR3!5?HA~ zW!?=@%&vspQ9RGK{7>@@-msrqAlW3;(NLSqM$}Gnk!?MKR!o_gcA=WYo)ENY2>%iZ zJ}ff#;py6Q0d_jbDFIfL5eqzZYTiKGb_*P&()6+F@N;Zfp$arHr@FZ4f3d-Zs06Of zc2D)53sA=G@AD3WSrLDXQR~XSj?82*oQj~*_E+2k!ilep<Y01BN?3ispFcg_o!&SM z%h-eaH{WHqhz1LwwG?|mqbUO*b=CmGrnM#`oB$DEB(JI^B++yCGhi9B-RaIa90>n$ z-27y)=%|?Imi<hQT;8+-fK&vnE^?fVziZ(+<JLreYo+0Lc|i|&-9H%>y9>V!N9(Kc b(vE)tR=vS9SH@o300000NkvXXu0mjfr1x?h diff --git a/assets/images/wallet_guides.png b/assets/images/wallet_guides.png deleted file mode 100644 index 3f2d9f27059e0ee31cdc7016cbd0ea5caeb93f53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1760 zcmV<61|Ru}P)<h;3K|Lk000e1NJLTq001HY001Hg1^@s6I!6n_00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH26ah9K~#7FomkCo zTU8LAIlhhq0>ycPI=n#LH)xTNDj_PPN=R&I!iuhF5fV$MYZg^^-NhhOu_$W0V1-1o zf@M;PeVr$$D^VqG>@&>oxyPu8rYExRPwqK0=bLZ7nQMf9jnOUYzyA_0b|_zJ05%$e zL6`4$h@iU!(DTg4ob|j*-Q8~=;PKrN^>07M8NB6aY6qG*j5~AMCWH+{KqLTU2jrOK z9Qccn^dA2K@sj|%GJkFTbael-`IuhiD>om%Glg@GBwts*q5-^uLtgn78{J@oC>HF) zcf`1yi+6mH%nN;{jHNnzq1U9tz3cN4oO7rn-42X-)q$?gyHpE`hN8gN)S}}P!_k$6 z^l?TO;L*>cS6{<9Mv{=Qm2Jq1vmrsPAv8=Nwl9Yy7`=8^f}Dg-o~OINTss-V8;-PC zEQYdsf!h}MF!%?;Xf}3;k=CKO@*#-%Iywh&{N&pFjhsnHX_zX5Ne<PHvEqV;2wJ2h zlIyFUprc8_Azp9%>nA6B@V|~A^Z{b`6i7HHpr9j&rJ$}Eq@)IIbRa@Qfg~7SOm2eh z-#$J)+`mly|8#^W41yEM_laeFM<bjvuAl|TF3<8}OE*F=m2}qskt4_7$ulkyT}<zu z9PVFzK6pJM@@OCe<V00)WygiM<{JfSm=p!1j(bhmnI%;lr-#m^at_KJ9Q2^K|L1F* zNd}+nBA_(w2=dC8!CgB^nj1VYElC&co^_{&AX$i<E7&@v^Y}C9P;dY6qrZo%q2YAE zDr>OHnpR8He92gkmm1~Sy5Nq=I~^nsTcltKlWa~mC^4V`AAkR=az+qQ!74=6IP0es zua?B7ArW`J>aYgwjf{k}q#gb~#@Ikv6HKENkrMh%%(x%UG>ECx4uxN{(qmNWN(fzf zPBKAvE=oFII}@$Ay<;_I>*46-h#7W~i8R0r#;B#92=W|+EN61Ug_NWm9O3nw%L$Y2 zizX9FHEsC$h7C6CLYI*#*DPpV_JgajUU&JL&ynx(k>vjF&cogvc+1hS=gPvu2`I9T zwbUoeM!@VaD=_3dQ256`eR?|LP~GE=9(;bz3f%C@h*T3bl+})I1TD2yT2bIuf_pes z*d&7xhrF#lLG8)46Yf=DDv0vY`WZf713Pb)B*yuFJU_#eCMid92$}AZ7c?}4;gGRP zTXdqDG?>Wg)Kpb$%?{-iXNM6<bw_t=HA~Ue9*3`3l{Zq#B|V+ts*F|cx7m`wQ?t~f zy7oZTCS(k84EvrvP-~6Zv85U)23^!7R9Um-1^;UnPFm_@(6H#vD7d5ZsjbR=Ua23_ zj>YE?#!}ZXLCC+PuX=A2QV<nkdYaEZygxaA%O`{RF=0zLY9vI+Fq|RdVvDLJv+XLJ z(5>N%w{=1Wlkuoj?#Mi8yz0WKK16XLLBvKWdP2~ghu?g;c+|}}6LxF2o&`ed+#?g> zzI64G6<uAHMr@eD_BFwCpK=JJRcLe4IAVo5yLTi!Go8q+cx3u7lL)ONLtj8A$TUL` zsy?JL5(SW2xffS*v<aqF$rLxE79wmLAg@;|nGuriac^5jYahMZRt2*~xlGY(BYCNc z(fXLOl2u^6NhKR3W1dC|gU1_+zNpH|P0kV;mULfn+`GC$P}LS)sxGABT*HDjL(lMp z0XshXe$x2>-f%p)e!9=|E{nC~8KLV{-J0o-DRXK&K64D=IPtEg)`MmYz}eePIL{!Q zVHhq=vm0-lB=BC>&~4ROo|rY%q$A`KtyQe;IXAw$v3SN=!L>pwuhs}r;We$yQKdCY z`drqBt!fsIwE6(iK0pxH5mT;kJ)onea{^Cs4W6?DeXBDrY}`d@V{Hp-TZjdL=vNHl z$PDm`U6%z~aW2r(TBJ~LcESlRj?!epux9u{v&Tz1)I^F`g2*DzjzmQob)#}q)zgf4 z*GyQ7AVm?e_2M0fzb9J<n=^H6u}F9L&NNasIgs(HS-qdwf>1#Vt&A5Q7>4Z|fOAvz zg4}C$5T@&Aom~h{2`aEmS9tP|7|@$Awa!5M0$7}-h(AP60@i7oGfq_Up2b5dmwCqB zz`Z%1UE2KPonvTu)s9=+@;1L1_Lj?GmwD4r=Yo{zh6yc4m3EG+{#XMd?EpRSA8(`q zk{@ugm31NWn&0Qneb(bfiD>zBeevGW*1_tJI{yH@j<TLYn(83{0000<MNUMnLSTa0 Cf=4s} diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 403bb9f08..62f649704 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,8 +1,2 @@ -Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing -Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings -Support Monero node proxy -UI improvements when sending to Address Book entry -Allow renaming Monero account names -Send templates now support multiple recipients (try using to make Monero change) -Onramper improvements -Scan node QR codes (for Umbrel) \ No newline at end of file +Bug fixes +Fiat Onramp improvements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index cedec7b7f..62f649704 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,9 +1,2 @@ -Ethereum! Store ETH and ERC-20 tokens -Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing -Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings -Support Monero node proxy -UI improvements when sending to Address Book entry -Allow renaming Monero/Haven account names -Send templates now support multiple recipients (try using to make Monero change) -Onramper improvements -Scan node QR codes (for Umbrel) \ No newline at end of file +Bug fixes +Fiat Onramp improvements \ No newline at end of file diff --git a/cw_core/lib/cake_hive.dart b/cw_core/lib/cake_hive.dart deleted file mode 100644 index aadf6bf9a..000000000 --- a/cw_core/lib/cake_hive.dart +++ /dev/null @@ -1,4 +0,0 @@ -import 'package:hive/hive.dart'; -import 'package:hive/src/hive_impl.dart'; - -final HiveInterface CakeHive = HiveImpl(); diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index fd27aaba6..db5b6db5b 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -1,5 +1,4 @@ import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'erc20_token.g.dart'; @@ -54,7 +53,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { iconPath: icon, ); - static const typeId = ERC20_TOKEN_TYPE_ID; + static const typeId = 12; static const boxName = 'Erc20Tokens'; @override diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart deleted file mode 100644 index 0961182bc..000000000 --- a/cw_core/lib/hive_type_ids.dart +++ /dev/null @@ -1,13 +0,0 @@ -const CONTACT_TYPE_ID = 0; -const NODE_TYPE_ID = 1; -const TRANSACTION_TYPE_ID = 2; -const TRADE_TYPE_ID = 3; -const WALLET_INFO_TYPE_ID = 4; -const WALLET_TYPE_TYPE_ID = 5; -const TEMPLATE_TYPE_ID = 6; -const EXCHANGE_TEMPLATE_TYPE_ID = 7; -const ORDER_TYPE_ID = 8; -const UNSPENT_COINS_INFO_TYPE_ID = 9; -const ANONPAY_INVOICE_INFO_TYPE_ID = 10; - -const ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 59a1450f6..3fa45b44c 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -3,7 +3,6 @@ import 'package:cw_core/keyable.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:hive/hive.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; @@ -38,7 +37,7 @@ class Node extends HiveObject with Keyable { trusted = map['trusted'] as bool? ?? false, socksProxyAddress = map['socksProxyPort'] as String?; - static const typeId = NODE_TYPE_ID; + static const typeId = 1; static const boxName = 'Nodes'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 33be2eb2c..75c13f2cd 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'unspent_coins_info.g.dart'; @@ -15,7 +14,7 @@ class UnspentCoinsInfo extends HiveObject { required this.vout, required this.value}); - static const typeId = UNSPENT_COINS_INFO_TYPE_ID; + static const typeId = 9; static const boxName = 'Unspent'; static const boxKey = 'unspentBoxKey'; @@ -46,4 +45,4 @@ class UnspentCoinsInfo extends HiveObject { String get note => noteRaw ?? ''; set note(String value) => noteRaw = value; -} +} \ No newline at end of file diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 6b3fa9e98..a25702cf7 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,7 +1,7 @@ -import 'dart:async'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'dart:async'; part 'wallet_info.g.dart'; @@ -30,7 +30,7 @@ class WalletInfo extends HiveObject { yatEid, yatLastUsedAddressRaw, showIntroCakePayCard); } - static const typeId = WALLET_INFO_TYPE_ID; + static const typeId = 4; static const boxName = 'WalletInfo'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 62c2ad410..a65839041 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -1,5 +1,4 @@ import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'wallet_type.g.dart'; @@ -11,8 +10,9 @@ const walletTypes = [ WalletType.haven, WalletType.ethereum, ]; +const walletTypeTypeId = 5; -@HiveType(typeId: WALLET_TYPE_TYPE_ID) +@HiveType(typeId: walletTypeTypeId) enum WalletType { @HiveField(0) monero, diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 404b78ca2..d94e4ec95 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'dart:math'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pending_transaction.dart'; @@ -59,8 +58,8 @@ abstract class EthereumWalletBase this.walletInfo = walletInfo; transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password); - if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { - CakeHive.registerAdapter(Erc20TokenAdapter()); + if (!Hive.isAdapterRegistered(Erc20Token.typeId)) { + Hive.registerAdapter(Erc20TokenAdapter()); } _sharedPrefs.complete(SharedPreferences.getInstance()); @@ -96,7 +95,7 @@ abstract class EthereumWalletBase Completer<SharedPreferences> _sharedPrefs = Completer(); Future<void> init() async { - erc20TokensBox = await CakeHive.openBox<Erc20Token>(Erc20Token.boxName); + erc20TokensBox = await Hive.openBox<Erc20Token>(Erc20Token.boxName); await walletAddresses.init(); await transactionHistory.init(); _privateKey = await getPrivateKey(_mnemonic, _password); diff --git a/lib/anonpay/anonpay_invoice_info.dart b/lib/anonpay/anonpay_invoice_info.dart index bd6776d00..89613224e 100644 --- a/lib/anonpay/anonpay_invoice_info.dart +++ b/lib/anonpay/anonpay_invoice_info.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/keyable.dart'; import 'package:hive/hive.dart'; @@ -36,7 +35,7 @@ class AnonpayInvoiceInfo extends HiveObject with Keyable implements AnonpayInfoB @HiveField(13) final String provider; - static const typeId = ANONPAY_INVOICE_INFO_TYPE_ID; + static const typeId = 10; static const boxName = 'AnonpayInvoiceInfo'; AnonpayInvoiceInfo({ diff --git a/lib/buy/order.dart b/lib/buy/order.dart index 5a677d291..387fbcd34 100644 --- a/lib/buy/order.dart +++ b/lib/buy/order.dart @@ -1,8 +1,7 @@ import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:hive/hive.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:hive/hive.dart'; part 'order.g.dart'; @@ -27,7 +26,7 @@ class Order extends HiveObject { } } - static const typeId = ORDER_TYPE_ID; + static const typeId = 8; static const boxName = 'Orders'; static const boxKey = 'ordersBoxKey'; @@ -67,4 +66,4 @@ class Order extends HiveObject { BuyProviderDescription.deserialize(raw: providerRaw); String amountFormatted() => formatAmount(amount); -} +} \ No newline at end of file diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 6476891ed..2e27d83c9 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; @@ -9,7 +10,6 @@ import 'package:path_provider/path_provider.dart'; import 'package:cryptography/cryptography.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:archive/archive_io.dart'; -import 'package:cw_core/cake_hive.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; @@ -17,7 +17,6 @@ import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/wallet_types.g.dart'; - import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { @@ -171,14 +170,14 @@ class BackupService { Future<Box<WalletInfo>> _reloadHiveWalletInfoBox() async { final appDir = await getApplicationDocumentsDirectory(); - await CakeHive.close(); - CakeHive.init(appDir.path); + await Hive.close(); + Hive.init(appDir.path); - if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { - CakeHive.registerAdapter(WalletInfoAdapter()); + if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { + Hive.registerAdapter(WalletInfoAdapter()); } - return await CakeHive.openBox<WalletInfo>(WalletInfo.boxName); + return await Hive.openBox<WalletInfo>(WalletInfo.boxName); } Future<void> _importPreferencesDump() async { diff --git a/lib/di.dart b/lib/di.dart index 2a54c85a3..b02742e64 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -36,8 +36,6 @@ import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; -import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; -import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -871,12 +869,6 @@ Future setup({ getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>())); - getIt.registerFactory(() => - SupportChatPage( - getIt.get<SupportViewModel>(), secureStorage: getIt.get<FlutterSecureStorage>())); - - getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>())); - getIt.registerFactory(() { final wallet = getIt.get<AppStore>().wallet; diff --git a/lib/entities/contact.dart b/lib/entities/contact.dart index cd4fa55a2..e111429ca 100644 --- a/lib/entities/contact.dart +++ b/lib/entities/contact.dart @@ -1,7 +1,8 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:cw_core/keyable.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cw_core/keyable.dart'; part 'contact.g.dart'; @@ -13,7 +14,7 @@ class Contact extends HiveObject with Keyable { } } - static const typeId = CONTACT_TYPE_ID; + static const typeId = 0; static const boxName = 'Contacts'; @HiveField(0, defaultValue: '') diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index e67380bb8..5fc4983d7 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,18 +1,23 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:cw_core/cake_hive.dart'; +import 'package:hive/hive.dart'; Future<List<int>> getEncryptionKey( {required String forKey, required FlutterSecureStorage secureStorage}) async { - final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); + final stringifiedKey = + await secureStorage.read(key: 'transactionDescriptionsBoxKey'); List<int> key; if (stringifiedKey == null) { - key = CakeHive.generateSecureKey(); + key = Hive.generateSecureKey(); final keyStringified = key.join(','); - await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified); + await secureStorage.write( + key: 'transactionDescriptionsBoxKey', value: keyStringified); } else { - key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); + key = stringifiedKey + .split(',') + .map((i) => int.parse(i)) + .toList(); } return key; -} +} \ No newline at end of file diff --git a/lib/entities/template.dart b/lib/entities/template.dart index 7cdd2c74a..6955136e0 100644 --- a/lib/entities/template.dart +++ b/lib/entities/template.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'template.g.dart'; @@ -15,7 +14,7 @@ class Template extends HiveObject { required this.amountFiatRaw, this.additionalRecipientsRaw}); - static const typeId = TEMPLATE_TYPE_ID; + static const typeId = 6; static const boxName = 'Template'; @HiveField(0) diff --git a/lib/entities/transaction_description.dart b/lib/entities/transaction_description.dart index 088f9c480..86d6b043a 100644 --- a/lib/entities/transaction_description.dart +++ b/lib/entities/transaction_description.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'transaction_description.g.dart'; @@ -7,7 +6,7 @@ part 'transaction_description.g.dart'; class TransactionDescription extends HiveObject { TransactionDescription({required this.id, this.recipientAddress, this.transactionNote}); - static const typeId = TRANSACTION_TYPE_ID; + static const typeId = 2; static const boxName = 'TransactionDescriptions'; static const boxKey = 'transactionDescriptionsBoxKey'; diff --git a/lib/exchange/exchange_template.dart b/lib/exchange/exchange_template.dart index 2182efd8c..dcfd8d8e8 100644 --- a/lib/exchange/exchange_template.dart +++ b/lib/exchange/exchange_template.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'exchange_template.g.dart'; @@ -15,7 +14,7 @@ class ExchangeTemplate extends HiveObject { required this.depositCurrencyTitleRaw, required this.receiveCurrencyTitleRaw}); - static const typeId = EXCHANGE_TEMPLATE_TYPE_ID; + static const typeId = 7; static const boxName = 'ExchangeTemplate'; @HiveField(0) diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index db8c8fb3b..70dfa5713 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -1,9 +1,8 @@ +import 'package:hive/hive.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:hive/hive.dart'; part 'trade.g.dart'; @@ -42,7 +41,7 @@ class Trade extends HiveObject { } } - static const typeId = TRADE_TYPE_ID; + static const typeId = 3; static const boxName = 'Trades'; static const boxKey = 'tradesBoxKey'; diff --git a/lib/main.dart b/lib/main.dart index 62a0bfc9c..e0cf58e62 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,7 +7,6 @@ import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -39,7 +38,6 @@ import 'package:uni_links/uni_links.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/cake_hive.dart'; final navigatorKey = GlobalKey<NavigatorState>(); final rootKey = GlobalKey<RootState>(); @@ -59,7 +57,7 @@ Future<void> main() async { return true; }; - await CakeHive.close(); + await Hive.close(); await initializeAppConfigs(); @@ -71,50 +69,50 @@ Future<void> main() async { Future<void> initializeAppConfigs() async { final appDir = await getApplicationDocumentsDirectory(); - CakeHive.init(appDir.path); + Hive.init(appDir.path); - if (!CakeHive.isAdapterRegistered(Contact.typeId)) { - CakeHive.registerAdapter(ContactAdapter()); + if (!Hive.isAdapterRegistered(Contact.typeId)) { + Hive.registerAdapter(ContactAdapter()); } - if (!CakeHive.isAdapterRegistered(Node.typeId)) { - CakeHive.registerAdapter(NodeAdapter()); + if (!Hive.isAdapterRegistered(Node.typeId)) { + Hive.registerAdapter(NodeAdapter()); } - if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) { - CakeHive.registerAdapter(TransactionDescriptionAdapter()); + if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) { + Hive.registerAdapter(TransactionDescriptionAdapter()); } - if (!CakeHive.isAdapterRegistered(Trade.typeId)) { - CakeHive.registerAdapter(TradeAdapter()); + if (!Hive.isAdapterRegistered(Trade.typeId)) { + Hive.registerAdapter(TradeAdapter()); } - if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { - CakeHive.registerAdapter(WalletInfoAdapter()); + if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { + Hive.registerAdapter(WalletInfoAdapter()); } - if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { - CakeHive.registerAdapter(WalletTypeAdapter()); + if (!Hive.isAdapterRegistered(walletTypeTypeId)) { + Hive.registerAdapter(WalletTypeAdapter()); } - if (!CakeHive.isAdapterRegistered(Template.typeId)) { - CakeHive.registerAdapter(TemplateAdapter()); + if (!Hive.isAdapterRegistered(Template.typeId)) { + Hive.registerAdapter(TemplateAdapter()); } - if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) { - CakeHive.registerAdapter(ExchangeTemplateAdapter()); + if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) { + Hive.registerAdapter(ExchangeTemplateAdapter()); } - if (!CakeHive.isAdapterRegistered(Order.typeId)) { - CakeHive.registerAdapter(OrderAdapter()); + if (!Hive.isAdapterRegistered(Order.typeId)) { + Hive.registerAdapter(OrderAdapter()); } - if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); + if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + Hive.registerAdapter(UnspentCoinsInfoAdapter()); } - if (!CakeHive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { - CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); + if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { + Hive.registerAdapter(AnonpayInvoiceInfoAdapter()); } final secureStorage = FlutterSecureStorage(); @@ -122,21 +120,21 @@ Future<void> initializeAppConfigs() async { await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey); - final contacts = await CakeHive.openBox<Contact>(Contact.boxName); - final nodes = await CakeHive.openBox<Node>(Node.boxName); - final transactionDescriptions = await CakeHive.openBox<TransactionDescription>( + final contacts = await Hive.openBox<Contact>(Contact.boxName); + final nodes = await Hive.openBox<Node>(Node.boxName); + final transactionDescriptions = await Hive.openBox<TransactionDescription>( TransactionDescription.boxName, encryptionKey: transactionDescriptionsBoxKey); - final trades = await CakeHive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey); - final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey); - final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName); - final templates = await CakeHive.openBox<Template>(Template.boxName); - final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName); - final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName); + final trades = await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey); + final orders = await Hive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey); + final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName); + final templates = await Hive.openBox<Template>(Template.boxName); + final exchangeTemplates = await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName); + final anonpayInvoiceInfo = await Hive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName); Box<UnspentCoinsInfo>? unspentCoinsInfoSource; if (!isMoneroOnly) { - unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); + unspentCoinsInfoSource = await Hive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); } await initialSetup( diff --git a/lib/router.dart b/lib/router.dart index 7d63ad1ea..031a1075b 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -41,8 +41,6 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; -import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; -import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/utils/payment_request.dart'; @@ -50,6 +48,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -442,17 +441,9 @@ Route<dynamic> createRoute(RouteSettings settings) { builder: (_) => getIt.get<RestoreFromBackupPage>()); case Routes.support: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<SupportPage>()); - - case Routes.supportLiveChat: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<SupportChatPage>()); - - case Routes.supportOtherLinks: return CupertinoPageRoute<void>( fullscreenDialog: true, - builder: (_) => getIt.get<SupportOtherLinksPage>()); + builder: (_) => getIt.get<SupportPage>()); case Routes.unspentCoinsList: return MaterialPageRoute<void>( diff --git a/lib/routes.dart b/lib/routes.dart index 62c303ce8..7187a7263 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -48,8 +48,6 @@ class Routes { static const editBackupPassword = '/edit_backup_passowrd'; static const restoreFromBackup = '/restore_from_backup'; static const support = '/support'; - static const supportLiveChat = '/support/live_chat'; - static const supportOtherLinks = '/support/other'; static const orderDetails = '/order_details'; static const preOrder = '/pre_order'; static const buyWebView = '/buy_web_view'; diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 74e33b87a..93a44c752 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -2,10 +2,12 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/language_list.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:flutter/cupertino.dart'; diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index 817ebbc72..aa44947b5 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -1,11 +1,12 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class RestoreButton extends StatelessWidget { - const RestoreButton( - {required this.onPressed, - required this.image, - required this.title, - required this.description}); + const RestoreButton({ + required this.onPressed, + required this.image, + required this.title, + required this.description}); final VoidCallback onPressed; final Image image; @@ -23,7 +24,10 @@ class RestoreButton extends StatelessWidget { alignment: Alignment.topLeft, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).accentTextTheme.bodySmall!.color!, + color: Theme.of(context) + .accentTextTheme! + .bodySmall! + .color!, ), child: Row( mainAxisSize: MainAxisSize.max, @@ -45,7 +49,7 @@ class RestoreButton extends StatelessWidget { fontSize: 16, fontWeight: FontWeight.w500, color: Theme.of(context) - .primaryTextTheme + .primaryTextTheme! .titleLarge! .color!), ), @@ -57,7 +61,7 @@ class RestoreButton extends StatelessWidget { fontSize: 14, fontWeight: FontWeight.normal, color: Theme.of(context) - .primaryTextTheme + .primaryTextTheme! .labelSmall! .color!), ), diff --git a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart index 163d59f4f..1d97db08c 100644 --- a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart +++ b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart @@ -6,6 +6,7 @@ class SettingsCellWithArrow extends StandardListRow { : super(title: title, isSelected: false, onTap: handler); @override - Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png', - color: Theme.of(context).primaryTextTheme.labelSmall!.color!); -} + Widget buildTrailing(BuildContext context) => + Image.asset('assets/images/select_arrow.png', + color: Theme.of(context).primaryTextTheme!.labelSmall!.color!); +} \ No newline at end of file diff --git a/lib/src/screens/support/support_page.dart b/lib/src/screens/support/support_page.dart index 883677832..b385530fb 100644 --- a/lib/src/screens/support/support_page.dart +++ b/lib/src/screens/support/support_page.dart @@ -1,78 +1,55 @@ -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/support/widgets/support_tiles.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/utils/device_info.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/view_model/settings/link_list_item.dart'; +import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; import 'package:cake_wallet/view_model/support_view_model.dart'; import 'package:flutter/material.dart'; -import 'package:url_launcher/url_launcher.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/generated/i18n.dart'; class SupportPage extends BasePage { SupportPage(this.supportViewModel); final SupportViewModel supportViewModel; - final imageLiveSupport = Image.asset('assets/images/live_support.png'); - final imageWalletGuides = Image.asset('assets/images/wallet_guides.png'); - final imageMoreLinks = Image.asset('assets/images/more_links.png'); - @override String get title => S.current.settings_support; - @override - AppBarStyle get appBarStyle => AppBarStyle.regular; - @override Widget body(BuildContext context) { - return Container( - child: Center( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 330), - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 24), - child: SupportTile( - image: imageLiveSupport, - title: S.of(context).support_title_live_chat, - description: S.of(context).support_description_live_chat, - onPressed: () { - if (DeviceInfo.instance.isDesktop) { - _launchUrl(supportViewModel.fetchUrl()); - } else { - Navigator.pushNamed(context, Routes.supportLiveChat); - } - }, - ), - ), - Padding( - padding: EdgeInsets.only(top: 24), - child: SupportTile( - image: imageWalletGuides, - title: S.of(context).support_title_guides, - description: S.of(context).support_description_guides, - onPressed: () => _launchUrl(supportViewModel.guidesUrl), - ), - ), - Padding( - padding: EdgeInsets.only(top: 24), - child: SupportTile( - image: imageMoreLinks, - title: S.of(context).support_title_other_links, - description: S.of(context).support_description_other_links, - onPressed: () => Navigator.pushNamed(context, Routes.supportOtherLinks), - ), - ), - ], - ), - ), + final iconColor = Theme.of(context) + .accentTextTheme! + .displayLarge! + .backgroundColor!; + // FIX-ME: Added `context` it was not used here before, maby bug ? + return Center( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 500), + child: SectionStandardList( + context: context, + sectionCount: 1, + itemCounter: (int _) => supportViewModel.items.length, + itemBuilder: (_, __, index) { + final item = supportViewModel.items[index]; + + if (item is RegularListItem) { + return SettingsCellWithArrow(title: item.title, handler: item.handler); + } + + if (item is LinkListItem) { + return SettingsLinkProviderCell( + title: item.title, + icon: item.icon, + iconColor: item.hasIconColor ? iconColor : null, + link: item.link, + linkTitle: item.linkTitle); + } + + return Container(); + }), ), ); } - - void _launchUrl(String url) async { - try { - await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); - } catch (e) {} - } } diff --git a/lib/src/screens/support/widgets/support_tiles.dart b/lib/src/screens/support/widgets/support_tiles.dart deleted file mode 100644 index 9d7c65719..000000000 --- a/lib/src/screens/support/widgets/support_tiles.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:flutter/material.dart'; - -class SupportTile extends StatelessWidget { - const SupportTile( - {required this.onPressed, - required this.image, - required this.title, - required this.description}); - - final VoidCallback onPressed; - final Image image; - final String title; - final String description; - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onPressed, - child: Container( - width: double.infinity, - padding: EdgeInsets.all(24), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).accentTextTheme.bodySmall!.color!, - ), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[ - image, - Expanded( - child: Padding( - padding: EdgeInsets.only(left: 16), - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[ - Text( - title, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, - ), - ), - Padding( - padding: EdgeInsets.only(top: 5), - child: Text( - description, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.labelSmall!.color!, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/src/screens/support_chat/support_chat_page.dart b/lib/src/screens/support_chat/support_chat_page.dart deleted file mode 100644 index e84965b23..000000000 --- a/lib/src/screens/support_chat/support_chat_page.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart'; -import 'package:cake_wallet/view_model/support_view_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; - - -class SupportChatPage extends BasePage { - SupportChatPage(this.supportViewModel, {required this.secureStorage}); - - final SupportViewModel supportViewModel; - final FlutterSecureStorage secureStorage; - - @override - String get title => S.current.settings_support; - - @override - AppBarStyle get appBarStyle => AppBarStyle.regular; - - @override - Widget body(BuildContext context) => FutureBuilder<String>( - future: getCookie(), - builder: (BuildContext context, AsyncSnapshot<String> snapshot) { - print(snapshot.data); - if (snapshot.hasData) - return ChatwootWidget( - secureStorage, - supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!) - ); - return Container(); - }, - ); - - Future<String> getCookie() async { - return await secureStorage.read(key: COOKIE_KEY) ?? ""; - } -} diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart deleted file mode 100644 index d9a5f9bb8..000000000 --- a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; - -const COOKIE_KEY = 'chatwootCookie'; - -class ChatwootWidget extends StatefulWidget { - ChatwootWidget(this.secureStorage, {required this.supportUrl}); - - final FlutterSecureStorage secureStorage; - final String supportUrl; - - @override - ChatwootWidgetState createState() => ChatwootWidgetState(); -} - -class ChatwootWidgetState extends State<ChatwootWidget> { - final GlobalKey _webViewkey = GlobalKey(); - - @override - Widget build(BuildContext context) => InAppWebView( - key: _webViewkey, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(transparentBackground: true), - ), - initialUrlRequest: URLRequest(url: Uri.tryParse(widget.supportUrl)), - onWebViewCreated: (InAppWebViewController controller) { - controller.addWebMessageListener( - WebMessageListener( - jsObjectName: 'ReactNativeWebView', - onPostMessage: (String? message, Uri? sourceOrigin, bool isMainFrame, - JavaScriptReplyProxy replyProxy) { - final shortenedMessage = message?.substring(16); - if (shortenedMessage != null && isJsonString(shortenedMessage)) { - final parsedMessage = jsonDecode(shortenedMessage); - final eventType = parsedMessage["event"]; - if (eventType == 'loaded') { - final authToken = parsedMessage["config"]["authToken"]; - print(authToken); - storeCookie(authToken as String); - } - } - }, - ), - ); - }, - ); - - bool isJsonString(String str) { - try { - jsonDecode(str); - } catch (e) { - return false; - } - return true; - } - - Future<void> storeCookie(String value) async => - await widget.secureStorage.write(key: COOKIE_KEY, value: value); -} diff --git a/lib/src/screens/support_other_links/support_other_links_page.dart b/lib/src/screens/support_other_links/support_other_links_page.dart deleted file mode 100644 index e904e7fab..000000000 --- a/lib/src/screens/support_other_links/support_other_links_page.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/view_model/settings/link_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; -import 'package:cake_wallet/view_model/support_view_model.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -class SupportOtherLinksPage extends BasePage { - SupportOtherLinksPage(this.supportViewModel); - - final SupportViewModel supportViewModel; - - @override - String get title => S.current.settings_support; - - @override - AppBarStyle get appBarStyle => AppBarStyle.transparent; - - @override - Widget body(BuildContext context) { - final iconColor = - Theme.of(context).accentTextTheme.displayLarge!.backgroundColor!; - - return Container( - child: Center( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), - child: SectionStandardList( - context: context, - sectionCount: 1, - itemCounter: (int _) => supportViewModel.items.length, - itemBuilder: (_, __, index) { - final item = supportViewModel.items[index]; - - if (item is RegularListItem) { - return SettingsCellWithArrow( - title: item.title, handler: item.handler); - } - - if (item is LinkListItem) { - return SettingsLinkProviderCell( - title: item.title, - icon: item.icon, - iconColor: item.hasIconColor ? iconColor : null, - link: item.link, - linkTitle: item.linkTitle); - } - - return Container(); - }), - ), - ), - ); - } -} diff --git a/lib/view_model/support_view_model.dart b/lib/view_model/support_view_model.dart index ec84a5582..15c25968f 100644 --- a/lib/view_model/support_view_model.dart +++ b/lib/view_model/support_view_model.dart @@ -1,9 +1,12 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/settings/link_list_item.dart'; +import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; import 'package:cake_wallet/view_model/settings/settings_list_item.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:url_launcher/url_launcher.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; part 'support_view_model.g.dart'; @@ -12,6 +15,14 @@ class SupportViewModel = SupportViewModelBase with _$SupportViewModel; abstract class SupportViewModelBase with Store { SupportViewModelBase() : items = [ + RegularListItem( + title: S.current.faq, + handler: (BuildContext context) async { + try { + await launch(url); + } catch (e) {} + }, + ), LinkListItem( title: 'Email', linkTitle: 'support@cakewallet.com', @@ -74,17 +85,7 @@ abstract class SupportViewModelBase with Store { // link: 'mailto:support@y.at') ]; - final guidesUrl = 'https://guides.cakewallet.com'; - - String fetchUrl({String locale = "en", String authToken = ""}) { - var supportUrl = - "https://support.cakewallet.com/widget?website_token=${secrets.chatwootWebsiteToken}&locale=${locale}"; - - if (authToken.isNotEmpty) - supportUrl += "&cw_conversation=$authToken"; - - return supportUrl; - } + static const url = 'https://guides.cakewallet.com'; List<SettingsListItem> items; -} +} \ No newline at end of file diff --git a/pubspec_base.yaml b/pubspec_base.yaml index ce7d04b3f..d0690b3ab 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -100,7 +100,6 @@ dev_dependencies: # check flutter_launcher_icons for usage pedantic: ^1.8.0 # replace https://github.com/dart-lang/lints#migrating-from-packagepedantic - translator: ^0.1.7 flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 63905a94b..092b498d0 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -630,18 +630,18 @@ "setup_totp_recommended": "إعداد TOTP (موصى به)", "disable_buy": "تعطيل إجراء الشراء", "disable_sell": "قم بتعطيل إجراء البيع", - "cake_2fa_preset": " كعكة 2FA مسبقا", + "cake_2fa_preset" : " كعكة 2FA مسبقا", "narrow": "ضيق", "normal": "طبيعي", "aggressive": "عنيف", "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", - "require_for_sends_to_non_contacts": "تتطلب لارسال لغير جهات الاتصال", - "require_for_sends_to_contacts": "تتطلب لارسال جهات الاتصال", - "require_for_sends_to_internal_wallets": "تتطلب عمليات الإرسال إلى المحافظ الداخلية", - "require_for_exchanges_to_internal_wallets": "تتطلب عمليات التبادل إلى المحافظ الداخلية", - "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", - "require_for_creating_new_wallets": "تتطلب إنشاء محافظ جديدة", - "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", + "require_for_sends_to_non_contacts" : "تتطلب لارسال لغير جهات الاتصال", + "require_for_sends_to_contacts" : "تتطلب لارسال جهات الاتصال", + "require_for_sends_to_internal_wallets" : "تتطلب عمليات الإرسال إلى المحافظ الداخلية", + "require_for_exchanges_to_internal_wallets" : "تتطلب عمليات التبادل إلى المحافظ الداخلية", + "require_for_adding_contacts" : "تتطلب إضافة جهات اتصال", + "require_for_creating_new_wallets" : "تتطلب إنشاء محافظ جديدة", + "require_for_all_security_and_backup_settings" : "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", "available_balance_description": "الرصيد المتاح هو الرصيد الذي يمكنك إنفاقه أو تحويله إلى محفظة أخرى. يتم تجميد الرصيد المتاح للمعاملات الصادرة والمعاملات الواردة غير المؤكدة.", "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", "syncing_wallet_alert_content": "قد لا يكتمل رصيدك وقائمة المعاملات الخاصة بك حتى تظهر عبارة “SYNCHRONIZED“ في الأعلى. انقر / اضغط لمعرفة المزيد.", @@ -668,11 +668,5 @@ "slidable": "قابل للانزلاق", "etherscan_history": "Etherscan تاريخ", "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", - "template_name": "اسم القالب", - "support_title_live_chat": "الدعم المباشر", - "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", - "support_title_guides": "أدلة محفظة كعكة", - "support_description_guides": "توثيق ودعم القضايا المشتركة", - "support_title_other_links": "روابط دعم أخرى", - "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى" -} \ No newline at end of file + "template_name": "اسم القالب" +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 5563f0c20..f2679f3c7 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -664,11 +664,5 @@ "slidable": "Плъзгащ се", "etherscan_history": "История на Etherscan", "manage_nodes": "Управление на възли", - "template_name": "Име на шаблон", - "support_title_live_chat": "Подкрепа на живо", - "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", - "support_title_guides": "Ръководства за портфейл за торта", - "support_description_guides": "Документация и подкрепа за общи проблеми", - "support_title_other_links": "Други връзки за поддръжка", - "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи" + "template_name": "Име на шаблон" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index b528d6237..d35915f39 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -664,11 +664,5 @@ "slidable": "Posuvné", "manage_nodes": "Spravovat uzly", "etherscan_history": "Historie Etherscanu", - "template_name": "Název šablony", - "support_title_live_chat": "Živá podpora", - "support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory", - "support_title_guides": "Průvodce peněženkami dortu", - "support_description_guides": "Dokumentace a podpora běžných otázek", - "support_title_other_links": "Další odkazy na podporu", - "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody" + "template_name": "Název šablony" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 211708c28..169e65488 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -211,7 +211,7 @@ "settings_only_trades": "Nur Handel", "settings_only_transactions": "Nur Transaktionen", "settings_none": "Keiner", - "settings_support": "Hilfe", + "settings_support": "Unterstützen", "settings_terms_and_conditions": "Geschäftsbedingungen", "pin_is_incorrect": "PIN ist falsch", "setup_pin": "PIN einrichten", @@ -672,11 +672,5 @@ "slidable": "Verschiebbar", "manage_nodes": "Knoten verwalten", "etherscan_history": "Etherscan-Geschichte", - "template_name": "Vorlagenname", - "support_title_live_chat": "Live Support", - "support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen", - "support_title_guides": "Cake Wallet Guides", - "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", - "support_title_other_links": "Andere Support-Links", - "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden" + "template_name": "Vorlagenname" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4de56de80..15df01a57 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -672,11 +672,5 @@ "slidable": "Slidable", "manage_nodes": "Manage nodes", "etherscan_history": "Etherscan history", - "template_name": "Template Name", - "support_title_live_chat": "Live support", - "support_description_live_chat": "Free and fast! Trained support representatives are available to assist", - "support_title_guides": "Cake Wallet guides", - "support_description_guides": "Documentation and support for common issues", - "support_title_other_links": "Other support links", - "support_description_other_links": "Join our communities or reach us our our partners through other methods" + "template_name": "Template Name" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7910e8515..9507e22c5 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -672,11 +672,5 @@ "slidable": "deslizable", "manage_nodes": "Administrar nodos", "etherscan_history": "historia de etherscan", - "template_name": "Nombre de la plantilla", - "support_title_live_chat": "Soporte vital", - "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar", - "support_title_guides": "Guías de billetera para pastel", - "support_description_guides": "Documentación y apoyo para problemas comunes", - "support_title_other_links": "Otros enlaces de soporte", - "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos" + "template_name": "Nombre de la plantilla" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 240e5821e..ee9178d3f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -672,11 +672,5 @@ "slidable": "Glissable", "manage_nodes": "Gérer les nœuds", "etherscan_history": "Historique d'Etherscan", - "template_name": "Nom du modèle", - "support_title_live_chat": "Support en direct", - "support_description_live_chat": "GRATUIT ET RAPIDE! Des représentants de soutien formé sont disponibles pour aider", - "support_title_guides": "Guides de portefeuille à gâteau", - "support_description_guides": "Documentation et soutien aux problèmes communs", - "support_title_other_links": "Autres liens d'assistance", - "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes" + "template_name": "Nom du modèle" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 5a232be2d..203be46a4 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -650,11 +650,5 @@ "slidable": "Mai iya zamewa", "etherscan_history": "Etherscan tarihin kowane zamani", "manage_nodes": "Sarrafa nodes", - "template_name": "Sunan Samfura", - "support_title_live_chat": "Tallafi na Live", - "support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa", - "support_title_guides": "Jagorar Cake", - "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", - "support_title_other_links": "Sauran hanyoyin tallafi", - "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi" + "template_name": "Sunan Samfura" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f60bf7180..f35e0a613 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -672,11 +672,5 @@ "slidable": "फिसलने लायक", "manage_nodes": "नोड्स प्रबंधित करें", "etherscan_history": "इथरस्कैन इतिहास", - "template_name": "टेम्पलेट नाम", - "support_title_live_chat": "लाइव सहायता", - "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", - "support_title_guides": "केक वॉलेट गाइड", - "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", - "support_title_other_links": "अन्य समर्थन लिंक", - "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें" + "template_name": "टेम्पलेट नाम" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 1b6592102..f8913c5cc 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -672,11 +672,5 @@ "slidable": "Klizna", "manage_nodes": "Upravljanje čvorovima", "etherscan_history": "Etherscan povijest", - "template_name": "Naziv predloška", - "support_title_live_chat": "Podrška uživo", - "support_description_live_chat": "Besplatno i brzo! Obučeni predstavnici podrške dostupni su za pomoć", - "support_title_guides": "Vodiči za torte", - "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", - "support_title_other_links": "Ostale veze za podršku", - "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama" + "template_name": "Naziv predloška" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 313d0a358..f0580df0b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -660,11 +660,5 @@ "slidable": "Dapat digeser", "manage_nodes": "Kelola node", "etherscan_history": "Sejarah Etherscan", - "template_name": "Nama Templat", - "support_title_live_chat": "Dukungan langsung", - "support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu", - "support_title_guides": "Panduan Dompet Kue", - "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", - "support_title_other_links": "Tautan dukungan lainnya", - "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain" + "template_name": "Nama Templat" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a1cdc676a..3425b7179 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -672,11 +672,5 @@ "slidable": "Scorrevole", "manage_nodes": "Gestisci i nodi", "etherscan_history": "Storia Etherscan", - "template_name": "Nome modello", - "support_title_live_chat": "Supporto dal vivo", - "support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere", - "support_title_guides": "Guide del portafoglio per torte", - "support_description_guides": "Documentazione e supporto per problemi comuni", - "support_title_other_links": "Altri collegamenti di supporto", - "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi" + "template_name": "Nome modello" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 787876204..e302b8819 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "TOTP を設定する (推奨)", "disable_buy": "購入アクションを無効にする", "disable_sell": "販売アクションを無効にする", - "cake_2fa_preset": "ケーキ 2FA プリセット", + "cake_2fa_preset" : "ケーキ 2FA プリセット", "narrow": "狭い", "normal": "普通", "aggressive": "熱心すぎる", "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", - "require_for_sends_to_non_contacts": "非連絡先への送信に必須", - "require_for_sends_to_contacts": "連絡先に送信する場合に必須", - "require_for_sends_to_internal_wallets": "内部ウォレットへの送信に必須", - "require_for_exchanges_to_internal_wallets": "内部ウォレットへの交換に必要", - "require_for_adding_contacts": "連絡先の追加に必要", - "require_for_creating_new_wallets": "新しいウォレットを作成するために必要です", - "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", + "require_for_sends_to_non_contacts" : "非連絡先への送信に必須", + "require_for_sends_to_contacts" : "連絡先に送信する場合に必須", + "require_for_sends_to_internal_wallets" : "内部ウォレットへの送信に必須", + "require_for_exchanges_to_internal_wallets" : "内部ウォレットへの交換に必要", + "require_for_adding_contacts" : "連絡先の追加に必要", + "require_for_creating_new_wallets" : "新しいウォレットを作成するために必要です", + "require_for_all_security_and_backup_settings" : "すべてのセキュリティおよびバックアップ設定に必須", "available_balance_description": "利用可能な残高は、ウォレットの残高から冷凍残高を差し引いたものです。", "syncing_wallet_alert_title": "ウォレットは同期中です", "syncing_wallet_alert_content": "上部に「同期済み」と表示されるまで、残高と取引リストが完了していない可能性があります。詳細については、クリック/タップしてください。", @@ -672,11 +672,5 @@ "slidable": "スライド可能", "manage_nodes": "ノードの管理", "etherscan_history": "イーサスキャンの歴史", - "template_name": "テンプレート名", - "support_title_live_chat": "ライブサポート", - "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", - "support_title_guides": "ケーキウォレットガイド", - "support_description_guides": "一般的な問題のドキュメントとサポート", - "support_title_other_links": "その他のサポートリンク", - "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください" -} \ No newline at end of file + "template_name": "テンプレート名" +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 76014f54b..8cbda4344 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "TOTP 설정(권장)", "disable_buy": "구매 행동 비활성화", "disable_sell": "판매 조치 비활성화", - "cake_2fa_preset": "케이크 2FA 프리셋", + "cake_2fa_preset" : "케이크 2FA 프리셋", "narrow": "좁은", "normal": "정상", "aggressive": "지나치게 열심인", "require_for_assessing_wallet": "지갑 접근을 위해 필요", - "require_for_sends_to_non_contacts": "비접촉자에게 보내는 데 필요", - "require_for_sends_to_contacts": "연락처로 보내기에 필요", - "require_for_sends_to_internal_wallets": "내부 지갑으로 보내는 데 필요", - "require_for_exchanges_to_internal_wallets": "내부 지갑으로의 교환에 필요", - "require_for_adding_contacts": "연락처 추가에 필요", - "require_for_creating_new_wallets": "새 지갑 생성에 필요", - "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", + "require_for_sends_to_non_contacts" : "비접촉자에게 보내는 데 필요", + "require_for_sends_to_contacts" : "연락처로 보내기에 필요", + "require_for_sends_to_internal_wallets" : "내부 지갑으로 보내는 데 필요", + "require_for_exchanges_to_internal_wallets" : "내부 지갑으로의 교환에 필요", + "require_for_adding_contacts" : "연락처 추가에 필요", + "require_for_creating_new_wallets" : "새 지갑 생성에 필요", + "require_for_all_security_and_backup_settings" : "모든 보안 및 백업 설정에 필요", "available_balance_description": "이 지갑에서 사용할 수 있는 잔액입니다. 이 잔액은 블록체인에서 가져온 것이며, Cake Wallet이 사용할 수 없습니다.", "syncing_wallet_alert_title": "지갑 동기화 중", "syncing_wallet_alert_content": "상단에 \"동기화됨\"이라고 표시될 때까지 잔액 및 거래 목록이 완전하지 않을 수 있습니다. 자세히 알아보려면 클릭/탭하세요.", @@ -672,11 +672,5 @@ "slidable": "슬라이딩 가능", "manage_nodes": "노드 관리", "etherscan_history": "이더스캔 역사", - "template_name": "템플릿 이름", - "support_title_live_chat": "실시간 지원", - "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", - "support_title_guides": "케이크 지갑 가이드", - "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", - "support_title_other_links": "다른 지원 링크", - "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오." -} \ No newline at end of file + "template_name": "템플릿 이름" +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index b3ba2a7dd..c9210077a 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -632,18 +632,18 @@ "setup_totp_recommended": "TOTP ကို စနစ်ထည့်သွင်းပါ (အကြံပြုထားသည်)", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", + "cake_2fa_preset" : "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", "narrow": "ကျဉ်းသော", "normal": "ပုံမှန်", "aggressive": "စိတ်အားထက်သန်ခြင်း။", "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", - "require_for_sends_to_non_contacts": "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_contacts": "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_internal_wallets": "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_exchanges_to_internal_wallets": "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", - "require_for_creating_new_wallets": "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", - "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", + "require_for_sends_to_non_contacts" : "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_contacts" : "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_internal_wallets" : "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_exchanges_to_internal_wallets" : "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", + "require_for_adding_contacts" : "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", + "require_for_creating_new_wallets" : "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", + "require_for_all_security_and_backup_settings" : "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", "available_balance_description": "သင့်ရဲ့ အကောင့်တွင် ရရှိနိုင်သော ငွေကျန်ငွေကို ပြန်လည်ပေးသွင်းပါ။", "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", "syncing_wallet_alert_content": "သင်၏လက်ကျန်နှင့် ငွေပေးငွေယူစာရင်းသည် ထိပ်တွင် \"Synchronizeed\" ဟုပြောသည်အထိ မပြီးမြောက်နိုင်ပါ။ ပိုမိုလေ့လာရန် နှိပ်/နှိပ်ပါ။", @@ -670,11 +670,5 @@ "slidable": "လျှောချနိုင်သည်။", "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", "etherscan_history": "Etherscan သမိုင်း", - "template_name": "နမူနာပုံစံ", - "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", - "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", - "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", - "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", - "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", - "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ" -} \ No newline at end of file + "template_name": "နမူနာပုံစံ" +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index aca33d051..1a11ceb19 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -672,11 +672,5 @@ "slidable": "Verschuifbaar", "manage_nodes": "Beheer knooppunten", "etherscan_history": "Etherscan-geschiedenis", - "template_name": "Sjabloonnaam", - "support_title_live_chat": "Live ondersteuning", - "support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen", - "support_title_guides": "Cake -portemonnee gidsen", - "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", - "support_title_other_links": "Andere ondersteuningslinks", - "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden" + "template_name": "Sjabloonnaam" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 56871f242..26543da46 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -672,11 +672,5 @@ "slidable": "Przesuwne", "manage_nodes": "Zarządzaj węzłami", "etherscan_history": "Historia Etherscanu", - "template_name": "Nazwa szablonu", - "support_title_live_chat": "Wsparcie na żywo", - "support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia", - "support_title_guides": "Przewodniki portfela ciasta", - "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", - "support_title_other_links": "Inne linki wsparcia", - "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod" + "template_name": "Nazwa szablonu" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7cccc3c9e..ac76d4df8 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -671,11 +671,5 @@ "slidable": "Deslizável", "manage_nodes": "Gerenciar nós", "etherscan_history": "história Etherscan", - "template_name": "Nome do modelo", - "support_title_live_chat": "Apoio ao vivo", - "support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar", - "support_title_guides": "Guias da carteira de bolo", - "support_description_guides": "Documentação e suporte para problemas comuns", - "support_title_other_links": "Outros links de suporte", - "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos" + "template_name": "Nome do modelo" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 40f9447ba..c0022c0e4 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -270,6 +270,7 @@ "error_text_node_address": "Пожалуйста, введите iPv4 адрес", "error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535", "error_text_node_proxy_address": "Введите <IPv4-адрес>:<порт>, например 127.0.0.1:9050.", + "error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex", "error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12", "error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2", @@ -634,18 +635,18 @@ "setup_totp_recommended": "Настроить TOTP (рекомендуется)", "disable_buy": "Отключить действие покупки", "disable_sell": "Отключить действие продажи", - "cake_2fa_preset": "Торт 2FA Preset", + "cake_2fa_preset" : "Торт 2FA Preset", "narrow": "Узкий", "normal": "Нормальный", "aggressive": "чрезмерно усердный", "require_for_assessing_wallet": "Требовать для доступа к кошельку", - "require_for_sends_to_non_contacts": "Требовать для отправки не контактам", - "require_for_sends_to_contacts": "Требовать для отправки контактам", - "require_for_sends_to_internal_wallets": "Требовать отправки на внутренние кошельки", - "require_for_exchanges_to_internal_wallets": "Требовать для обмена на внутренние кошельки", - "require_for_adding_contacts": "Требовать добавления контактов", - "require_for_creating_new_wallets": "Требовать для создания новых кошельков", - "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", + "require_for_sends_to_non_contacts" : "Требовать для отправки не контактам", + "require_for_sends_to_contacts" : "Требовать для отправки контактам", + "require_for_sends_to_internal_wallets" : "Требовать отправки на внутренние кошельки", + "require_for_exchanges_to_internal_wallets" : "Требовать для обмена на внутренние кошельки", + "require_for_adding_contacts" : "Требовать добавления контактов", + "require_for_creating_new_wallets" : "Требовать для создания новых кошельков", + "require_for_all_security_and_backup_settings" : "Требовать все настройки безопасности и резервного копирования", "available_balance_description": "Доступный баланс - это средства, которые вы можете использовать для покупки или продажи криптовалюты.", "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", "syncing_wallet_alert_content": "Ваш баланс и список транзакций могут быть неполными, пока вверху не будет написано «СИНХРОНИЗИРОВАНО». Щелкните/коснитесь, чтобы узнать больше.", @@ -672,11 +673,5 @@ "slidable": "Скользящий", "manage_nodes": "Управление узлами", "etherscan_history": "История Эфириума", - "template_name": "Имя Шаблона", - "support_title_live_chat": "Живая поддержка", - "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", - "support_title_guides": "Корт -гиды", - "support_description_guides": "Документация и поддержка общих вопросов", - "support_title_other_links": "Другие ссылки на поддержку", - "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов" -} \ No newline at end of file + "template_name": "Имя Шаблона" +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 9ffd7af11..f9aff7f14 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -632,18 +632,18 @@ "setup_totp_recommended": "ตั้งค่า TOTP (แนะนำ)", "disable_buy": "ปิดการใช้งานการซื้อ", "disable_sell": "ปิดการใช้งานการขาย", - "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", + "cake_2fa_preset" : "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", "narrow": "แคบ", "normal": "ปกติ", "aggressive": "กระตือรือร้นมากเกินไป", "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", - "require_for_sends_to_non_contacts": "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", - "require_for_sends_to_contacts": "จำเป็นต้องส่งไปยังผู้ติดต่อ", - "require_for_sends_to_internal_wallets": "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", - "require_for_exchanges_to_internal_wallets": "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", - "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", - "require_for_creating_new_wallets": "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", - "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", + "require_for_sends_to_non_contacts" : "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", + "require_for_sends_to_contacts" : "จำเป็นต้องส่งไปยังผู้ติดต่อ", + "require_for_sends_to_internal_wallets" : "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", + "require_for_exchanges_to_internal_wallets" : "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", + "require_for_adding_contacts" : "ต้องการสำหรับการเพิ่มผู้ติดต่อ", + "require_for_creating_new_wallets" : "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", + "require_for_all_security_and_backup_settings" : "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", "available_balance_description": "จำนวนเงินที่คุณสามารถใช้ได้ในการซื้อหรือขาย", "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", "syncing_wallet_alert_content": "รายการยอดเงินและธุรกรรมของคุณอาจไม่สมบูรณ์จนกว่าจะมีข้อความว่า “ซิงโครไนซ์” ที่ด้านบน คลิก/แตะเพื่อเรียนรู้เพิ่มเติม่", @@ -670,11 +670,5 @@ "slidable": "เลื่อนได้", "manage_nodes": "จัดการโหนด", "etherscan_history": "ประวัติอีเธอร์สแกน", - "template_name": "ชื่อแม่แบบ", - "support_title_live_chat": "การสนับสนุนสด", - "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", - "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", - "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", - "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", - "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ" -} \ No newline at end of file + "template_name": "ชื่อแม่แบบ" +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index dedf7cf28..9386a6571 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -671,11 +671,5 @@ "slidable": "kaydırılabilir", "manage_nodes": "Düğümleri yönet", "etherscan_history": "Etherscan geçmişi", - "template_name": "şablon adı", - "support_title_live_chat": "Canlı destek", - "support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur", - "support_title_guides": "Kek Cüzdan Kılavuzları", - "support_description_guides": "Ortak sorunlara belge ve destek", - "support_title_other_links": "Diğer destek bağlantıları", - "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın" + "template_name": "şablon adı" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f8a2777e5..744691cdd 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -672,11 +672,5 @@ "slidable": "Розсувний", "manage_nodes": "Керуйте вузлами", "etherscan_history": "Історія Etherscan", - "template_name": "Назва шаблону", - "support_title_live_chat": "Жива підтримка", - "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", - "support_title_guides": "Поклики для гаманців тортів", - "support_description_guides": "Документація та підтримка загальних питань", - "support_title_other_links": "Інші посилання на підтримку", - "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами" + "template_name": "Назва шаблону" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 5eed0d35b..f016d56c7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -626,18 +626,18 @@ "setup_totp_recommended": "TOTP ترتیب دیں (تجویز کردہ)", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", - "cake_2fa_preset": "کیک 2FA پیش سیٹ", + "cake_2fa_preset" : "کیک 2FA پیش سیٹ", "narrow": "تنگ", "normal": "نارمل", "aggressive": "حد سے زیادہ پرجوش", "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", - "require_for_sends_to_non_contacts": "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_contacts": "رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_internal_wallets": "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", - "require_for_exchanges_to_internal_wallets": "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", - "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", - "require_for_creating_new_wallets": "نئے بٹوے بنانے کی ضرورت ہے۔", - "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", + "require_for_sends_to_non_contacts" : "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_for_sends_to_contacts" : "رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_for_sends_to_internal_wallets" : "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", + "require_for_exchanges_to_internal_wallets" : "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", + "require_for_adding_contacts" : "رابطوں کو شامل کرنے کی ضرورت ہے۔", + "require_for_creating_new_wallets" : "نئے بٹوے بنانے کی ضرورت ہے۔", + "require_for_all_security_and_backup_settings" : "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", "available_balance_description": "”دستیاب بیلنس” یا ”تصدیق شدہ بیلنس” وہ فنڈز ہیں جو فوری طور پر خرچ کیے جا سکتے ہیں۔ اگر فنڈز کم بیلنس میں ظاہر ہوتے ہیں لیکن اوپر کے بیلنس میں نہیں، تو آپ کو مزید نیٹ ورک کی تصدیقات حاصل کرنے کے لیے آنے والے فنڈز کے لیے چند منٹ انتظار کرنا چاہیے۔ مزید تصدیق حاصل کرنے کے بعد، وہ قابل خرچ ہوں گے۔", "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", "syncing_wallet_alert_content": "آپ کے بیلنس اور لین دین کی فہرست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ یہ سب سے اوپر \"SYNCRONIZED\" نہ کہے۔ مزید جاننے کے لیے کلک/تھپتھپائیں۔", @@ -664,11 +664,5 @@ "slidable": "سلائیڈ ایبل", "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", - "template_name": "ٹیمپلیٹ کا نام", - "support_title_live_chat": "براہ راست مدد", - "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", - "support_title_guides": "کیک پرس گائڈز", - "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", - "support_title_other_links": "دوسرے سپورٹ لنکس", - "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں" -} \ No newline at end of file + "template_name": "ٹیمپلیٹ کا نام" +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index c99b00ebd..74c03005f 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -628,18 +628,18 @@ "setup_totp_recommended": "Sọ TOTP (Kẹṣọdọ)", "disable_buy": "Ko iṣọrọ ọja", "disable_sell": "Ko iṣọrọ iṣọrọ", - "cake_2fa_preset": "Cake 2FA Tito", + "cake_2fa_preset" : "Cake 2FA Tito", "narrow": "Taara", "normal": "Deede", "aggressive": "Onítara", "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", - "require_for_sends_to_non_contacts": "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", - "require_for_sends_to_contacts": "Beere fun fifiranṣẹ si awọn olubasọrọ", - "require_for_sends_to_internal_wallets": "Beere fun fifiranṣẹ si awọn apamọwọ inu", - "require_for_exchanges_to_internal_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", - "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", - "require_for_creating_new_wallets": "Beere fun ṣiṣẹda titun Woleti", - "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", + "require_for_sends_to_non_contacts" : "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", + "require_for_sends_to_contacts" : "Beere fun fifiranṣẹ si awọn olubasọrọ", + "require_for_sends_to_internal_wallets" : "Beere fun fifiranṣẹ si awọn apamọwọ inu", + "require_for_exchanges_to_internal_wallets" : "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", + "require_for_adding_contacts" : "Beere fun fifi awọn olubasọrọ kun", + "require_for_creating_new_wallets" : "Beere fun ṣiṣẹda titun Woleti", + "require_for_all_security_and_backup_settings" : "Beere fun gbogbo aabo ati awọn eto afẹyinti", "available_balance_description": "“Iwọntunwọnsi Wa” tabi “Iwọntunwọnsi Ijẹrisi” jẹ awọn owo ti o le ṣee lo lẹsẹkẹsẹ. Ti awọn owo ba han ni iwọntunwọnsi kekere ṣugbọn kii ṣe iwọntunwọnsi oke, lẹhinna o gbọdọ duro iṣẹju diẹ fun awọn owo ti nwọle lati gba awọn ijẹrisi nẹtiwọọki diẹ sii. Lẹhin ti wọn gba awọn ijẹrisi diẹ sii, wọn yoo jẹ inawo.", "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", "syncing_wallet_alert_content": "Iwontunws.funfun rẹ ati atokọ idunadura le ma pari titi ti yoo fi sọ “SYNCHRONIZED” ni oke. Tẹ/tẹ ni kia kia lati ni imọ siwaju sii.", @@ -666,11 +666,5 @@ "slidable": "Slidable", "manage_nodes": "Ṣakoso awọn apa", "etherscan_history": "Etherscan itan", - "template_name": "Orukọ Awoṣe", - "support_title_live_chat": "Atilẹyin ifiwe", - "support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ", - "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", - "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", - "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", - "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran" -} \ No newline at end of file + "template_name": "Orukọ Awoṣe" +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index dc1cfd139..7184e4d40 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -633,18 +633,18 @@ "setup_totp_recommended": "设置 TOTP(推荐)", "disable_buy": "禁用购买操作", "disable_sell": "禁用卖出操作", - "cake_2fa_preset": "蛋糕 2FA 预设", + "cake_2fa_preset" : "蛋糕 2FA 预设", "narrow": "狭窄的", "normal": "普通的", "aggressive": "过分热心", "require_for_assessing_wallet": "需要访问钱包", - "require_for_sends_to_non_contacts": "需要发送给非联系人", - "require_for_sends_to_contacts": "需要发送给联系人", - "require_for_sends_to_internal_wallets": "需要发送到内部钱包", - "require_for_exchanges_to_internal_wallets": "需要兑换到内部钱包", - "require_for_adding_contacts": "需要添加联系人", - "require_for_creating_new_wallets": "创建新钱包的要求", - "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", + "require_for_sends_to_non_contacts" : "需要发送给非联系人", + "require_for_sends_to_contacts" : "需要发送给联系人", + "require_for_sends_to_internal_wallets" : "需要发送到内部钱包", + "require_for_exchanges_to_internal_wallets" : "需要兑换到内部钱包", + "require_for_adding_contacts" : "需要添加联系人", + "require_for_creating_new_wallets" : "创建新钱包的要求", + "require_for_all_security_and_backup_settings" : "需要所有安全和备份设置", "available_balance_description": "可用余额是您可以使用的金额。冻结余额是您当前正在等待确认的金额。", "syncing_wallet_alert_title": "您的钱包正在同步", "syncing_wallet_alert_content": "您的余额和交易列表可能不完整,直到顶部显示“已同步”。单击/点击以了解更多信息。", @@ -671,11 +671,5 @@ "slidable": "可滑动", "manage_nodes": "管理节点", "etherscan_history": "以太扫描历史", - "template_name": "模板名称", - "support_title_live_chat": "实时支持", - "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", - "support_title_guides": "蛋糕钱包指南", - "support_description_guides": "对常见问题的文档和支持", - "support_title_other_links": "其他支持链接", - "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴" -} \ No newline at end of file + "template_name": "模板名称" +} diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 75f3bbd06..741eb8780 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.5.0" -MONERO_COM_BUILD_NUMBER=54 +MONERO_COM_VERSION="1.5.1" +MONERO_COM_BUILD_NUMBER=55 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.8.0" -CAKEWALLET_BUILD_NUMBER=167 +CAKEWALLET_VERSION="4.8.1" +CAKEWALLET_BUILD_NUMBER=168 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 68d3f69a8..401755b40 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.5.0" -MONERO_COM_BUILD_NUMBER=52 +MONERO_COM_VERSION="1.5.1" +MONERO_COM_BUILD_NUMBER=53 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.8.0" -CAKEWALLET_BUILD_NUMBER=175 +CAKEWALLET_VERSION="4.8.1" +CAKEWALLET_BUILD_NUMBER=176 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 387bd39c5..a531ce926 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.1.0" -CAKEWALLET_BUILD_NUMBER=28 +CAKEWALLET_VERSION="1.1.1" +CAKEWALLET_BUILD_NUMBER=30 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/append_translation.dart b/tool/append_translation.dart deleted file mode 100644 index e56ad89d6..000000000 --- a/tool/append_translation.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:translator/translator.dart'; - -const defaultLang = "en"; -const langs = [ - "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", - "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", - "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) -]; -final translator = GoogleTranslator(); - -void main(List<String> args) async { - if (args.length != 2) { - throw Exception( - 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); - } - - final name = args.first; - final text = args.last; - - print('Appending "$name": "$text"'); - - for (var lang in langs) { - final fileName = getFileName(lang); - final translation = await getTranslation(text, lang); - - appendArbFile(fileName, name, translation); - } -} - -void appendArbFile(String fileName, String name, String text) { - final file = File(fileName); - final inputContent = file.readAsStringSync(); - final arbObj = json.decode(inputContent) as Map<String, dynamic>; - - if (arbObj.containsKey(name)) { - print("String $name already exists in $fileName!"); - return; - } - - arbObj.addAll({name: text}); - - final outputContent = json - .encode(arbObj) - .replaceAll('","', '",\n "') - .replaceAll('{"', '{\n "') - .replaceAll('"}', '"\n}') - .replaceAll('":"', '": "'); - - file.writeAsStringSync(outputContent); -} - - -Future<String> getTranslation(String text, String lang) async { - if (lang == defaultLang) return text; - return (await translator.translate(text, from: defaultLang, to: lang)).text; -} - -String getFileName(String lang) { - final shortLang = lang - .split("-") - .first; - return "./res/values/strings_$shortLang.arb"; -} diff --git a/tool/update_secrets.dart b/tool/update_secrets.dart index 0f2e59419..69e3f8447 100644 --- a/tool/update_secrets.dart +++ b/tool/update_secrets.dart @@ -33,7 +33,8 @@ Future<void> updateSecretsConfig(List<String> args) async { }); final fileConfig = - json.decode(configFile.readAsStringSync()) as Map<String, dynamic>; + json.decode(configFile.readAsStringSync()) as Map<String, dynamic> ?? + <String, dynamic>{}; fileConfig.forEach((key, dynamic value) { if (secrets[key] == null) { secrets[key] = value; diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 7819a582c..1b62dbf60 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -31,7 +31,6 @@ class SecretKey { SecretKey('anonPayReferralCode', () => ''), SecretKey('fiatApiKey', () => ''), SecretKey('payfuraApiKey', () => ''), - SecretKey('chatwootWebsiteToken', () => ''), ]; static final ethereumSecrets = [ From 5ec930cbc65cb4be6930aa25fc31e461da7f633c Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Tue, 15 Aug 2023 03:47:25 +0300 Subject: [PATCH 02/18] Re add chatwoot (#1044) * Revert "Revert "Cw 397 chatwoot live support (#1011)"" This reverts commit ecdc7baa2e3c8f46c3c5013f56c8b864f088ec9f. * Re-add chatwoot Change chatwoot base url --- .github/workflows/pr_test_build.yml | 1 + assets/images/live_support.png | Bin 0 -> 1776 bytes assets/images/more_links.png | Bin 0 -> 1889 bytes assets/images/wallet_guides.png | Bin 0 -> 1760 bytes cw_core/lib/cake_hive.dart | 4 + cw_core/lib/erc20_token.dart | 3 +- cw_core/lib/hive_type_ids.dart | 13 +++ cw_core/lib/node.dart | 3 +- cw_core/lib/unspent_coins_info.dart | 5 +- cw_core/lib/wallet_info.dart | 8 +- cw_core/lib/wallet_type.dart | 4 +- cw_ethereum/lib/ethereum_wallet.dart | 7 +- lib/anonpay/anonpay_invoice_info.dart | 3 +- lib/buy/order.dart | 7 +- lib/core/backup_service.dart | 13 +-- lib/di.dart | 8 ++ lib/entities/contact.dart | 7 +- lib/entities/get_encryption_key.dart | 17 ++- lib/entities/template.dart | 3 +- lib/entities/transaction_description.dart | 3 +- lib/exchange/exchange_template.dart | 3 +- lib/exchange/trade.dart | 5 +- lib/main.dart | 70 +++++++------ lib/router.dart | 13 ++- lib/routes.dart | 2 + .../screens/restore/restore_options_page.dart | 2 - .../restore/widgets/restore_button.dart | 20 ++-- .../widgets/settings_cell_with_arrow.dart | 7 +- lib/src/screens/support/support_page.dart | 99 +++++++++++------- .../support/widgets/support_tiles.dart | 69 ++++++++++++ .../support_chat/support_chat_page.dart | 38 +++++++ .../support_chat/widgets/chatwoot_widget.dart | 62 +++++++++++ .../support_other_links_page.dart | 58 ++++++++++ lib/view_model/support_view_model.dart | 29 +++-- pubspec_base.yaml | 1 + res/values/strings_ar.arb | 26 +++-- res/values/strings_bg.arb | 8 +- res/values/strings_cs.arb | 8 +- res/values/strings_de.arb | 10 +- res/values/strings_en.arb | 8 +- res/values/strings_es.arb | 8 +- res/values/strings_fr.arb | 8 +- res/values/strings_ha.arb | 8 +- res/values/strings_hi.arb | 8 +- res/values/strings_hr.arb | 8 +- res/values/strings_id.arb | 8 +- res/values/strings_it.arb | 8 +- res/values/strings_ja.arb | 26 +++-- res/values/strings_ko.arb | 26 +++-- res/values/strings_my.arb | 26 +++-- res/values/strings_nl.arb | 8 +- res/values/strings_pl.arb | 8 +- res/values/strings_pt.arb | 8 +- res/values/strings_ru.arb | 27 +++-- res/values/strings_th.arb | 26 +++-- res/values/strings_tr.arb | 8 +- res/values/strings_uk.arb | 8 +- res/values/strings_ur.arb | 26 +++-- res/values/strings_yo.arb | 26 +++-- res/values/strings_zh.arb | 26 +++-- tool/append_translation.dart | 66 ++++++++++++ tool/update_secrets.dart | 3 +- tool/utils/secret_key.dart | 1 + 63 files changed, 762 insertions(+), 260 deletions(-) create mode 100644 assets/images/live_support.png create mode 100644 assets/images/more_links.png create mode 100644 assets/images/wallet_guides.png create mode 100644 cw_core/lib/cake_hive.dart create mode 100644 cw_core/lib/hive_type_ids.dart create mode 100644 lib/src/screens/support/widgets/support_tiles.dart create mode 100644 lib/src/screens/support_chat/support_chat_page.dart create mode 100644 lib/src/screens/support_chat/widgets/chatwoot_widget.dart create mode 100644 lib/src/screens/support_other_links/support_other_links_page.dart create mode 100644 tool/append_translation.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index e2b932202..47378eef5 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -127,6 +127,7 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart + echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties diff --git a/assets/images/live_support.png b/assets/images/live_support.png new file mode 100644 index 0000000000000000000000000000000000000000..89ad61f458cddcb9ee9c17f751c1d545137d6d95 GIT binary patch literal 1776 zcmV<M1`qj(P)<h;3K|Lk000e1NJLTq001HY001Hg1^@s6I!6n_00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH28BsPK~#7FtyoWQ z8$}d<GrQ~5DYVWfs8h};2@(?Gj}l)B5)w^7NR2>>jZj5TaV4(M<j4V9IM5q)52$b` zbwt$$gcRq<0Z2YU%_oQ}A)MIWdA#>#-tM~4G*lU9y|cTsGrxK7_j~U-29B{^U+h<t z#GH@ORuhCuf(VH-Js1tQ;jhWgQiuAFX$Fp=eYK49u^X;ghYJJ%V?+}pFbIqRO_Bme zbS^n)MJcS;Hp|^(1+un?mDA<X6#}p-3zG%tY+?r<fCKP=JP<w;$cJ=q{nh)E*NSsl zc*@2g%9Fz_n!5?Kh@nF^Mquc|Sh9@nG&@kv6?*o?ujl$#js?iXGox9Wbcc=(t=pr6 zCNqSF4q1?{1&qH4Ak+oM8eIGB^}m}s-?4Cn+w}|mg=A<~Vgq${33DZK$Y+R%GkjJz zu?r({A@*Q6n49ZNb)VWIkG4zSl{+8ao@n66P19w|yDPVXMYa@s3&o4{C2mUMWEJ2D z7HQV8LNm^n&@B?t77~Z2={yyaB50?(blojs)HZ|R_N8{NhFc`%34|@OL^Wm$(Y@G{ zRY)A6w-)vH4${F{a~Obub*l-HktV3HsS`FQD}z-KBwAvViwj7q4sJr4t~UapI~-S> zxkJxqlc1#Fo+1#Q>x2JvO}##t?MLnpCKQpZB4{yup_tV0ixKO<iJ>vLVkNfr!S`<; zh$5B<(9rg47H~%h3t=REJh7$mdo%w6(zu8#aT5PdPpc-3^8Q3nH3%5?I9bK;e0=sm zS;oB5mD`K^S3Q`iUJ@VF=y{jl<HHIg&_JdnQyByD-X&Ziv^O%DA!Li20-ub@7cK0} zFM^qMns?71+~C_a0%P2$!DB7kMaF6131rqeE_{Slo8mPiyOSeZS^J*-ApG|)TU5+6 z5%NNe%Y+S}bM<>~`dCrhe6~Y(z67-@_}IeW$-fUXAhf$JdQvetA;2$LK%N1@5INC6 z4%m#DJ4DvVM4#S&qhICzuz#>leCZYE6gN4uBS4nPCA3Jj5Qc?T)}YB;f?oYlbP>u# zXhC`8O|0?44|G$d$b2JK>5z*MTVV1SBVb|J5g-n+o^b*KCvZG0TQ;TfI}Ic@-g3bT zm~({(8b3fSSle3ItH?u(8^WVpg`H`RtjrC%T2L#PZ1+KD!U=y<Kxp3Z)=-eh%F$~G zzV{sPW25p!ogcl(T%ioiuC*xk-Vl7F2xbb%#pl*|VeqbOW=4^%QHuoE1dyD>9(9+W z#Hz_CDyvJau|BRC>B|h(I#>wu3?$>}QOUVY({xoW)=T0c&Dy5PyW{!9^oWRU>UNoZ z!GhjXLRvGUKoHVDMPVXi570{FltAP6XZ#;JaF;)C#kJ3F#?$nqqgYdC8z0}ASaSQN zIlAsCkWuR9F8pv}iHfnBfWlA`<f~URi_qqRD>1i{pbwJt6p)D{M~mk!=%`Bu{YdU# zZkt{Vehj_T)%>zdXWCd#izQW}HREY5SicKya9M!pSFV;&VcBT4S?^arc^_wp0CkO| zCnraew!eNC=V|1k@ZVwe+jj<Xe`9ffm0mxSsVj>sxTheV|K;Qwrgr+dt;w^j7y-6? zF>OW$u4aWx$fm`<FK&FlB*n3$bdYSC)ur+dKQp0r^<zSorT)%KKTXcTW15Yu+sS1{ zUru+Tnbu^rXYi?yT^h<mAPdPzRF&tbkc&{5y90+b8}G*yUWr^GgsOBQBbxWKhV(#A zm8}nCLB>kXOy1#r?mCxl915h>;=&hOYL#5N*&>jq_+UA$Ey8*^De)2DS<vgg{PU^y zp+Mx@xebuqlBItPKMx=e>-tf!#Z<0Y$V*Z!Vna-#&rNtj^FZR5B<GA8Tzsv$0`sf~ zSsjsE!)gT5h1DYd9iH>SE1M_RjszqgjjDcOAIvnr*bo)9%(Gb^vjho&GDY|0E~8!? zEx{359Ppgi&~C-N>hHX^;9{w8oh7#r`h&`}*a_nt)L*+-+C2&o8?euEgtcCAIbp+M z00rL%by&;_4zUQ|w4pqv8+)mR#{6daiQE_iVlmwgzf@7HCat&wSv?p@-8qrR>dw4& z*>*9!aPG%)3;stF*9=DSwQ`gaPw)(d>s<<nZFey0QkbuhDVhXkMT&LFO9ilAt_q-& zrnvsr-Es$>qM4%%;$Qx!%A*-lR;`5Q42Sbbe&3p2<kH;%oM<=NkN+pkQQALJ%Zw-4 S$a=g00000<MNUMnLSTY`lS)zm literal 0 HcmV?d00001 diff --git a/assets/images/more_links.png b/assets/images/more_links.png new file mode 100644 index 0000000000000000000000000000000000000000..97891f3ad5a8a68d7c6be3fe11a7fcaa06ed429d GIT binary patch literal 1889 zcmV-n2cGzeP)<h;3K|Lk000e1NJLTq001Ze001Zm1^@s6jQ+T700009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH2KGrrK~#7F?N~o= z97Pm=Z+7qEiyU$(5s_kl0^1bS4vIvQCKrVGBamW4kwA)^J37Z5ogINt8qgV01c|~8 z6$oF1M2BL30l0huUlb{Ea^88oKQps?7oWqWBpGSFd%H99e((4Gjsaec|M@_8fzfJH z^R-8CsR4ezQ9yI*fMDvt!*K$bDgcgqx$`@@d+PJ^&beP2oA3f-Vt}n{G;<7S`<SPh zh8Hjb&cHA*(q|$(UhuPmBy1Sq-qcfEeDn9l{Ym6Gm~=Q;=f7uUp(7w*PzbgW5&<Hh zK8MTkTafnzGcKbJOgJV2c%IoqpcVsz00JEfrT|WUGiFB$3L|K_XZ*z97XN;m&P*b6 zB7k{*zyO&sWYQRdz(8iu05br6BcLLqK?#!844A(U@ZrKFGA9Cvn9n#BsBEBKiNO*C zg2!lfaRUr@)6F#}5DEDtlc7lL2oPb1eb7uOKr;nH7yv0?WgG&NF!>m}=Dq8*{=w&d z@8heq9^YjU!ruIixiS{zF7M>CDxfUdUCpniCR5I56!+V{_;~e?i;wpHyzpp!B7m(g zXqAPw`D(Jc+MiuF$BurLsc;Jd@jc-(21I6z#Yjdd85OXUxk7c^KL2=zzun~hnhd%9 z*E@%Ud<Nj<t2D>j-c)B-!NaLi!+@gMlqu9m72)QI7}<&u9Q;s$a#|V^t}FDS_Puit z7oQ8z=g^KhEP{#OG7rh$P|ZgQrplHp1(Sg@C4!kTs|ur-D=iJ>kgXmGP)ZoDS~Be= zQZ=s)QE1>|BDS0tnFwr!^kSw(jcf*s;rod2=+mkk(%ikpz2;beMFDe(Jur6Uc`7m} zVeBd7J;DTpf*E5l=*Ae5x8@;vt;%GTATc6Jrg_e(X`GrH3y`PG2X-_QTQWv^hQVM~ z7lK1KR|YT&t@vN*k20qSK>~>g!yki*wVxjg5WJraFVUIq%FwV97PV1(3yWCROlT%% z4`PiWO3Ku$44T<V^C`uEDQ3q4bm*EGf+8}2LzA;;TB^E1s?A{yNF`C`%)Hgo7l*hF zdJ`4vw)(1fC&vN=b7o8+M>fsaNzK0uWH4`<H*!&Cxvxy_Nr5O_6FFHfRe?BKZbp5u zj8O9%Emg3eASR!35a*UmmjPnmqhD!q$B<KL@IZHRMKk&yl!3;T<_LgMkV}=o1bQg6 z1IcQGow8~`NG}#fym_D1-(UqgJf~;hvFvQTbwB%A(UZLjpEWJP8;dGSeDWv;1xlG_ zLaLDDN)}n2Z|ge@pj%cFGq-%I59+f^Ki5~@-)bz^9G&HtKbV3gtE~0i)7?`$Dwyb! zS`9-flv(VP{wM~^>OrXlS;EE}?IqF#iU)&b_R~#Xc-MLCc!y`(ck0W_TiB2LT-a*# z_zbdCJMat4PKTN5@^xz;2AAU;-nxacRWo<d$R90jL+w_^WLuwSZXKdjHfcKNSNYw_ z?M|b|_vMj&V7*1n6Scv*M5ZhJ+A@QD>(}X>!{$o&B1Zt3TUI5|K*~mH{}4ce0<A?z zizo&To232am4hZc8LWMEM?ofFdHvu<27@+vIGOR1+_~0I?>^b^-fw=iRnC<TCPTl@ zf?8Ez`i#~H0}U%P1oy*hMTb+vm7FKmID&I_?3(zX+!<(1qLH=E33lp4efG_n8sQB8 zhMeEm^bVBs+M2BqMs{o7_jz5jPB_Pmpw9Ku{pdVi$BlySt9x(0ad&$8PzD)oKjpbZ zdn*31`;h3>pwS#CK5AWcNZ^DRtYAj~nv*y&w<%2usg}#|mIh7W{VJxBQdjiQjzW|U zJYe-V)m<phAhDWMgkhNvOC>8=A?zL^J7$AQrQv2`Z!Ey<SZ!Ov-XT>4VHw#`Sa^oe z#e_<bqCbL92PLSmX6|NdQW*^ON@lxacPzjkzs6mj+OIZ}21ZYsrM6^8OfyNU7-(ri z`$MXlF_pA3e^yzK%80z)>)jLGu>h4t@V8QDQZ0MtUKVGu<qFNJi)<!PIGR3!5?HA~ zW!?=@%&vspQ9RGK{7>@@-msrqAlW3;(NLSqM$}Gnk!?MKR!o_gcA=WYo)ENY2>%iZ zJ}ff#;py6Q0d_jbDFIfL5eqzZYTiKGb_*P&()6+F@N;Zfp$arHr@FZ4f3d-Zs06Of zc2D)53sA=G@AD3WSrLDXQR~XSj?82*oQj~*_E+2k!ilep<Y01BN?3ispFcg_o!&SM z%h-eaH{WHqhz1LwwG?|mqbUO*b=CmGrnM#`oB$DEB(JI^B++yCGhi9B-RaIa90>n$ z-27y)=%|?Imi<hQT;8+-fK&vnE^?fVziZ(+<JLreYo+0Lc|i|&-9H%>y9>V!N9(Kc b(vE)tR=vS9SH@o300000NkvXXu0mjfr1x?h literal 0 HcmV?d00001 diff --git a/assets/images/wallet_guides.png b/assets/images/wallet_guides.png new file mode 100644 index 0000000000000000000000000000000000000000..3f2d9f27059e0ee31cdc7016cbd0ea5caeb93f53 GIT binary patch literal 1760 zcmV<61|Ru}P)<h;3K|Lk000e1NJLTq001HY001Hg1^@s6I!6n_00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH26ah9K~#7FomkCo zTU8LAIlhhq0>ycPI=n#LH)xTNDj_PPN=R&I!iuhF5fV$MYZg^^-NhhOu_$W0V1-1o zf@M;PeVr$$D^VqG>@&>oxyPu8rYExRPwqK0=bLZ7nQMf9jnOUYzyA_0b|_zJ05%$e zL6`4$h@iU!(DTg4ob|j*-Q8~=;PKrN^>07M8NB6aY6qG*j5~AMCWH+{KqLTU2jrOK z9Qccn^dA2K@sj|%GJkFTbael-`IuhiD>om%Glg@GBwts*q5-^uLtgn78{J@oC>HF) zcf`1yi+6mH%nN;{jHNnzq1U9tz3cN4oO7rn-42X-)q$?gyHpE`hN8gN)S}}P!_k$6 z^l?TO;L*>cS6{<9Mv{=Qm2Jq1vmrsPAv8=Nwl9Yy7`=8^f}Dg-o~OINTss-V8;-PC zEQYdsf!h}MF!%?;Xf}3;k=CKO@*#-%Iywh&{N&pFjhsnHX_zX5Ne<PHvEqV;2wJ2h zlIyFUprc8_Azp9%>nA6B@V|~A^Z{b`6i7HHpr9j&rJ$}Eq@)IIbRa@Qfg~7SOm2eh z-#$J)+`mly|8#^W41yEM_laeFM<bjvuAl|TF3<8}OE*F=m2}qskt4_7$ulkyT}<zu z9PVFzK6pJM@@OCe<V00)WygiM<{JfSm=p!1j(bhmnI%;lr-#m^at_KJ9Q2^K|L1F* zNd}+nBA_(w2=dC8!CgB^nj1VYElC&co^_{&AX$i<E7&@v^Y}C9P;dY6qrZo%q2YAE zDr>OHnpR8He92gkmm1~Sy5Nq=I~^nsTcltKlWa~mC^4V`AAkR=az+qQ!74=6IP0es zua?B7ArW`J>aYgwjf{k}q#gb~#@Ikv6HKENkrMh%%(x%UG>ECx4uxN{(qmNWN(fzf zPBKAvE=oFII}@$Ay<;_I>*46-h#7W~i8R0r#;B#92=W|+EN61Ug_NWm9O3nw%L$Y2 zizX9FHEsC$h7C6CLYI*#*DPpV_JgajUU&JL&ynx(k>vjF&cogvc+1hS=gPvu2`I9T zwbUoeM!@VaD=_3dQ256`eR?|LP~GE=9(;bz3f%C@h*T3bl+})I1TD2yT2bIuf_pes z*d&7xhrF#lLG8)46Yf=DDv0vY`WZf713Pb)B*yuFJU_#eCMid92$}AZ7c?}4;gGRP zTXdqDG?>Wg)Kpb$%?{-iXNM6<bw_t=HA~Ue9*3`3l{Zq#B|V+ts*F|cx7m`wQ?t~f zy7oZTCS(k84EvrvP-~6Zv85U)23^!7R9Um-1^;UnPFm_@(6H#vD7d5ZsjbR=Ua23_ zj>YE?#!}ZXLCC+PuX=A2QV<nkdYaEZygxaA%O`{RF=0zLY9vI+Fq|RdVvDLJv+XLJ z(5>N%w{=1Wlkuoj?#Mi8yz0WKK16XLLBvKWdP2~ghu?g;c+|}}6LxF2o&`ed+#?g> zzI64G6<uAHMr@eD_BFwCpK=JJRcLe4IAVo5yLTi!Go8q+cx3u7lL)ONLtj8A$TUL` zsy?JL5(SW2xffS*v<aqF$rLxE79wmLAg@;|nGuriac^5jYahMZRt2*~xlGY(BYCNc z(fXLOl2u^6NhKR3W1dC|gU1_+zNpH|P0kV;mULfn+`GC$P}LS)sxGABT*HDjL(lMp z0XshXe$x2>-f%p)e!9=|E{nC~8KLV{-J0o-DRXK&K64D=IPtEg)`MmYz}eePIL{!Q zVHhq=vm0-lB=BC>&~4ROo|rY%q$A`KtyQe;IXAw$v3SN=!L>pwuhs}r;We$yQKdCY z`drqBt!fsIwE6(iK0pxH5mT;kJ)onea{^Cs4W6?DeXBDrY}`d@V{Hp-TZjdL=vNHl z$PDm`U6%z~aW2r(TBJ~LcESlRj?!epux9u{v&Tz1)I^F`g2*DzjzmQob)#}q)zgf4 z*GyQ7AVm?e_2M0fzb9J<n=^H6u}F9L&NNasIgs(HS-qdwf>1#Vt&A5Q7>4Z|fOAvz zg4}C$5T@&Aom~h{2`aEmS9tP|7|@$Awa!5M0$7}-h(AP60@i7oGfq_Up2b5dmwCqB zz`Z%1UE2KPonvTu)s9=+@;1L1_Lj?GmwD4r=Yo{zh6yc4m3EG+{#XMd?EpRSA8(`q zk{@ugm31NWn&0Qneb(bfiD>zBeevGW*1_tJI{yH@j<TLYn(83{0000<MNUMnLSTa0 Cf=4s} literal 0 HcmV?d00001 diff --git a/cw_core/lib/cake_hive.dart b/cw_core/lib/cake_hive.dart new file mode 100644 index 000000000..aadf6bf9a --- /dev/null +++ b/cw_core/lib/cake_hive.dart @@ -0,0 +1,4 @@ +import 'package:hive/hive.dart'; +import 'package:hive/src/hive_impl.dart'; + +final HiveInterface CakeHive = HiveImpl(); diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index db5b6db5b..fd27aaba6 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -1,4 +1,5 @@ import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'erc20_token.g.dart'; @@ -53,7 +54,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { iconPath: icon, ); - static const typeId = 12; + static const typeId = ERC20_TOKEN_TYPE_ID; static const boxName = 'Erc20Tokens'; @override diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart new file mode 100644 index 000000000..0961182bc --- /dev/null +++ b/cw_core/lib/hive_type_ids.dart @@ -0,0 +1,13 @@ +const CONTACT_TYPE_ID = 0; +const NODE_TYPE_ID = 1; +const TRANSACTION_TYPE_ID = 2; +const TRADE_TYPE_ID = 3; +const WALLET_INFO_TYPE_ID = 4; +const WALLET_TYPE_TYPE_ID = 5; +const TEMPLATE_TYPE_ID = 6; +const EXCHANGE_TEMPLATE_TYPE_ID = 7; +const ORDER_TYPE_ID = 8; +const UNSPENT_COINS_INFO_TYPE_ID = 9; +const ANONPAY_INVOICE_INFO_TYPE_ID = 10; + +const ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 3fa45b44c..59a1450f6 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -3,6 +3,7 @@ import 'package:cw_core/keyable.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:hive/hive.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; @@ -37,7 +38,7 @@ class Node extends HiveObject with Keyable { trusted = map['trusted'] as bool? ?? false, socksProxyAddress = map['socksProxyPort'] as String?; - static const typeId = 1; + static const typeId = NODE_TYPE_ID; static const boxName = 'Nodes'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 75c13f2cd..33be2eb2c 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'unspent_coins_info.g.dart'; @@ -14,7 +15,7 @@ class UnspentCoinsInfo extends HiveObject { required this.vout, required this.value}); - static const typeId = 9; + static const typeId = UNSPENT_COINS_INFO_TYPE_ID; static const boxName = 'Unspent'; static const boxKey = 'unspentBoxKey'; @@ -45,4 +46,4 @@ class UnspentCoinsInfo extends HiveObject { String get note => noteRaw ?? ''; set note(String value) => noteRaw = value; -} \ No newline at end of file +} diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index a25702cf7..6b3fa9e98 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,7 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_core/wallet_type.dart'; import 'dart:async'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; part 'wallet_info.g.dart'; @@ -30,7 +30,7 @@ class WalletInfo extends HiveObject { yatEid, yatLastUsedAddressRaw, showIntroCakePayCard); } - static const typeId = 4; + static const typeId = WALLET_INFO_TYPE_ID; static const boxName = 'WalletInfo'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index a65839041..62c2ad410 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -1,4 +1,5 @@ import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'wallet_type.g.dart'; @@ -10,9 +11,8 @@ const walletTypes = [ WalletType.haven, WalletType.ethereum, ]; -const walletTypeTypeId = 5; -@HiveType(typeId: walletTypeTypeId) +@HiveType(typeId: WALLET_TYPE_TYPE_ID) enum WalletType { @HiveField(0) monero, diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index d94e4ec95..404b78ca2 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'dart:math'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pending_transaction.dart'; @@ -58,8 +59,8 @@ abstract class EthereumWalletBase this.walletInfo = walletInfo; transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password); - if (!Hive.isAdapterRegistered(Erc20Token.typeId)) { - Hive.registerAdapter(Erc20TokenAdapter()); + if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { + CakeHive.registerAdapter(Erc20TokenAdapter()); } _sharedPrefs.complete(SharedPreferences.getInstance()); @@ -95,7 +96,7 @@ abstract class EthereumWalletBase Completer<SharedPreferences> _sharedPrefs = Completer(); Future<void> init() async { - erc20TokensBox = await Hive.openBox<Erc20Token>(Erc20Token.boxName); + erc20TokensBox = await CakeHive.openBox<Erc20Token>(Erc20Token.boxName); await walletAddresses.init(); await transactionHistory.init(); _privateKey = await getPrivateKey(_mnemonic, _password); diff --git a/lib/anonpay/anonpay_invoice_info.dart b/lib/anonpay/anonpay_invoice_info.dart index 89613224e..bd6776d00 100644 --- a/lib/anonpay/anonpay_invoice_info.dart +++ b/lib/anonpay/anonpay_invoice_info.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/keyable.dart'; import 'package:hive/hive.dart'; @@ -35,7 +36,7 @@ class AnonpayInvoiceInfo extends HiveObject with Keyable implements AnonpayInfoB @HiveField(13) final String provider; - static const typeId = 10; + static const typeId = ANONPAY_INVOICE_INFO_TYPE_ID; static const boxName = 'AnonpayInvoiceInfo'; AnonpayInvoiceInfo({ diff --git a/lib/buy/order.dart b/lib/buy/order.dart index 387fbcd34..5a677d291 100644 --- a/lib/buy/order.dart +++ b/lib/buy/order.dart @@ -1,7 +1,8 @@ import 'package:cake_wallet/buy/buy_provider_description.dart'; -import 'package:hive/hive.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; part 'order.g.dart'; @@ -26,7 +27,7 @@ class Order extends HiveObject { } } - static const typeId = 8; + static const typeId = ORDER_TYPE_ID; static const boxName = 'Orders'; static const boxKey = 'ordersBoxKey'; @@ -66,4 +67,4 @@ class Order extends HiveObject { BuyProviderDescription.deserialize(raw: providerRaw); String amountFormatted() => formatAmount(amount); -} \ No newline at end of file +} diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2e27d83c9..6476891ed 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; @@ -10,6 +9,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:cryptography/cryptography.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:archive/archive_io.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; @@ -17,6 +17,7 @@ import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/wallet_types.g.dart'; + import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { @@ -170,14 +171,14 @@ class BackupService { Future<Box<WalletInfo>> _reloadHiveWalletInfoBox() async { final appDir = await getApplicationDocumentsDirectory(); - await Hive.close(); - Hive.init(appDir.path); + await CakeHive.close(); + CakeHive.init(appDir.path); - if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { - Hive.registerAdapter(WalletInfoAdapter()); + if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { + CakeHive.registerAdapter(WalletInfoAdapter()); } - return await Hive.openBox<WalletInfo>(WalletInfo.boxName); + return await CakeHive.openBox<WalletInfo>(WalletInfo.boxName); } Future<void> _importPreferencesDump() async { diff --git a/lib/di.dart b/lib/di.dart index b02742e64..2a54c85a3 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -36,6 +36,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; +import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; +import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -869,6 +871,12 @@ Future setup({ getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>())); + getIt.registerFactory(() => + SupportChatPage( + getIt.get<SupportViewModel>(), secureStorage: getIt.get<FlutterSecureStorage>())); + + getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>())); + getIt.registerFactory(() { final wallet = getIt.get<AppStore>().wallet; diff --git a/lib/entities/contact.dart b/lib/entities/contact.dart index e111429ca..cd4fa55a2 100644 --- a/lib/entities/contact.dart +++ b/lib/entities/contact.dart @@ -1,8 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/keyable.dart'; +import 'package:hive/hive.dart'; part 'contact.g.dart'; @@ -14,7 +13,7 @@ class Contact extends HiveObject with Keyable { } } - static const typeId = 0; + static const typeId = CONTACT_TYPE_ID; static const boxName = 'Contacts'; @HiveField(0, defaultValue: '') diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index 5fc4983d7..e67380bb8 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,23 +1,18 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:hive/hive.dart'; +import 'package:cw_core/cake_hive.dart'; Future<List<int>> getEncryptionKey( {required String forKey, required FlutterSecureStorage secureStorage}) async { - final stringifiedKey = - await secureStorage.read(key: 'transactionDescriptionsBoxKey'); + final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); List<int> key; if (stringifiedKey == null) { - key = Hive.generateSecureKey(); + key = CakeHive.generateSecureKey(); final keyStringified = key.join(','); - await secureStorage.write( - key: 'transactionDescriptionsBoxKey', value: keyStringified); + await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified); } else { - key = stringifiedKey - .split(',') - .map((i) => int.parse(i)) - .toList(); + key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); } return key; -} \ No newline at end of file +} diff --git a/lib/entities/template.dart b/lib/entities/template.dart index 6955136e0..7cdd2c74a 100644 --- a/lib/entities/template.dart +++ b/lib/entities/template.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'template.g.dart'; @@ -14,7 +15,7 @@ class Template extends HiveObject { required this.amountFiatRaw, this.additionalRecipientsRaw}); - static const typeId = 6; + static const typeId = TEMPLATE_TYPE_ID; static const boxName = 'Template'; @HiveField(0) diff --git a/lib/entities/transaction_description.dart b/lib/entities/transaction_description.dart index 86d6b043a..088f9c480 100644 --- a/lib/entities/transaction_description.dart +++ b/lib/entities/transaction_description.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'transaction_description.g.dart'; @@ -6,7 +7,7 @@ part 'transaction_description.g.dart'; class TransactionDescription extends HiveObject { TransactionDescription({required this.id, this.recipientAddress, this.transactionNote}); - static const typeId = 2; + static const typeId = TRANSACTION_TYPE_ID; static const boxName = 'TransactionDescriptions'; static const boxKey = 'transactionDescriptionsBoxKey'; diff --git a/lib/exchange/exchange_template.dart b/lib/exchange/exchange_template.dart index dcfd8d8e8..2182efd8c 100644 --- a/lib/exchange/exchange_template.dart +++ b/lib/exchange/exchange_template.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'exchange_template.g.dart'; @@ -14,7 +15,7 @@ class ExchangeTemplate extends HiveObject { required this.depositCurrencyTitleRaw, required this.receiveCurrencyTitleRaw}); - static const typeId = 7; + static const typeId = EXCHANGE_TEMPLATE_TYPE_ID; static const boxName = 'ExchangeTemplate'; @HiveField(0) diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index 70dfa5713..db8c8fb3b 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -1,8 +1,9 @@ -import 'package:hive/hive.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; part 'trade.g.dart'; @@ -41,7 +42,7 @@ class Trade extends HiveObject { } } - static const typeId = 3; + static const typeId = TRADE_TYPE_ID; static const boxName = 'Trades'; static const boxKey = 'tradesBoxKey'; diff --git a/lib/main.dart b/lib/main.dart index e0cf58e62..62a0bfc9c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cw_core/hive_type_ids.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -38,6 +39,7 @@ import 'package:uni_links/uni_links.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cw_core/cake_hive.dart'; final navigatorKey = GlobalKey<NavigatorState>(); final rootKey = GlobalKey<RootState>(); @@ -57,7 +59,7 @@ Future<void> main() async { return true; }; - await Hive.close(); + await CakeHive.close(); await initializeAppConfigs(); @@ -69,50 +71,50 @@ Future<void> main() async { Future<void> initializeAppConfigs() async { final appDir = await getApplicationDocumentsDirectory(); - Hive.init(appDir.path); + CakeHive.init(appDir.path); - if (!Hive.isAdapterRegistered(Contact.typeId)) { - Hive.registerAdapter(ContactAdapter()); + if (!CakeHive.isAdapterRegistered(Contact.typeId)) { + CakeHive.registerAdapter(ContactAdapter()); } - if (!Hive.isAdapterRegistered(Node.typeId)) { - Hive.registerAdapter(NodeAdapter()); + if (!CakeHive.isAdapterRegistered(Node.typeId)) { + CakeHive.registerAdapter(NodeAdapter()); } - if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) { - Hive.registerAdapter(TransactionDescriptionAdapter()); + if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) { + CakeHive.registerAdapter(TransactionDescriptionAdapter()); } - if (!Hive.isAdapterRegistered(Trade.typeId)) { - Hive.registerAdapter(TradeAdapter()); + if (!CakeHive.isAdapterRegistered(Trade.typeId)) { + CakeHive.registerAdapter(TradeAdapter()); } - if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { - Hive.registerAdapter(WalletInfoAdapter()); + if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { + CakeHive.registerAdapter(WalletInfoAdapter()); } - if (!Hive.isAdapterRegistered(walletTypeTypeId)) { - Hive.registerAdapter(WalletTypeAdapter()); + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { + CakeHive.registerAdapter(WalletTypeAdapter()); } - if (!Hive.isAdapterRegistered(Template.typeId)) { - Hive.registerAdapter(TemplateAdapter()); + if (!CakeHive.isAdapterRegistered(Template.typeId)) { + CakeHive.registerAdapter(TemplateAdapter()); } - if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) { - Hive.registerAdapter(ExchangeTemplateAdapter()); + if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) { + CakeHive.registerAdapter(ExchangeTemplateAdapter()); } - if (!Hive.isAdapterRegistered(Order.typeId)) { - Hive.registerAdapter(OrderAdapter()); + if (!CakeHive.isAdapterRegistered(Order.typeId)) { + CakeHive.registerAdapter(OrderAdapter()); } - if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - Hive.registerAdapter(UnspentCoinsInfoAdapter()); + if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); } - if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { - Hive.registerAdapter(AnonpayInvoiceInfoAdapter()); + if (!CakeHive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { + CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } final secureStorage = FlutterSecureStorage(); @@ -120,21 +122,21 @@ Future<void> initializeAppConfigs() async { await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey); - final contacts = await Hive.openBox<Contact>(Contact.boxName); - final nodes = await Hive.openBox<Node>(Node.boxName); - final transactionDescriptions = await Hive.openBox<TransactionDescription>( + final contacts = await CakeHive.openBox<Contact>(Contact.boxName); + final nodes = await CakeHive.openBox<Node>(Node.boxName); + final transactionDescriptions = await CakeHive.openBox<TransactionDescription>( TransactionDescription.boxName, encryptionKey: transactionDescriptionsBoxKey); - final trades = await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey); - final orders = await Hive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey); - final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName); - final templates = await Hive.openBox<Template>(Template.boxName); - final exchangeTemplates = await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName); - final anonpayInvoiceInfo = await Hive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName); + final trades = await CakeHive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey); + final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey); + final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName); + final templates = await CakeHive.openBox<Template>(Template.boxName); + final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName); + final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName); Box<UnspentCoinsInfo>? unspentCoinsInfoSource; if (!isMoneroOnly) { - unspentCoinsInfoSource = await Hive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); + unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); } await initialSetup( diff --git a/lib/router.dart b/lib/router.dart index 031a1075b..7d63ad1ea 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -41,6 +41,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; +import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; +import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/utils/payment_request.dart'; @@ -48,7 +50,6 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; -import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -442,9 +443,17 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.support: return CupertinoPageRoute<void>( - fullscreenDialog: true, builder: (_) => getIt.get<SupportPage>()); + case Routes.supportLiveChat: + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<SupportChatPage>()); + + case Routes.supportOtherLinks: + return CupertinoPageRoute<void>( + fullscreenDialog: true, + builder: (_) => getIt.get<SupportOtherLinksPage>()); + case Routes.unspentCoinsList: return MaterialPageRoute<void>( builder: (_) => getIt.get<UnspentCoinsListPage>()); diff --git a/lib/routes.dart b/lib/routes.dart index 7187a7263..62c303ce8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -48,6 +48,8 @@ class Routes { static const editBackupPassword = '/edit_backup_passowrd'; static const restoreFromBackup = '/restore_from_backup'; static const support = '/support'; + static const supportLiveChat = '/support/live_chat'; + static const supportOtherLinks = '/support/other'; static const orderDetails = '/order_details'; static const preOrder = '/pre_order'; static const buyWebView = '/buy_web_view'; diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 93a44c752..74e33b87a 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -2,12 +2,10 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/language_list.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:flutter/cupertino.dart'; diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index aa44947b5..817ebbc72 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -1,12 +1,11 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class RestoreButton extends StatelessWidget { - const RestoreButton({ - required this.onPressed, - required this.image, - required this.title, - required this.description}); + const RestoreButton( + {required this.onPressed, + required this.image, + required this.title, + required this.description}); final VoidCallback onPressed; final Image image; @@ -24,10 +23,7 @@ class RestoreButton extends StatelessWidget { alignment: Alignment.topLeft, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context) - .accentTextTheme! - .bodySmall! - .color!, + color: Theme.of(context).accentTextTheme.bodySmall!.color!, ), child: Row( mainAxisSize: MainAxisSize.max, @@ -49,7 +45,7 @@ class RestoreButton extends StatelessWidget { fontSize: 16, fontWeight: FontWeight.w500, color: Theme.of(context) - .primaryTextTheme! + .primaryTextTheme .titleLarge! .color!), ), @@ -61,7 +57,7 @@ class RestoreButton extends StatelessWidget { fontSize: 14, fontWeight: FontWeight.normal, color: Theme.of(context) - .primaryTextTheme! + .primaryTextTheme .labelSmall! .color!), ), diff --git a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart index 1d97db08c..163d59f4f 100644 --- a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart +++ b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart @@ -6,7 +6,6 @@ class SettingsCellWithArrow extends StandardListRow { : super(title: title, isSelected: false, onTap: handler); @override - Widget buildTrailing(BuildContext context) => - Image.asset('assets/images/select_arrow.png', - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!); -} \ No newline at end of file + Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png', + color: Theme.of(context).primaryTextTheme.labelSmall!.color!); +} diff --git a/lib/src/screens/support/support_page.dart b/lib/src/screens/support/support_page.dart index b385530fb..883677832 100644 --- a/lib/src/screens/support/support_page.dart +++ b/lib/src/screens/support/support_page.dart @@ -1,55 +1,78 @@ -import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; -import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cake_wallet/view_model/settings/link_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/support/widgets/support_tiles.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/view_model/support_view_model.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/generated/i18n.dart'; +import 'package:url_launcher/url_launcher.dart'; class SupportPage extends BasePage { SupportPage(this.supportViewModel); final SupportViewModel supportViewModel; + final imageLiveSupport = Image.asset('assets/images/live_support.png'); + final imageWalletGuides = Image.asset('assets/images/wallet_guides.png'); + final imageMoreLinks = Image.asset('assets/images/more_links.png'); + @override String get title => S.current.settings_support; + @override + AppBarStyle get appBarStyle => AppBarStyle.regular; + @override Widget body(BuildContext context) { - final iconColor = Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!; - // FIX-ME: Added `context` it was not used here before, maby bug ? - return Center( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), - child: SectionStandardList( - context: context, - sectionCount: 1, - itemCounter: (int _) => supportViewModel.items.length, - itemBuilder: (_, __, index) { - final item = supportViewModel.items[index]; - - if (item is RegularListItem) { - return SettingsCellWithArrow(title: item.title, handler: item.handler); - } - - if (item is LinkListItem) { - return SettingsLinkProviderCell( - title: item.title, - icon: item.icon, - iconColor: item.hasIconColor ? iconColor : null, - link: item.link, - linkTitle: item.linkTitle); - } - - return Container(); - }), + return Container( + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 330), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 24), + child: SupportTile( + image: imageLiveSupport, + title: S.of(context).support_title_live_chat, + description: S.of(context).support_description_live_chat, + onPressed: () { + if (DeviceInfo.instance.isDesktop) { + _launchUrl(supportViewModel.fetchUrl()); + } else { + Navigator.pushNamed(context, Routes.supportLiveChat); + } + }, + ), + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: SupportTile( + image: imageWalletGuides, + title: S.of(context).support_title_guides, + description: S.of(context).support_description_guides, + onPressed: () => _launchUrl(supportViewModel.guidesUrl), + ), + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: SupportTile( + image: imageMoreLinks, + title: S.of(context).support_title_other_links, + description: S.of(context).support_description_other_links, + onPressed: () => Navigator.pushNamed(context, Routes.supportOtherLinks), + ), + ), + ], + ), + ), ), ); } + + void _launchUrl(String url) async { + try { + await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); + } catch (e) {} + } } diff --git a/lib/src/screens/support/widgets/support_tiles.dart b/lib/src/screens/support/widgets/support_tiles.dart new file mode 100644 index 000000000..9d7c65719 --- /dev/null +++ b/lib/src/screens/support/widgets/support_tiles.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; + +class SupportTile extends StatelessWidget { + const SupportTile( + {required this.onPressed, + required this.image, + required this.title, + required this.description}); + + final VoidCallback onPressed; + final Image image; + final String title; + final String description; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(24), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12)), + color: Theme.of(context).accentTextTheme.bodySmall!.color!, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + image, + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 16), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + title, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + ), + ), + Padding( + padding: EdgeInsets.only(top: 5), + child: Text( + description, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Theme.of(context).primaryTextTheme.labelSmall!.color!, + ), + ), + ) + ], + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/src/screens/support_chat/support_chat_page.dart b/lib/src/screens/support_chat/support_chat_page.dart new file mode 100644 index 000000000..e84965b23 --- /dev/null +++ b/lib/src/screens/support_chat/support_chat_page.dart @@ -0,0 +1,38 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart'; +import 'package:cake_wallet/view_model/support_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + + +class SupportChatPage extends BasePage { + SupportChatPage(this.supportViewModel, {required this.secureStorage}); + + final SupportViewModel supportViewModel; + final FlutterSecureStorage secureStorage; + + @override + String get title => S.current.settings_support; + + @override + AppBarStyle get appBarStyle => AppBarStyle.regular; + + @override + Widget body(BuildContext context) => FutureBuilder<String>( + future: getCookie(), + builder: (BuildContext context, AsyncSnapshot<String> snapshot) { + print(snapshot.data); + if (snapshot.hasData) + return ChatwootWidget( + secureStorage, + supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!) + ); + return Container(); + }, + ); + + Future<String> getCookie() async { + return await secureStorage.read(key: COOKIE_KEY) ?? ""; + } +} diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart new file mode 100644 index 000000000..d9a5f9bb8 --- /dev/null +++ b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart @@ -0,0 +1,62 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +const COOKIE_KEY = 'chatwootCookie'; + +class ChatwootWidget extends StatefulWidget { + ChatwootWidget(this.secureStorage, {required this.supportUrl}); + + final FlutterSecureStorage secureStorage; + final String supportUrl; + + @override + ChatwootWidgetState createState() => ChatwootWidgetState(); +} + +class ChatwootWidgetState extends State<ChatwootWidget> { + final GlobalKey _webViewkey = GlobalKey(); + + @override + Widget build(BuildContext context) => InAppWebView( + key: _webViewkey, + initialOptions: InAppWebViewGroupOptions( + crossPlatform: InAppWebViewOptions(transparentBackground: true), + ), + initialUrlRequest: URLRequest(url: Uri.tryParse(widget.supportUrl)), + onWebViewCreated: (InAppWebViewController controller) { + controller.addWebMessageListener( + WebMessageListener( + jsObjectName: 'ReactNativeWebView', + onPostMessage: (String? message, Uri? sourceOrigin, bool isMainFrame, + JavaScriptReplyProxy replyProxy) { + final shortenedMessage = message?.substring(16); + if (shortenedMessage != null && isJsonString(shortenedMessage)) { + final parsedMessage = jsonDecode(shortenedMessage); + final eventType = parsedMessage["event"]; + if (eventType == 'loaded') { + final authToken = parsedMessage["config"]["authToken"]; + print(authToken); + storeCookie(authToken as String); + } + } + }, + ), + ); + }, + ); + + bool isJsonString(String str) { + try { + jsonDecode(str); + } catch (e) { + return false; + } + return true; + } + + Future<void> storeCookie(String value) async => + await widget.secureStorage.write(key: COOKIE_KEY, value: value); +} diff --git a/lib/src/screens/support_other_links/support_other_links_page.dart b/lib/src/screens/support_other_links/support_other_links_page.dart new file mode 100644 index 000000000..e904e7fab --- /dev/null +++ b/lib/src/screens/support_other_links/support_other_links_page.dart @@ -0,0 +1,58 @@ +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/view_model/settings/link_list_item.dart'; +import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; +import 'package:cake_wallet/view_model/support_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +class SupportOtherLinksPage extends BasePage { + SupportOtherLinksPage(this.supportViewModel); + + final SupportViewModel supportViewModel; + + @override + String get title => S.current.settings_support; + + @override + AppBarStyle get appBarStyle => AppBarStyle.transparent; + + @override + Widget body(BuildContext context) { + final iconColor = + Theme.of(context).accentTextTheme.displayLarge!.backgroundColor!; + + return Container( + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 500), + child: SectionStandardList( + context: context, + sectionCount: 1, + itemCounter: (int _) => supportViewModel.items.length, + itemBuilder: (_, __, index) { + final item = supportViewModel.items[index]; + + if (item is RegularListItem) { + return SettingsCellWithArrow( + title: item.title, handler: item.handler); + } + + if (item is LinkListItem) { + return SettingsLinkProviderCell( + title: item.title, + icon: item.icon, + iconColor: item.hasIconColor ? iconColor : null, + link: item.link, + linkTitle: item.linkTitle); + } + + return Container(); + }), + ), + ), + ); + } +} diff --git a/lib/view_model/support_view_model.dart b/lib/view_model/support_view_model.dart index 15c25968f..d3b14c59b 100644 --- a/lib/view_model/support_view_model.dart +++ b/lib/view_model/support_view_model.dart @@ -1,12 +1,9 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/settings/link_list_item.dart'; -import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; import 'package:cake_wallet/view_model/settings/settings_list_item.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:mobx/mobx.dart'; -import 'package:url_launcher/url_launcher.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/.secrets.g.dart' as secrets; part 'support_view_model.g.dart'; @@ -15,14 +12,6 @@ class SupportViewModel = SupportViewModelBase with _$SupportViewModel; abstract class SupportViewModelBase with Store { SupportViewModelBase() : items = [ - RegularListItem( - title: S.current.faq, - handler: (BuildContext context) async { - try { - await launch(url); - } catch (e) {} - }, - ), LinkListItem( title: 'Email', linkTitle: 'support@cakewallet.com', @@ -85,7 +74,17 @@ abstract class SupportViewModelBase with Store { // link: 'mailto:support@y.at') ]; - static const url = 'https://guides.cakewallet.com'; + final guidesUrl = 'https://guides.cakewallet.com'; + + String fetchUrl({String locale = "en", String authToken = ""}) { + var supportUrl = + "https://app.chatwoot.com/widget?website_token=${secrets.chatwootWebsiteToken}&locale=${locale}"; + + if (authToken.isNotEmpty) + supportUrl += "&cw_conversation=$authToken"; + + return supportUrl; + } List<SettingsListItem> items; -} \ No newline at end of file +} diff --git a/pubspec_base.yaml b/pubspec_base.yaml index d0690b3ab..ce7d04b3f 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -100,6 +100,7 @@ dev_dependencies: # check flutter_launcher_icons for usage pedantic: ^1.8.0 # replace https://github.com/dart-lang/lints#migrating-from-packagepedantic + translator: ^0.1.7 flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 092b498d0..63905a94b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -630,18 +630,18 @@ "setup_totp_recommended": "إعداد TOTP (موصى به)", "disable_buy": "تعطيل إجراء الشراء", "disable_sell": "قم بتعطيل إجراء البيع", - "cake_2fa_preset" : " كعكة 2FA مسبقا", + "cake_2fa_preset": " كعكة 2FA مسبقا", "narrow": "ضيق", "normal": "طبيعي", "aggressive": "عنيف", "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", - "require_for_sends_to_non_contacts" : "تتطلب لارسال لغير جهات الاتصال", - "require_for_sends_to_contacts" : "تتطلب لارسال جهات الاتصال", - "require_for_sends_to_internal_wallets" : "تتطلب عمليات الإرسال إلى المحافظ الداخلية", - "require_for_exchanges_to_internal_wallets" : "تتطلب عمليات التبادل إلى المحافظ الداخلية", - "require_for_adding_contacts" : "تتطلب إضافة جهات اتصال", - "require_for_creating_new_wallets" : "تتطلب إنشاء محافظ جديدة", - "require_for_all_security_and_backup_settings" : "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", + "require_for_sends_to_non_contacts": "تتطلب لارسال لغير جهات الاتصال", + "require_for_sends_to_contacts": "تتطلب لارسال جهات الاتصال", + "require_for_sends_to_internal_wallets": "تتطلب عمليات الإرسال إلى المحافظ الداخلية", + "require_for_exchanges_to_internal_wallets": "تتطلب عمليات التبادل إلى المحافظ الداخلية", + "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", + "require_for_creating_new_wallets": "تتطلب إنشاء محافظ جديدة", + "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", "available_balance_description": "الرصيد المتاح هو الرصيد الذي يمكنك إنفاقه أو تحويله إلى محفظة أخرى. يتم تجميد الرصيد المتاح للمعاملات الصادرة والمعاملات الواردة غير المؤكدة.", "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", "syncing_wallet_alert_content": "قد لا يكتمل رصيدك وقائمة المعاملات الخاصة بك حتى تظهر عبارة “SYNCHRONIZED“ في الأعلى. انقر / اضغط لمعرفة المزيد.", @@ -668,5 +668,11 @@ "slidable": "قابل للانزلاق", "etherscan_history": "Etherscan تاريخ", "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", - "template_name": "اسم القالب" -} + "template_name": "اسم القالب", + "support_title_live_chat": "الدعم المباشر", + "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", + "support_title_guides": "أدلة محفظة كعكة", + "support_description_guides": "توثيق ودعم القضايا المشتركة", + "support_title_other_links": "روابط دعم أخرى", + "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index f2679f3c7..5563f0c20 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -664,5 +664,11 @@ "slidable": "Плъзгащ се", "etherscan_history": "История на Etherscan", "manage_nodes": "Управление на възли", - "template_name": "Име на шаблон" + "template_name": "Име на шаблон", + "support_title_live_chat": "Подкрепа на живо", + "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", + "support_title_guides": "Ръководства за портфейл за торта", + "support_description_guides": "Документация и подкрепа за общи проблеми", + "support_title_other_links": "Други връзки за поддръжка", + "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index d35915f39..b528d6237 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -664,5 +664,11 @@ "slidable": "Posuvné", "manage_nodes": "Spravovat uzly", "etherscan_history": "Historie Etherscanu", - "template_name": "Název šablony" + "template_name": "Název šablony", + "support_title_live_chat": "Živá podpora", + "support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory", + "support_title_guides": "Průvodce peněženkami dortu", + "support_description_guides": "Dokumentace a podpora běžných otázek", + "support_title_other_links": "Další odkazy na podporu", + "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 169e65488..211708c28 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -211,7 +211,7 @@ "settings_only_trades": "Nur Handel", "settings_only_transactions": "Nur Transaktionen", "settings_none": "Keiner", - "settings_support": "Unterstützen", + "settings_support": "Hilfe", "settings_terms_and_conditions": "Geschäftsbedingungen", "pin_is_incorrect": "PIN ist falsch", "setup_pin": "PIN einrichten", @@ -672,5 +672,11 @@ "slidable": "Verschiebbar", "manage_nodes": "Knoten verwalten", "etherscan_history": "Etherscan-Geschichte", - "template_name": "Vorlagenname" + "template_name": "Vorlagenname", + "support_title_live_chat": "Live Support", + "support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen", + "support_title_guides": "Cake Wallet Guides", + "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", + "support_title_other_links": "Andere Support-Links", + "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 15df01a57..4de56de80 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -672,5 +672,11 @@ "slidable": "Slidable", "manage_nodes": "Manage nodes", "etherscan_history": "Etherscan history", - "template_name": "Template Name" + "template_name": "Template Name", + "support_title_live_chat": "Live support", + "support_description_live_chat": "Free and fast! Trained support representatives are available to assist", + "support_title_guides": "Cake Wallet guides", + "support_description_guides": "Documentation and support for common issues", + "support_title_other_links": "Other support links", + "support_description_other_links": "Join our communities or reach us our our partners through other methods" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 9507e22c5..7910e8515 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -672,5 +672,11 @@ "slidable": "deslizable", "manage_nodes": "Administrar nodos", "etherscan_history": "historia de etherscan", - "template_name": "Nombre de la plantilla" + "template_name": "Nombre de la plantilla", + "support_title_live_chat": "Soporte vital", + "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar", + "support_title_guides": "Guías de billetera para pastel", + "support_description_guides": "Documentación y apoyo para problemas comunes", + "support_title_other_links": "Otros enlaces de soporte", + "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index ee9178d3f..240e5821e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -672,5 +672,11 @@ "slidable": "Glissable", "manage_nodes": "Gérer les nœuds", "etherscan_history": "Historique d'Etherscan", - "template_name": "Nom du modèle" + "template_name": "Nom du modèle", + "support_title_live_chat": "Support en direct", + "support_description_live_chat": "GRATUIT ET RAPIDE! Des représentants de soutien formé sont disponibles pour aider", + "support_title_guides": "Guides de portefeuille à gâteau", + "support_description_guides": "Documentation et soutien aux problèmes communs", + "support_title_other_links": "Autres liens d'assistance", + "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 203be46a4..5a232be2d 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -650,5 +650,11 @@ "slidable": "Mai iya zamewa", "etherscan_history": "Etherscan tarihin kowane zamani", "manage_nodes": "Sarrafa nodes", - "template_name": "Sunan Samfura" + "template_name": "Sunan Samfura", + "support_title_live_chat": "Tallafi na Live", + "support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa", + "support_title_guides": "Jagorar Cake", + "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", + "support_title_other_links": "Sauran hanyoyin tallafi", + "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f35e0a613..f60bf7180 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -672,5 +672,11 @@ "slidable": "फिसलने लायक", "manage_nodes": "नोड्स प्रबंधित करें", "etherscan_history": "इथरस्कैन इतिहास", - "template_name": "टेम्पलेट नाम" + "template_name": "टेम्पलेट नाम", + "support_title_live_chat": "लाइव सहायता", + "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", + "support_title_guides": "केक वॉलेट गाइड", + "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", + "support_title_other_links": "अन्य समर्थन लिंक", + "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index f8913c5cc..1b6592102 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -672,5 +672,11 @@ "slidable": "Klizna", "manage_nodes": "Upravljanje čvorovima", "etherscan_history": "Etherscan povijest", - "template_name": "Naziv predloška" + "template_name": "Naziv predloška", + "support_title_live_chat": "Podrška uživo", + "support_description_live_chat": "Besplatno i brzo! Obučeni predstavnici podrške dostupni su za pomoć", + "support_title_guides": "Vodiči za torte", + "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", + "support_title_other_links": "Ostale veze za podršku", + "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index f0580df0b..313d0a358 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -660,5 +660,11 @@ "slidable": "Dapat digeser", "manage_nodes": "Kelola node", "etherscan_history": "Sejarah Etherscan", - "template_name": "Nama Templat" + "template_name": "Nama Templat", + "support_title_live_chat": "Dukungan langsung", + "support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu", + "support_title_guides": "Panduan Dompet Kue", + "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", + "support_title_other_links": "Tautan dukungan lainnya", + "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 3425b7179..a1cdc676a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -672,5 +672,11 @@ "slidable": "Scorrevole", "manage_nodes": "Gestisci i nodi", "etherscan_history": "Storia Etherscan", - "template_name": "Nome modello" + "template_name": "Nome modello", + "support_title_live_chat": "Supporto dal vivo", + "support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere", + "support_title_guides": "Guide del portafoglio per torte", + "support_description_guides": "Documentazione e supporto per problemi comuni", + "support_title_other_links": "Altri collegamenti di supporto", + "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index e302b8819..787876204 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "TOTP を設定する (推奨)", "disable_buy": "購入アクションを無効にする", "disable_sell": "販売アクションを無効にする", - "cake_2fa_preset" : "ケーキ 2FA プリセット", + "cake_2fa_preset": "ケーキ 2FA プリセット", "narrow": "狭い", "normal": "普通", "aggressive": "熱心すぎる", "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", - "require_for_sends_to_non_contacts" : "非連絡先への送信に必須", - "require_for_sends_to_contacts" : "連絡先に送信する場合に必須", - "require_for_sends_to_internal_wallets" : "内部ウォレットへの送信に必須", - "require_for_exchanges_to_internal_wallets" : "内部ウォレットへの交換に必要", - "require_for_adding_contacts" : "連絡先の追加に必要", - "require_for_creating_new_wallets" : "新しいウォレットを作成するために必要です", - "require_for_all_security_and_backup_settings" : "すべてのセキュリティおよびバックアップ設定に必須", + "require_for_sends_to_non_contacts": "非連絡先への送信に必須", + "require_for_sends_to_contacts": "連絡先に送信する場合に必須", + "require_for_sends_to_internal_wallets": "内部ウォレットへの送信に必須", + "require_for_exchanges_to_internal_wallets": "内部ウォレットへの交換に必要", + "require_for_adding_contacts": "連絡先の追加に必要", + "require_for_creating_new_wallets": "新しいウォレットを作成するために必要です", + "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", "available_balance_description": "利用可能な残高は、ウォレットの残高から冷凍残高を差し引いたものです。", "syncing_wallet_alert_title": "ウォレットは同期中です", "syncing_wallet_alert_content": "上部に「同期済み」と表示されるまで、残高と取引リストが完了していない可能性があります。詳細については、クリック/タップしてください。", @@ -672,5 +672,11 @@ "slidable": "スライド可能", "manage_nodes": "ノードの管理", "etherscan_history": "イーサスキャンの歴史", - "template_name": "テンプレート名" -} + "template_name": "テンプレート名", + "support_title_live_chat": "ライブサポート", + "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", + "support_title_guides": "ケーキウォレットガイド", + "support_description_guides": "一般的な問題のドキュメントとサポート", + "support_title_other_links": "その他のサポートリンク", + "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 8cbda4344..76014f54b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "TOTP 설정(권장)", "disable_buy": "구매 행동 비활성화", "disable_sell": "판매 조치 비활성화", - "cake_2fa_preset" : "케이크 2FA 프리셋", + "cake_2fa_preset": "케이크 2FA 프리셋", "narrow": "좁은", "normal": "정상", "aggressive": "지나치게 열심인", "require_for_assessing_wallet": "지갑 접근을 위해 필요", - "require_for_sends_to_non_contacts" : "비접촉자에게 보내는 데 필요", - "require_for_sends_to_contacts" : "연락처로 보내기에 필요", - "require_for_sends_to_internal_wallets" : "내부 지갑으로 보내는 데 필요", - "require_for_exchanges_to_internal_wallets" : "내부 지갑으로의 교환에 필요", - "require_for_adding_contacts" : "연락처 추가에 필요", - "require_for_creating_new_wallets" : "새 지갑 생성에 필요", - "require_for_all_security_and_backup_settings" : "모든 보안 및 백업 설정에 필요", + "require_for_sends_to_non_contacts": "비접촉자에게 보내는 데 필요", + "require_for_sends_to_contacts": "연락처로 보내기에 필요", + "require_for_sends_to_internal_wallets": "내부 지갑으로 보내는 데 필요", + "require_for_exchanges_to_internal_wallets": "내부 지갑으로의 교환에 필요", + "require_for_adding_contacts": "연락처 추가에 필요", + "require_for_creating_new_wallets": "새 지갑 생성에 필요", + "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", "available_balance_description": "이 지갑에서 사용할 수 있는 잔액입니다. 이 잔액은 블록체인에서 가져온 것이며, Cake Wallet이 사용할 수 없습니다.", "syncing_wallet_alert_title": "지갑 동기화 중", "syncing_wallet_alert_content": "상단에 \"동기화됨\"이라고 표시될 때까지 잔액 및 거래 목록이 완전하지 않을 수 있습니다. 자세히 알아보려면 클릭/탭하세요.", @@ -672,5 +672,11 @@ "slidable": "슬라이딩 가능", "manage_nodes": "노드 관리", "etherscan_history": "이더스캔 역사", - "template_name": "템플릿 이름" -} + "template_name": "템플릿 이름", + "support_title_live_chat": "실시간 지원", + "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", + "support_title_guides": "케이크 지갑 가이드", + "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", + "support_title_other_links": "다른 지원 링크", + "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오." +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c9210077a..b3ba2a7dd 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -632,18 +632,18 @@ "setup_totp_recommended": "TOTP ကို စနစ်ထည့်သွင်းပါ (အကြံပြုထားသည်)", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "cake_2fa_preset" : "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", + "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", "narrow": "ကျဉ်းသော", "normal": "ပုံမှန်", "aggressive": "စိတ်အားထက်သန်ခြင်း။", "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", - "require_for_sends_to_non_contacts" : "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_contacts" : "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_internal_wallets" : "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_exchanges_to_internal_wallets" : "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "require_for_adding_contacts" : "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", - "require_for_creating_new_wallets" : "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", - "require_for_all_security_and_backup_settings" : "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", + "require_for_sends_to_non_contacts": "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_contacts": "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_internal_wallets": "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_exchanges_to_internal_wallets": "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", + "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", + "require_for_creating_new_wallets": "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", + "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", "available_balance_description": "သင့်ရဲ့ အကောင့်တွင် ရရှိနိုင်သော ငွေကျန်ငွေကို ပြန်လည်ပေးသွင်းပါ။", "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", "syncing_wallet_alert_content": "သင်၏လက်ကျန်နှင့် ငွေပေးငွေယူစာရင်းသည် ထိပ်တွင် \"Synchronizeed\" ဟုပြောသည်အထိ မပြီးမြောက်နိုင်ပါ။ ပိုမိုလေ့လာရန် နှိပ်/နှိပ်ပါ။", @@ -670,5 +670,11 @@ "slidable": "လျှောချနိုင်သည်။", "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", "etherscan_history": "Etherscan သမိုင်း", - "template_name": "နမူနာပုံစံ" -} + "template_name": "နမူနာပုံစံ", + "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", + "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", + "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", + "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", + "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", + "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 1a11ceb19..aca33d051 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -672,5 +672,11 @@ "slidable": "Verschuifbaar", "manage_nodes": "Beheer knooppunten", "etherscan_history": "Etherscan-geschiedenis", - "template_name": "Sjabloonnaam" + "template_name": "Sjabloonnaam", + "support_title_live_chat": "Live ondersteuning", + "support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen", + "support_title_guides": "Cake -portemonnee gidsen", + "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", + "support_title_other_links": "Andere ondersteuningslinks", + "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 26543da46..56871f242 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -672,5 +672,11 @@ "slidable": "Przesuwne", "manage_nodes": "Zarządzaj węzłami", "etherscan_history": "Historia Etherscanu", - "template_name": "Nazwa szablonu" + "template_name": "Nazwa szablonu", + "support_title_live_chat": "Wsparcie na żywo", + "support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia", + "support_title_guides": "Przewodniki portfela ciasta", + "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", + "support_title_other_links": "Inne linki wsparcia", + "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ac76d4df8..7cccc3c9e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -671,5 +671,11 @@ "slidable": "Deslizável", "manage_nodes": "Gerenciar nós", "etherscan_history": "história Etherscan", - "template_name": "Nome do modelo" + "template_name": "Nome do modelo", + "support_title_live_chat": "Apoio ao vivo", + "support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar", + "support_title_guides": "Guias da carteira de bolo", + "support_description_guides": "Documentação e suporte para problemas comuns", + "support_title_other_links": "Outros links de suporte", + "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c0022c0e4..40f9447ba 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -270,7 +270,6 @@ "error_text_node_address": "Пожалуйста, введите iPv4 адрес", "error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535", "error_text_node_proxy_address": "Введите <IPv4-адрес>:<порт>, например 127.0.0.1:9050.", - "error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex", "error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12", "error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2", @@ -635,18 +634,18 @@ "setup_totp_recommended": "Настроить TOTP (рекомендуется)", "disable_buy": "Отключить действие покупки", "disable_sell": "Отключить действие продажи", - "cake_2fa_preset" : "Торт 2FA Preset", + "cake_2fa_preset": "Торт 2FA Preset", "narrow": "Узкий", "normal": "Нормальный", "aggressive": "чрезмерно усердный", "require_for_assessing_wallet": "Требовать для доступа к кошельку", - "require_for_sends_to_non_contacts" : "Требовать для отправки не контактам", - "require_for_sends_to_contacts" : "Требовать для отправки контактам", - "require_for_sends_to_internal_wallets" : "Требовать отправки на внутренние кошельки", - "require_for_exchanges_to_internal_wallets" : "Требовать для обмена на внутренние кошельки", - "require_for_adding_contacts" : "Требовать добавления контактов", - "require_for_creating_new_wallets" : "Требовать для создания новых кошельков", - "require_for_all_security_and_backup_settings" : "Требовать все настройки безопасности и резервного копирования", + "require_for_sends_to_non_contacts": "Требовать для отправки не контактам", + "require_for_sends_to_contacts": "Требовать для отправки контактам", + "require_for_sends_to_internal_wallets": "Требовать отправки на внутренние кошельки", + "require_for_exchanges_to_internal_wallets": "Требовать для обмена на внутренние кошельки", + "require_for_adding_contacts": "Требовать добавления контактов", + "require_for_creating_new_wallets": "Требовать для создания новых кошельков", + "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", "available_balance_description": "Доступный баланс - это средства, которые вы можете использовать для покупки или продажи криптовалюты.", "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", "syncing_wallet_alert_content": "Ваш баланс и список транзакций могут быть неполными, пока вверху не будет написано «СИНХРОНИЗИРОВАНО». Щелкните/коснитесь, чтобы узнать больше.", @@ -673,5 +672,11 @@ "slidable": "Скользящий", "manage_nodes": "Управление узлами", "etherscan_history": "История Эфириума", - "template_name": "Имя Шаблона" -} + "template_name": "Имя Шаблона", + "support_title_live_chat": "Живая поддержка", + "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", + "support_title_guides": "Корт -гиды", + "support_description_guides": "Документация и поддержка общих вопросов", + "support_title_other_links": "Другие ссылки на поддержку", + "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f9aff7f14..9ffd7af11 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -632,18 +632,18 @@ "setup_totp_recommended": "ตั้งค่า TOTP (แนะนำ)", "disable_buy": "ปิดการใช้งานการซื้อ", "disable_sell": "ปิดการใช้งานการขาย", - "cake_2fa_preset" : "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", + "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", "narrow": "แคบ", "normal": "ปกติ", "aggressive": "กระตือรือร้นมากเกินไป", "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", - "require_for_sends_to_non_contacts" : "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", - "require_for_sends_to_contacts" : "จำเป็นต้องส่งไปยังผู้ติดต่อ", - "require_for_sends_to_internal_wallets" : "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", - "require_for_exchanges_to_internal_wallets" : "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", - "require_for_adding_contacts" : "ต้องการสำหรับการเพิ่มผู้ติดต่อ", - "require_for_creating_new_wallets" : "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", - "require_for_all_security_and_backup_settings" : "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", + "require_for_sends_to_non_contacts": "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", + "require_for_sends_to_contacts": "จำเป็นต้องส่งไปยังผู้ติดต่อ", + "require_for_sends_to_internal_wallets": "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", + "require_for_exchanges_to_internal_wallets": "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", + "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", + "require_for_creating_new_wallets": "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", + "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", "available_balance_description": "จำนวนเงินที่คุณสามารถใช้ได้ในการซื้อหรือขาย", "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", "syncing_wallet_alert_content": "รายการยอดเงินและธุรกรรมของคุณอาจไม่สมบูรณ์จนกว่าจะมีข้อความว่า “ซิงโครไนซ์” ที่ด้านบน คลิก/แตะเพื่อเรียนรู้เพิ่มเติม่", @@ -670,5 +670,11 @@ "slidable": "เลื่อนได้", "manage_nodes": "จัดการโหนด", "etherscan_history": "ประวัติอีเธอร์สแกน", - "template_name": "ชื่อแม่แบบ" -} + "template_name": "ชื่อแม่แบบ", + "support_title_live_chat": "การสนับสนุนสด", + "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", + "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", + "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", + "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", + "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 9386a6571..dedf7cf28 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -671,5 +671,11 @@ "slidable": "kaydırılabilir", "manage_nodes": "Düğümleri yönet", "etherscan_history": "Etherscan geçmişi", - "template_name": "şablon adı" + "template_name": "şablon adı", + "support_title_live_chat": "Canlı destek", + "support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur", + "support_title_guides": "Kek Cüzdan Kılavuzları", + "support_description_guides": "Ortak sorunlara belge ve destek", + "support_title_other_links": "Diğer destek bağlantıları", + "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 744691cdd..f8a2777e5 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -672,5 +672,11 @@ "slidable": "Розсувний", "manage_nodes": "Керуйте вузлами", "etherscan_history": "Історія Etherscan", - "template_name": "Назва шаблону" + "template_name": "Назва шаблону", + "support_title_live_chat": "Жива підтримка", + "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", + "support_title_guides": "Поклики для гаманців тортів", + "support_description_guides": "Документація та підтримка загальних питань", + "support_title_other_links": "Інші посилання на підтримку", + "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index f016d56c7..5eed0d35b 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -626,18 +626,18 @@ "setup_totp_recommended": "TOTP ترتیب دیں (تجویز کردہ)", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", - "cake_2fa_preset" : "کیک 2FA پیش سیٹ", + "cake_2fa_preset": "کیک 2FA پیش سیٹ", "narrow": "تنگ", "normal": "نارمل", "aggressive": "حد سے زیادہ پرجوش", "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", - "require_for_sends_to_non_contacts" : "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_contacts" : "رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_internal_wallets" : "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", - "require_for_exchanges_to_internal_wallets" : "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", - "require_for_adding_contacts" : "رابطوں کو شامل کرنے کی ضرورت ہے۔", - "require_for_creating_new_wallets" : "نئے بٹوے بنانے کی ضرورت ہے۔", - "require_for_all_security_and_backup_settings" : "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", + "require_for_sends_to_non_contacts": "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_for_sends_to_contacts": "رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_for_sends_to_internal_wallets": "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", + "require_for_exchanges_to_internal_wallets": "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", + "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", + "require_for_creating_new_wallets": "نئے بٹوے بنانے کی ضرورت ہے۔", + "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", "available_balance_description": "”دستیاب بیلنس” یا ”تصدیق شدہ بیلنس” وہ فنڈز ہیں جو فوری طور پر خرچ کیے جا سکتے ہیں۔ اگر فنڈز کم بیلنس میں ظاہر ہوتے ہیں لیکن اوپر کے بیلنس میں نہیں، تو آپ کو مزید نیٹ ورک کی تصدیقات حاصل کرنے کے لیے آنے والے فنڈز کے لیے چند منٹ انتظار کرنا چاہیے۔ مزید تصدیق حاصل کرنے کے بعد، وہ قابل خرچ ہوں گے۔", "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", "syncing_wallet_alert_content": "آپ کے بیلنس اور لین دین کی فہرست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ یہ سب سے اوپر \"SYNCRONIZED\" نہ کہے۔ مزید جاننے کے لیے کلک/تھپتھپائیں۔", @@ -664,5 +664,11 @@ "slidable": "سلائیڈ ایبل", "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", - "template_name": "ٹیمپلیٹ کا نام" -} + "template_name": "ٹیمپلیٹ کا نام", + "support_title_live_chat": "براہ راست مدد", + "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", + "support_title_guides": "کیک پرس گائڈز", + "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", + "support_title_other_links": "دوسرے سپورٹ لنکس", + "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 74c03005f..c99b00ebd 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -628,18 +628,18 @@ "setup_totp_recommended": "Sọ TOTP (Kẹṣọdọ)", "disable_buy": "Ko iṣọrọ ọja", "disable_sell": "Ko iṣọrọ iṣọrọ", - "cake_2fa_preset" : "Cake 2FA Tito", + "cake_2fa_preset": "Cake 2FA Tito", "narrow": "Taara", "normal": "Deede", "aggressive": "Onítara", "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", - "require_for_sends_to_non_contacts" : "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", - "require_for_sends_to_contacts" : "Beere fun fifiranṣẹ si awọn olubasọrọ", - "require_for_sends_to_internal_wallets" : "Beere fun fifiranṣẹ si awọn apamọwọ inu", - "require_for_exchanges_to_internal_wallets" : "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", - "require_for_adding_contacts" : "Beere fun fifi awọn olubasọrọ kun", - "require_for_creating_new_wallets" : "Beere fun ṣiṣẹda titun Woleti", - "require_for_all_security_and_backup_settings" : "Beere fun gbogbo aabo ati awọn eto afẹyinti", + "require_for_sends_to_non_contacts": "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", + "require_for_sends_to_contacts": "Beere fun fifiranṣẹ si awọn olubasọrọ", + "require_for_sends_to_internal_wallets": "Beere fun fifiranṣẹ si awọn apamọwọ inu", + "require_for_exchanges_to_internal_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", + "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", + "require_for_creating_new_wallets": "Beere fun ṣiṣẹda titun Woleti", + "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", "available_balance_description": "“Iwọntunwọnsi Wa” tabi “Iwọntunwọnsi Ijẹrisi” jẹ awọn owo ti o le ṣee lo lẹsẹkẹsẹ. Ti awọn owo ba han ni iwọntunwọnsi kekere ṣugbọn kii ṣe iwọntunwọnsi oke, lẹhinna o gbọdọ duro iṣẹju diẹ fun awọn owo ti nwọle lati gba awọn ijẹrisi nẹtiwọọki diẹ sii. Lẹhin ti wọn gba awọn ijẹrisi diẹ sii, wọn yoo jẹ inawo.", "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", "syncing_wallet_alert_content": "Iwontunws.funfun rẹ ati atokọ idunadura le ma pari titi ti yoo fi sọ “SYNCHRONIZED” ni oke. Tẹ/tẹ ni kia kia lati ni imọ siwaju sii.", @@ -666,5 +666,11 @@ "slidable": "Slidable", "manage_nodes": "Ṣakoso awọn apa", "etherscan_history": "Etherscan itan", - "template_name": "Orukọ Awoṣe" -} + "template_name": "Orukọ Awoṣe", + "support_title_live_chat": "Atilẹyin ifiwe", + "support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ", + "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", + "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", + "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", + "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 7184e4d40..dc1cfd139 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -633,18 +633,18 @@ "setup_totp_recommended": "设置 TOTP(推荐)", "disable_buy": "禁用购买操作", "disable_sell": "禁用卖出操作", - "cake_2fa_preset" : "蛋糕 2FA 预设", + "cake_2fa_preset": "蛋糕 2FA 预设", "narrow": "狭窄的", "normal": "普通的", "aggressive": "过分热心", "require_for_assessing_wallet": "需要访问钱包", - "require_for_sends_to_non_contacts" : "需要发送给非联系人", - "require_for_sends_to_contacts" : "需要发送给联系人", - "require_for_sends_to_internal_wallets" : "需要发送到内部钱包", - "require_for_exchanges_to_internal_wallets" : "需要兑换到内部钱包", - "require_for_adding_contacts" : "需要添加联系人", - "require_for_creating_new_wallets" : "创建新钱包的要求", - "require_for_all_security_and_backup_settings" : "需要所有安全和备份设置", + "require_for_sends_to_non_contacts": "需要发送给非联系人", + "require_for_sends_to_contacts": "需要发送给联系人", + "require_for_sends_to_internal_wallets": "需要发送到内部钱包", + "require_for_exchanges_to_internal_wallets": "需要兑换到内部钱包", + "require_for_adding_contacts": "需要添加联系人", + "require_for_creating_new_wallets": "创建新钱包的要求", + "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", "available_balance_description": "可用余额是您可以使用的金额。冻结余额是您当前正在等待确认的金额。", "syncing_wallet_alert_title": "您的钱包正在同步", "syncing_wallet_alert_content": "您的余额和交易列表可能不完整,直到顶部显示“已同步”。单击/点击以了解更多信息。", @@ -671,5 +671,11 @@ "slidable": "可滑动", "manage_nodes": "管理节点", "etherscan_history": "以太扫描历史", - "template_name": "模板名称" -} + "template_name": "模板名称", + "support_title_live_chat": "实时支持", + "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", + "support_title_guides": "蛋糕钱包指南", + "support_description_guides": "对常见问题的文档和支持", + "support_title_other_links": "其他支持链接", + "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴" +} \ No newline at end of file diff --git a/tool/append_translation.dart b/tool/append_translation.dart new file mode 100644 index 000000000..e56ad89d6 --- /dev/null +++ b/tool/append_translation.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:translator/translator.dart'; + +const defaultLang = "en"; +const langs = [ + "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", + "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", + "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) +]; +final translator = GoogleTranslator(); + +void main(List<String> args) async { + if (args.length != 2) { + throw Exception( + 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); + } + + final name = args.first; + final text = args.last; + + print('Appending "$name": "$text"'); + + for (var lang in langs) { + final fileName = getFileName(lang); + final translation = await getTranslation(text, lang); + + appendArbFile(fileName, name, translation); + } +} + +void appendArbFile(String fileName, String name, String text) { + final file = File(fileName); + final inputContent = file.readAsStringSync(); + final arbObj = json.decode(inputContent) as Map<String, dynamic>; + + if (arbObj.containsKey(name)) { + print("String $name already exists in $fileName!"); + return; + } + + arbObj.addAll({name: text}); + + final outputContent = json + .encode(arbObj) + .replaceAll('","', '",\n "') + .replaceAll('{"', '{\n "') + .replaceAll('"}', '"\n}') + .replaceAll('":"', '": "'); + + file.writeAsStringSync(outputContent); +} + + +Future<String> getTranslation(String text, String lang) async { + if (lang == defaultLang) return text; + return (await translator.translate(text, from: defaultLang, to: lang)).text; +} + +String getFileName(String lang) { + final shortLang = lang + .split("-") + .first; + return "./res/values/strings_$shortLang.arb"; +} diff --git a/tool/update_secrets.dart b/tool/update_secrets.dart index 69e3f8447..0f2e59419 100644 --- a/tool/update_secrets.dart +++ b/tool/update_secrets.dart @@ -33,8 +33,7 @@ Future<void> updateSecretsConfig(List<String> args) async { }); final fileConfig = - json.decode(configFile.readAsStringSync()) as Map<String, dynamic> ?? - <String, dynamic>{}; + json.decode(configFile.readAsStringSync()) as Map<String, dynamic>; fileConfig.forEach((key, dynamic value) { if (secrets[key] == null) { secrets[key] = value; diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 1b62dbf60..7819a582c 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -31,6 +31,7 @@ class SecretKey { SecretKey('anonPayReferralCode', () => ''), SecretKey('fiatApiKey', () => ''), SecretKey('payfuraApiKey', () => ''), + SecretKey('chatwootWebsiteToken', () => ''), ]; static final ethereumSecrets = [ From 09c942564ed94ca2e5ec0faccfce808be4076edc Mon Sep 17 00:00:00 2001 From: Rafael Saes <76502841+saltrafael@users.noreply.github.com> Date: Thu, 17 Aug 2023 12:28:31 -0300 Subject: [PATCH 03/18] Cw 396 additional themes (#962) * fix: SectionStandardList using BuildContext as param * refactor: deprecated backgroundColor -> colorScheme.background * refactor: themeBase and current themes * refactor: accentTextTheme.titleLarge.color -> dialogTheme.backgroundColor * refactor: gradient background * refactor: text themes using the same color as primaryColor * refactor: accentTextTheme.bodySmall.color -> cardColor * refactor: text themes using same dialogBackgroundColor * refactor: scrollbarTheme * refactor: create SyncIndicatorTheme * refactor: SectionDivider * refactor: base_page improvements and simplify * refactor: collapsible_standart_list improvements * refactor: accentTextTheme.bodyLarge.backgroundColor -> KeyboardTheme.keyboardBarColor * refactor: create PinCodeTheme for accentTextTheme.bodyMedium * refactor: create SupportPageTheme for accentTextTheme.displayLarge.backgroundColor and fix cases that use it * refactor: accentTextTheme.displayLarge.color -> disabledColor * refactor: create ExchangePageTheme * refactor: create DashboardPageTheme and use textColor * refactor: create NewWalletTheme for accentTextTheme.displayMedium * refactor: create BalancePageTheme for accentTextTheme.displaySmall.backgroundColor * refactor: create AddressTheme for accentTextTheme.displaySmall.color * refactor: create IndicatorDotTheme * refactor: create CakeMenuTheme * refactor: create FilterTheme * refactor: create WalletListTheme * refactor: accentTextTheme.bodySmall.decorationColor -> InfoTheme.textColor * refactor: accentTextTheme.titleLarge.backgroundColor -> PickerTheme.dividerColor * refactor: primaryTextTheme.bodyLarge.backgroundColor -> AlertTheme.leftButtonTextColor * refactor: primaryTextTheme.displayLarge.backgroundColor -> OrderTheme.iconColor * refactor: create SendPageTheme * fix: missing migrated styles * refactor: primaryTextTheme.labelSmall.decorationColor -> PlaceholderTheme.color * refactor: create TransactionTradeTheme * refactor: create CakeTextTheme * refactor: create AccountListTheme * refactor: create ReceivePageTheme * refactor: create QRCodeTheme * refactor: move remaining items to CakeTextTheme and some missing fixes * feat(display_settings): add new theme selector * feat: additional themes * fix: conflict error * fix(lag): move colorScheme initialization to constructor * feat: add backdropColor to alert and picker backdrop filters * fix: merge fixes * fix: send template page missing new colors * fix: anonpay pages title and icon colors * fix: merge fixes * fix: unspent coins page * fix: also fix exchange template * fix: missing checkbox * fix: fixes for high contrast theme * Merge branch 'main' into CW-396-additional-themes * fix: merge fixes * fix: .gitignore and rm added files * Fix review comments --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> --- .gitignore | 2 +- cw_bitcoin/pubspec.lock | 2 +- cw_core/pubspec.lock | 2 +- cw_monero/example/pubspec.lock | 2 +- cw_monero/pubspec.lock | 2 +- lib/palette.dart | 9 +- .../anonpay_details/anonpay_details_page.dart | 3 +- lib/src/screens/backup/backup_page.dart | 2 +- .../backup/edit_backup_password_page.dart | 11 +- lib/src/screens/base_page.dart | 66 ++- lib/src/screens/buy/buy_webview_page.dart | 3 - lib/src/screens/buy/pre_order_page.dart | 26 +- .../screens/contact/contact_list_page.dart | 34 +- lib/src/screens/contact/contact_page.dart | 20 +- lib/src/screens/dashboard/dashboard_page.dart | 53 +- .../desktop_action_button.dart | 20 +- .../desktop_sidebar/side_menu_item.dart | 3 +- .../desktop_wallet_selection_dropdown.dart | 10 +- .../desktop_widgets/dropdown_item_widget.dart | 3 +- .../screens/dashboard/edit_token_page.dart | 9 +- .../screens/dashboard/home_settings_page.dart | 18 +- .../dashboard/widgets/action_button.dart | 8 +- .../dashboard/widgets/address_page.dart | 46 +- .../widgets/anonpay_transaction_row.dart | 8 +- .../dashboard/widgets/balance_page.dart | 47 +- .../dashboard/widgets/date_section_raw.dart | 6 +- .../dashboard/widgets/filter_widget.dart | 17 +- .../screens/dashboard/widgets/header_row.dart | 11 +- .../dashboard/widgets/market_place_page.dart | 6 +- .../dashboard/widgets/menu_widget.dart | 223 ++++---- .../screens/dashboard/widgets/order_row.dart | 14 +- .../present_receive_option_picker.dart | 22 +- .../dashboard/widgets/sync_indicator.dart | 7 +- .../widgets/sync_indicator_icon.dart | 6 +- .../screens/dashboard/widgets/trade_row.dart | 8 +- .../dashboard/widgets/transaction_raw.dart | 21 +- .../dashboard/widgets/transactions_page.dart | 6 +- .../screens/disclaimer/disclaimer_page.dart | 47 +- lib/src/screens/exchange/exchange_page.dart | 20 +- .../exchange/exchange_template_page.dart | 43 +- .../widgets/currency_picker_item_widget.dart | 27 +- .../widgets/currency_picker_widget.dart | 6 +- .../exchange/widgets/exchange_card.dart | 62 +-- .../mobile_exchange_cards_section.dart | 12 +- .../widgets/present_provider_picker.dart | 6 +- .../exchange_trade/exchange_confirm_page.dart | 43 +- .../exchange_trade/exchange_trade_page.dart | 54 +- .../exchange_trade/information_page.dart | 12 +- lib/src/screens/faq/faq_item.dart | 7 +- .../ionia/auth/ionia_create_account_page.dart | 21 +- .../screens/ionia/auth/ionia_login_page.dart | 11 +- .../ionia/auth/ionia_verify_otp_page.dart | 17 +- .../ionia/auth/ionia_welcome_page.dart | 17 +- .../ionia/cards/ionia_account_cards_page.dart | 46 +- .../ionia/cards/ionia_account_page.dart | 16 +- .../cards/ionia_activate_debit_card_page.dart | 11 +- .../cards/ionia_buy_card_detail_page.dart | 45 +- .../ionia/cards/ionia_buy_gift_card.dart | 53 +- .../ionia/cards/ionia_custom_redeem_page.dart | 48 +- .../ionia/cards/ionia_custom_tip_page.dart | 48 +- .../ionia/cards/ionia_debit_card_page.dart | 50 +- .../cards/ionia_gift_card_detail_page.dart | 19 +- .../ionia/cards/ionia_manage_cards_page.dart | 65 +-- .../ionia/cards/ionia_more_options_page.dart | 13 +- .../cards/ionia_payment_status_page.dart | 25 +- .../ionia/widgets/ionia_alert_model.dart | 11 +- .../ionia/widgets/ionia_filter_modal.dart | 12 +- lib/src/screens/ionia/widgets/ionia_tile.dart | 6 +- .../ionia/widgets/rounded_checkbox.dart | 2 +- .../ionia/widgets/text_icon_button.dart | 5 +- .../monero_account_edit_or_create_page.dart | 2 +- .../monero_account_list_page.dart | 4 +- .../monero_accounts/widgets/account_tile.dart | 44 +- .../advanced_privacy_settings_page.dart | 11 +- .../screens/new_wallet/new_wallet_page.dart | 33 +- .../new_wallet/new_wallet_type_page.dart | 5 +- .../new_wallet/widgets/select_button.dart | 27 +- .../nodes/node_create_or_edit_page.dart | 5 +- .../screens/nodes/widgets/node_list_row.dart | 13 +- .../order_details/order_details_page.dart | 3 +- lib/src/screens/pin_code/pin_code_widget.dart | 28 +- .../screens/receive/anonpay_invoice_page.dart | 29 +- .../screens/receive/anonpay_receive_page.dart | 37 +- .../screens/receive/fullscreen_qr_page.dart | 34 +- lib/src/screens/receive/receive_page.dart | 76 +-- .../widgets/anonpay_currency_input_field.dart | 29 +- .../receive/widgets/anonpay_input_form.dart | 22 +- .../widgets/anonpay_status_section.dart | 25 +- .../receive/widgets/copy_link_item.dart | 16 +- .../receive/widgets/currency_input_field.dart | 30 +- .../screens/receive/widgets/header_tile.dart | 12 +- .../screens/receive/widgets/qr_widget.dart | 19 +- .../release_notes/release_notes_screen.dart | 15 +- lib/src/screens/rescan/rescan_page.dart | 5 +- .../restore/restore_from_backup_page.dart | 5 +- .../restore_wallet_from_seed_details.dart | 5 +- .../screens/restore/sweeping_wallet_page.dart | 17 +- .../wallet_restore_from_keys_form.dart | 6 +- .../wallet_restore_from_seed_form.dart | 6 +- .../screens/restore/wallet_restore_page.dart | 21 +- .../restore/widgets/restore_button.dart | 1 + lib/src/screens/seed/pre_seed_page.dart | 5 +- lib/src/screens/seed/wallet_seed_page.dart | 17 +- .../seed_language/seed_language_page.dart | 3 +- lib/src/screens/send/send_page.dart | 8 +- lib/src/screens/send/send_template_page.dart | 26 +- .../widgets/choose_yat_address_alert.dart | 7 +- .../send/widgets/confirm_sending_alert.dart | 26 +- .../widgets/prefix_currency_icon_widget.dart | 13 +- lib/src/screens/send/widgets/send_card.dart | 58 +-- .../send/widgets/send_template_card.dart | 23 +- .../desktop_settings_page.dart | 6 +- .../settings/display_settings_page.dart | 14 +- .../screens/settings/manage_nodes_page.dart | 3 +- .../widgets/settings_cell_with_arrow.dart | 3 +- .../widgets/settings_choices_cell.dart | 14 +- .../widgets/settings_link_provider_cell.dart | 2 +- .../widgets/settings_picker_cell.dart | 3 +- .../widgets/settings_theme_choice.dart | 117 +++++ .../widgets/settings_version_cell.dart | 3 +- lib/src/screens/setup_2fa/setup_2fa.dart | 5 +- .../setup_2fa/setup_2fa_enter_code_page.dart | 2 +- .../screens/setup_2fa/setup_2fa_qr_page.dart | 5 +- .../widgets/popup_cancellable_alert.dart | 5 +- .../address_edit_or_create_page.dart | 5 +- .../support/widgets/support_tiles.dart | 7 +- .../support_other_links_page.dart | 10 +- .../trade_details/trade_details_page.dart | 3 +- .../transaction_details_page.dart | 8 +- .../widgets/textfield_list_row.dart | 14 +- .../unspent_coins_details_page.dart | 3 +- .../unspent_coins_list_page.dart | 2 +- .../widgets/unspent_coins_list_item.dart | 20 +- .../widgets/unspent_coins_switch_row.dart | 6 +- lib/src/screens/wallet/wallet_edit_page.dart | 2 +- .../screens/wallet_keys/wallet_keys_page.dart | 106 ++-- .../screens/wallet_list/wallet_list_page.dart | 54 +- lib/src/screens/welcome/welcome_page.dart | 42 +- lib/src/screens/yat_emoji_id.dart | 12 +- lib/src/widgets/add_template_button.dart | 13 +- lib/src/widgets/address_text_field.dart | 26 +- lib/src/widgets/alert_background.dart | 6 +- lib/src/widgets/alert_with_one_action.dart | 10 +- lib/src/widgets/base_alert_dialog.dart | 41 +- lib/src/widgets/base_text_form_field.dart | 18 +- lib/src/widgets/blockchain_height_widget.dart | 3 +- lib/src/widgets/cake_scrollbar.dart | 5 +- lib/src/widgets/check_box_picker.dart | 30 +- lib/src/widgets/checkbox_widget.dart | 10 +- .../widgets/collapsible_standart_list.dart | 82 +-- lib/src/widgets/dashboard_card_widget.dart | 17 +- lib/src/widgets/gradient_background.dart | 30 ++ lib/src/widgets/introducing_card.dart | 14 +- lib/src/widgets/list_row.dart | 12 +- lib/src/widgets/picker.dart | 82 ++- .../widgets/picker_inner_wrapper_widget.dart | 5 +- lib/src/widgets/search_bar_widget.dart | 13 +- lib/src/widgets/section_divider.dart | 27 +- lib/src/widgets/seed_widget.dart | 22 +- lib/src/widgets/setting_action_button.dart | 11 +- lib/src/widgets/standard_checkbox.dart | 14 +- lib/src/widgets/standard_list.dart | 180 +++---- lib/src/widgets/standard_list_card.dart | 5 +- lib/src/widgets/standard_list_status_row.dart | 12 +- lib/src/widgets/standard_switch.dart | 10 +- lib/src/widgets/template_tile.dart | 10 +- lib/src/widgets/trail_button.dart | 6 +- lib/themes/bitcoin_dark_theme.dart | 14 + lib/themes/bitcoin_light_theme.dart | 13 + lib/themes/bright_theme.dart | 369 ++++---------- lib/themes/dark_theme.dart | 482 ++++++++---------- lib/themes/extensions/account_list_theme.dart | 58 +++ lib/themes/extensions/address_theme.dart | 24 + lib/themes/extensions/alert_theme.dart | 28 + lib/themes/extensions/balance_page_theme.dart | 53 ++ .../extensions/cake_scrollbar_theme.dart | 28 + lib/themes/extensions/cake_text_theme.dart | 65 +++ .../extensions/dashboard_page_theme.dart | 79 +++ .../extensions/exchange_page_theme.dart | 88 ++++ lib/themes/extensions/filter_theme.dart | 68 +++ .../extensions/indicator_dot_theme.dart | 30 ++ lib/themes/extensions/info_theme.dart | 21 + lib/themes/extensions/keyboard_theme.dart | 26 + lib/themes/extensions/menu_theme.dart | 75 +++ lib/themes/extensions/new_wallet_theme.dart | 30 ++ lib/themes/extensions/order_theme.dart | 21 + lib/themes/extensions/picker_theme.dart | 54 ++ lib/themes/extensions/pin_code_theme.dart | 28 + lib/themes/extensions/placeholder_theme.dart | 20 + lib/themes/extensions/qr_code_theme.dart | 28 + lib/themes/extensions/receive_page_theme.dart | 70 +++ lib/themes/extensions/seed_widget_theme.dart | 22 + lib/themes/extensions/send_page_theme.dart | 117 +++++ lib/themes/extensions/support_page_theme.dart | 21 + .../extensions/sync_indicator_theme.dart | 48 ++ .../extensions/transaction_trade_theme.dart | 29 ++ lib/themes/extensions/wallet_list_theme.dart | 38 ++ lib/themes/high_contrast_theme.dart | 118 +++++ lib/themes/light_theme.dart | 470 ++++++++--------- lib/themes/matrix_green_theme.dart | 14 + lib/themes/monero_dark_theme.dart | 194 +++++++ lib/themes/monero_light_theme.dart | 159 ++++++ lib/themes/theme_base.dart | 148 +++++- lib/themes/theme_list.dart | 39 +- res/values/strings_ar.arb | 8 +- res/values/strings_bg.arb | 6 + res/values/strings_cs.arb | 6 + res/values/strings_de.arb | 6 + res/values/strings_en.arb | 6 + res/values/strings_es.arb | 6 + res/values/strings_fr.arb | 6 + res/values/strings_ha.arb | 6 + res/values/strings_hi.arb | 6 + res/values/strings_hr.arb | 6 + res/values/strings_id.arb | 6 + res/values/strings_it.arb | 6 + res/values/strings_ja.arb | 8 +- res/values/strings_ko.arb | 8 +- res/values/strings_my.arb | 8 +- res/values/strings_nl.arb | 6 + res/values/strings_pl.arb | 6 + res/values/strings_pt.arb | 6 + res/values/strings_ru.arb | 8 +- res/values/strings_th.arb | 8 +- res/values/strings_tr.arb | 6 + res/values/strings_uk.arb | 6 + res/values/strings_ur.arb | 8 +- res/values/strings_yo.arb | 10 +- res/values/strings_zh.arb | 10 +- 229 files changed, 4089 insertions(+), 2869 deletions(-) create mode 100644 lib/src/screens/settings/widgets/settings_theme_choice.dart create mode 100644 lib/src/widgets/gradient_background.dart create mode 100644 lib/themes/bitcoin_dark_theme.dart create mode 100644 lib/themes/bitcoin_light_theme.dart create mode 100644 lib/themes/extensions/account_list_theme.dart create mode 100644 lib/themes/extensions/address_theme.dart create mode 100644 lib/themes/extensions/alert_theme.dart create mode 100644 lib/themes/extensions/balance_page_theme.dart create mode 100644 lib/themes/extensions/cake_scrollbar_theme.dart create mode 100644 lib/themes/extensions/cake_text_theme.dart create mode 100644 lib/themes/extensions/dashboard_page_theme.dart create mode 100644 lib/themes/extensions/exchange_page_theme.dart create mode 100644 lib/themes/extensions/filter_theme.dart create mode 100644 lib/themes/extensions/indicator_dot_theme.dart create mode 100644 lib/themes/extensions/info_theme.dart create mode 100644 lib/themes/extensions/keyboard_theme.dart create mode 100644 lib/themes/extensions/menu_theme.dart create mode 100644 lib/themes/extensions/new_wallet_theme.dart create mode 100644 lib/themes/extensions/order_theme.dart create mode 100644 lib/themes/extensions/picker_theme.dart create mode 100644 lib/themes/extensions/pin_code_theme.dart create mode 100644 lib/themes/extensions/placeholder_theme.dart create mode 100644 lib/themes/extensions/qr_code_theme.dart create mode 100644 lib/themes/extensions/receive_page_theme.dart create mode 100644 lib/themes/extensions/seed_widget_theme.dart create mode 100644 lib/themes/extensions/send_page_theme.dart create mode 100644 lib/themes/extensions/support_page_theme.dart create mode 100644 lib/themes/extensions/sync_indicator_theme.dart create mode 100644 lib/themes/extensions/transaction_trade_theme.dart create mode 100644 lib/themes/extensions/wallet_list_theme.dart create mode 100644 lib/themes/high_contrast_theme.dart create mode 100644 lib/themes/matrix_green_theme.dart create mode 100644 lib/themes/monero_dark_theme.dart create mode 100644 lib/themes/monero_light_theme.dart diff --git a/.gitignore b/.gitignore index 6fd8f33d6..09583004b 100644 --- a/.gitignore +++ b/.gitignore @@ -143,4 +143,4 @@ assets/images/app_logo.png macos/Runner/Info.plist macos/Runner/DebugProfile.entitlements -macos/Runner/Release.entitlements \ No newline at end of file +macos/Runner/Release.entitlements diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 4d864059f..bfcd9e5a6 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -746,5 +746,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <4.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.0.0" diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 70652ec35..01e19dda4 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -665,5 +665,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <4.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 19d9cef8f..f4c36e69c 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -399,5 +399,5 @@ packages: source: hosted version: "0.2.0+3" sdks: - dart: ">=2.18.1 <4.0.0" + dart: ">=2.18.1 <3.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 1e33631d5..437184a7d 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -672,5 +672,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <4.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.0.0" diff --git a/lib/palette.dart b/lib/palette.dart index 6f4526e67..46e2e8165 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -15,6 +15,9 @@ class Palette { static const Color nightBlue = Color.fromRGBO(46, 57, 96, 1.0); static const Color moderateOrangeYellow = Color.fromRGBO(245, 134, 82, 1.0); static const Color moderateOrange = Color.fromRGBO(235, 117, 63, 1.0); + static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0); + static const Color moneroLightOrange = Color.fromRGBO(250, 240, 246, 1.0); + static const Color bitcoinOrange = Color.fromRGBO(242, 169, 0, 1.0); static const Color shineGreen = Color.fromRGBO(76, 189, 87, 1.0); static const Color moderateGreen = Color.fromRGBO(45, 158, 56, 1.0); static const Color cornflower = Color.fromRGBO(85, 147, 240, 1.0); @@ -48,6 +51,7 @@ class Palette { static const Color paleCornflowerBlue = Color.fromRGBO(185, 196, 237, 1.0); static const Color manatee = Color.fromRGBO(153, 161, 176, 1.0); static const Color stateGray = Color.fromRGBO(68, 74, 89, 1.0); + static const Color highContrastGray = Color.fromRGBO(76, 76, 76, 1.0); static const Color frostySky = Color.fromRGBO(0, 184, 250, 1.0); } @@ -90,4 +94,7 @@ class PaletteDark { static const Color lightPurpleBlue = Color.fromRGBO(120, 133, 170, 1.0); static const Color indicatorVioletBlue = Color.fromRGBO(59, 72, 119, 1.0); static const Color granite = Color.fromRGBO(48, 51, 60, 1.0); -} \ No newline at end of file + static const Color matrixGreen = Color.fromRGBO(18, 229, 90, 1.0); + static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0); + static const Color moneroCard = Color.fromRGBO(20, 21, 24, 1.0); +} diff --git a/lib/src/screens/anonpay_details/anonpay_details_page.dart b/lib/src/screens/anonpay_details/anonpay_details_page.dart index 7491bb7a3..fc03617fa 100644 --- a/lib/src/screens/anonpay_details/anonpay_details_page.dart +++ b/lib/src/screens/anonpay_details/anonpay_details_page.dart @@ -42,10 +42,9 @@ class _AnonpayDetailsPageBodyState extends State<AnonpayDetailsPageBody> { @override Widget build(BuildContext context) { return SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => widget.anonpayDetailsViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (__, index) { final item = widget.anonpayDetailsViewModel.items[index]; if (item is DetailsListStatusItem) { diff --git a/lib/src/screens/backup/backup_page.dart b/lib/src/screens/backup/backup_page.dart index 1b3b7e3d9..f7a224aac 100644 --- a/lib/src/screens/backup/backup_page.dart +++ b/lib/src/screens/backup/backup_page.dart @@ -80,7 +80,7 @@ class BackupPage extends BasePage { isLoading: backupViewModelBase.state is IsExecutingState, onPressed: () => onExportBackup(context), text: S.of(context).export_backup, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), diff --git a/lib/src/screens/backup/edit_backup_password_page.dart b/lib/src/screens/backup/edit_backup_password_page.dart index 40eb722c9..93207c191 100644 --- a/lib/src/screens/backup/edit_backup_password_page.dart +++ b/lib/src/screens/backup/edit_backup_password_page.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/view_model/edit_backup_password_view_model.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; class EditBackupPasswordPage extends BasePage { EditBackupPasswordPage(this.editBackupPasswordViewModel) @@ -39,19 +40,13 @@ class EditBackupPasswordPage extends BasePage { controller: textEditingController, style: TextStyle( fontSize: 26, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!)))), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)))), Positioned( child: Observer( builder: (_) => PrimaryButton( onPressed: () => onSave(context), text: S.of(context).save, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: !editBackupPasswordViewModel.canSave)), bottom: 24, diff --git a/lib/src/screens/base_page.dart b/lib/src/screens/base_page.dart index 2e1d50f9a..20c918be6 100644 --- a/lib/src/screens/base_page.dart +++ b/lib/src/screens/base_page.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/src/widgets/nav_bar.dart'; @@ -10,22 +9,22 @@ import 'package:cake_wallet/generated/i18n.dart'; enum AppBarStyle { regular, withShadow, transparent } abstract class BasePage extends StatelessWidget { - BasePage() - : _scaffoldKey = GlobalKey<ScaffoldState>(); + BasePage() : _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey; - final Image closeButtonImage = - Image.asset('assets/images/close_button.png'); + final Image closeButtonImage = Image.asset('assets/images/close_button.png'); final Image closeButtonImageDarkTheme = - Image.asset('assets/images/close_button_dark_theme.png'); + Image.asset('assets/images/close_button_dark_theme.png'); String? get title => null; - Color get backgroundLightColor => Colors.white; + Color? get backgroundLightColor => null; - Color get backgroundDarkColor => PaletteDark.backgroundColor; + Color? get backgroundDarkColor => null; - Color? get titleColor => null; + bool get gradientBackground => false; + + bool get gradientAll => false; bool get resizeToAvoidBottomInset => true; @@ -43,15 +42,41 @@ abstract class BasePage extends StatelessWidget { void onClose(BuildContext context) => Navigator.of(context).pop(); + Color pageBackgroundColor(BuildContext context) => + (currentTheme.type == ThemeType.dark + ? backgroundDarkColor + : backgroundLightColor) ?? + (gradientBackground && currentTheme.type == ThemeType.bright + ? Colors.transparent + : Theme.of(context).colorScheme.background); + + Color titleColor(BuildContext context) => + (gradientBackground && currentTheme.type == ThemeType.bright) || + (gradientAll && currentTheme.brightness == Brightness.light) + ? Colors.white + : Theme.of(context).appBarTheme.titleTextStyle!.color!; + + Color? pageIconColor(BuildContext context) => titleColor(context); + + Widget closeButton(BuildContext context) => Image.asset( + currentTheme.type == ThemeType.dark + ? 'assets/images/close_button_dark_theme.png' + : 'assets/images/close_button.png', + color: pageIconColor(context), + height: 16, + ); + + Widget backButton(BuildContext context) => Icon( + Icons.arrow_back_ios, + color: pageIconColor(context), + size: 16, + ); + Widget? leading(BuildContext context) { if (ModalRoute.of(context)?.isFirst ?? true) { return null; } - final _backButton = Icon(Icons.arrow_back_ios, - color: titleColor ?? Theme.of(context).primaryTextTheme!.titleLarge!.color!, - size: 16,); - return MergeSemantics( child: SizedBox( height: 37, @@ -66,7 +91,7 @@ abstract class BasePage extends StatelessWidget { (states) => Colors.transparent), ), onPressed: () => onClose(context), - child: _backButton, + child: backButton(context), ), ), ), @@ -83,8 +108,7 @@ abstract class BasePage extends StatelessWidget { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: titleColor ?? - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + color: titleColor(context)), ); } @@ -93,9 +117,8 @@ abstract class BasePage extends StatelessWidget { Widget? floatingActionButton(BuildContext context) => null; ObstructingPreferredSizeWidget appBar(BuildContext context) { - final appBarColor = currentTheme.type == ThemeType.dark - ? backgroundDarkColor : backgroundLightColor; - + final appBarColor = pageBackgroundColor(context); + switch (appBarStyle) { case AppBarStyle.regular: // FIX-ME: NavBar no context @@ -139,12 +162,9 @@ abstract class BasePage extends StatelessWidget { @override Widget build(BuildContext context) { - final _backgroundColor = currentTheme.type == ThemeType.dark - ? backgroundDarkColor : backgroundLightColor; - final root = Scaffold( key: _scaffoldKey, - backgroundColor: _backgroundColor, + backgroundColor: pageBackgroundColor(context), resizeToAvoidBottomInset: resizeToAvoidBottomInset, extendBodyBehindAppBar: extendBodyBehindAppBar, endDrawer: endDrawer, diff --git a/lib/src/screens/buy/buy_webview_page.dart b/lib/src/screens/buy/buy_webview_page.dart index b19a112fc..a6ea2ab7b 100644 --- a/lib/src/screens/buy/buy_webview_page.dart +++ b/lib/src/screens/buy/buy_webview_page.dart @@ -24,9 +24,6 @@ class BuyWebViewPage extends BasePage { @override Color get backgroundDarkColor => Colors.white; - @override - Color get titleColor => Palette.darkBlueCraiola; - @override Widget body(BuildContext context) => BuyWebViewPageBody(buyViewModel, ordersStore: ordersStore, url: url); diff --git a/lib/src/screens/buy/pre_order_page.dart b/lib/src/screens/buy/pre_order_page.dart index ccd6a5422..67b9a18a1 100644 --- a/lib/src/screens/buy/pre_order_page.dart +++ b/lib/src/screens/buy/pre_order_page.dart @@ -3,6 +3,10 @@ import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/screens/buy/widgets/buy_list_item.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -58,9 +62,6 @@ class PreOrderPage extends BasePage { @override String get title => S.current.buy + ' ' + walletTypeToString(buyViewModel.wallet.type); - @override - Color get titleColor => Colors.white; - @override bool get resizeToAvoidBottomInset => false; @@ -80,10 +81,7 @@ class PreOrderPage extends BasePage { return KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -104,10 +102,8 @@ class PreOrderPage extends BasePage { bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context) - .primaryTextTheme!.titleMedium! - .decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), child: Padding( @@ -162,11 +158,11 @@ class PreOrderPage extends BasePage { ), ), hintText: '0.00', - borderColor: Theme.of(context).primaryTextTheme!.bodyLarge!.decorationColor!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, borderWidth: 0.5, textStyle: TextStyle(fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context).primaryTextTheme!.headlineSmall!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 36, ), @@ -181,7 +177,7 @@ class PreOrderPage extends BasePage { S.of(context).buy_with + ':', textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, fontSize: 18, fontWeight: FontWeight.bold ), @@ -248,7 +244,7 @@ class PreOrderPage extends BasePage { ? S.of(context).buy : S.of(context).buy_with + ' ${buyViewModel.selectedProvider!.description.title}', - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: buyViewModel.isRunning, isDisabled: (buyViewModel.selectedProvider == null) || diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 601133c56..6c00b64f9 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/entities/contact_record.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -32,13 +33,13 @@ class ContactListPage extends BasePage { height: 32.0, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).accentTextTheme!.bodySmall!.color!), + color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor), child: Stack( alignment: Alignment.center, children: <Widget>[ Icon( Icons.add, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).dialogTheme.backgroundColor, size: 22.0, ), ButtonTheme( @@ -48,17 +49,15 @@ class ContactListPage extends BasePage { // FIX-ME: Style //shape: CircleBorder(), onPressed: () async { - if (contactListViewModel - .shouldRequireTOTP2FAForAddingContacts) { + if (contactListViewModel.shouldRequireTOTP2FAForAddingContacts) { authService.authenticateAction( context, route: Routes.addressBookAddContact, - conditionToDetermineIfToUse2FA: contactListViewModel - .shouldRequireTOTP2FAForAddingContacts, + conditionToDetermineIfToUse2FA: + contactListViewModel.shouldRequireTOTP2FAForAddingContacts, ); } else { - await Navigator.of(context) - .pushNamed(Routes.addressBookAddContact); + await Navigator.of(context).pushNamed(Routes.addressBookAddContact); } }, child: Offstage()), @@ -77,12 +76,8 @@ class ContactListPage extends BasePage { final contacts = contactListViewModel.contactsToShow; final walletContacts = contactListViewModel.walletContactsToShow; return CollapsibleSectionList( - context: context, sectionCount: 2, - themeColor: Theme.of(context).primaryTextTheme.titleLarge!.color!, - dividerThemeColor: - Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!, - sectionTitleBuilder: (_, int sectionIndex) { + sectionTitleBuilder: (int sectionIndex) { var title = S.current.contact_list_contacts; if (sectionIndex == 0) { @@ -95,7 +90,7 @@ class ContactListPage extends BasePage { }, itemCounter: (int sectionIndex) => sectionIndex == 0 ? walletContacts.length : contacts.length, - itemBuilder: (_, sectionIndex, index) { + itemBuilder: (int sectionIndex, index) { if (sectionIndex == 0) { final walletInfo = walletContacts[index]; return generateRaw(context, walletInfo); @@ -128,8 +123,7 @@ class ContactListPage extends BasePage { return; } - final isCopied = await showNameAndAddressDialog( - context, contact.name, contact.address); + final isCopied = await showNameAndAddressDialog(context, contact.name, contact.address); if (isCopied) { await Clipboard.setData(ClipboardData(text: contact.address)); @@ -152,7 +146,7 @@ class ContactListPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).dialogTheme.backgroundColor, ), ), )) @@ -177,8 +171,7 @@ class ContactListPage extends BasePage { false; } - Future<bool> showNameAndAddressDialog( - BuildContext context, String name, String address) async { + Future<bool> showNameAndAddressDialog(BuildContext context, String name, String address) async { return await showPopUp<bool>( context: context, builder: (BuildContext context) { @@ -193,8 +186,7 @@ class ContactListPage extends BasePage { false; } - ActionPane _actionPane(BuildContext context, ContactRecord contact) => - ActionPane( + ActionPane _actionPane(BuildContext context, ContactRecord contact) => ActionPane( motion: const ScrollMotion(), extentRatio: 0.4, children: [ diff --git a/lib/src/screens/contact/contact_page.dart b/lib/src/screens/contact/contact_page.dart index fc9c6c109..099be41d5 100644 --- a/lib/src/screens/contact/contact_page.dart +++ b/lib/src/screens/contact/contact_page.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; @@ -17,6 +18,8 @@ import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; class ContactPage extends BasePage { ContactPage(this.contactViewModel) @@ -47,7 +50,7 @@ class ContactPage extends BasePage { @override Widget body(BuildContext context) { final downArrow = Image.asset('assets/images/arrow_bottom_purple_icon.png', - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, height: 8); reaction((_) => contactViewModel.state, (ExecutionState state) { @@ -99,15 +102,9 @@ class ContactPage extends BasePage { AddressTextFieldOption.paste, AddressTextFieldOption.qrCode, ], - buttonColor: Theme.of(context) - .accentTextTheme! - .displaySmall! - .color!, + buttonColor: Theme.of(context).extension<AddressTheme>()!.actionButtonColor, iconColor: PaletteDark.gray, - borderColor: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .backgroundColor!, + borderColor: Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor, validator: AddressValidator(type: contactViewModel.currency!), ), @@ -143,10 +140,7 @@ class ContactPage extends BasePage { await contactViewModel.save(); }, text: S.of(context).save, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: !contactViewModel.isReady))) ], diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index ff9f85784..a1db0860b 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -4,6 +4,8 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/main_actions.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/version_comparator.dart'; import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; @@ -29,6 +31,8 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class DashboardPage extends StatelessWidget { DashboardPage({ @@ -81,28 +85,11 @@ class _DashboardPageView extends BasePage { final BalancePage balancePage; @override - Color get backgroundLightColor => - currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; - - @override - Color get backgroundDarkColor => Colors.transparent; + bool get gradientBackground => true; @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], - begin: Alignment.topRight, - end: Alignment.bottomLeft, - ), - ), - child: scaffold, - ); + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold); @override bool get resizeToAvoidBottomInset => false; @@ -199,8 +186,10 @@ class _DashboardPageView extends BasePage { dotWidth: 6.0, dotHeight: 6.0, dotColor: Theme.of(context).indicatorColor, - activeDotColor: - Theme.of(context).accentTextTheme.headlineMedium!.backgroundColor!, + activeDotColor: Theme.of(context) + .extension<DashboardPageTheme>()! + .indicatorDotTheme + .activeIndicatorColor, ), ), ); @@ -216,12 +205,11 @@ class _DashboardPageView extends BasePage { decoration: BoxDecoration( borderRadius: BorderRadius.circular(50.0), border: Border.all( - color: currentTheme.type == ThemeType.bright - ? Color.fromRGBO(255, 255, 255, 0.2) - : Colors.transparent, + color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor, width: 1, ), - color: Theme.of(context).textTheme.titleLarge!.backgroundColor!, + color: + Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, ), child: Container( padding: EdgeInsets.only(left: 32, right: 32), @@ -240,13 +228,11 @@ class _DashboardPageView extends BasePage { width: 24, color: action.isEnabled?.call(dashboardViewModel) ?? true ? Theme.of(context) - .accentTextTheme - .displayMedium! - .backgroundColor! + .extension<DashboardPageTheme>()! + .mainActionsIconColor : Theme.of(context) - .accentTextTheme - .displaySmall! - .backgroundColor!, + .extension<BalancePageTheme>()! + .labelTextColor, ), title: action.name(context), onClick: () async => @@ -254,9 +240,8 @@ class _DashboardPageView extends BasePage { textColor: action.isEnabled?.call(dashboardViewModel) ?? true ? null : Theme.of(context) - .accentTextTheme - .displaySmall! - .backgroundColor!, + .extension<BalancePageTheme>()! + .labelTextColor, ), ), ) diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_action_button.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_action_button.dart index 6e6db72cc..7e9b2b23d 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_action_button.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_action_button.dart @@ -1,4 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:flutter/material.dart'; class DesktopActionButton extends StatelessWidget { @@ -30,7 +33,7 @@ class DesktopActionButton extends StatelessWidget { width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15.0), - color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, ), child: Center( child: Row( @@ -41,14 +44,8 @@ class DesktopActionButton extends StatelessWidget { height: 30, width: 30, color: isEnabled - ? Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor! - : Theme.of(context) - .accentTextTheme! - .displaySmall! - .backgroundColor!, + ? Theme.of(context).extension<DashboardPageTheme>()!.textColor + : Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, ), const SizedBox(width: 10), AutoSizeText( @@ -58,10 +55,7 @@ class DesktopActionButton extends StatelessWidget { fontFamily: 'Lato', fontWeight: FontWeight.bold, color: isEnabled - ? Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor! + ? Theme.of(context).extension<DashboardPageTheme>()!.textColor : null, height: 1, ), diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart index 74ad54870..8119e9fd4 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; class SideMenuItem extends StatelessWidget { const SideMenuItem({ @@ -16,7 +17,7 @@ class SideMenuItem extends StatelessWidget { Color _setColor(BuildContext context) { if (isSelected) { - return Theme.of(context).primaryTextTheme!.titleLarge!.color!; + return Theme.of(context).extension<CakeTextTheme>()!.titleColor; } else { return Theme.of(context).highlightColor; } diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 089987d5d..684f7cd08 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -1,10 +1,12 @@ import 'package:another_flushbar/flushbar.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/desktop_dropdown_item.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; @@ -37,14 +39,14 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD 'assets/images/new_wallet.png', height: 12, width: 12, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ); Image _restoreWalletImage(BuildContext context) => Image.asset( 'assets/images/restore_wallet.png', height: 12, width: 12, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ); Flushbar<void>? _progressBar; @@ -94,8 +96,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD onChanged: (item) { item?.onSelected(); }, - dropdownColor: themeData.textTheme!.bodyLarge?.decorationColor, - style: TextStyle(color: themeData.primaryTextTheme!.titleLarge?.color), + dropdownColor: themeData.extension<CakeMenuTheme>()!.backgroundColor, + style: TextStyle(color: themeData.extension<CakeTextTheme>()!.titleColor), selectedItemBuilder: (context) => dropDownItems.map((item) => item.child).toList(), value: dropDownItems.firstWhere((element) => element.isSelected), underline: const SizedBox(), diff --git a/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart b/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart index 14dcbb0d8..aa7012ae5 100644 --- a/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart +++ b/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; class DropDownItemWidget extends StatelessWidget { @@ -23,7 +24,7 @@ class DropDownItemWidget extends StatelessWidget { style: TextStyle( fontSize: 22, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), overflow: TextOverflow.ellipsis, maxLines: 1, diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 9d1abc893..50bcb24e1 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/widgets/checkbox_widget.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:flutter/material.dart'; @@ -111,7 +112,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> { Container( padding: EdgeInsets.symmetric(vertical: 16, horizontal: 28), decoration: BoxDecoration( - color: Theme.of(context).accentTextTheme.bodySmall!.color!, + color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), ), child: Row( @@ -128,7 +129,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).dialogTheme.backgroundColor, ), ), Padding( @@ -138,7 +139,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ), ), @@ -197,7 +198,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> { } }, text: S.of(context).save, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index c6b005bde..9303cb053 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -7,6 +7,8 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -34,7 +36,7 @@ class HomeSettingsPage extends BasePage { onItemSelected: _homeSettingsViewModel.setSortBalanceBy, ), ), - Divider(color: Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!), + Divider(color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor), Observer( builder: (_) => SettingsSwitcherCell( title: S.of(context).pin_at_top(_homeSettingsViewModel.nativeToken.title), @@ -44,7 +46,7 @@ class HomeSettingsPage extends BasePage { }, ), ), - Divider(color: Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!), + Divider(color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor), const SizedBox(height: 20), Row( children: [ @@ -53,12 +55,12 @@ class HomeSettingsPage extends BasePage { padding: const EdgeInsetsDirectional.only(start: 16), child: TextFormField( controller: _searchController, - style: TextStyle(color: Theme.of(context).primaryTextTheme.titleLarge!.color!), + style: TextStyle(color: Theme.of(context).dialogTheme.backgroundColor), decoration: InputDecoration( hintText: S.of(context).search_add_token, prefixIcon: Image.asset("assets/images/search_icon.png"), filled: true, - fillColor: Theme.of(context).accentTextTheme.displaySmall!.color!, + fillColor: Theme.of(context).extension<AddressTheme>()!.actionButtonColor, alignLabelWithHint: false, contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), enabledBorder: OutlineInputBorder( @@ -84,15 +86,15 @@ class HomeSettingsPage extends BasePage { }); }, elevation: 0, - fillColor: Theme.of(context).accentTextTheme.bodySmall!.color!, + fillColor: Theme.of(context).cardColor, child: Icon( Icons.add, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).dialogTheme.backgroundColor, size: 22.0, ), padding: EdgeInsets.all(12), shape: CircleBorder(), - splashColor: Theme.of(context).accentTextTheme.bodySmall!.color!, + splashColor: Theme.of(context).cardColor, ), ], ), @@ -146,7 +148,7 @@ class HomeSettingsPage extends BasePage { ), ), decoration: BoxDecoration( - color: Theme.of(context).accentTextTheme.bodySmall!.color!, + color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(30), ), ); diff --git a/lib/src/screens/dashboard/widgets/action_button.dart b/lib/src/screens/dashboard/widgets/action_button.dart index a3626fe3f..23f5c2f93 100644 --- a/lib/src/screens/dashboard/widgets/action_button.dart +++ b/lib/src/screens/dashboard/widgets/action_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class ActionButton extends StatelessWidget { ActionButton( @@ -46,14 +47,11 @@ class ActionButton extends StatelessWidget { style: TextStyle( fontSize: 10, color: textColor ?? - Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor), ) ], ), ), ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 18f85fa07..9d97c4e4f 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -1,10 +1,15 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/share_util.dart'; @@ -21,6 +26,8 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class AddressPage extends BasePage { AddressPage({ @@ -48,11 +55,7 @@ class AddressPage extends BasePage { final FocusNode _cryptoAmountFocus; @override - Color get backgroundLightColor => - currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; - - @override - Color get backgroundDarkColor => Colors.transparent; + bool get gradientBackground => true; @override bool get resizeToAvoidBottomInset => false; @@ -84,7 +87,7 @@ class AddressPage extends BasePage { overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent), ), onPressed: () => onClose(context), - child: !isMobileView ? _closeButton : _backButton, + child: !isMobileView ? closeButton(context) : backButton(context), ), ), ), @@ -94,20 +97,11 @@ class AddressPage extends BasePage { @override Widget middle(BuildContext context) => PresentReceiveOptionPicker( - receiveOptionViewModel: receiveOptionViewModel, - hasWhiteBackground: currentTheme.type == ThemeType.light, - ); + color: titleColor(context), receiveOptionViewModel: receiveOptionViewModel); @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], begin: Alignment.topRight, end: Alignment.bottomLeft)), - child: scaffold); + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold); @override Widget? trailing(BuildContext context) { @@ -201,8 +195,13 @@ class AddressPage extends BasePage { decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(25)), border: Border.all( - color: Theme.of(context).textTheme.titleMedium!.color!, width: 1), - color: Theme.of(context).textTheme.titleLarge!.backgroundColor!), + color: Theme.of(context) + .extension<ReceivePageTheme>()! + .iconsBackgroundColor, + width: 1), + color: Theme.of(context) + .extension<SyncIndicatorTheme>()! + .syncedBackgroundColor), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -215,15 +214,13 @@ class AddressPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme.displayMedium! - .backgroundColor!), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor), )), Icon( Icons.arrow_forward_ios, size: 14, color: - Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + Theme.of(context).extension<DashboardPageTheme>()!.textColor, ) ], ), @@ -234,8 +231,7 @@ class AddressPage extends BasePage { textAlign: TextAlign.center, style: TextStyle( fontSize: 15, - color: - Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!)); + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor)); } else { return const SizedBox(); } diff --git a/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart b/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart index 3b33e8e22..cb8bef0b7 100644 --- a/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart +++ b/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class AnonpayTransactionRow extends StatelessWidget { AnonpayTransactionRow({ @@ -37,19 +39,19 @@ class AnonpayTransactionRow extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)), Text(amount + ' ' + currency, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)) + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)) ]), SizedBox(height: 5), Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(createdAt, style: TextStyle( fontSize: 14, - color: Theme.of(context).textTheme!.labelSmall!.backgroundColor!)) + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)) ]) ], )) diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart index 0fc0f8112..f799950ea 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -10,6 +11,8 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/src/widgets/introducing_card.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class BalancePage extends StatelessWidget { BalancePage({required this.dashboardViewModel, required this.settingsStore}); @@ -41,7 +44,8 @@ class BalancePage extends StatelessWidget { fontSize: 24, fontFamily: 'Lato', fontWeight: FontWeight.w600, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: + Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor, height: 1, ), maxLines: 1, @@ -55,8 +59,9 @@ class BalancePage extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Image.asset( 'assets/images/home_screen_settings_icon.png', - color: - Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: Theme.of(context) + .extension<DashboardPageTheme>()! + .pageTitleTextColor, ), ), ), @@ -139,7 +144,7 @@ class BalancePage extends StatelessWidget { : Colors.transparent, width: 1, ), - color: Theme.of(context).textTheme.titleLarge!.backgroundColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, ), child: Container( margin: const EdgeInsets.only(top: 16, left: 24, right: 24, bottom: 24), @@ -164,9 +169,8 @@ class BalancePage extends StatelessWidget { fontFamily: 'Lato', fontWeight: FontWeight.w400, color: Theme.of(context) - .accentTextTheme! - .displaySmall! - .backgroundColor!, + .extension<BalancePageTheme>()! + .labelTextColor, height: 1)), if (hasAdditionalBalance) Padding( @@ -174,9 +178,8 @@ class BalancePage extends StatelessWidget { child: Icon(Icons.help_outline, size: 16, color: Theme.of(context) - .accentTextTheme! - .displaySmall! - .backgroundColor!), + .extension<BalancePageTheme>()! + .labelTextColor), ), ], ), @@ -187,9 +190,8 @@ class BalancePage extends StatelessWidget { fontFamily: 'Lato', fontWeight: FontWeight.w900, color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + .extension<BalancePageTheme>()! + .balanceAmountColor, height: 1), maxLines: 1, textAlign: TextAlign.start), @@ -200,10 +202,7 @@ class BalancePage extends StatelessWidget { fontSize: 16, fontFamily: 'Lato', fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.textColor, height: 1)), ], ), @@ -213,7 +212,7 @@ class BalancePage extends StatelessWidget { fontSize: 28, fontFamily: 'Lato', fontWeight: FontWeight.w800, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor, height: 1)), ], ), @@ -229,7 +228,7 @@ class BalancePage extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, height: 1, ), ), @@ -240,7 +239,7 @@ class BalancePage extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, height: 1, ), maxLines: 1, @@ -254,7 +253,7 @@ class BalancePage extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, height: 1, ), ), @@ -272,7 +271,7 @@ class BalancePage extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, height: 1, ), ), @@ -283,7 +282,7 @@ class BalancePage extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, height: 1, ), maxLines: 1, @@ -297,7 +296,7 @@ class BalancePage extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, height: 1, ), ), diff --git a/lib/src/screens/dashboard/widgets/date_section_raw.dart b/lib/src/screens/dashboard/widgets/date_section_raw.dart index 7abaa0ba7..73f9f03a1 100644 --- a/lib/src/screens/dashboard/widgets/date_section_raw.dart +++ b/lib/src/screens/dashboard/widgets/date_section_raw.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:intl/intl.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/date_formatter.dart'; @@ -36,9 +37,6 @@ class DateSectionRaw extends StatelessWidget { child: Text(title, style: TextStyle( fontSize: 12, - color: Theme.of(context) - .textTheme! - .labelSmall! - .backgroundColor!))); + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))); } } diff --git a/lib/src/screens/dashboard/widgets/filter_widget.dart b/lib/src/screens/dashboard/widgets/filter_widget.dart index da13208bc..ec867ae49 100644 --- a/lib/src/screens/dashboard/widgets/filter_widget.dart +++ b/lib/src/screens/dashboard/widgets/filter_widget.dart @@ -1,12 +1,15 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart'; import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; //import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class FilterWidget extends StatelessWidget { FilterWidget({required this.dashboardViewModel}); @@ -15,7 +18,7 @@ class FilterWidget extends StatelessWidget { @override Widget build(BuildContext context) { - const sectionDivider = const SectionDivider(); + const sectionDivider = const HorizontalSectionDivider(); return PickerWrapperWidget( children: [ Padding( @@ -23,7 +26,7 @@ class FilterWidget extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(24)), child: Container( - color: Theme.of(context).textTheme!.bodyLarge!.decorationColor!, + color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -32,10 +35,7 @@ class FilterWidget extends StatelessWidget { child: Text( S.of(context).filter_by, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, fontSize: 16, fontFamily: 'Lato', decoration: TextDecoration.none, @@ -63,10 +63,7 @@ class FilterWidget extends StatelessWidget { child: Text( title, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, fontSize: 16, fontFamily: 'Lato', fontWeight: FontWeight.bold, diff --git a/lib/src/screens/dashboard/widgets/header_row.dart b/lib/src/screens/dashboard/widgets/header_row.dart index 44fdb6c59..79b7b3fe6 100644 --- a/lib/src/screens/dashboard/widgets/header_row.dart +++ b/lib/src/screens/dashboard/widgets/header_row.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class HeaderRow extends StatelessWidget { HeaderRow({required this.dashboardViewModel}); @@ -12,7 +14,7 @@ class HeaderRow extends StatelessWidget { @override Widget build(BuildContext context) { final filterIcon = Image.asset('assets/images/filter_icon.png', - color: Theme.of(context).textTheme!.bodySmall!.decorationColor!); + color: Theme.of(context).extension<FilterTheme>()!.iconColor); return Container( height: 52, @@ -27,10 +29,7 @@ class HeaderRow extends StatelessWidget { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor), ), GestureDetector( onTap: () { @@ -45,7 +44,7 @@ class HeaderRow extends StatelessWidget { width: 36, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).textTheme!.labelSmall!.color!), + color: Theme.of(context).extension<FilterTheme>()!.buttonColor), child: filterIcon, ), ) diff --git a/lib/src/screens/dashboard/widgets/market_place_page.dart b/lib/src/screens/dashboard/widgets/market_place_page.dart index eeed4bee0..2d6539370 100644 --- a/lib/src/screens/dashboard/widgets/market_place_page.dart +++ b/lib/src/screens/dashboard/widgets/market_place_page.dart @@ -8,6 +8,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class MarketPlacePage extends StatelessWidget { MarketPlacePage({ @@ -40,10 +41,7 @@ class MarketPlacePage extends StatelessWidget { style: TextStyle( fontSize: 24, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor, ), ), Expanded( diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart index 9dd08add9..6303d587a 100644 --- a/lib/src/screens/dashboard/widgets/menu_widget.dart +++ b/lib/src/screens/dashboard/widgets/menu_widget.dart @@ -1,13 +1,12 @@ import 'package:cake_wallet/src/widgets/setting_action_button.dart'; import 'package:cake_wallet/src/widgets/setting_actions.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -// FIXME: terrible design. - class MenuWidget extends StatefulWidget { MenuWidget(this.dashboardViewModel); @@ -19,18 +18,18 @@ class MenuWidget extends StatefulWidget { class MenuWidgetState extends State<MenuWidget> { MenuWidgetState() - : this.menuWidth = 0, - this.screenWidth = 0, - this.screenHeight = 0, - this.headerHeight = 120, - this.tileHeight = 60, - this.fromTopEdge = 50, - this.fromBottomEdge = 25, - this.moneroIcon = Image.asset('assets/images/monero_menu.png'), - this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'), - this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'), - this.havenIcon = Image.asset('assets/images/haven_menu.png'), - this.ethereumIcon = Image.asset('assets/images/eth_icon.png'); + : this.menuWidth = 0, + this.screenWidth = 0, + this.screenHeight = 0, + this.headerHeight = 120, + this.tileHeight = 60, + this.fromTopEdge = 50, + this.fromBottomEdge = 25, + this.moneroIcon = Image.asset('assets/images/monero_menu.png'), + this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'), + this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'), + this.havenIcon = Image.asset('assets/images/haven_menu.png'), + this.ethereumIcon = Image.asset('assets/images/eth_icon.png'); final largeScreen = 731; @@ -86,121 +85,111 @@ class MenuWidgetState extends State<MenuWidget> { final itemCount = SettingActions.all.length; moneroIcon = Image.asset('assets/images/monero_menu.png', - color: Theme.of(context) - .accentTextTheme - .labelSmall! - .decorationColor!); + color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor); bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png', - color: Theme.of(context) - .accentTextTheme - .labelSmall! - .decorationColor!); + color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor); return Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Padding( - padding: EdgeInsets.only(left: 24), - child: Container( - height: 60, - width: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(2)), color: PaletteDark.gray), - )), + padding: EdgeInsets.only(left: 24), + child: Container( + height: 60, + width: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(2)), color: PaletteDark.gray), + ), + ), SizedBox(width: 12), Expanded( - child: ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)), - child: Container( - color: - Theme.of(context).textTheme!.bodyLarge!.decorationColor!, - child: ListView.separated( - padding: EdgeInsets.only(top: 0), - itemBuilder: (_, index) { - if (index == 0) { - return Container( - height: headerHeight, - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Theme.of(context) - .accentTextTheme! - .headlineMedium! - .color!, - Theme.of(context) - .accentTextTheme! - .headlineMedium! - .decorationColor!, ], begin: Alignment.topLeft, end: Alignment.bottomRight), - ), - padding: EdgeInsets.only( - left: 24, top: fromTopEdge, right: 24, bottom: fromBottomEdge), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: <Widget>[ - _iconFor(type: widget.dashboardViewModel.type), - SizedBox(width: 12), - SingleChildScrollView( - child: Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: widget.dashboardViewModel.subname.isNotEmpty - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: <Widget>[ - Text( - widget.dashboardViewModel.name, - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold), - ), - if (widget.dashboardViewModel.subname.isNotEmpty) - Observer( - builder: (_) => Text( - widget.dashboardViewModel.subname, - style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .labelSmall! - .decorationColor!, - fontWeight: FontWeight.w500, - fontSize: 12), - )) - ], + child: ClipRRect( + borderRadius: + BorderRadius.only(topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)), + child: Container( + color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor, + child: ListView.separated( + padding: EdgeInsets.only(top: 0), + itemBuilder: (_, index) { + if (index == 0) { + return Container( + height: headerHeight, + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + Theme.of(context).extension<CakeMenuTheme>()!.headerFirstGradientColor, + Theme.of(context).extension<CakeMenuTheme>()!.headerSecondGradientColor, + ], begin: Alignment.topLeft, end: Alignment.bottomRight), + ), + padding: EdgeInsets.only( + left: 24, top: fromTopEdge, right: 24, bottom: fromBottomEdge), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: <Widget>[ + _iconFor(type: widget.dashboardViewModel.type), + SizedBox(width: 12), + SingleChildScrollView( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: widget.dashboardViewModel.subname.isNotEmpty + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: <Widget>[ + Text( + widget.dashboardViewModel.name, + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.bold), ), - )) - ], + if (widget.dashboardViewModel.subname.isNotEmpty) + Observer( + builder: (_) => Text( + widget.dashboardViewModel.subname, + style: TextStyle( + color: Theme.of(context) + .extension<CakeMenuTheme>()! + .subnameTextColor, + fontWeight: FontWeight.w500, + fontSize: 12), + ), + ), + ], + ), ), - ); - } - - index--; - - final item = SettingActions.all[index]; - - final isLastTile = index == itemCount - 1; - - return SettingActionButton( - isLastTile: isLastTile, - tileHeight: tileHeight, - selectionActive: false, - fromBottomEdge: fromBottomEdge, - fromTopEdge: fromTopEdge, - onTap: () => item.onTap.call(context), - image: item.image, - title: item.name.call(context), - ); - }, - separatorBuilder: (_, index) => Container( - height: 1, - color: Theme.of(context) - .primaryTextTheme! - .bodySmall! - .decorationColor!, ), - itemCount: itemCount + 1), - ))) + ], + ), + ); + } + + index--; + + final item = SettingActions.all[index]; + + final isLastTile = index == itemCount - 1; + + return SettingActionButton( + isLastTile: isLastTile, + tileHeight: tileHeight, + selectionActive: false, + fromBottomEdge: fromBottomEdge, + fromTopEdge: fromTopEdge, + onTap: () => item.onTap.call(context), + image: item.image, + title: item.name.call(context), + ); + }, + separatorBuilder: (_, index) => Container( + height: 1, + color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor, + ), + itemCount: itemCount + 1, + ), + ), + ), + ), ], ); } diff --git a/lib/src/screens/dashboard/widgets/order_row.dart b/lib/src/screens/dashboard/widgets/order_row.dart index 961f31784..8adc6e0d5 100644 --- a/lib/src/screens/dashboard/widgets/order_row.dart +++ b/lib/src/screens/dashboard/widgets/order_row.dart @@ -1,6 +1,9 @@ import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/buy/get_buy_provider_icon.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class OrderRow extends StatelessWidget { OrderRow({ @@ -20,7 +23,7 @@ class OrderRow extends StatelessWidget { @override Widget build(BuildContext context) { final iconColor = - Theme.of(context).primaryTextTheme!.displayLarge!.backgroundColor!; + Theme.of(context).extension<OrderTheme>()!.iconColor; final providerIcon = getBuyProviderIcon(provider, iconColor: iconColor); @@ -48,14 +51,14 @@ class OrderRow extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor! + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor )), formattedAmount != null ? Text(formattedAmount! + ' ' + to, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor! + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor )) : Container() ]), @@ -66,10 +69,7 @@ class OrderRow extends StatelessWidget { Text(createdAtFormattedDate, style: TextStyle( fontSize: 14, - color: Theme.of(context) - .textTheme! - .labelSmall! - .backgroundColor!)) + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)) ]) ], ) diff --git a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart index cf2ae7e3d..aae42049b 100644 --- a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart +++ b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/rounded_checkbox.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; @@ -10,22 +11,16 @@ import 'package:cake_wallet/generated/i18n.dart'; class PresentReceiveOptionPicker extends StatelessWidget { PresentReceiveOptionPicker( - {required this.receiveOptionViewModel, this.hasWhiteBackground = false}); + {required this.receiveOptionViewModel, required this.color}); final ReceiveOptionViewModel receiveOptionViewModel; - final bool hasWhiteBackground; + final Color color; @override Widget build(BuildContext context) { - final textIconTheme = hasWhiteBackground - ? Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor! - : Colors.white; final arrowBottom = Image.asset( 'assets/images/arrow_bottom_purple_icon.png', - color: textIconTheme, + color: color, height: 6, ); @@ -51,14 +46,14 @@ class PresentReceiveOptionPicker extends StatelessWidget { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: textIconTheme), + color: color), ), Observer( builder: (_) => Text(receiveOptionViewModel.selectedReceiveOption.toString(), style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w500, - color: textIconTheme))) + color: color))) ], ), SizedBox(width: 5), @@ -113,10 +108,7 @@ class PresentReceiveOptionPicker extends StatelessWidget { Text(option.toString(), textAlign: TextAlign.left, style: textSmall( - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ).copyWith( fontWeight: value == option ? FontWeight.w800 : FontWeight.w500, diff --git a/lib/src/screens/dashboard/widgets/sync_indicator.dart b/lib/src/screens/dashboard/widgets/sync_indicator.dart index 11a973d6e..52e596a83 100644 --- a/lib/src/screens/dashboard/widgets/sync_indicator.dart +++ b/lib/src/screens/dashboard/widgets/sync_indicator.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/core/sync_status_title.dart'; @@ -32,7 +33,7 @@ class SyncIndicator extends StatelessWidget { child: Container( height: 30, width: syncIndicatorWidth, - color: Theme.of(context).textTheme!.titleLarge!.decorationColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.notSyncedBackgroundColor, child: Stack( alignment: Alignment.center, children: <Widget>[ @@ -44,7 +45,7 @@ class SyncIndicator extends StatelessWidget { child: Container( width: indicatorWidth, height: 30, - color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, ) ) : Offstage(), @@ -66,7 +67,7 @@ class SyncIndicator extends StatelessWidget { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: Theme.of(context).textTheme!.titleLarge!.color! + color: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor ), ), ) diff --git a/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart b/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart index 0aa8fa7c5..11bde6dfa 100644 --- a/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart +++ b/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -26,7 +28,7 @@ class SyncIndicatorIcon extends StatelessWidget { if (boolMode) { indicatorColor = isSynced ? PaletteDark.brightGreen - : Theme.of(context).textTheme!.bodySmall!.color!; + : Theme.of(context).extension<SyncIndicatorTheme>()!.notSyncedIconColor; } else { switch (value.toLowerCase()) { case waiting: @@ -34,7 +36,7 @@ class SyncIndicatorIcon extends StatelessWidget { break; case actionRequired: indicatorColor = - Theme.of(context).textTheme!.displayMedium!.decorationColor!; + Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor; break; case created: indicatorColor = PaletteDark.brightGreen; diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index 754e9d237..a42593f24 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -1,6 +1,8 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class TradeRow extends StatelessWidget { TradeRow({ @@ -43,14 +45,14 @@ class TradeRow extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)), formattedAmount != null ? Text(formattedAmount! + ' ' + amountCrypto, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: - Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)) + Theme.of(context).extension<DashboardPageTheme>()!.textColor)) : Container() ]), SizedBox(height: 5), @@ -59,7 +61,7 @@ class TradeRow extends StatelessWidget { Text(createdAtFormattedDate!, style: TextStyle( fontSize: 14, - color: Theme.of(context).textTheme!.labelSmall!.backgroundColor!)) + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)) ]) ], )) diff --git a/lib/src/screens/dashboard/widgets/transaction_raw.dart b/lib/src/screens/dashboard/widgets/transaction_raw.dart index aae3397ee..3a95b9f2e 100644 --- a/lib/src/screens/dashboard/widgets/transaction_raw.dart +++ b/lib/src/screens/dashboard/widgets/transaction_raw.dart @@ -1,5 +1,8 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cw_core/transaction_direction.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class TransactionRow extends StatelessWidget { TransactionRow( @@ -35,7 +38,7 @@ class TransactionRow extends StatelessWidget { width: 36, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).textTheme!.labelSmall!.decorationColor! + color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor ), child: Image.asset( direction == TransactionDirection.incoming @@ -54,14 +57,12 @@ class TransactionRow extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme! - .displayMedium!.backgroundColor!)), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)), Text(formattedAmount, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).accentTextTheme! - .displayMedium!.backgroundColor!)) + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)) ]), SizedBox(height: 5), Row( @@ -70,17 +71,11 @@ class TransactionRow extends StatelessWidget { Text(formattedDate, style: TextStyle( fontSize: 14, - color: Theme.of(context) - .textTheme! - .labelSmall! - .backgroundColor!)), + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)), Text(formattedFiatAmount, style: TextStyle( fontSize: 14, - color: Theme.of(context) - .textTheme! - .labelSmall! - .backgroundColor!)) + color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)) ]) ], ) diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 644d7b421..3f6b8a3c6 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_row.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart'; +import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; @@ -155,10 +156,7 @@ class TransactionsPage extends StatelessWidget { S.of(context).placeholder_transactions, style: TextStyle( fontSize: 14, - color: Theme.of(context) - .primaryTextTheme - .labelSmall! - .decorationColor!), + color: Theme.of(context).extension<PlaceholderTheme>()!.color), ), ); })) diff --git a/lib/src/screens/disclaimer/disclaimer_page.dart b/lib/src/screens/disclaimer/disclaimer_page.dart index 1bb05eca0..3805f6240 100644 --- a/lib/src/screens/disclaimer/disclaimer_page.dart +++ b/lib/src/screens/disclaimer/disclaimer_page.dart @@ -1,6 +1,8 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -87,10 +89,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ) ], @@ -107,10 +106,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ) ], @@ -126,10 +122,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.normal, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), )) ], ), @@ -146,10 +139,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ) ], @@ -167,7 +157,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { changenowUrl, textAlign: TextAlign.left, style: TextStyle( - color: Palette.blueCraiola, + color: Theme.of(context).primaryColor, fontSize: 14.0, fontWeight: FontWeight.normal, decoration: TextDecoration.underline), @@ -193,7 +183,8 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { gradient: LinearGradient( colors: [ Theme.of(context) - .backgroundColor + .colorScheme + .background .withOpacity(0.0), Theme.of(context).colorScheme.background, ], @@ -232,10 +223,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { ), decoration: BoxDecoration( border: Border.all( - color: Theme.of(context) - .primaryTextTheme! - .bodySmall! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor, width: 1.0), borderRadius: BorderRadius.all( Radius.circular(8.0)), @@ -253,10 +241,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14.0, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ) ], ), @@ -273,14 +258,8 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> { .popAndPushNamed(Routes.welcome) : null, text: 'Accept', - color: Theme.of(context) - .accentTextTheme! - .titleSmall! - .decorationColor!, - textColor: Theme.of(context) - .accentTextTheme! - .headlineSmall! - .decorationColor!), + color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor, + textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor), ), ], ], diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 53d823f18..98929a692 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,8 +1,11 @@ +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/debounce.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -78,7 +81,10 @@ class ExchangePage extends BasePage { String get title => S.current.exchange; @override - Color get titleColor => Colors.white; + bool get gradientBackground => true; + + @override + bool get gradientAll => true; @override bool get resizeToAvoidBottomInset => false; @@ -115,7 +121,7 @@ class ExchangePage extends BasePage { Widget? leading(BuildContext context) { final _backButton = Icon( Icons.arrow_back_ios, - color: titleColor, + color: titleColor(context), size: 16, ); final _closeButton = @@ -152,7 +158,7 @@ class ExchangePage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context).accentTextTheme.bodyLarge!.backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -205,8 +211,8 @@ class ExchangePage extends BasePage { textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context) - .primaryTextTheme.displayLarge! - .decorationColor!, + .extension<ExchangePageTheme>()! + .receiveAmountColor, fontWeight: FontWeight.w500, fontSize: 12), ), @@ -625,7 +631,7 @@ class ExchangePage extends BasePage { imageArrow: arrowBottomPurple, currencyButtonColor: Colors.transparent, addressButtonsColor: Theme.of(context).focusColor, - borderColor: Theme.of(context).primaryTextTheme.bodyLarge!.color!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor, currencyValueValidator: (value) { return !exchangeViewModel.isFixedRateMode ? AmountValidator( @@ -673,7 +679,7 @@ class ExchangePage extends BasePage { imageArrow: arrowBottomCakeGreen, currencyButtonColor: Colors.transparent, addressButtonsColor: Theme.of(context).focusColor, - borderColor: Theme.of(context).primaryTextTheme.bodyLarge!.decorationColor!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, currencyValueValidator: (value) { return exchangeViewModel.isFixedRateMode ? AmountValidator( diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index ddd2c90b7..62f36a3fd 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; @@ -29,10 +31,10 @@ class ExchangeTemplatePage extends BasePage { var _isReactionsSet = false; @override - String get title => S.current.exchange_new_template; + bool get gradientAll => true; @override - Color get titleColor => Colors.white; + String get title => S.current.exchange_new_template; @override bool get extendBodyBehindAppBar => true; @@ -73,10 +75,7 @@ class ExchangeTemplatePage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -101,8 +100,8 @@ class ExchangeTemplatePage extends BasePage { ), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.bodyMedium!.color!, - Theme.of(context).primaryTextTheme!.bodyMedium!.decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientBottomPanelColor, ], stops: [0.35, 1.0], begin: Alignment.topLeft, @@ -120,12 +119,8 @@ class ExchangeTemplatePage extends BasePage { ), gradient: LinearGradient( colors: [ - Theme.of(context) - .primaryTextTheme!.titleSmall! - .color!, - Theme.of(context) - .primaryTextTheme!.titleSmall! - .decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight), @@ -157,10 +152,8 @@ class ExchangeTemplatePage extends BasePage { imageArrow: arrowBottomPurple, currencyButtonColor: Colors.transparent, addressButtonsColor: - Theme.of(context).focusColor, - borderColor: Theme.of(context) - .primaryTextTheme!.bodyLarge! - .color!, + Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, currencyValueValidator: AmountValidator( currency: exchangeViewModel.depositCurrency), //addressTextFieldValidator: AddressValidator( @@ -197,10 +190,8 @@ class ExchangeTemplatePage extends BasePage { imageArrow: arrowBottomCakeGreen, currencyButtonColor: Colors.transparent, addressButtonsColor: - Theme.of(context).focusColor, - borderColor: Theme.of(context) - .primaryTextTheme!.bodyLarge! - .decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, currencyValueValidator: AmountValidator( currency: exchangeViewModel.receiveCurrency), //addressTextFieldValidator: AddressValidator( @@ -226,9 +217,7 @@ class ExchangeTemplatePage extends BasePage { description, textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme!.displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor, fontWeight: FontWeight.w500, fontSize: 12), ), @@ -256,7 +245,7 @@ class ExchangeTemplatePage extends BasePage { } }, text: S.of(context).save, - color: Colors.green, + color: Theme.of(context).primaryColor, textColor: Colors.white), ]), )) @@ -444,4 +433,4 @@ class ExchangeTemplatePage extends BasePage { key.currentState!.addressController.text = ''; } } -} \ No newline at end of file +} diff --git a/lib/src/screens/exchange/widgets/currency_picker_item_widget.dart b/lib/src/screens/exchange/widgets/currency_picker_item_widget.dart index 3dc0f80e3..03c6fdd47 100644 --- a/lib/src/screens/exchange/widgets/currency_picker_item_widget.dart +++ b/lib/src/screens/exchange/widgets/currency_picker_item_widget.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -20,10 +22,7 @@ class PickerItemWidget extends StatelessWidget { return GestureDetector( onTap: onTap, child: Container( - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24), child: Row( @@ -44,10 +43,7 @@ class PickerItemWidget extends StatelessWidget { style: TextStyle( color: isSelected ? Palette.blueCraiola - : Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + : Theme.of(context).extension<CakeTextTheme>()!.titleColor, fontSize: isSelected ? 16 : 14.0, fontFamily: 'Lato', fontWeight: FontWeight.w600, @@ -65,19 +61,13 @@ class PickerItemWidget extends StatelessWidget { style: TextStyle( fontSize: 7.0, fontFamily: 'Lato', - color: Theme.of(context) - .textTheme! - .bodyMedium! - .color!), + color: Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor), ), ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.0), //border: Border.all(color: ), - color: Theme.of(context) - .textTheme! - .bodyMedium! - .decorationColor!, + color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor, ), ), ), @@ -86,10 +76,7 @@ class PickerItemWidget extends StatelessWidget { ), if (isSelected) Icon(Icons.check_circle, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!) + color: Theme.of(context).primaryColor) ], ), ), diff --git a/lib/src/screens/exchange/widgets/currency_picker_widget.dart b/lib/src/screens/exchange/widgets/currency_picker_widget.dart index de835fe18..35d0198f2 100644 --- a/lib/src/screens/exchange/widgets/currency_picker_widget.dart +++ b/lib/src/screens/exchange/widgets/currency_picker_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; import 'currency_picker_item_widget.dart'; @@ -20,10 +21,7 @@ class CurrencyPickerWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, child: Scrollbar( controller: _scrollController, child: GridView.builder( diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index ce8928cc6..9c4707529 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -1,6 +1,8 @@ import 'package:cake_wallet/entities/contact_base.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/payment_request.dart'; @@ -12,6 +14,7 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class ExchangeCard extends StatefulWidget { ExchangeCard( @@ -160,7 +163,7 @@ class ExchangeCardState extends State<ExchangeCard> { final copyImage = Image.asset('assets/images/copy_content.png', height: 16, width: 16, - color: Theme.of(context).primaryTextTheme!.displaySmall!.color!); + color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor); return Container( width: double.infinity, @@ -175,7 +178,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, - color: Theme.of(context).textTheme!.headlineSmall!.color!), + color: Theme.of(context).extension<QRCodeTheme>()!.qrCodeColor), ) ], ), @@ -211,10 +214,7 @@ class ExchangeCardState extends State<ExchangeCard> { height: 32, decoration: BoxDecoration( color: widget.addressButtonsColor ?? - Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .color!, + Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: Center( @@ -224,10 +224,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!)), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)), ), ), ), @@ -268,10 +265,7 @@ class ExchangeCardState extends State<ExchangeCard> { placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor), validator: _isAmountEditable ? widget.currencyValueValidator : null), @@ -282,10 +276,7 @@ class ExchangeCardState extends State<ExchangeCard> { height: 32, width: 32, decoration: BoxDecoration( - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: InkWell( @@ -296,10 +287,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!)), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)), ), ), ) @@ -310,10 +298,7 @@ class ExchangeCardState extends State<ExchangeCard> { )), Divider( height: 1, - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .decorationColor!), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), Padding( padding: EdgeInsets.only(top: 5), child: Container( @@ -329,10 +314,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor), ) : Offstage(), _min != null ? SizedBox(width: 10) : Offstage(), @@ -344,10 +326,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!)) + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor)) : Offstage(), ])), ), @@ -359,10 +338,7 @@ class ExchangeCardState extends State<ExchangeCard> { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor), )) : Offstage(), _isAddressEditable @@ -400,10 +376,7 @@ class ExchangeCardState extends State<ExchangeCard> { hintStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor), buttonColor: widget.addressButtonsColor, validator: widget.addressTextFieldValidator, onPushPasteButton: widget.onPushPasteButton, @@ -472,10 +445,7 @@ class ExchangeCardState extends State<ExchangeCard> { 6))), child: Image.asset( 'assets/images/open_book.png', - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, )), )), ), diff --git a/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart b/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart index 61da007f1..126bca835 100644 --- a/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart +++ b/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:flutter/material.dart'; class MobileExchangeCardsSection extends StatelessWidget { @@ -21,8 +22,8 @@ class MobileExchangeCardsSection extends StatelessWidget { ), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.bodyMedium!.color!, - Theme.of(context).primaryTextTheme!.bodyMedium!.decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientBottomPanelColor, ], stops: [0.35, 1.0], begin: Alignment.topLeft, @@ -37,11 +38,8 @@ class MobileExchangeCardsSection extends StatelessWidget { bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleSmall!.color!, - Theme.of(context) - .primaryTextTheme! - .titleSmall! - .decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, diff --git a/lib/src/screens/exchange/widgets/present_provider_picker.dart b/lib/src/screens/exchange/widgets/present_provider_picker.dart index 20d3bf70c..75429aea9 100644 --- a/lib/src/screens/exchange/widgets/present_provider_picker.dart +++ b/lib/src/screens/exchange/widgets/present_provider_picker.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/src/widgets/check_box_picker.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -49,10 +50,7 @@ class PresentProviderPicker extends StatelessWidget { style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .textTheme! - .headlineSmall! - .color!))) + color: Theme.of(context).extension<QRCodeTheme>()!.qrCodeColor))) ], ), SizedBox(width: 5), diff --git a/lib/src/screens/exchange_trade/exchange_confirm_page.dart b/lib/src/screens/exchange_trade/exchange_confirm_page.dart index e4422c36f..8070febdf 100644 --- a/lib/src/screens/exchange_trade/exchange_confirm_page.dart +++ b/lib/src/screens/exchange_trade/exchange_confirm_page.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -9,6 +11,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class ExchangeConfirmPage extends BasePage { ExchangeConfirmPage({required this.tradesStore}) : trade = tradesStore.trade!; @@ -36,10 +39,7 @@ class ExchangeConfirmPage extends BasePage { style: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), )), Container( @@ -48,14 +48,8 @@ class ExchangeConfirmPage extends BasePage { borderRadius: BorderRadius.all(Radius.circular(30)), border: Border.all( width: 1, - color: Theme.of(context) - .accentTextTheme! - .bodySmall! - .color!), - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).cardColor), + color: Theme.of(context).dialogTheme.backgroundColor), child: Column( children: <Widget>[ Expanded( @@ -70,10 +64,7 @@ class ExchangeConfirmPage extends BasePage { style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), ), Text( trade.id, @@ -82,10 +73,7 @@ class ExchangeConfirmPage extends BasePage { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ], ), @@ -100,14 +88,8 @@ class ExchangeConfirmPage extends BasePage { context, S.of(context).copied_to_clipboard); }, text: S.of(context).copy_id, - color: Theme.of(context) - .accentTextTheme! - .bodySmall! - .backgroundColor!, - textColor: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ) ], @@ -136,10 +118,7 @@ class ExchangeConfirmPage extends BasePage { onPressed: () => Navigator.of(context) .pushReplacementNamed(Routes.exchangeTrade), text: S.of(context).saved_the_trade_id, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white) ], ), diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index c03c775a0..dbf6676a1 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -1,4 +1,6 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/utils/request_review_handler.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -20,6 +22,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; void showInformation( ExchangeTradeViewModel exchangeTradeViewModel, BuildContext context) { @@ -51,7 +54,7 @@ class ExchangeTradePage extends BasePage { @override Widget trailing(BuildContext context) { final questionImage = Image.asset('assets/images/question_mark.png', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!); + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor); return SizedBox( height: 20.0, @@ -111,7 +114,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { final copyImage = Image.asset('assets/images/copy_content.png', height: 16, width: 16, - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!); + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor); _setEffects(); @@ -133,17 +136,11 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), ), if (trade.expiredAt != null) TimerWidget(trade.expiredAt!, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!) + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor) ]) : Offstage(), Padding( @@ -160,10 +157,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context) - .accentTextTheme! - .titleSmall! - .color! + color: Theme.of(context).extension<ExchangePageTheme>()!.qrCodeColor ) ), child: QrImage(data: trade.inputAddress ?? fetchingLabel), @@ -179,10 +173,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { itemCount: widget.exchangeTradeViewModel.items.length, separatorBuilder: (context, index) => Container( height: 1, - color: Theme.of(context) - .accentTextTheme! - .titleSmall! - .backgroundColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.dividerCodeColor, ), itemBuilder: (context, index) { final item = widget.exchangeTradeViewModel.items[index]; @@ -228,10 +219,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { onPressed: () => widget.exchangeTradeViewModel.confirmSending(), text: S.of(context).confirm, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white) : Offstage(); })), @@ -321,7 +309,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { return Stack( children: <Widget>[ Container( - color: Theme.of(popupContext).backgroundColor, + color: Theme.of(popupContext).colorScheme.background, child: Center( child: Image.asset( 'assets/images/birthday_cake.png'), @@ -341,10 +329,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, - color: Theme.of(popupContext) - .primaryTextTheme! - .titleLarge! - .color, + color: Theme.of(popupContext).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -360,10 +345,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { RequestReviewHandler.requestReview(); }, text: S.of(popupContext).got_it, - color: Theme.of(popupContext) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(popupContext).primaryColor, textColor: Colors.white)) ], ); @@ -372,7 +354,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { return Stack( children: <Widget>[ Container( - color: Theme.of(popupContext).backgroundColor, + color: Theme.of(popupContext).colorScheme.background, child: Center( child: Image.asset( 'assets/images/birthday_cake.png'), @@ -384,7 +366,8 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { child: Container( decoration: BoxDecoration( color: Theme.of(popupContext) - .backgroundColor + .colorScheme + .background .withOpacity(0.25)), child: Center( child: Padding( @@ -395,10 +378,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> { style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, - color: Theme.of(popupContext) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(popupContext).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), diff --git a/lib/src/screens/exchange_trade/information_page.dart b/lib/src/screens/exchange_trade/information_page.dart index 260060485..eed124b97 100644 --- a/lib/src/screens/exchange_trade/information_page.dart +++ b/lib/src/screens/exchange_trade/information_page.dart @@ -1,9 +1,13 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/info_theme.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; class InformationPage extends StatelessWidget { InformationPage({required this.information}); @@ -21,7 +25,7 @@ class InformationPage extends StatelessWidget { ), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30)), - color: Theme.of(context).textTheme!.bodyLarge!.decorationColor! + color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor ), child: Column( mainAxisSize: MainAxisSize.min, @@ -36,7 +40,7 @@ class InformationPage extends StatelessWidget { fontWeight: FontWeight.normal, fontFamily: 'Lato', decoration: TextDecoration.none, - color: Theme.of(context).accentTextTheme!.bodySmall!.decorationColor! + color: Theme.of(context).extension<InfoTheme>()!.textColor ), ), ), @@ -45,8 +49,8 @@ class InformationPage extends StatelessWidget { child: PrimaryButton( onPressed: () => Navigator.of(context).pop(), text: S.of(context).got_it, - color: Theme.of(context).accentTextTheme!.bodySmall!.backgroundColor!, - textColor: Theme.of(context).primaryTextTheme!.titleLarge!.color! + color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor ), ) ], diff --git a/lib/src/screens/faq/faq_item.dart b/lib/src/screens/faq/faq_item.dart index c41adf399..9ed346ef4 100644 --- a/lib/src/screens/faq/faq_item.dart +++ b/lib/src/screens/faq/faq_item.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -26,12 +27,12 @@ class FAQItemState extends State<FAQItem> { @override Widget build(BuildContext context) { final addIcon = Icon(Icons.add, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!); + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor); final removeIcon = Icon(Icons.remove, color: Palette.blueCraiola); final icon = isActive ? removeIcon : addIcon; final color = isActive ? Palette.blueCraiola - : Theme.of(context).primaryTextTheme!.titleLarge!.color!; + : Theme.of(context).extension<CakeTextTheme>()!.titleColor; return ListTileTheme( contentPadding: EdgeInsets.fromLTRB(0, 6, 24, 6), @@ -54,7 +55,7 @@ class FAQItemState extends State<FAQItem> { fontSize: 14, fontWeight: FontWeight.normal, color: - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), )) ]) diff --git a/lib/src/screens/ionia/auth/ionia_create_account_page.dart b/lib/src/screens/ionia/auth/ionia_create_account_page.dart index 3c8c71290..e6dc83c3c 100644 --- a/lib/src/screens/ionia/auth/ionia_create_account_page.dart +++ b/lib/src/screens/ionia/auth/ionia_create_account_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/email_validator.dart'; import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/routes.dart'; @@ -40,10 +41,7 @@ class IoniaCreateAccountPage extends BasePage { return Text( S.current.sign_up, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -84,10 +82,7 @@ class IoniaCreateAccountPage extends BasePage { onPressed: _createAccount, isLoading: _authViewModel.createUserState is IoniaCreateStateLoading, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), @@ -107,10 +102,7 @@ class IoniaCreateAccountPage extends BasePage { TextSpan( text: S.of(context).settings_terms_and_conditions, style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, fontWeight: FontWeight.w700, ), recognizer: TapGestureRecognizer() @@ -122,10 +114,7 @@ class IoniaCreateAccountPage extends BasePage { TextSpan( text: S.of(context).privacy_policy, style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, fontWeight: FontWeight.w700, ), recognizer: TapGestureRecognizer() diff --git a/lib/src/screens/ionia/auth/ionia_login_page.dart b/lib/src/screens/ionia/auth/ionia_login_page.dart index 912b9c3dc..1bdcfc3a4 100644 --- a/lib/src/screens/ionia/auth/ionia_login_page.dart +++ b/lib/src/screens/ionia/auth/ionia_login_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/core/email_validator.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -33,10 +34,7 @@ class IoniaLoginPage extends BasePage { return Text( S.current.login, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -74,10 +72,7 @@ class IoniaLoginPage extends BasePage { text: S.of(context).login, onPressed: _login, isLoading: _authViewModel.signInState is IoniaCreateStateLoading, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), diff --git a/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart b/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart index 7382a6aee..e8327b71c 100644 --- a/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart +++ b/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; @@ -41,10 +43,7 @@ class IoniaVerifyIoniaOtp extends BasePage { return Text( S.current.verification, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -65,10 +64,7 @@ class IoniaVerifyIoniaOtp extends BasePage { return KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -126,10 +122,7 @@ class IoniaVerifyIoniaOtp extends BasePage { onPressed: _verify, isDisabled: _authViewModel.otpState is IoniaOtpSendDisabled, isLoading: _authViewModel.otpState is IoniaOtpValidating, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), diff --git a/lib/src/screens/ionia/auth/ionia_welcome_page.dart b/lib/src/screens/ionia/auth/ionia_welcome_page.dart index 91d09c2db..e44e3a26d 100644 --- a/lib/src/screens/ionia/auth/ionia_welcome_page.dart +++ b/lib/src/screens/ionia/auth/ionia_welcome_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -14,10 +15,7 @@ class IoniaWelcomePage extends BasePage { return Text( S.current.welcome_to_cakepay, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -38,7 +36,7 @@ class IoniaWelcomePage extends BasePage { fontSize: 18, fontWeight: FontWeight.w400, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), SizedBox(height: 20), @@ -48,7 +46,7 @@ class IoniaWelcomePage extends BasePage { fontSize: 18, fontWeight: FontWeight.w400, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], @@ -59,10 +57,7 @@ class IoniaWelcomePage extends BasePage { PrimaryButton( text: S.of(context).create_account, onPressed: () => Navigator.of(context).pushNamed(Routes.ioniaCreateAccountPage), - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), SizedBox( @@ -74,7 +69,7 @@ class IoniaWelcomePage extends BasePage { fontSize: 15, fontWeight: FontWeight.w500, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), SizedBox(height: 8), diff --git a/lib/src/screens/ionia/cards/ionia_account_cards_page.dart b/lib/src/screens/ionia/cards/ionia_account_cards_page.dart index 1e88078ee..b96249b69 100644 --- a/lib/src/screens/ionia/cards/ionia_account_cards_page.dart +++ b/lib/src/screens/ionia/cards/ionia_account_cards_page.dart @@ -1,14 +1,19 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class IoniaAccountCardsPage extends BasePage { IoniaAccountCardsPage(this.ioniaAccountViewModel); @@ -20,10 +25,7 @@ class IoniaAccountCardsPage extends BasePage { return Text( S.of(context).cards, style: textLargeSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -72,10 +74,7 @@ class _IoniaCardTabsState extends State<_IoniaCardTabs> with SingleTickerProvide width: 230, padding: EdgeInsets.all(5), decoration: BoxDecoration( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor! + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor .withOpacity(0.1), borderRadius: BorderRadius.circular( 25.0, @@ -89,17 +88,11 @@ class _IoniaCardTabsState extends State<_IoniaCardTabs> with SingleTickerProvide borderRadius: BorderRadius.circular( 25.0, ), - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, ), - labelColor: Theme.of(context) - .primaryTextTheme! - .displayLarge! - .backgroundColor!, + labelColor: Theme.of(context).extension<OrderTheme>()!.iconColor, unselectedLabelColor: - Theme.of(context).primaryTextTheme!.titleLarge!.color!, + Theme.of(context).extension<CakeTextTheme>()!.titleColor, tabs: [ Tab( text: S.of(context).active, @@ -169,12 +162,9 @@ class _IoniaCardListView extends StatelessWidget { if(isLoading){ return Center( child: CircularProgressIndicator( - backgroundColor: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + backgroundColor: Theme.of(context).extension<DashboardPageTheme>()!.textColor, valueColor: AlwaysStoppedAnimation<Color>( - Theme.of(context).primaryTextTheme!.bodyMedium!.color!), + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor), ), ); } @@ -184,7 +174,7 @@ class _IoniaCardListView extends StatelessWidget { emptyText, textAlign: TextAlign.center, style: textSmall( - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ), ) @@ -197,18 +187,12 @@ class _IoniaCardListView extends StatelessWidget { child: CardItem( onTap: () => onTap?.call(merchant), title: merchant.legalName, - backgroundColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor! + backgroundColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor .withOpacity(0.1), discount: 0, hideBorder: true, discountBackground: AssetImage('assets/images/red_badge_discount.png'), - titleColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + titleColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor, subtitleColor: Theme.of(context).hintColor, subTitle: '', logoUrl: merchant.logoUrl, diff --git a/lib/src/screens/ionia/cards/ionia_account_page.dart b/lib/src/screens/ionia/cards/ionia_account_page.dart index f3ce3f560..8fddc507a 100644 --- a/lib/src/screens/ionia/cards/ionia_account_page.dart +++ b/lib/src/screens/ionia/cards/ionia_account_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -8,6 +9,7 @@ import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class IoniaAccountPage extends BasePage { IoniaAccountPage(this.ioniaAccountViewModel); @@ -19,10 +21,7 @@ class IoniaAccountPage extends BasePage { return Text( S.current.account, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -136,10 +135,7 @@ class IoniaAccountPage extends BasePage { bottomSection: Column( children: [ PrimaryButton( - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, text: S.of(context).logout, onPressed: () { @@ -170,8 +166,8 @@ class _GradiantContainer extends StatelessWidget { borderRadius: BorderRadius.circular(15), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.decorationColor!, - Theme.of(context).primaryTextTheme!.titleMedium!.color!, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, ], begin: Alignment.topRight, end: Alignment.bottomLeft, diff --git a/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart b/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart index ff1b918eb..f0e641c42 100644 --- a/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart +++ b/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -23,10 +24,7 @@ class IoniaActivateDebitCardPage extends BasePage { return Text( S.current.debit_card, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -79,10 +77,7 @@ class IoniaActivateDebitCardPage extends BasePage { }, isLoading: _cardsListViewModel.createCardState is IoniaCreateCardLoading, text: S.of(context).agree_and_continue, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ); diff --git a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart index 5d91b3464..917c1d8fd 100644 --- a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/palette.dart'; @@ -9,6 +11,7 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/discount_badge.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; @@ -18,6 +21,8 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class IoniaBuyGiftCardDetailPage extends BasePage { IoniaBuyGiftCardDetailPage(this.ioniaPurchaseViewModel); @@ -28,7 +33,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { Widget middle(BuildContext context) { return Text( ioniaPurchaseViewModel.ioniaMerchant.legalName, - style: textMediumSemiBold(color: Theme.of(context).accentTextTheme!.displayLarge!.backgroundColor!), + style: textMediumSemiBold(color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ); } @@ -96,8 +101,8 @@ class IoniaBuyGiftCardDetailPage extends BasePage { borderRadius: BorderRadius.circular(20), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context).primaryTextTheme!.titleMedium!.decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -163,7 +168,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { Text( S.of(context).tip, style: TextStyle( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, fontWeight: FontWeight.w700, fontSize: 14, ), @@ -202,7 +207,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { ioniaPurchaseViewModel.invoiceCommittingState is IsExecutingState, onPressed: () => purchaseCard(context), text: S.of(context).purchase_gift_card, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ); }), @@ -212,7 +217,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { onTap: () => _showTermsAndCondition(context), child: Text(S.of(context).settings_terms_and_conditions, style: textMediumSemiBold( - color: Theme.of(context).primaryTextTheme.bodyMedium!.color!, + color: Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor, ).copyWith(fontSize: 12)), ), SizedBox(height: 16) @@ -232,7 +237,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { child: Text( ioniaPurchaseViewModel.ioniaMerchant.termsAndConditions, style: textMedium( - color: Theme.of(context).textTheme!.displaySmall!.color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), ), ), @@ -270,13 +275,13 @@ class IoniaBuyGiftCardDetailPage extends BasePage { child: Text( instruction.header, style: textLargeSemiBold( - color: Theme.of(context).textTheme!.displaySmall!.color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), )), Text( instruction.body, style: textMedium( - color: Theme.of(context).textTheme!.displaySmall!.color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), ) ]; @@ -323,7 +328,7 @@ class IoniaBuyGiftCardDetailPage extends BasePage { alertLeftActionButtonTextColor: Colors.white, alertRightActionButtonTextColor: Colors.white, alertLeftActionButtonColor: Palette.brightOrange, - alertRightActionButtonColor: Theme.of(context).textTheme!.titleSmall!.color, + alertRightActionButtonColor: Theme.of(context).primaryColor, actionRightButton: () async { Navigator.of(context).pop(); await ioniaPurchaseViewModel.commitPaymentInvoice(); @@ -399,34 +404,34 @@ class TipButton extends StatelessWidget { Color captionTextColor(BuildContext context) { if (isDark(context)) { - return Theme.of(context).primaryTextTheme!.titleLarge!.color!; + return Theme.of(context).extension<CakeTextTheme>()!.titleColor; } return isSelected - ? Theme.of(context).accentTextTheme!.titleLarge!.color! - : Theme.of(context).primaryTextTheme!.titleLarge!.color!; + ? Theme.of(context).dialogTheme.backgroundColor! + : Theme.of(context).extension<CakeTextTheme>()!.titleColor; } Color subTitleTextColor(BuildContext context) { if (isDark(context)) { - return Theme.of(context).primaryTextTheme!.titleLarge!.color!; + return Theme.of(context).extension<CakeTextTheme>()!.titleColor; } return isSelected - ? Theme.of(context).accentTextTheme!.titleLarge!.color! - : Theme.of(context).primaryTextTheme!.labelSmall!.color!; + ? Theme.of(context).dialogTheme.backgroundColor! + : Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor; } Color? backgroundColor(BuildContext context) { if (isDark(context)) { return isSelected ? null - : Theme.of(context).accentTextTheme!.displayLarge!.backgroundColor!.withOpacity(0.01); + : Theme.of(context).extension<CakeTextTheme>()!.titleColor.withOpacity(0.01); } return isSelected ? null - : Theme.of(context).accentTextTheme!.displayLarge!.backgroundColor!.withOpacity(0.1); + : Theme.of(context).extension<CakeTextTheme>()!.titleColor.withOpacity(0.1); } @override @@ -459,8 +464,8 @@ class TipButton extends StatelessWidget { gradient: isSelected ? LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context).primaryTextTheme!.titleMedium!.decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, diff --git a/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart b/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart index e8dce712e..ba5b4fbbd 100644 --- a/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart +++ b/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; @@ -13,6 +15,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class IoniaBuyGiftCardPage extends BasePage { IoniaBuyGiftCardPage( @@ -29,9 +32,6 @@ class IoniaBuyGiftCardPage extends BasePage { @override String get title => S.current.enter_amount; - @override - Color get titleColor => Colors.white; - @override bool get extendBodyBehindAppBar => true; @@ -50,10 +50,7 @@ class IoniaBuyGiftCardPage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -75,11 +72,8 @@ class IoniaBuyGiftCardPage extends BasePage { bottomRight: Radius.circular(24), ), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context) - .primaryTextTheme! - .titleMedium! - .decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), child: Column( @@ -101,10 +95,7 @@ class IoniaBuyGiftCardPage extends BasePage { ], hintText: '1000', placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, fontWeight: FontWeight.w600, fontSize: 36, ), @@ -124,10 +115,7 @@ class IoniaBuyGiftCardPage extends BasePage { ), ), Divider( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, height: 1, ), SizedBox(height: 8), @@ -138,19 +126,13 @@ class IoniaBuyGiftCardPage extends BasePage { Text( S.of(context).min_amount(merchant.minimumCardPurchase.toStringAsFixed(2)), style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, ), ), Text( S.of(context).max_amount(merchant.maximumCardPurchase.toStringAsFixed(2)), style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, ), ), ], @@ -163,16 +145,10 @@ class IoniaBuyGiftCardPage extends BasePage { padding: const EdgeInsets.all(24.0), child: CardItem( title: merchant.legalName, - backgroundColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor! + backgroundColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor .withOpacity(0.1), discount: merchant.discount, - titleColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + titleColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor, subtitleColor: Theme.of(context).hintColor, subTitle: merchant.avaibilityStatus, logoUrl: merchant.logoUrl, @@ -195,10 +171,7 @@ class IoniaBuyGiftCardPage extends BasePage { ), text: S.of(context).continue_text, isDisabled: !ioniaBuyCardViewModel.isEnablePurchase, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ); diff --git a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart index 2a5f39845..7cc4d1f0c 100644 --- a/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart +++ b/lib/src/screens/ionia/cards/ionia_custom_redeem_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; @@ -12,6 +14,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class IoniaCustomRedeemPage extends BasePage { IoniaCustomRedeemPage( @@ -28,9 +31,6 @@ class IoniaCustomRedeemPage extends BasePage { @override String get title => S.current.custom_redeem_amount; - @override - Color get titleColor => Colors.white; - @override bool get extendBodyBehindAppBar => true; @@ -50,10 +50,7 @@ class IoniaCustomRedeemPage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -73,11 +70,8 @@ class IoniaCustomRedeemPage extends BasePage { borderRadius: BorderRadius.only( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context) - .primaryTextTheme! - .titleMedium! - .decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), child: Column( @@ -92,17 +86,11 @@ class IoniaCustomRedeemPage extends BasePage { inputFormatters: [FilteringTextInputFormatter.deny(RegExp('[\-|\ ]'))], hintText: '1000', placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, fontWeight: FontWeight.w500, fontSize: 36, ), - borderColor: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textColor: Colors.white, textStyle: TextStyle( color: Colors.white, @@ -133,10 +121,7 @@ class IoniaCustomRedeemPage extends BasePage { child: Text( '\$${giftCard.remainingAmount} - \$${ioniaCustomRedeemViewModel.amount} = \$${ioniaCustomRedeemViewModel.formattedRemaining} ${S.of(context).remaining}', style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, ), ), ) @@ -150,18 +135,12 @@ class IoniaCustomRedeemPage extends BasePage { padding: const EdgeInsets.all(24.0), child: CardItem( title: giftCard.legalName, - backgroundColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor! + backgroundColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor .withOpacity(0.1), discount: giftCard.remainingAmount, isAmount: true, discountBackground: AssetImage('assets/images/red_badge_discount.png'), - titleColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + titleColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor, subtitleColor: Theme.of(context).hintColor, subTitle: S.of(context).online, logoUrl: giftCard.logoUrl, @@ -178,10 +157,7 @@ class IoniaCustomRedeemPage extends BasePage { isLoading: ioniaCustomRedeemViewModel.redeemState is IsExecutingState, isDisabled: ioniaCustomRedeemViewModel.disableRedeem, text: S.of(context).add_custom_redemption, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, onPressed: () => ioniaCustomRedeemViewModel.addCustomRedeem().then((value) { Navigator.of(context).pop(ioniaCustomRedeemViewModel.remaining.toString()); diff --git a/lib/src/screens/ionia/cards/ionia_custom_tip_page.dart b/lib/src/screens/ionia/cards/ionia_custom_tip_page.dart index f31f0ef30..eced01e96 100644 --- a/lib/src/screens/ionia/cards/ionia_custom_tip_page.dart +++ b/lib/src/screens/ionia/cards/ionia_custom_tip_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; @@ -12,6 +14,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class IoniaCustomTipPage extends BasePage { IoniaCustomTipPage( @@ -29,9 +32,6 @@ class IoniaCustomTipPage extends BasePage { @override String get title => S.current.enter_amount; - @override - Color get titleColor => Colors.white; - @override bool get extendBodyBehindAppBar => true; @@ -51,10 +51,7 @@ class IoniaCustomTipPage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -73,11 +70,8 @@ class IoniaCustomTipPage extends BasePage { decoration: BoxDecoration( borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context) - .primaryTextTheme! - .titleMedium! - .decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), child: Column( @@ -92,17 +86,11 @@ class IoniaCustomTipPage extends BasePage { inputFormatters: [FilteringTextInputFormatter.deny(RegExp('[\-|\ ]'))], hintText: '1000', placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, fontWeight: FontWeight.w500, fontSize: 36, ), - borderColor: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textColor: Colors.white, textStyle: TextStyle( color: Colors.white, @@ -137,10 +125,7 @@ class IoniaCustomTipPage extends BasePage { text: TextSpan( text: '\$${_amountController.text}', style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .headlineSmall! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, ), children: [ TextSpan(text: ' ${S.of(context).is_percentage} '), @@ -158,16 +143,10 @@ class IoniaCustomTipPage extends BasePage { padding: const EdgeInsets.all(24.0), child: CardItem( title: merchant.legalName, - backgroundColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor! + backgroundColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor .withOpacity(0.1), discount: 0.0, - titleColor: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + titleColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor, subtitleColor: Theme.of(context).hintColor, subTitle: merchant.isOnline ? S.of(context).online : S.of(context).offline, logoUrl: merchant.logoUrl, @@ -184,10 +163,7 @@ class IoniaCustomTipPage extends BasePage { Navigator.of(context).pop(customTipViewModel.customTip); }, text: S.of(context).add_tip, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), diff --git a/lib/src/screens/ionia/cards/ionia_debit_card_page.dart b/lib/src/screens/ionia/cards/ionia_debit_card_page.dart index 3cdb7c5df..7e6a43253 100644 --- a/lib/src/screens/ionia/cards/ionia_debit_card_page.dart +++ b/lib/src/screens/ionia/cards/ionia_debit_card_page.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/ionia/ionia_create_state.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_virtual_card.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -6,12 +8,14 @@ import 'package:cake_wallet/src/screens/ionia/widgets/text_icon_button.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class IoniaDebitCardPage extends BasePage { final IoniaGiftCardsListViewModel _cardsListViewModel; @@ -23,10 +27,7 @@ class IoniaDebitCardPage extends BasePage { return Text( S.current.debit_card, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -55,10 +56,7 @@ class IoniaDebitCardPage extends BasePage { child: Text( S.of(context).billing_address_info, style: textSmall( - color: Theme.of(context) - .textTheme! - .headlineMedium! - .color!), + color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor), textAlign: TextAlign.center, ), ), @@ -67,16 +65,13 @@ class IoniaDebitCardPage extends BasePage { text: S.of(context).order_physical_card, onPressed: () {}, color: Color(0xffE9F2FC), - textColor: Theme.of(context).textTheme!.displaySmall!.color!, + textColor: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), SizedBox(height: 8), PrimaryButton( text: S.of(context).add_value, onPressed: () {}, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), SizedBox(height: 16) @@ -124,15 +119,12 @@ class IoniaDebitCardPage extends BasePage { text: S.of(context).get_a, style: textMedium( color: - Theme.of(context).textTheme!.displaySmall!.color!), + Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor), children: [ TextSpan( text: S.of(context).digital_and_physical_card, style: textMediumBold( - color: Theme.of(context) - .textTheme! - .displaySmall! - .color!), + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor), ), TextSpan( text: S.of(context).get_card_note, @@ -150,10 +142,7 @@ class IoniaDebitCardPage extends BasePage { bottomSection: PrimaryButton( text: S.of(context).activate, onPressed: () => _showHowToUseCard(context, activate: true), - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ); @@ -185,7 +174,7 @@ class IoniaDebitCardPage extends BasePage { S.of(context).how_to_use_card, style: textLargeSemiBold( color: - Theme.of(context).textTheme!.bodyMedium!.color!, + Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor, ), ), SizedBox(height: 24), @@ -194,10 +183,7 @@ class IoniaDebitCardPage extends BasePage { child: Text( S.of(context).signup_for_card_accept_terms, style: textSmallSemiBold( - color: Theme.of(context) - .textTheme! - .displaySmall! - .color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), ), ), @@ -219,7 +205,7 @@ class IoniaDebitCardPage extends BasePage { text: S.of(context).got_it, color: Color.fromRGBO(233, 242, 252, 1), textColor: - Theme.of(context).textTheme!.displaySmall!.color!, + Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), SizedBox(height: 21), ], @@ -283,8 +269,8 @@ class _IoniaDebitCardState extends State<_IoniaDebitCard> { borderRadius: BorderRadius.circular(24), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context).primaryTextTheme!.titleMedium!.decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -393,13 +379,13 @@ class _TitleSubtitleTile extends StatelessWidget { Text( title, style: textSmallSemiBold( - color: Theme.of(context).textTheme!.displaySmall!.color!), + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor), ), SizedBox(height: 4), Text( subtitle, style: textSmall( - color: Theme.of(context).textTheme!.displaySmall!.color!), + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor), ), ], ); diff --git a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart index 5107dedee..dba78f557 100644 --- a/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_gift_card_detail_page.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -33,7 +35,7 @@ class IoniaGiftCardDetailPage extends BasePage { final _backButton = Icon( Icons.arrow_back_ios, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, size: 16, ); return Padding( @@ -60,10 +62,7 @@ class IoniaGiftCardDetailPage extends BasePage { return Text( viewModel.giftCard.legalName, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ); } @@ -145,8 +144,8 @@ class IoniaGiftCardDetailPage extends BasePage { viewModel.refeshCard(); }, text: S.of(context).more_options, - color: Theme.of(context).accentTextTheme!.bodySmall!.color!, - textColor: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).cardColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), SizedBox(height: 12), LoadingPrimaryButton( @@ -158,7 +157,7 @@ class IoniaGiftCardDetailPage extends BasePage { }, ), text: S.of(context).mark_as_redeemed, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ], @@ -201,13 +200,13 @@ class IoniaGiftCardDetailPage extends BasePage { child: Text( instruction.header, style: textLargeSemiBold( - color: Theme.of(context).textTheme!.displaySmall!.color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), )), Text( instruction.body, style: textMedium( - color: Theme.of(context).textTheme!.displaySmall!.color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor, ), ) ]; diff --git a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart index b4ab07ca7..c29f571b4 100644 --- a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart +++ b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart @@ -2,10 +2,13 @@ import 'package:cake_wallet/ionia/ionia_create_state.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_menu.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/ionia_filter_modal.dart'; import 'package:cake_wallet/src/widgets/cake_scrollbar.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/debounce.dart'; import 'package:cake_wallet/typography.dart'; @@ -15,6 +18,9 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; class IoniaManageCardsPage extends BasePage { IoniaManageCardsPage(this._cardsListViewModel): searchFocusNode = FocusNode() { @@ -36,29 +42,12 @@ class IoniaManageCardsPage extends BasePage { final _searchController = TextEditingController(); @override - Color get backgroundLightColor => currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; + bool get gradientBackground => true; @override - Color get backgroundDarkColor => Colors.transparent; - - @override - Color get titleColor => currentTheme.type == ThemeType.bright ? Colors.white : Colors.black; - - @override - Widget Function(BuildContext, Widget) get rootWrapper => (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], - begin: Alignment.topRight, - end: Alignment.bottomLeft, - ), - ), - child: scaffold, - ); + Widget Function(BuildContext, Widget) get rootWrapper => + (BuildContext context, Widget scaffold) => + GradientBackground(scaffold: scaffold); @override bool get resizeToAvoidBottomInset => false; @@ -71,10 +60,7 @@ class IoniaManageCardsPage extends BasePage { return Text( S.of(context).gift_cards, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ); } @@ -100,7 +86,7 @@ class IoniaManageCardsPage extends BasePage { width: 32, padding: EdgeInsets.all(8), decoration: BoxDecoration( - color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, border: Border.all( color: Colors.white.withOpacity(0.2), ), @@ -108,7 +94,7 @@ class IoniaManageCardsPage extends BasePage { ), child: Image.asset( 'assets/images/filter.png', - color: Theme.of(context).textTheme!.bodySmall!.decorationColor!, + color: Theme.of(context).extension<FilterTheme>()!.iconColor, ), )), ); @@ -208,9 +194,9 @@ class _IoniaManageCardsPageBodyState extends State<IoniaManageCardsPageBody> { }, title: merchant.legalName, subTitle: merchant.avaibilityStatus, - backgroundColor: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, - titleColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, - subtitleColor: Theme.of(context).accentTextTheme!.displaySmall!.backgroundColor!, + backgroundColor: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, + titleColor: Theme.of(context).extension<DashboardPageTheme>()!.textColor, + subtitleColor: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, discount: merchant.discount, ); }, @@ -221,8 +207,8 @@ class _IoniaManageCardsPageBodyState extends State<IoniaManageCardsPageBody> { thumbHeight: thumbHeight, rightOffset: 1, width: 3, - backgroundColor: Theme.of(context).textTheme!.bodySmall!.decorationColor!.withOpacity(0.05), - thumbColor: Theme.of(context).textTheme!.bodySmall!.decorationColor!.withOpacity(0.5), + backgroundColor: Theme.of(context).extension<FilterTheme>()!.iconColor.withOpacity(0.05), + thumbColor: Theme.of(context).extension<FilterTheme>()!.iconColor.withOpacity(0.5), fromTop: widget.cardsListViewModel.scrollOffsetFromTop, ) : Offstage() @@ -230,8 +216,8 @@ class _IoniaManageCardsPageBodyState extends State<IoniaManageCardsPageBody> { } return Center( child: CircularProgressIndicator( - backgroundColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, - valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).primaryTextTheme!.bodyMedium!.color!), + backgroundColor: Theme.of(context).extension<DashboardPageTheme>()!.textColor, + valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor), ), ); } @@ -254,14 +240,14 @@ class _SearchWidget extends StatelessWidget { padding: EdgeInsets.all(8), child: Image.asset( 'assets/images/mini_search_icon.png', - color: Theme.of(context).textTheme!.bodySmall!.decorationColor!, + color: Theme.of(context).extension<FilterTheme>()!.iconColor, ), ), ); return TextField( focusNode: focusNode, - style: TextStyle(color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!), + style: TextStyle(color: Theme.of(context).extension<DashboardPageTheme>()!.textColor), controller: controller, decoration: InputDecoration( filled: true, @@ -269,10 +255,10 @@ class _SearchWidget extends StatelessWidget { top: 10, left: 10, ), - fillColor: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + fillColor: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, hintText: S.of(context).search, hintStyle: TextStyle( - color: Theme.of(context).accentTextTheme!.displaySmall!.backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, ), alignLabelWithHint: true, floatingLabelBehavior: FloatingLabelBehavior.never, @@ -318,8 +304,7 @@ class _TrailingIcon extends StatelessWidget { onPressed: onPressed, icon: Image.asset( asset, - color: - Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), ), diff --git a/lib/src/screens/ionia/cards/ionia_more_options_page.dart b/lib/src/screens/ionia/cards/ionia_more_options_page.dart index c2b76c1b8..eb6ed8860 100644 --- a/lib/src/screens/ionia/cards/ionia_more_options_page.dart +++ b/lib/src/screens/ionia/cards/ionia_more_options_page.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/ionia/ionia_gift_card.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:flutter/material.dart'; @@ -15,10 +17,7 @@ class IoniaMoreOptionsPage extends BasePage { return Text( S.current.more_options, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ); } @@ -37,7 +36,7 @@ class IoniaMoreOptionsPage extends BasePage { child: Text( S.of(context).choose_from_available_options, style: textMedium( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ), @@ -80,8 +79,8 @@ class _GradiantContainer extends StatelessWidget { borderRadius: BorderRadius.circular(15), gradient: LinearGradient( colors: [ - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).colorScheme.secondary, + Theme.of(context).extension<DashboardPageTheme>()!.secondGradientBackgroundColor, + Theme.of(context).extension<DashboardPageTheme>()!.firstGradientBackgroundColor, ], begin: Alignment.topRight, end: Alignment.bottomLeft, diff --git a/lib/src/screens/ionia/cards/ionia_payment_status_page.dart b/lib/src/screens/ionia/cards/ionia_payment_status_page.dart index 50af2f2f6..dce976444 100644 --- a/lib/src/screens/ionia/cards/ionia_payment_status_page.dart +++ b/lib/src/screens/ionia/cards/ionia_payment_status_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/ionia/ionia_gift_card.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; @@ -11,6 +12,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class IoniaPaymentStatusPage extends BasePage { IoniaPaymentStatusPage(this.viewModel); @@ -23,10 +25,7 @@ class IoniaPaymentStatusPage extends BasePage { S.of(context).generating_gift_card, textAlign: TextAlign.center, style: textMediumSemiBold( - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .backgroundColor!)); + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)); } @override @@ -93,7 +92,7 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage Text( S.of(context).awaiting_payment_confirmation, style: textLargeSemiBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!)) + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)) ]), SizedBox(height: 40), Row(children: [ @@ -132,7 +131,7 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage Text( S.of(context).gift_card_is_generated, style: textLargeSemiBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!)) + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)) ])); } @@ -150,7 +149,7 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage Text( S.of(context).generating_gift_card, style: textLargeSemiBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!))]); + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor))]); }), ], ), @@ -163,7 +162,7 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage widget.viewModel.payingByBitcoin ? S.of(context).bitcoin_payments_require_1_confirmation : S.of(context).proceed_after_one_minute, style: textMedium( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ).copyWith(fontWeight: FontWeight.w500), textAlign: TextAlign.center, )), @@ -175,15 +174,15 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage Routes.ioniaGiftCardDetailPage, arguments: [widget.viewModel.giftCard]), text: S.of(context).open_gift_card, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white); } return PrimaryButton( onPressed: () => Navigator.of(context).pushNamed(Routes.support), text: S.of(context).contact_support, - color: Theme.of(context).accentTextTheme!.bodySmall!.color!, - textColor: Theme.of(context).primaryTextTheme!.titleLarge!.color!); + color: Theme.of(context).cardColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor); }) ]) ), @@ -199,14 +198,14 @@ class _IoniaPaymentStatusPageBodyBodyState extends State<_IoniaPaymentStatusPage Text( title, style: textXSmall( - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ), SizedBox(height: 8), Text( subtitle, style: textMedium( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], diff --git a/lib/src/screens/ionia/widgets/ionia_alert_model.dart b/lib/src/screens/ionia/widgets/ionia_alert_model.dart index 536bb19d4..57a93a127 100644 --- a/lib/src/screens/ionia/widgets/ionia_alert_model.dart +++ b/lib/src/screens/ionia/widgets/ionia_alert_model.dart @@ -1,5 +1,7 @@ import 'package:cake_wallet/src/widgets/alert_background.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:flutter/material.dart'; @@ -41,7 +43,7 @@ class IoniaAlertModal extends StatelessWidget { Text( title, style: textLargeSemiBold( - color: Theme.of(context).textTheme!.bodyMedium!.color!, + color: Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor, ), ), Container( @@ -56,12 +58,9 @@ class IoniaAlertModal extends StatelessWidget { PrimaryButton( onPressed: () => Navigator.pop(context), text: actionTitle, - color: Theme.of(context) - .accentTextTheme! - .bodySmall! - .color!, + color: Theme.of(context).cardColor, textColor: - Theme.of(context).primaryTextTheme!.titleLarge!.color!, + Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), SizedBox(height: 21), ], diff --git a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart index 4c40270b1..8a6820fcd 100644 --- a/lib/src/screens/ionia/widgets/ionia_filter_modal.dart +++ b/lib/src/screens/ionia/widgets/ionia_filter_modal.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/src/screens/ionia/widgets/rounded_checkbox.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -6,6 +7,7 @@ import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.da import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; class IoniaFilterModal extends StatelessWidget { IoniaFilterModal({required this.ioniaGiftCardsListViewModel}){ @@ -20,7 +22,7 @@ class IoniaFilterModal extends StatelessWidget { padding: EdgeInsets.all(10), child: Image.asset( 'assets/images/mini_search_icon.png', - color: Theme.of(context).textTheme!.titleSmall!.color!, + color: Theme.of(context).primaryColor, ), ); return Scaffold( @@ -46,14 +48,14 @@ class IoniaFilterModal extends StatelessWidget { child: TextField( onChanged: ioniaGiftCardsListViewModel.onSearchFilter, style: textMedium( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), decoration: InputDecoration( filled: true, prefixIcon: searchIcon, hintText: S.of(context).search_category, contentPadding: EdgeInsets.only(bottom: 5), - fillColor: Theme.of(context).primaryTextTheme!.bodySmall!.decorationColor!.withOpacity(0.5), + fillColor: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor.withOpacity(0.5), border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(8), @@ -84,12 +86,12 @@ class IoniaFilterModal extends StatelessWidget { children: [ Image.asset( category.iconPath, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), SizedBox(width: 10), Text(category.title, style: textSmall( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ).copyWith(fontWeight: FontWeight.w500)), ], ), diff --git a/lib/src/screens/ionia/widgets/ionia_tile.dart b/lib/src/screens/ionia/widgets/ionia_tile.dart index b7a672b35..932674451 100644 --- a/lib/src/screens/ionia/widgets/ionia_tile.dart +++ b/lib/src/screens/ionia/widgets/ionia_tile.dart @@ -1,5 +1,7 @@ import 'package:cake_wallet/typography.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class IoniaTile extends StatelessWidget { const IoniaTile({ @@ -26,14 +28,14 @@ class IoniaTile extends StatelessWidget { Text( title, style: textXSmall( - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ), SizedBox(height: 8), Text( subTitle, style: textMediumBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], diff --git a/lib/src/screens/ionia/widgets/rounded_checkbox.dart b/lib/src/screens/ionia/widgets/rounded_checkbox.dart index 51a09e5d9..509708dc2 100644 --- a/lib/src/screens/ionia/widgets/rounded_checkbox.dart +++ b/lib/src/screens/ionia/widgets/rounded_checkbox.dart @@ -15,7 +15,7 @@ class RoundedCheckbox extends StatelessWidget { width: 20.0, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(50.0)), - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, ), child: Icon( Icons.check, diff --git a/lib/src/screens/ionia/widgets/text_icon_button.dart b/lib/src/screens/ionia/widgets/text_icon_button.dart index 600e62aa2..937df3a36 100644 --- a/lib/src/screens/ionia/widgets/text_icon_button.dart +++ b/lib/src/screens/ionia/widgets/text_icon_button.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/typography.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; class TextIconButton extends StatelessWidget { @@ -22,12 +23,12 @@ class TextIconButton extends StatelessWidget { Text( label, style: textMediumSemiBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), Icon( Icons.chevron_right_rounded, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ], ), diff --git a/lib/src/screens/monero_accounts/monero_account_edit_or_create_page.dart b/lib/src/screens/monero_accounts/monero_account_edit_or_create_page.dart index 1b5f6be6b..779628be8 100644 --- a/lib/src/screens/monero_accounts/monero_account_edit_or_create_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_edit_or_create_page.dart @@ -56,7 +56,7 @@ class MoneroAccountEditOrCreatePage extends BasePage { text: moneroAccountCreationViewModel.isEdit ? S.of(context).rename : S.of(context).add, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: moneroAccountCreationViewModel.state is IsExecutingState, diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index be3cfc083..6b3d3e08b 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -31,7 +31,7 @@ class MoneroAccountListPage extends StatelessWidget { child: ListView.separated( padding: EdgeInsets.zero, controller: controller, - separatorBuilder: (context, index) => const SectionDivider(), + separatorBuilder: (context, index) => const VerticalSectionDivider(), itemCount: accounts.length, itemBuilder: (context, index) { final account = accounts[index]; @@ -59,7 +59,7 @@ class MoneroAccountListPage extends StatelessWidget { await Navigator.of(context).pushNamed(Routes.accountCreation), child: Container( height: buttonHeight, - color: Theme.of(context).cardColor, + color: Theme.of(context).primaryColor, padding: EdgeInsets.symmetric(horizontal: 24), child: Center( child: Row( diff --git a/lib/src/screens/monero_accounts/widgets/account_tile.dart b/lib/src/screens/monero_accounts/widgets/account_tile.dart index d034ca11a..fa8221513 100644 --- a/lib/src/screens/monero_accounts/widgets/account_tile.dart +++ b/lib/src/screens/monero_accounts/widgets/account_tile.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -21,11 +23,11 @@ class AccountTile extends StatelessWidget { @override Widget build(BuildContext context) { final color = isCurrent - ? Theme.of(context).textTheme.titleSmall!.decorationColor! - : Theme.of(context).textTheme.displayLarge!.decorationColor!; + ? Theme.of(context).extension<AccountListTheme>()!.currentAccountBackgroundColor + : Theme.of(context).extension<AccountListTheme>()!.tilesBackgroundColor; final textColor = isCurrent - ? Theme.of(context).textTheme.titleSmall!.color! - : Theme.of(context).textTheme.displayLarge!.color!; + ? Theme.of(context).extension<AccountListTheme>()!.currentAccountTextColor + : Theme.of(context).extension<AccountListTheme>()!.tilesTextColor; final Widget cell = GestureDetector( onTap: onTap, @@ -61,7 +63,9 @@ class AccountTile extends StatelessWidget { fontSize: 15, fontWeight: FontWeight.w600, fontFamily: 'Lato', - color: Theme.of(context).textTheme.headlineMedium!.color!, + color: isCurrent + ? Theme.of(context).extension<AccountListTheme>()!.currentAccountAmountColor + : Theme.of(context).extension<AccountListTheme>()!.tilesAmountColor, decoration: TextDecoration.none, ), ), @@ -72,24 +76,20 @@ class AccountTile extends StatelessWidget { ); // return cell; - return Slidable( - key: Key(accountName), - child: cell, - endActionPane: _actionPane(context) - ); + return Slidable(key: Key(accountName), child: cell, endActionPane: _actionPane(context)); } ActionPane _actionPane(BuildContext context) => ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.3, - children: [ - SlidableAction( - onPressed: (_) => onEdit.call(), - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - icon: Icons.edit, - label: S.of(context).edit, - ), - ], - ); + motion: const ScrollMotion(), + extentRatio: 0.3, + children: [ + SlidableAction( + onPressed: (_) => onEdit.call(), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + icon: Icons.edit, + label: S.of(context).edit, + ), + ], + ); } diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index c568761b9..386f3012b 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; @@ -111,10 +112,7 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod Navigator.pop(context); }, text: S.of(context).continue_text, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), const SizedBox(height: 25), @@ -125,10 +123,7 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod S.of(context).settings_can_be_changed_later, textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .color, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), ), ), diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 39cd006f5..b9dcc5ae3 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/theme_base.dart'; @@ -17,6 +18,8 @@ import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_pick import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class NewWalletPage extends BasePage { NewWalletPage(this._walletNewVM); @@ -117,32 +120,20 @@ class _WalletNameFormState extends State<WalletNameForm> { style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), decoration: InputDecoration( hintStyle: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .color), + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor), hintText: S.of(context).wallet_name, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .decorationColor!, + color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor, width: 1.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .decorationColor!, + color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor, width: 1.0), ), suffixIcon: Semantics( @@ -169,10 +160,7 @@ class _WalletNameFormState extends State<WalletNameForm> { height: 34, child: Image.asset( 'assets/images/refresh_icon.png', - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), @@ -193,10 +181,7 @@ class _WalletNameFormState extends State<WalletNameForm> { style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ), Padding( diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index d28ff9d77..6f3bb078b 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/search_bar_widget.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/wallet_types.g.dart'; @@ -80,7 +81,7 @@ class WalletTypeFormState extends State<WalletTypeForm> { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ), Padding( @@ -112,7 +113,7 @@ class WalletTypeFormState extends State<WalletTypeForm> { bottomSection: PrimaryButton( onPressed: () => onTypeSelected(), text: S.of(context).seed_language_next, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: selected == null, ), diff --git a/lib/src/screens/new_wallet/widgets/select_button.dart b/lib/src/screens/new_wallet/widgets/select_button.dart index 5d3892ede..e220b281e 100644 --- a/lib/src/screens/new_wallet/widgets/select_button.dart +++ b/lib/src/screens/new_wallet/widgets/select_button.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; class SelectButton extends StatelessWidget { SelectButton({ @@ -21,25 +24,13 @@ class SelectButton extends StatelessWidget { Widget build(BuildContext context) { final color = isSelected ? Colors.green - : Theme.of(context) - .accentTextTheme! - .bodySmall! - .color!; + : Theme.of(context).cardColor; final textColor = isSelected - ? Theme.of(context) - .accentTextTheme! - .headlineSmall! - .decorationColor! - : Theme.of(context).primaryTextTheme!.titleLarge!.color!; + ? Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor + : Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor; final arrowColor = isSelected - ? Theme.of(context) - .accentTextTheme! - .headlineSmall! - .decorationColor! - : Theme.of(context) - .accentTextTheme! - .titleMedium! - .color!; + ? Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor + : Theme.of(context).extension<FilterTheme>()!.titlesColor; final selectArrowImage = Image.asset('assets/images/select_arrow.png', color: arrowColor); @@ -86,4 +77,4 @@ class SelectButton extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index c1b07d8c5..3525160e8 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -182,10 +182,7 @@ class NodeCreateOrEditPage extends BasePage { Navigator.of(context).pop(); }, text: S.of(context).save, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: (!nodeCreateOrEditViewModel.isReady)|| (nodeCreateOrEditViewModel diff --git a/lib/src/screens/nodes/widgets/node_list_row.dart b/lib/src/screens/nodes/widgets/node_list_row.dart index 89ec3bcc7..1739848d7 100644 --- a/lib/src/screens/nodes/widgets/node_list_row.dart +++ b/lib/src/screens/nodes/widgets/node_list_row.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_indicator.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:cw_core/node.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; class NodeListRow extends StandardListRow { NodeListRow( @@ -38,12 +40,13 @@ class NodeListRow extends StandardListRow { decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context) - .textTheme - .headlineMedium! - .decorationColor!), + .extension<ReceivePageTheme>()! + .iconsBackgroundColor), child: Icon(Icons.edit, size: 14, - color: Theme.of(context).textTheme.headlineMedium!.color!))); + color: Theme.of(context) + .extension<ReceivePageTheme>()! + .iconsColor))); } } @@ -56,7 +59,7 @@ class NodeHeaderListRow extends StandardListRow { return SizedBox( width: 20, child: Icon(Icons.add, - color: Theme.of(context).accentTextTheme!.titleMedium!.color,size: 24.0), + color: Theme.of(context).extension<FilterTheme>()!.titlesColor,size: 24.0), ); } } diff --git a/lib/src/screens/order_details/order_details_page.dart b/lib/src/screens/order_details/order_details_page.dart index 0784c7008..10254eaef 100644 --- a/lib/src/screens/order_details/order_details_page.dart +++ b/lib/src/screens/order_details/order_details_page.dart @@ -48,10 +48,9 @@ class OrderDetailsPageBodyState extends State<OrderDetailsPageBody> { Widget build(BuildContext context) { return Observer(builder: (_) { return SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => orderDetailsViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (__, index) { final item = orderDetailsViewModel.items[index]; if (item is TrackTradeListItem) { diff --git a/lib/src/screens/pin_code/pin_code_widget.dart b/lib/src/screens/pin_code/pin_code_widget.dart index e4df2d2fa..9b22fa822 100644 --- a/lib/src/screens/pin_code/pin_code_widget.dart +++ b/lib/src/screens/pin_code/pin_code_widget.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:another_flushbar/flushbar.dart'; @@ -110,11 +112,11 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> { Widget body(BuildContext context) { final deleteIconImage = Image.asset( 'assets/images/delete_icon.png', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ); final faceImage = Image.asset( 'assets/images/face.png', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ); return RawKeyboardListener( @@ -143,7 +145,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> { fontSize: 20, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme!.titleLarge!.color!)), + Theme.of(context).extension<CakeTextTheme>()!.titleColor)), Spacer(flex: 3), Container( width: 180, @@ -159,14 +161,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> { decoration: BoxDecoration( shape: BoxShape.circle, color: isFilled - ? Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color! - : Theme.of(context) - .accentTextTheme! - .bodyMedium! - .color! + ? Theme.of(context).extension<CakeTextTheme>()!.titleColor + : Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor .withOpacity(0.25), )); }), @@ -185,10 +181,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> { style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.normal, - color: Theme.of(context) - .accentTextTheme! - .bodyMedium! - .decorationColor!), + color: Theme.of(context).extension<PinCodeTheme>()!.switchColor), ), ) ], @@ -256,10 +249,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> { style: TextStyle( fontSize: 30.0, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!)), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)), ), ); }), diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index 88547e483..606383faa 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; @@ -40,8 +42,9 @@ class AnonPayInvoicePage extends BasePage { final _formKey = GlobalKey<FormState>(); bool effectsInstalled = false; + @override - Color get titleColor => Colors.white; + bool get gradientAll => true; @override bool get resizeToAvoidBottomInset => false; @@ -56,8 +59,9 @@ class AnonPayInvoicePage extends BasePage { void onClose(BuildContext context) => Navigator.popUntil(context, (route) => route.isFirst); @override - Widget middle(BuildContext context) => - PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel); + Widget middle(BuildContext context) => PresentReceiveOptionPicker( + receiveOptionViewModel: receiveOptionViewModel, + color: titleColor(context)); @override Widget trailing(BuildContext context) => TrailButton( @@ -82,10 +86,7 @@ class AnonPayInvoicePage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -103,8 +104,8 @@ class AnonPayInvoicePage extends BasePage { bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme!.titleSmall!.color!, - Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -142,10 +143,7 @@ class AnonPayInvoicePage extends BasePage { : S.of(context).anonpay_description("a donation link", "donate"), textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor, fontWeight: FontWeight.w500, fontSize: 12), ), @@ -173,10 +171,7 @@ class AnonPayInvoicePage extends BasePage { anonInvoicePageViewModel.generateDonationLink(); } }, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: anonInvoicePageViewModel.state is IsExecutingState, ), diff --git a/lib/src/screens/receive/anonpay_receive_page.dart b/lib/src/screens/receive/anonpay_receive_page.dart index 4deae7972..1dae8e452 100644 --- a/lib/src/screens/receive/anonpay_receive_page.dart +++ b/lib/src/screens/receive/anonpay_receive_page.dart @@ -5,13 +5,15 @@ import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/screens/receive/widgets/anonpay_status_section.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; import 'package:cake_wallet/src/screens/receive/widgets/copy_link_item.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:device_display_brightness/device_display_brightness.dart'; import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart' as qr; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class AnonPayReceivePage extends BasePage { final AnonpayInfoBase invoiceInfo; @@ -22,11 +24,7 @@ class AnonPayReceivePage extends BasePage { String get title => S.current.receive; @override - Color get backgroundLightColor => - currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; - - @override - Color get backgroundDarkColor => Colors.transparent; + bool get gradientBackground => true; @override bool get resizeToAvoidBottomInset => false; @@ -44,10 +42,7 @@ class AnonPayReceivePage extends BasePage { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + color: titleColor(context)), ), Text( invoiceInfo is AnonpayInvoiceInfo @@ -56,7 +51,7 @@ class AnonPayReceivePage extends BasePage { style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w500, - color: Theme.of(context).textTheme!.headlineSmall!.color!), + color: Theme.of(context).extension<QRCodeTheme>()!.qrCodeColor), ) ], ); @@ -78,10 +73,7 @@ class AnonPayReceivePage extends BasePage { ), icon: Icon( Icons.edit, - color: Theme.of(context) - .accentTextTheme! - .bodySmall! - .color!, + color: pageIconColor(context), size: 22.0, ), ), @@ -90,14 +82,8 @@ class AnonPayReceivePage extends BasePage { @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], begin: Alignment.topRight, end: Alignment.bottomLeft)), - child: scaffold); + (BuildContext context, Widget scaffold) => + GradientBackground(scaffold: scaffold); @override Widget body(BuildContext context) { @@ -139,10 +125,7 @@ class AnonPayReceivePage extends BasePage { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), child: QrImage( diff --git a/lib/src/screens/receive/fullscreen_qr_page.dart b/lib/src/screens/receive/fullscreen_qr_page.dart index b7949013e..d11722ccf 100644 --- a/lib/src/screens/receive/fullscreen_qr_page.dart +++ b/lib/src/screens/receive/fullscreen_qr_page.dart @@ -1,8 +1,9 @@ import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class FullscreenQRPage extends BasePage { FullscreenQRPage({required this.qrViewData}); @@ -10,10 +11,7 @@ class FullscreenQRPage extends BasePage { final QrViewData qrViewData; @override - Color get backgroundLightColor => currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; - - @override - Color get backgroundDarkColor => Colors.transparent; + bool get gradientBackground => true; @override bool get resizeToAvoidBottomInset => false; @@ -22,10 +20,7 @@ class FullscreenQRPage extends BasePage { Widget leading(BuildContext context) { final _backButton = Icon( Icons.arrow_back_ios, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, size: 16, ); @@ -47,19 +42,9 @@ class FullscreenQRPage extends BasePage { } @override - Widget Function(BuildContext, Widget) get rootWrapper => (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], - begin: Alignment.topRight, - end: Alignment.bottomLeft, - ), - ), - child: scaffold); + Widget Function(BuildContext, Widget) get rootWrapper => + (BuildContext context, Widget scaffold) => + GradientBackground(scaffold: scaffold); @override Widget body(BuildContext context) { @@ -75,10 +60,7 @@ class FullscreenQRPage extends BasePage { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!)), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)), child: Container( decoration: BoxDecoration( border: Border.all(width: 3, color: Colors.white)), diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 5c498b442..fa150f979 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -1,3 +1,6 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/themes/theme_base.dart'; @@ -19,6 +22,7 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class ReceivePage extends BasePage { ReceivePage({required this.addressListViewModel}) @@ -41,21 +45,13 @@ class ReceivePage extends BasePage { String get title => S.current.receive; @override - Color get backgroundLightColor => - currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white; - - @override - Color get backgroundDarkColor => Colors.transparent; + bool get gradientBackground => true; @override bool get resizeToAvoidBottomInset => false; final FocusNode _cryptoAmountFocus; - @override - Color? get titleColor => - currentTheme.type == ThemeType.bright ? Colors.white : null; - @override Widget middle(BuildContext context) { return Text( @@ -64,23 +60,14 @@ class ReceivePage extends BasePage { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + color: pageIconColor(context)), ); } @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor, - ], begin: Alignment.topRight, end: Alignment.bottomLeft)), - child: scaffold); + (BuildContext context, Widget scaffold) => + GradientBackground(scaffold: scaffold); @override Widget trailing(BuildContext context) { @@ -103,10 +90,7 @@ class ReceivePage extends BasePage { icon: Icon( Icons.share, size: 20, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: pageIconColor(context), ), ), )); @@ -119,10 +103,7 @@ class ReceivePage extends BasePage { ? KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -146,7 +127,7 @@ class ReceivePage extends BasePage { Observer( builder: (_) => ListView.separated( padding: EdgeInsets.all(0), - separatorBuilder: (context, _) => const SectionDivider(), + separatorBuilder: (context, _) => const HorizontalSectionDivider(), shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: addressListViewModel.items.length, @@ -163,10 +144,7 @@ class ReceivePage extends BasePage { icon: Icon( Icons.arrow_forward_ios, size: 14, - color: Theme.of(context) - .textTheme! - .headlineMedium! - .color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor, )); } @@ -178,10 +156,7 @@ class ReceivePage extends BasePage { icon: Icon( Icons.add, size: 20, - color: Theme.of(context) - .textTheme! - .headlineMedium! - .color!, + color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor, )); } @@ -190,23 +165,11 @@ class ReceivePage extends BasePage { final isCurrent = item.address == addressListViewModel.address.address; final backgroundColor = isCurrent - ? Theme.of(context) - .textTheme! - .displayMedium! - .decorationColor! - : Theme.of(context) - .textTheme! - .displaySmall! - .decorationColor!; + ? Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor + : Theme.of(context).extension<ReceivePageTheme>()!.tilesBackgroundColor; final textColor = isCurrent - ? Theme.of(context) - .textTheme! - .displayMedium! - .color! - : Theme.of(context) - .textTheme! - .displaySmall! - .color!; + ? Theme.of(context).extension<ReceivePageTheme>()!.currentTileTextColor + : Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor; return AddressCell.fromItem(item, isCurrent: isCurrent, @@ -252,10 +215,7 @@ class ReceivePage extends BasePage { textAlign: TextAlign.center, style: TextStyle( fontSize: 15, - color: Theme.of(context) - .accentTextTheme! - .displaySmall! - .backgroundColor!)), + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor)), ], ), ); diff --git a/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart b/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart index 5bca308c9..be39ac3bb 100644 --- a/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart +++ b/lib/src/screens/receive/widgets/anonpay_currency_input_field.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class AnonpayCurrencyInputField extends StatelessWidget { const AnonpayCurrencyInputField( @@ -33,7 +35,7 @@ class AnonpayCurrencyInputField extends StatelessWidget { border: Border( bottom: BorderSide( color: - Theme.of(context).primaryTextTheme!.bodyLarge!.color!, + Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, width: 1)), ), child: Padding( @@ -65,10 +67,7 @@ class AnonpayCurrencyInputField extends StatelessWidget { child: Container( height: 32, decoration: BoxDecoration( - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: Center( child: Padding( @@ -78,10 +77,7 @@ class AnonpayCurrencyInputField extends StatelessWidget { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), @@ -119,10 +115,7 @@ class AnonpayCurrencyInputField extends StatelessWidget { placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor, ), validator: null, ), @@ -143,20 +136,14 @@ class AnonpayCurrencyInputField extends StatelessWidget { style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor), ), SizedBox(width: 10), Text(S.of(context).max_value(maxAmount, selectedCurrency.toString()), style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!)), + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor)), ], ), ) diff --git a/lib/src/screens/receive/widgets/anonpay_input_form.dart b/lib/src/screens/receive/widgets/anonpay_input_form.dart index b041aeee9..6dc30d177 100644 --- a/lib/src/screens/receive/widgets/anonpay_input_form.dart +++ b/lib/src/screens/receive/widgets/anonpay_input_form.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/screens/receive/widgets/anonpay_currency_input_field.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; @@ -69,17 +70,14 @@ class AnonInvoiceForm extends StatelessWidget { BaseTextFormField( controller: nameController, focusNode: _nameFocusNode, - borderColor: Theme.of(context).primaryTextTheme!.bodyLarge!.color!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor, suffixIcon: SizedBox(width: 36), hintText: S.of(context).optional_name, textInputAction: TextInputAction.next, placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor, ), textStyle: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), validator: null, @@ -91,16 +89,13 @@ class AnonInvoiceForm extends StatelessWidget { controller: descriptionController, focusNode: _descriptionFocusNode, textInputAction: TextInputAction.next, - borderColor: Theme.of(context).primaryTextTheme!.bodyLarge!.color!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor, suffixIcon: SizedBox(width: 36), hintText: S.of(context).optional_description, placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor, ), textStyle: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), validator: null, @@ -110,17 +105,14 @@ class AnonInvoiceForm extends StatelessWidget { controller: emailController, textInputAction: TextInputAction.next, focusNode: _emailFocusNode, - borderColor: Theme.of(context).primaryTextTheme!.bodyLarge!.color!, + borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor, suffixIcon: SizedBox(width: 36), keyboardType: TextInputType.emailAddress, hintText: S.of(context).optional_email_hint, placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor, ), textStyle: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), validator: EmailValidator(), diff --git a/lib/src/screens/receive/widgets/anonpay_status_section.dart b/lib/src/screens/receive/widgets/anonpay_status_section.dart index 21817d686..f92186aa4 100644 --- a/lib/src/screens/receive/widgets/anonpay_status_section.dart +++ b/lib/src/screens/receive/widgets/anonpay_status_section.dart @@ -1,6 +1,9 @@ import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/typography.dart'; import 'package:flutter/material.dart'; @@ -31,19 +34,13 @@ class AnonInvoiceStatusSection extends StatelessWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor, ), ), Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( - color: Theme.of(context) - .accentTextTheme! - .displaySmall! - .color!, + color: Theme.of(context).extension<AddressTheme>()!.actionButtonColor, borderRadius: BorderRadius.circular(10), ), child: Row( @@ -58,10 +55,7 @@ class AnonInvoiceStatusSection extends StatelessWidget { Text( invoiceInfo.status ?? '', style: textSmallSemiBold( - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ) ], @@ -78,16 +72,13 @@ class AnonInvoiceStatusSection extends StatelessWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .displayLarge! - .decorationColor!, + color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor, ), ), Text( invoiceInfo.invoiceId ?? '', style: textSmallSemiBold( - color: Theme.of(context).primaryTextTheme!.titleLarge!.color, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], diff --git a/lib/src/screens/receive/widgets/copy_link_item.dart b/lib/src/screens/receive/widgets/copy_link_item.dart index cecf33e6c..7c1ffa874 100644 --- a/lib/src/screens/receive/widgets/copy_link_item.dart +++ b/lib/src/screens/receive/widgets/copy_link_item.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class CopyLinkItem extends StatelessWidget { const CopyLinkItem({super.key, required this.url, required this.title}); @@ -14,10 +15,7 @@ class CopyLinkItem extends StatelessWidget { @override Widget build(BuildContext context) { final copyImage = Image.asset('assets/images/copy_address.png', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!); + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor); return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -25,10 +23,7 @@ class CopyLinkItem extends StatelessWidget { Text( title, style: textMedium( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), SizedBox(width: 50), @@ -51,10 +46,7 @@ class CopyLinkItem extends StatelessWidget { onPressed: () => Share.share(url), icon: Icon( Icons.share, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ) ], diff --git a/lib/src/screens/receive/widgets/currency_input_field.dart b/lib/src/screens/receive/widgets/currency_input_field.dart index 85e2cdbe2..20e7bd660 100644 --- a/lib/src/screens/receive/widgets/currency_input_field.dart +++ b/lib/src/screens/receive/widgets/currency_input_field.dart @@ -3,6 +3,9 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class CurrencyInputField extends StatelessWidget { const CurrencyInputField({ @@ -24,7 +27,7 @@ class CurrencyInputField extends StatelessWidget { Widget build(BuildContext context) { final arrowBottomPurple = Image.asset( 'assets/images/arrow_bottom_purple_icon.png', - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, height: 8, ); // This magic number for wider screen sets the text input focus at center of the inputfield @@ -46,13 +49,13 @@ class CurrencyInputField extends StatelessWidget { placeholderTextStyle: isLight ? null : TextStyle( - color: Theme.of(context).primaryTextTheme!.headlineSmall!.color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, fontWeight: FontWeight.w600, ), - borderColor: Theme.of(context).accentTextTheme!.titleLarge!.backgroundColor!, - textColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + borderColor: Theme.of(context).extension<PickerTheme>()!.dividerColor, + textColor: Theme.of(context).extension<DashboardPageTheme>()!.textColor, textStyle: TextStyle( - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), prefixIcon: Padding( padding: EdgeInsets.only( @@ -75,10 +78,7 @@ class CurrencyInputField extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 16, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), if (selectedCurrency.tag != null) @@ -86,7 +86,7 @@ class CurrencyInputField extends StatelessWidget { padding: const EdgeInsets.only(right: 3.0), child: Container( decoration: BoxDecoration( - color: Theme.of(context).primaryTextTheme!.headlineMedium!.color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all( Radius.circular(6), ), @@ -97,10 +97,7 @@ class CurrencyInputField extends StatelessWidget { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), @@ -113,10 +110,7 @@ class CurrencyInputField extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 20, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), ), diff --git a/lib/src/screens/receive/widgets/header_tile.dart b/lib/src/screens/receive/widgets/header_tile.dart index ef9cd7779..e9c134ea5 100644 --- a/lib/src/screens/receive/widgets/header_tile.dart +++ b/lib/src/screens/receive/widgets/header_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; class HeaderTile extends StatelessWidget { HeaderTile({ @@ -22,7 +23,7 @@ class HeaderTile extends StatelessWidget { top: 24, bottom: 24 ), - color: Theme.of(context).textTheme!.displaySmall!.decorationColor!, + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesBackgroundColor, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -32,17 +33,14 @@ class HeaderTile extends StatelessWidget { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, - color: Theme.of(context)!.textTheme.displaySmall!.color!), + color: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor), ), Container( height: 32, width: 32, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context) - .textTheme! - .headlineMedium! - .decorationColor!), + color: Theme.of(context).extension<ReceivePageTheme>()!.iconsBackgroundColor), child: icon, ) ], @@ -50,4 +48,4 @@ class HeaderTile extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index 70a8e48bc..0d2a7c80d 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart'; @@ -12,6 +13,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class QRWidget extends StatelessWidget { QRWidget({ @@ -35,7 +37,7 @@ class QRWidget extends StatelessWidget { @override Widget build(BuildContext context) { final copyImage = Image.asset('assets/images/copy_address.png', - color: Theme.of(context).textTheme!.titleMedium!.decorationColor!); + color: Theme.of(context).extension<QRCodeTheme>()!.qrWidgetCopyButtonColor); return Column( mainAxisSize: MainAxisSize.min, @@ -51,10 +53,7 @@ class QRWidget extends StatelessWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor), ), ), Row( @@ -85,10 +84,7 @@ class QRWidget extends StatelessWidget { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), child: Container( @@ -152,10 +148,7 @@ class QRWidget extends StatelessWidget { style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!), + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor), ), ), Padding( diff --git a/lib/src/screens/release_notes/release_notes_screen.dart b/lib/src/screens/release_notes/release_notes_screen.dart index f72a85a3e..999abc142 100644 --- a/lib/src/screens/release_notes/release_notes_screen.dart +++ b/lib/src/screens/release_notes/release_notes_screen.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -33,8 +34,8 @@ class ReleaseNotesScreen extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(30.0), gradient: LinearGradient(colors: [ - Theme.of(context).colorScheme.secondary, - Theme.of(context).scaffoldBackgroundColor, + Theme.of(context).extension<DashboardPageTheme>()!.firstGradientBackgroundColor, + Theme.of(context).extension<DashboardPageTheme>()!.secondGradientBackgroundColor, ], begin: Alignment.centerLeft, end: Alignment.centerRight)), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), @@ -51,10 +52,7 @@ class ReleaseNotesScreen extends StatelessWidget { fontSize: 24.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), child: Text(title), ), @@ -121,10 +119,7 @@ class ReleaseNotesScreen extends StatelessWidget { decoration: TextDecoration.none, fontSize: 16.0, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/src/screens/rescan/rescan_page.dart b/lib/src/screens/rescan/rescan_page.dart index 58c51ae5b..3a0ba2473 100644 --- a/lib/src/screens/rescan/rescan_page.dart +++ b/lib/src/screens/rescan/rescan_page.dart @@ -35,10 +35,7 @@ class RescanPage extends BasePage { _blockchainHeightWidgetKey.currentState!.height); Navigator.of(context).pop(); }, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: !_rescanViewModel.isButtonEnabled, )) diff --git a/lib/src/screens/restore/restore_from_backup_page.dart b/lib/src/screens/restore/restore_from_backup_page.dart index a057dd131..bf944a6e1 100644 --- a/lib/src/screens/restore/restore_from_backup_page.dart +++ b/lib/src/screens/restore/restore_from_backup_page.dart @@ -75,10 +75,7 @@ class RestoreFromBackupPage extends BasePage { restoreFromBackupViewModel.state is IsExecutingState, onPressed: () => onImportHandler(context), text: S.of(context).import, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white); })) ])), diff --git a/lib/src/screens/restore/restore_wallet_from_seed_details.dart b/lib/src/screens/restore/restore_wallet_from_seed_details.dart index d13606fa1..8d08c441d 100644 --- a/lib/src/screens/restore/restore_wallet_from_seed_details.dart +++ b/lib/src/screens/restore/restore_wallet_from_seed_details.dart @@ -134,10 +134,7 @@ class _RestoreFromSeedDetailsFormState isLoading: widget.walletRestorationFromSeedVM.state is IsExecutingState, text: S.of(context).restore_recover, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: _nameController.text.isNotEmpty, ); diff --git a/lib/src/screens/restore/sweeping_wallet_page.dart b/lib/src/screens/restore/sweeping_wallet_page.dart index 96887b955..75fccf638 100644 --- a/lib/src/screens/restore/sweeping_wallet_page.dart +++ b/lib/src/screens/restore/sweeping_wallet_page.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter/scheduler.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; class SweepingWalletPage extends BasePage { SweepingWalletPage(); @@ -82,10 +84,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .color, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), textAlign: TextAlign.center, ), @@ -97,10 +96,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> { style: TextStyle( fontSize: 36, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), textAlign: TextAlign.center, ), @@ -112,10 +108,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .color, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), textAlign: TextAlign.center, ), diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index 732bd650e..4712cfb10 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_name_validator.dart'; import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class WalletRestoreFromKeysFrom extends StatefulWidget { WalletRestoreFromKeysFrom({ @@ -89,10 +90,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { height: 34, child: Image.asset( 'assets/images/refresh_icon.png', - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index eeba53b04..d10277ced 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_name_validator.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class WalletRestoreFromSeedForm extends StatefulWidget { WalletRestoreFromSeedForm( @@ -93,10 +94,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> { height: 34, child: Image.asset( 'assets/images/refresh_icon.png', - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 6adf9b858..10b5a521d 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -22,6 +24,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/core/seed_validator.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; class WalletRestorePage extends BasePage { WalletRestorePage(this.walletRestoreViewModel) @@ -91,8 +94,7 @@ class WalletRestorePage extends BasePage { fontSize: 18.0, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: titleColor ?? - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + color: titleColor(context)), )); final WalletRestoreViewModel walletRestoreViewModel; @@ -139,10 +141,7 @@ class WalletRestorePage extends BasePage { return KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -194,14 +193,8 @@ class WalletRestorePage extends BasePage { return LoadingPrimaryButton( onPressed: _confirmForm, text: S.of(context).restore_recover, - color: Theme.of(context) - .accentTextTheme! - .titleSmall! - .decorationColor!, - textColor: Theme.of(context) - .accentTextTheme! - .headlineSmall! - .decorationColor!, + color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor, + textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor, isLoading: walletRestoreViewModel.state is IsExecutingState, isDisabled: !walletRestoreViewModel.isButtonEnabled, ); diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index 817ebbc72..221dc37a2 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class RestoreButton extends StatelessWidget { const RestoreButton( diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index f1e7a0334..a2916d642 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -1,3 +1,6 @@ +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -52,7 +55,7 @@ class PreSeedPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.bodySmall!.color!), + color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor), ), ), PrimaryButton( diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index b3128375c..fa17d7ccf 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/clipboard_util.dart'; @@ -13,6 +15,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class WalletSeedPage extends BasePage { WalletSeedPage(this.walletSeedViewModel, {required this.isNewWalletCreated}); @@ -67,11 +70,13 @@ class WalletSeedPage extends BasePage { margin: EdgeInsets.only(left: 10), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(16)), - color: Theme.of(context).accentTextTheme.bodySmall!.color!), + color: Theme.of(context).cardColor), child: Text( S.of(context).seed_language_next, style: TextStyle( - fontSize: 14, fontWeight: FontWeight.w600, color: Palette.blueCraiola), + fontSize: 14, fontWeight: FontWeight.w600, color: Theme.of(context) + .extension<CakeTextTheme>()! + .buttonTextColor), ), ), ) @@ -105,7 +110,7 @@ class WalletSeedPage extends BasePage { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), Padding( padding: EdgeInsets.only(top: 20, left: 16, right: 16), @@ -115,7 +120,7 @@ class WalletSeedPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.bodySmall!.color!), + color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor), ), ) ], @@ -132,7 +137,7 @@ class WalletSeedPage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.labelSmall!.color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), ), ) : Offstage(), @@ -164,7 +169,7 @@ class WalletSeedPage extends BasePage { showBar<void>(context, S.of(context).copied_to_clipboard); }, text: S.of(context).copy, - color: Theme.of(context).accentTextTheme.bodyMedium!.color!, + color: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor, textColor: Colors.white)), )) ], diff --git a/lib/src/screens/seed_language/seed_language_page.dart b/lib/src/screens/seed_language/seed_language_page.dart index 287a1ef07..b15da0375 100644 --- a/lib/src/screens/seed_language/seed_language_page.dart +++ b/lib/src/screens/seed_language/seed_language_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/src/widgets/seed_language_selector.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -67,7 +68,7 @@ class SeedLanguageFormState extends State<SeedLanguageForm> { fontSize: 16.0, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ), Padding( diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index c32fa6f35..dab78f3ef 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -7,6 +7,8 @@ import 'package:cake_wallet/src/widgets/add_template_button.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/request_review_handler.dart'; @@ -49,7 +51,7 @@ class SendPage extends BasePage { String get title => S.current.send; @override - Color get titleColor => Colors.white; + bool get gradientAll => true; @override bool get resizeToAvoidBottomInset => false; @@ -61,7 +63,7 @@ class SendPage extends BasePage { Widget? leading(BuildContext context) { final _backButton = Icon( Icons.arrow_back_ios, - color: titleColor, + color: titleColor(context), size: 16, ); final _closeButton = currentTheme.type == ThemeType.dark @@ -403,7 +405,7 @@ class SendPage extends BasePage { }, text: S.of(context).send, color: - Theme.of(context).accentTextTheme!.bodyLarge!.color!, + Theme.of(context).primaryColor, textColor: Colors.white, isLoading: sendViewModel.state is IsExecutingState || sendViewModel.state is TransactionCommitting, diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index fb06f00ee..205fd62e1 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -1,3 +1,7 @@ +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/src/widgets/trail_button.dart'; import 'package:cake_wallet/view_model/send/template_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -7,6 +11,8 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/src/screens/send/widgets/prefix_currency_icon_widget.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_template_card.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; @@ -21,10 +27,10 @@ class SendTemplatePage extends BasePage { String get title => S.current.exchange_new_template; @override - Color get titleColor => Colors.white; + bool get extendBodyBehindAppBar => true; @override - bool get extendBodyBehindAppBar => true; + bool get gradientAll => true; @override AppBarStyle get appBarStyle => AppBarStyle.transparent; @@ -91,14 +97,8 @@ class SendTemplatePage extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context) - .primaryTextTheme - .displaySmall! - .backgroundColor!, - activeDotColor: Theme.of(context) - .primaryTextTheme - .displayMedium! - .backgroundColor!)) + dotColor: Theme.of(context).extension<SendPageTheme>()!.indicatorDotColor, + activeDotColor: Theme.of(context).extension<DashboardPageTheme>()!.indicatorDotTheme.activeIndicatorColor)) : Offstage(); }, ), @@ -119,10 +119,10 @@ class SendTemplatePage extends BasePage { }, text: S.of(context).add_receiver, color: Colors.transparent, - textColor: Theme.of(context).accentTextTheme.displaySmall!.decorationColor!, + textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor, isDottedBorder: true, borderColor: - Theme.of(context).primaryTextTheme.displaySmall!.decorationColor!)), + Theme.of(context).extension<SendPageTheme>()!.templateBackgroundColor)), PrimaryButton( onPressed: () { if (_formKey.currentState != null && _formKey.currentState!.validate()) { @@ -145,7 +145,7 @@ class SendTemplatePage extends BasePage { } }, text: S.of(context).save, - color: Colors.green, + color: Theme.of(context).primaryColor, textColor: Colors.white) ]))); } diff --git a/lib/src/screens/send/widgets/choose_yat_address_alert.dart b/lib/src/screens/send/widgets/choose_yat_address_alert.dart index f18c116f6..00f93ff4b 100644 --- a/lib/src/screens/send/widgets/choose_yat_address_alert.dart +++ b/lib/src/screens/send/widgets/choose_yat_address_alert.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/cake_scrollbar.dart'; import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:flutter/material.dart'; @@ -66,12 +67,12 @@ class ChooseYatAddressButtonsState extends State<ChooseYatAddressButtons> { Container( width: 300, height: 158, - color: Theme.of(context).accentTextTheme!.bodyMedium!.backgroundColor!, + color: Theme.of(context).dialogBackgroundColor, child: ListView.separated( controller: controller, padding: EdgeInsets.all(0), itemCount: itemCount, - separatorBuilder: (_, __) => const SectionDivider(), + separatorBuilder: (_, __) => const HorizontalSectionDivider(), itemBuilder: (context, index) { final address = addresses[index]; @@ -95,7 +96,7 @@ class ChooseYatAddressButtonsState extends State<ChooseYatAddressButtons> { fontSize: 15, fontWeight: FontWeight.w600, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ) diff --git a/lib/src/screens/send/widgets/confirm_sending_alert.dart b/lib/src/screens/send/widgets/confirm_sending_alert.dart index 775971fe8..7f74f54a2 100644 --- a/lib/src/screens/send/widgets/confirm_sending_alert.dart +++ b/lib/src/screens/send/widgets/confirm_sending_alert.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:flutter/material.dart'; @@ -205,8 +206,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme! - .titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -219,8 +219,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 18, fontWeight: FontWeight.w600, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme! - .titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -240,10 +239,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -256,10 +252,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 18, fontWeight: FontWeight.w600, fontFamily: 'Lato', - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -290,7 +283,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -303,7 +296,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 18, fontWeight: FontWeight.w600, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -332,10 +325,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent> fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), diff --git a/lib/src/screens/send/widgets/prefix_currency_icon_widget.dart b/lib/src/screens/send/widgets/prefix_currency_icon_widget.dart index 6e2428857..d30349066 100644 --- a/lib/src/screens/send/widgets/prefix_currency_icon_widget.dart +++ b/lib/src/screens/send/widgets/prefix_currency_icon_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:flutter/material.dart'; class PrefixCurrencyIcon extends StatelessWidget { @@ -23,7 +24,11 @@ class PrefixCurrencyIcon extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(26), - color: isSelected ? Colors.green : Colors.transparent, + color: isSelected + ? Theme.of(context) + .extension<SendPageTheme>()! + .templateSelectedCurrencyBackgroundColor + : Colors.transparent, ), child: Row( mainAxisSize: MainAxisSize.min, @@ -42,7 +47,11 @@ class PrefixCurrencyIcon extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Colors.white, + color: isSelected + ? Theme.of(context) + .extension<SendPageTheme>()! + .templateSelectedCurrencyTitleColor + : Colors.white, ), ), ], diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 8cdcd6dac..5e5bf44d3 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -20,6 +21,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class SendCard extends StatefulWidget { SendCard({ @@ -101,7 +103,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context).accentTextTheme.bodyLarge!.backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( @@ -126,8 +128,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient( colors: [ - Theme.of(context).primaryTextTheme.titleMedium!.color!, - Theme.of(context).primaryTextTheme.titleMedium!.decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -173,7 +175,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S fontSize: 14, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!), + Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), onPushPasteButton: (context) async { output.resetParsedAddress(); await output.fetchParsedAddress(context); @@ -194,7 +196,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S child: BaseTextFormField( controller: extractedAddressController, readOnly: true, - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), validator: sendViewModel.addressValidator)), @@ -249,10 +251,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S child: Container( height: 32, decoration: BoxDecoration( - color: Theme.of(context) - .primaryTextTheme - .headlineMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all( Radius.circular(6), )), @@ -264,10 +263,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .headlineMedium! - .decorationColor!), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor), ), ), ), @@ -308,10 +304,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .headlineSmall! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14), validator: output.sendAll @@ -329,10 +322,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S onTap: () async => output.setSendAll(), child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .primaryTextTheme - .headlineMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderRadius: BorderRadius.all( Radius.circular(6), ), @@ -344,10 +334,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .headlineMedium! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), @@ -363,7 +350,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S ), Divider( height: 1, - color: Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), Observer( builder: (_) => Padding( padding: EdgeInsets.only(top: 10), @@ -377,10 +364,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headlineSmall! - .decorationColor!), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), ), ), Text( @@ -388,10 +372,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headlineSmall! - .decorationColor!), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), ) ], ), @@ -448,7 +429,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S fontSize: 14, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!), + Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor), ), ), Observer( @@ -465,7 +446,6 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - //color: Theme.of(context).primaryTextTheme!.displaySmall!.color!, color: Colors.white), ), Container( @@ -483,7 +463,6 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - //color: Theme.of(context).primaryTextTheme!.displaySmall!.color!, color: Colors.white, ), ), @@ -498,10 +477,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headlineSmall! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, ), ), ), diff --git a/lib/src/screens/send/widgets/send_template_card.dart b/lib/src/screens/send/widgets/send_template_card.dart index 54538ce5d..fbc7e659d 100644 --- a/lib/src/screens/send/widgets/send_template_card.dart +++ b/lib/src/screens/send/widgets/send_template_card.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/screens/send/widgets/prefix_currency_icon_widget.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/send/template_view_model.dart'; @@ -43,8 +44,8 @@ class SendTemplateCard extends StatelessWidget { borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme.titleMedium!.color!, - Theme.of(context).primaryTextTheme.titleMedium!.decorationColor! + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor, + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor ], begin: Alignment.topLeft, end: Alignment.bottomRight)), child: Column( children: <Widget>[ @@ -58,11 +59,11 @@ class SendTemplateCard extends StatelessWidget { hintText: sendTemplateViewModel.recipients.length > 1 ? S.of(context).template_name : S.of(context).send_name, - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14), validator: sendTemplateViewModel.templateValidator), @@ -89,8 +90,8 @@ class SendTemplateCard extends StatelessWidget { template.output.resetParsedAddress(); await template.output.fetchParsedAddress(context); }, - buttonColor: Theme.of(context).primaryTextTheme.headlineMedium!.color!, - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + buttonColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, @@ -99,7 +100,7 @@ class SendTemplateCard extends StatelessWidget { hintStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, ), validator: sendTemplateViewModel.addressValidator, ), @@ -127,11 +128,11 @@ class SendTemplateCard extends StatelessWidget { ), ), hintText: '0.0000', - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14), validator: sendTemplateViewModel.amountValidator, @@ -156,11 +157,11 @@ class SendTemplateCard extends StatelessWidget { title: sendTemplateViewModel.fiatCurrency, isSelected: template.isFiatSelected)), hintText: '0.00', - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.headlineSmall!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14, ), diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart index dabdafb64..bcdb89aec 100644 --- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/src/widgets/setting_actions.dart'; import 'package:cake_wallet/typography.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/router.dart' as Router; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; final _settingsNavigatorKey = GlobalKey<NavigatorState>(); @@ -71,10 +72,7 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> { }, separatorBuilder: (_, index) => Container( height: 1, - color: Theme.of(context) - .primaryTextTheme! - .bodySmall! - .decorationColor!, + color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor, ), itemCount: itemCount, ), diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index 04fd134e6..6e572abe0 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -2,14 +2,11 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_theme_choice.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -78,14 +75,7 @@ class DisplaySettingsPage extends BasePage { }, ), if (ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile) - SettingsChoicesCell( - ChoicesListItem<ThemeBase>( - title: S.current.color_theme, - items: ThemeList.all, - selectedItem: _displaySettingsViewModel.theme, - onItemSelected: (ThemeBase theme) => _displaySettingsViewModel.setTheme(theme), - ), - ), + SettingsThemeChoicesCell(_displaySettingsViewModel), ], ), ); diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart index d4c4507e6..0a67f0502 100644 --- a/lib/src/screens/settings/manage_nodes_page.dart +++ b/lib/src/screens/settings/manage_nodes_page.dart @@ -37,12 +37,11 @@ class ManageNodesPage extends BasePage { return Flexible( child: SectionStandardList( sectionCount: 1, - context: context, dividerPadding: EdgeInsets.symmetric(horizontal: 24), itemCounter: (int sectionIndex) { return nodeListViewModel.nodes.length; }, - itemBuilder: (_, sectionIndex, index) { + itemBuilder: (_, index) { final node = nodeListViewModel.nodes[index]; final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex; final nodeListRow = NodeListRow( diff --git a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart index 163d59f4f..f0e19a715 100644 --- a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart +++ b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class SettingsCellWithArrow extends StandardListRow { SettingsCellWithArrow({required String title, required Function(BuildContext context)? handler}) @@ -7,5 +8,5 @@ class SettingsCellWithArrow extends StandardListRow { @override Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png', - color: Theme.of(context).primaryTextTheme.labelSmall!.color!); + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor); } diff --git a/lib/src/screens/settings/widgets/settings_choices_cell.dart b/lib/src/screens/settings/widgets/settings_choices_cell.dart index c03c923c3..4d4addb99 100644 --- a/lib/src/screens/settings/widgets/settings_choices_cell.dart +++ b/lib/src/screens/settings/widgets/settings_choices_cell.dart @@ -1,10 +1,12 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; class SettingsChoicesCell extends StatelessWidget { const SettingsChoicesCell(this.choicesListItem, {Key? key}) : super(key: key); - final ChoicesListItem choicesListItem; + final ChoicesListItem<dynamic> choicesListItem; @override Widget build(BuildContext context) { @@ -22,7 +24,7 @@ class SettingsChoicesCell extends StatelessWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], @@ -34,7 +36,7 @@ class SettingsChoicesCell extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), - color: Theme.of(context).accentTextTheme.displaySmall!.color!, + color: Theme.of(context).extension<AddressTheme>()!.actionButtonColor, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, @@ -42,18 +44,18 @@ class SettingsChoicesCell extends StatelessWidget { final isSelected = choicesListItem.selectedItem == e; return GestureDetector( onTap: () { - choicesListItem.onItemSelected?.call(e); + choicesListItem.onItemSelected.call(e); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 32, vertical: 8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: isSelected - ? Theme.of(context).accentTextTheme.bodyLarge!.color! + ? Theme.of(context).primaryColor : null, ), child: Text( - choicesListItem.displayItem?.call(e) ?? e.toString(), + choicesListItem.displayItem.call(e), style: TextStyle( color: isSelected ? Colors.white diff --git a/lib/src/screens/settings/widgets/settings_link_provider_cell.dart b/lib/src/screens/settings/widgets/settings_link_provider_cell.dart index e64d6543b..6e5d48a69 100644 --- a/lib/src/screens/settings/widgets/settings_link_provider_cell.dart +++ b/lib/src/screens/settings/widgets/settings_link_provider_cell.dart @@ -27,7 +27,7 @@ class SettingsLinkProviderCell extends StandardListRow { style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w500, - color: Palette.blueCraiola)); + color: Theme.of(context).primaryColor)); static void _launchUrl(String url) async { try { diff --git a/lib/src/screens/settings/widgets/settings_picker_cell.dart b/lib/src/screens/settings/widgets/settings_picker_cell.dart index 64086d8d1..8e0492330 100644 --- a/lib/src/screens/settings/widgets/settings_picker_cell.dart +++ b/lib/src/screens/settings/widgets/settings_picker_cell.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; @@ -55,7 +56,7 @@ class SettingsPickerCell<ItemType> extends StandardListRow { style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme!.labelSmall?.color, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ); } diff --git a/lib/src/screens/settings/widgets/settings_theme_choice.dart b/lib/src/screens/settings/widgets/settings_theme_choice.dart new file mode 100644 index 000000000..ffb9d7e7e --- /dev/null +++ b/lib/src/screens/settings/widgets/settings_theme_choice.dart @@ -0,0 +1,117 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; +import 'package:flutter/material.dart'; + +class SettingsThemeChoicesCell extends StatelessWidget { + SettingsThemeChoicesCell(this._displaySettingsViewModel); + + final items = ThemeList.all; + + final DisplaySettingsViewModel _displaySettingsViewModel; + + final double cellHeight = 25; + final double cellWidth = 12; + final double cellRadius = 6; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(cellHeight), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + S.current.color_theme, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: + Theme.of(context).extension<CakeTextTheme>()!.titleColor, + ), + ), + ], + ), + SizedBox(height: cellHeight), + GridView.builder( + itemCount: items.length, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + mainAxisExtent: 75, + crossAxisSpacing: 20, + ), + itemBuilder: (context, index) { + final ThemeBase e = items[index]; + final currentTheme = _displaySettingsViewModel.theme; + final isSelected = currentTheme == e; + + return Padding( + padding: EdgeInsets.all(5), + child: GestureDetector( + onTap: () { + _displaySettingsViewModel.setTheme(e); + }, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(cellRadius), + border: isSelected + ? Border.all( + color: Theme.of(context).primaryColor) + : null, + color: Theme.of(context) + .extension<CakeTextTheme>()! + .secondaryTextColor + .withOpacity( + currentTheme.brightness == Brightness.light + ? 0.1 + : 0.3), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(cellRadius), + bottomLeft: Radius.circular(cellRadius)), + color: e.themeData.primaryColor, + ), + ), + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + color: e.themeData.colorScheme.background, + ), + ), + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(cellRadius), + bottomRight: Radius.circular(cellRadius)), + color: e.themeData.cardColor, + ), + ), + ], + ), + ), + ), + ); + }), + ], + ), + ); + } +} diff --git a/lib/src/screens/settings/widgets/settings_version_cell.dart b/lib/src/screens/settings/widgets/settings_version_cell.dart index e314d549d..8ab1a1672 100644 --- a/lib/src/screens/settings/widgets/settings_version_cell.dart +++ b/lib/src/screens/settings/widgets/settings_version_cell.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class SettingsVersionCell extends StatelessWidget { SettingsVersionCell({required this.title}); @@ -18,7 +19,7 @@ class SettingsVersionCell extends StatelessWidget { style: TextStyle( fontSize: 12, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), ) ], ), diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index 6c60dcd1e..a74152e4f 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -33,7 +34,7 @@ class Setup2FAPage extends BasePage { fontWeight: FontWeight.w700, fontSize: 14, height: 1.571, - color: Theme.of(context).primaryTextTheme.headline6!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), SizedBox(height: 16), @@ -43,7 +44,7 @@ class Setup2FAPage extends BasePage { fontWeight: FontWeight.w400, fontSize: 14, height: 1.571, - color: Theme.of(context).primaryTextTheme.headline6!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ], diff --git a/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart b/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart index c4bee2b12..70660c59d 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart @@ -203,7 +203,7 @@ class TOTPEnterCode extends BasePage { }, text: S.of(context).continue_text, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ); }, diff --git a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart index b00d0eed8..82a079b39 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; @@ -53,7 +54,7 @@ class Setup2FAQRPage extends BasePage { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, ), ), child: Container( @@ -137,7 +138,7 @@ class Setup2FAQRPage extends BasePage { ); }, text: S.current.continue_text, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), SizedBox(height: 24), diff --git a/lib/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart b/lib/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart index fb8d26102..2535338e5 100644 --- a/lib/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart +++ b/lib/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:flutter/material.dart'; @@ -30,7 +31,7 @@ class PopUpCancellableAlertDialog extends StatelessWidget { fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ); @@ -55,7 +56,7 @@ class PopUpCancellableAlertDialog extends StatelessWidget { child: Container( width: 340, padding: EdgeInsets.all(10), - color: Theme.of(context).accentTextTheme.titleLarge!.decorationColor!, + color: Theme.of(context).dialogBackgroundColor, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ diff --git a/lib/src/screens/subaddress/address_edit_or_create_page.dart b/lib/src/screens/subaddress/address_edit_or_create_page.dart index 86659130a..e067c78d0 100644 --- a/lib/src/screens/subaddress/address_edit_or_create_page.dart +++ b/lib/src/screens/subaddress/address_edit_or_create_page.dart @@ -53,10 +53,7 @@ class AddressEditOrCreatePage extends BasePage { text: addressEditOrCreateViewModel.isEdit ? S.of(context).rename : S.of(context).new_subaddress_create, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: addressEditOrCreateViewModel.state is AddressIsSaving, diff --git a/lib/src/screens/support/widgets/support_tiles.dart b/lib/src/screens/support/widgets/support_tiles.dart index 9d7c65719..1db87953b 100644 --- a/lib/src/screens/support/widgets/support_tiles.dart +++ b/lib/src/screens/support/widgets/support_tiles.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:flutter/material.dart'; class SupportTile extends StatelessWidget { @@ -22,7 +23,7 @@ class SupportTile extends StatelessWidget { alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).accentTextTheme.bodySmall!.color!, + color: Theme.of(context).cardColor, ), child: Row( mainAxisSize: MainAxisSize.max, @@ -43,7 +44,7 @@ class SupportTile extends StatelessWidget { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).dialogTheme.backgroundColor, ), ), Padding( @@ -53,7 +54,7 @@ class SupportTile extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.labelSmall!.color!, + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, ), ), ) diff --git a/lib/src/screens/support_other_links/support_other_links_page.dart b/lib/src/screens/support_other_links/support_other_links_page.dart index e904e7fab..681a44f8f 100644 --- a/lib/src/screens/support_other_links/support_other_links_page.dart +++ b/lib/src/screens/support_other_links/support_other_links_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/themes/extensions/support_page_theme.dart'; import 'package:cake_wallet/view_model/settings/link_list_item.dart'; import 'package:cake_wallet/view_model/settings/regular_list_item.dart'; import 'package:cake_wallet/view_model/support_view_model.dart'; @@ -21,23 +22,20 @@ class SupportOtherLinksPage extends BasePage { @override Widget body(BuildContext context) { - final iconColor = - Theme.of(context).accentTextTheme.displayLarge!.backgroundColor!; + final iconColor = Theme.of(context).extension<SupportPageTheme>()!.iconColor; return Container( child: Center( child: ConstrainedBox( constraints: BoxConstraints(maxWidth: 500), child: SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => supportViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (_, index) { final item = supportViewModel.items[index]; if (item is RegularListItem) { - return SettingsCellWithArrow( - title: item.title, handler: item.handler); + return SettingsCellWithArrow(title: item.title, handler: item.handler); } if (item is LinkListItem) { diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 1958a7d58..17683c600 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -53,10 +53,9 @@ class TradeDetailsPageBodyState extends State<TradeDetailsPageBody> { return Observer(builder: (_) { // FIX-ME: Added `context` it was not used here before, maby bug ? return SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => tradeDetailsViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (__, index) { final item = tradeDetailsViewModel.items[index]; if (item is TrackTradeListItem) { diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 1b79ceeb0..96f67424c 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -10,11 +10,6 @@ import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/utils/date_formatter.dart'; - -import 'package:url_launcher/url_launcher.dart'; - -import 'package:hive/hive.dart'; class TransactionDetailsPage extends BasePage { TransactionDetailsPage({required this.transactionDetailsViewModel}); @@ -28,10 +23,9 @@ class TransactionDetailsPage extends BasePage { Widget body(BuildContext context) { // FIX-ME: Added `context` it was not used here before, maby bug ? return SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => transactionDetailsViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (__, index) { final item = transactionDetailsViewModel.items[index]; if (item is StandartListItem) { diff --git a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart index 18e5368a6..2c7934d19 100644 --- a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart +++ b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class TextFieldListRow extends StatelessWidget { TextFieldListRow( @@ -34,10 +36,7 @@ class TextFieldListRow extends StatelessWidget { style: TextStyle( fontSize: titleFontSize, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), textAlign: TextAlign.left), TextField( controller: _textController, @@ -49,7 +48,7 @@ class TextFieldListRow extends StatelessWidget { fontSize: valueFontSize, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + Theme.of(context).extension<CakeTextTheme>()!.titleColor), decoration: InputDecoration( isDense: true, contentPadding: EdgeInsets.only(top: 12, bottom: 0), @@ -57,10 +56,7 @@ class TextFieldListRow extends StatelessWidget { hintStyle: TextStyle( fontSize: valueFontSize, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), border: InputBorder.none), onSubmitted: (value) => onSubmitted?.call(value), ) diff --git a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart index 00c7b9796..dfa8e8435 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart @@ -26,10 +26,9 @@ class UnspentCoinsDetailsPage extends BasePage { Widget body(BuildContext context) { // FIX-ME: Added `context` it was not used here before, maby bug ? return SectionStandardList( - context: context, sectionCount: 1, itemCounter: (int _) => unspentCoinsDetailsViewModel.items.length, - itemBuilder: (_, __, index) { + itemBuilder: (__, index) { final item = unspentCoinsDetailsViewModel.items[index]; if (item is StandartListItem) { diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index 432fdc5f6..1c1fbfa5d 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -18,7 +18,7 @@ class UnspentCoinsListPage extends BasePage { //@override //Widget trailing(BuildContext context) { // final questionImage = Image.asset('assets/images/question_mark.png', - // color: Theme.of(context).primaryTextTheme!.titleLarge!.color!); + // color: Theme.of(context).extension<CakeTextTheme>()!.titleColor); // return SizedBox( // height: 20.0, diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index b1916d06c..154c3a2f5 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -1,8 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListItem extends StatelessWidget { @@ -15,11 +14,6 @@ class UnspentCoinsListItem extends StatelessWidget { this.onCheckBoxTap, }); - static const amountColor = Palette.darkBlueCraiola; - static const addressColor = Palette.darkGray; - static const selectedItemColor = Palette.paleCornflowerBlue; - static const unselectedItemColor = Palette.moderateLavender; - final String note; final String amount; final String address; @@ -29,7 +23,17 @@ class UnspentCoinsListItem extends StatelessWidget { @override Widget build(BuildContext context) { + final unselectedItemColor = Theme.of(context).cardColor; + final selectedItemColor = Theme.of(context).primaryColor; final itemColor = isSending ? selectedItemColor : unselectedItemColor; + + final amountColor = isSending + ? Colors.white + : Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor; + final addressColor = isSending + ? Colors.white.withOpacity(0.5) + : Theme.of(context).extension<CakeTextTheme>()!.buttonSecondaryTextColor; + return Container( height: 70, padding: EdgeInsets.symmetric(vertical: 6, horizontal: 12), @@ -41,6 +45,8 @@ class UnspentCoinsListItem extends StatelessWidget { Padding( padding: EdgeInsets.only(right: 12), child: StandardCheckbox( + iconColor: amountColor, + borderColor: addressColor, value: isSending, onChanged: (value) => onCheckBoxTap?.call())), Expanded( child: Column( diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart index 43550a9c5..f62582460 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_switch_row.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/src/widgets/standard_switch.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class UnspentCoinsSwitchRow extends StatelessWidget { UnspentCoinsSwitchRow( @@ -28,10 +29,7 @@ class UnspentCoinsSwitchRow extends StatelessWidget { style: TextStyle( fontSize: titleFontSize, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), textAlign: TextAlign.left), Padding( padding: EdgeInsets.only(top: 12), diff --git a/lib/src/screens/wallet/wallet_edit_page.dart b/lib/src/screens/wallet/wallet_edit_page.dart index 64575b722..7c90ba2c5 100644 --- a/lib/src/screens/wallet/wallet_edit_page.dart +++ b/lib/src/screens/wallet/wallet_edit_page.dart @@ -102,7 +102,7 @@ class WalletEditPage extends BasePage { } }, text: S.of(context).save, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: walletEditViewModel.newName.isEmpty || isLoading, ), diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index 63efdc5f9..37ed3a692 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -13,6 +13,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:qr_flutter/qr_flutter.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; class WalletKeysPage extends BasePage { WalletKeysPage(this.walletKeysViewModel); @@ -49,61 +50,68 @@ class WalletKeysPage extends BasePage { @override Widget body(BuildContext context) { return Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24.0), - child: Container( - width: double.infinity, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - color: Theme.of(context).accentTextTheme.bodySmall!.color!, - ), - child: Center( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: AutoSizeText( - S.of(context).do_not_share_warning_text.toUpperCase(), - textAlign: TextAlign.center, - maxLines: 4, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.red)), + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.0), + color: Theme.of(context).cardColor, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AutoSizeText( + S.of(context).do_not_share_warning_text.toUpperCase(), + textAlign: TextAlign.center, + maxLines: 4, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.red, + ), ), ), ), ), ), - Expanded( - flex: 7, + ), + Expanded( + flex: 7, child: Container( - padding: EdgeInsets.only(top: 20.0, bottom: 20.0), - child: Observer( - builder: (_) { - return ListView.separated( - separatorBuilder: (context, index) => Container( - height: 1, - padding: EdgeInsets.only(left: 24), - color: Theme.of(context).accentTextTheme.titleLarge!.backgroundColor!, - child: const SectionDivider(), - ), - itemCount: walletKeysViewModel.items.length, - itemBuilder: (BuildContext context, int index) { - final item = walletKeysViewModel.items[index]; + padding: EdgeInsets.only(top: 20.0, bottom: 20.0), + child: Observer( + builder: (_) { + return ListView.separated( + separatorBuilder: (context, index) => Container( + height: 1, + padding: EdgeInsets.only(left: 24), + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, + child: const HorizontalSectionDivider(), + ), + itemCount: walletKeysViewModel.items.length, + itemBuilder: (BuildContext context, int index) { + final item = walletKeysViewModel.items[index]; - return GestureDetector( - onTap: () { - ClipboardUtil.setSensitiveDataToClipboard(ClipboardData(text: item.value)); - showBar<void>(context, S.of(context).copied_key_to_clipboard(item.title)); - }, - child: ListRow( - title: item.title + ':', - value: item.value, - ), - ); - }); - }, - )))]); + return GestureDetector( + onTap: () { + ClipboardUtil.setSensitiveDataToClipboard(ClipboardData(text: item.value)); + showBar<void>(context, S.of(context).copied_key_to_clipboard(item.title)); + }, + child: ListRow( + title: item.title + ':', + value: item.value, + ), + ); + }, + ); + }, + ), + ), + ), + ], + ); } } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 81086fac9..2fcc491f0 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -15,6 +17,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; class WalletListPage extends BasePage { WalletListPage({required this.walletListViewModel, required this.authService}); @@ -56,7 +59,9 @@ class WalletListBodyState extends State<WalletListBody> { final newWalletImage = Image.asset('assets/images/new_wallet.png', height: 12, width: 12, color: Colors.white); final restoreWalletImage = Image.asset('assets/images/restore_wallet.png', - height: 12, width: 12, color: Theme.of(context).primaryTextTheme.titleLarge!.color!); + height: 12, + width: 12, + color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor); return Container( padding: EdgeInsets.only(top: 16), @@ -73,7 +78,9 @@ class WalletListBodyState extends State<WalletListBody> { itemBuilder: (__, index) { final wallet = widget.walletListViewModel.wallets[index]; final currentColor = wallet.isCurrent - ? Theme.of(context).accentTextTheme.titleSmall!.decorationColor! + ? Theme.of(context) + .extension<WalletListTheme>()! + .createNewWalletButtonBackgroundColor : Theme.of(context).colorScheme.background; final row = GestureDetector( onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), @@ -98,29 +105,25 @@ class WalletListBodyState extends State<WalletListBody> { color: Theme.of(context).colorScheme.background, alignment: Alignment.centerLeft, child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: <Widget>[ - wallet.isEnabled - ? _imageFor(type: wallet.type) - : nonWalletTypeIcon, - SizedBox(width: 10), - Flexible( - child: Text( + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + wallet.isEnabled + ? _imageFor(type: wallet.type) + : nonWalletTypeIcon, + SizedBox(width: 10), + Flexible( + child: Text( wallet.name, maxLines: null, softWrap: true, style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .titleLarge! - .color!, - ), - ), - ), - ], - ), + fontSize: 22, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension<CakeTextTheme>()! + .titleColor), + )) + ]), ), ), ], @@ -144,13 +147,14 @@ class WalletListBodyState extends State<WalletListBody> { decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context) - .textTheme - .headlineMedium! - .decorationColor!), + .extension<ReceivePageTheme>()! + .iconsBackgroundColor), child: Icon( Icons.edit, size: 14, - color: Theme.of(context).textTheme.headlineMedium!.color!, + color: Theme.of(context) + .extension<ReceivePageTheme>()! + .iconsColor, ), ), ), diff --git a/lib/src/screens/welcome/welcome_page.dart b/lib/src/screens/welcome/welcome_page.dart index 35537f063..19d63f2e7 100644 --- a/lib/src/screens/welcome/welcome_page.dart +++ b/lib/src/screens/welcome/welcome_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; @@ -6,6 +7,8 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; class WelcomePage extends BasePage { static const aspectRatioImage = 1.25; @@ -53,15 +56,12 @@ class WelcomePage extends BasePage { final newWalletImage = Image.asset('assets/images/new_wallet.png', height: 12, width: 12, - color: Theme.of(context) - .accentTextTheme.headlineSmall! - .decorationColor!); + color: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor); final restoreWalletImage = Image.asset('assets/images/restore_wallet.png', height: 12, width: 12, - - color: Theme.of(context).primaryTextTheme.titleLarge!.color!); + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor); return WillPopScope( onWillPop: () async => false, @@ -88,9 +88,7 @@ class WelcomePage extends BasePage { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme.displayMedium! - .color!, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), textAlign: TextAlign.center, ), @@ -102,9 +100,7 @@ class WelcomePage extends BasePage { style: TextStyle( fontSize: 36, fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme.titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), textAlign: TextAlign.center, ), @@ -116,9 +112,7 @@ class WelcomePage extends BasePage { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context) - .accentTextTheme.displayMedium! - .color!, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), textAlign: TextAlign.center, ), @@ -132,9 +126,7 @@ class WelcomePage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.normal, - color: Theme.of(context) - .accentTextTheme.displayMedium! - .color!, + color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor, ), textAlign: TextAlign.center, ), @@ -145,12 +137,8 @@ class WelcomePage extends BasePage { context, Routes.newWalletFromWelcome), image: newWalletImage, text: S.of(context).create_new, - color: Theme.of(context) - .accentTextTheme.titleSmall! - .decorationColor!, - textColor: Theme.of(context) - .accentTextTheme.headlineSmall! - .decorationColor!, + color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor, + textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor, ), ), Padding( @@ -163,12 +151,8 @@ class WelcomePage extends BasePage { }, image: restoreWalletImage, text: S.of(context).restore_wallet, - color: Theme.of(context) - .accentTextTheme.bodySmall! - .color!, - textColor: Theme.of(context) - .primaryTextTheme.titleLarge! - .color!), + color: Theme.of(context).cardColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor), ) ], ) diff --git a/lib/src/screens/yat_emoji_id.dart b/lib/src/screens/yat_emoji_id.dart index 6e3ec9cb1..944331285 100644 --- a/lib/src/screens/yat_emoji_id.dart +++ b/lib/src/screens/yat_emoji_id.dart @@ -6,12 +6,15 @@ import 'package:cake_wallet/src/screens/yat/widgets/yat_close_button.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/material.dart'; import 'package:animate_do/animate_do.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class YatEmojiId extends StatelessWidget { YatEmojiId(this.emojiId); @@ -39,7 +42,7 @@ class YatEmojiId extends StatelessWidget { child: Container( height: 420, color: - Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, padding: EdgeInsets.fromLTRB(24, 15, 24, 24), child: Column( mainAxisSize: MainAxisSize.max, @@ -89,7 +92,7 @@ class YatEmojiId extends StatelessWidget { fontSize: 32, fontWeight: FontWeight.bold, fontFamily: 'Lato', - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, decoration: TextDecoration.none, ) ), @@ -102,10 +105,7 @@ class YatEmojiId extends StatelessWidget { fontSize: 18, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displaySmall! - .backgroundColor!, + color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor, decoration: TextDecoration.none, ) ) diff --git a/lib/src/widgets/add_template_button.dart b/lib/src/widgets/add_template_button.dart index c88b72e7f..667a103ab 100644 --- a/lib/src/widgets/add_template_button.dart +++ b/lib/src/widgets/add_template_button.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class AddTemplateButton extends StatelessWidget { final Function() onTap; @@ -20,7 +21,7 @@ class AddTemplateButton extends StatelessWidget { borderType: BorderType.RRect, dashPattern: [6, 4], color: - Theme.of(context).primaryTextTheme!.displaySmall!.decorationColor!, + Theme.of(context).extension<SendPageTheme>()!.templateDottedBorderColor, strokeWidth: 2, radius: Radius.circular(20), child: Container( @@ -35,20 +36,14 @@ class AddTemplateButton extends StatelessWidget { child: currentTemplatesLength >= 1 ? Icon( Icons.add, - color: Theme.of(context) - .primaryTextTheme! - .displayMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.templateNewTextColor, ) : Text( S.of(context).new_template, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme! - .displayMedium! - .color!, + color: Theme.of(context).extension<SendPageTheme>()!.templateNewTextColor, ), ), ), diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 3462c7ed4..000e6325e 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/services.dart'; @@ -7,6 +8,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; enum AddressTextFieldOption { paste, qrCode, addressBook } @@ -64,7 +66,8 @@ class AddressTextField extends StatelessWidget { controller: controller, focusNode: focusNode, style: textStyle ?? - TextStyle(fontSize: 16, color: Theme.of(context).primaryTextTheme.titleLarge!.color!), + TextStyle( + fontSize: 16, color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), decoration: InputDecoration( suffixIcon: SizedBox( width: prefixIconWidth * options.length + (spaceBetweenPrefixIcons * options.length), @@ -113,15 +116,14 @@ class AddressTextField extends StatelessWidget { padding: EdgeInsets.all(8), decoration: BoxDecoration( color: buttonColor ?? - Theme.of(context).accentTextTheme.titleLarge!.color!, + Theme.of(context).dialogTheme.backgroundColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: Image.asset( 'assets/images/paste_ios.png', color: iconColor ?? Theme.of(context) - .primaryTextTheme - .headlineMedium! - .decorationColor!, + .extension<SendPageTheme>()! + .textFieldButtonIconColor, )), ), )), @@ -140,15 +142,14 @@ class AddressTextField extends StatelessWidget { padding: EdgeInsets.all(8), decoration: BoxDecoration( color: buttonColor ?? - Theme.of(context).accentTextTheme.titleLarge!.color!, + Theme.of(context).dialogTheme.backgroundColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: Image.asset( 'assets/images/qr_code_icon.png', color: iconColor ?? Theme.of(context) - .primaryTextTheme - .headlineMedium! - .decorationColor!, + .extension<SendPageTheme>()! + .textFieldButtonIconColor, )), ), )) @@ -167,15 +168,14 @@ class AddressTextField extends StatelessWidget { padding: EdgeInsets.all(8), decoration: BoxDecoration( color: buttonColor ?? - Theme.of(context).accentTextTheme.titleLarge!.color!, + Theme.of(context).dialogTheme.backgroundColor, borderRadius: BorderRadius.all(Radius.circular(6))), child: Image.asset( 'assets/images/open_book.png', color: iconColor ?? Theme.of(context) - .primaryTextTheme - .headlineMedium! - .decorationColor!, + .extension<SendPageTheme>()! + .textFieldButtonIconColor, )), ), )) diff --git a/lib/src/widgets/alert_background.dart b/lib/src/widgets/alert_background.dart index 1b72597af..0ced8ee06 100644 --- a/lib/src/widgets/alert_background.dart +++ b/lib/src/widgets/alert_background.dart @@ -1,7 +1,7 @@ import 'dart:ui'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/palette.dart'; class AlertBackground extends StatelessWidget { AlertBackground({required this.child}); @@ -20,7 +20,9 @@ class AlertBackground extends StatelessWidget { child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0), child: Container( - decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)), + decoration: BoxDecoration( + color: + Theme.of(context).extension<AlertTheme>()!.backdropColor), child: Center( child: Container( width: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint, diff --git a/lib/src/widgets/alert_with_one_action.dart b/lib/src/widgets/alert_with_one_action.dart index c3b364e8d..c06114f5b 100644 --- a/lib/src/widgets/alert_with_one_action.dart +++ b/lib/src/widgets/alert_with_one_action.dart @@ -31,10 +31,7 @@ class AlertWithOneAction extends BaseAlertDialog { width: 300, height: 52, padding: EdgeInsets.only(left: 12, right: 12), - color: Theme.of(context) - .accentTextTheme! - .bodyMedium! - .backgroundColor!, + color: Theme.of(context).dialogBackgroundColor, child: ButtonTheme( minWidth: double.infinity, child: TextButton( @@ -48,10 +45,7 @@ class AlertWithOneAction extends BaseAlertDialog { style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme! - .bodyMedium! - .backgroundColor!, + color: Theme.of(context).primaryColor, decoration: TextDecoration.none, ), )), diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 995e3f205..757ee1862 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/src/widgets/section_divider.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -25,7 +27,7 @@ class BaseAlertDialog extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ); @@ -39,7 +41,7 @@ class BaseAlertDialog extends StatelessWidget { fontSize: 16, fontWeight: FontWeight.normal, fontFamily: 'Lato', - color: Theme.of(context).primaryTextTheme!.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ); @@ -57,10 +59,7 @@ class BaseAlertDialog extends StatelessWidget { onPressed: actionLeft, style: TextButton.styleFrom( backgroundColor: leftActionButtonColor ?? - Theme.of(context) - .accentTextTheme! - .bodyLarge! - .decorationColor!, + Theme.of(context).dialogBackgroundColor, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.zero))), child: Text( @@ -71,24 +70,18 @@ class BaseAlertDialog extends StatelessWidget { fontFamily: 'Lato', fontWeight: FontWeight.w600, color: leftActionButtonTextColor ?? - Theme.of(context) - .primaryTextTheme! - .bodyLarge! - .backgroundColor!, + Theme.of(context).extension<AlertTheme>()!.leftButtonTextColor, decoration: TextDecoration.none, ), )), ), - const SectionDivider(), + const VerticalSectionDivider(), Expanded( child: TextButton( onPressed: actionRight, style: TextButton.styleFrom( backgroundColor: rightActionButtonColor ?? - Theme.of(context) - .accentTextTheme! - .bodyMedium! - .backgroundColor!, + Theme.of(context).dialogBackgroundColor, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.zero))), child: Text( @@ -99,10 +92,7 @@ class BaseAlertDialog extends StatelessWidget { fontFamily: 'Lato', fontWeight: FontWeight.w600, color: rightActionButtonTextColor ?? - Theme.of(context) - .primaryTextTheme! - .bodyMedium! - .backgroundColor!, + Theme.of(context).primaryColor, decoration: TextDecoration.none, ), )), @@ -120,7 +110,9 @@ class BaseAlertDialog extends StatelessWidget { child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0), child: Container( - decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)), + decoration: BoxDecoration( + color: + Theme.of(context).extension<AlertTheme>()!.backdropColor), child: Center( child: GestureDetector( onTap: () => null, @@ -128,10 +120,7 @@ class BaseAlertDialog extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(30)), child: Container( width: 300, - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .decorationColor!, + color: Theme.of(context).dialogBackgroundColor, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ @@ -145,7 +134,7 @@ class BaseAlertDialog extends StatelessWidget { isDividerExists ? Padding( padding: EdgeInsets.only(top: 16, bottom: 8), - child: const SectionDivider(), + child: const HorizontalSectionDivider(), ) : Offstage(), Padding( @@ -154,7 +143,7 @@ class BaseAlertDialog extends StatelessWidget { ) ], ), - const SectionDivider(), + const HorizontalSectionDivider(), actionButtons(context) ], ), diff --git a/lib/src/widgets/base_text_form_field.dart b/lib/src/widgets/base_text_form_field.dart index a9dd51380..5649a0784 100644 --- a/lib/src/widgets/base_text_form_field.dart +++ b/lib/src/widgets/base_text_form_field.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -78,7 +79,7 @@ class BaseTextFormField extends StatelessWidget { TextStyle( fontSize: 16.0, color: textColor ?? - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + Theme.of(context).extension<CakeTextTheme>()!.titleColor), decoration: InputDecoration( prefix: prefix, prefixIcon: prefixIcon, @@ -92,26 +93,17 @@ class BaseTextFormField extends StatelessWidget { focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: borderColor ?? - Theme.of(context) - .primaryTextTheme! - .titleLarge! - .backgroundColor!, + Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor, width: borderWidth)), disabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: borderColor ?? - Theme.of(context) - .primaryTextTheme! - .titleLarge! - .backgroundColor!, + Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor, width: borderWidth)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: borderColor ?? - Theme.of(context) - .primaryTextTheme! - .titleLarge! - .backgroundColor!, + Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor, width: borderWidth))), validator: validator, ); diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart index 6d2b891db..2ba0a3406 100644 --- a/lib/src/widgets/blockchain_height_widget.dart +++ b/lib/src/widgets/blockchain_height_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/date_picker.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -81,7 +82,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> { fontSize: 16.0, fontWeight: FontWeight.w500, color: - Theme.of(context).primaryTextTheme!.titleLarge!.color!), + Theme.of(context).extension<CakeTextTheme>()!.titleColor), ), ), Row( diff --git a/lib/src/widgets/cake_scrollbar.dart b/lib/src/widgets/cake_scrollbar.dart index 6b8cb59da..bf6604d8e 100644 --- a/lib/src/widgets/cake_scrollbar.dart +++ b/lib/src/widgets/cake_scrollbar.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; import 'package:flutter/material.dart'; class CakeScrollbar extends StatelessWidget { @@ -28,7 +29,7 @@ class CakeScrollbar extends StatelessWidget { width: width, decoration: BoxDecoration( color: backgroundColor ?? - Theme.of(context).textTheme!.bodyMedium!.decorationColor!, + Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor, borderRadius: BorderRadius.all(Radius.circular(3))), child: Stack( children: <Widget>[ @@ -40,7 +41,7 @@ class CakeScrollbar extends StatelessWidget { width: width, decoration: BoxDecoration( color: thumbColor ?? - Theme.of(context).textTheme!.bodyMedium!.color!, + Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor, borderRadius: BorderRadius.all(Radius.circular(3))), ), ) diff --git a/lib/src/widgets/check_box_picker.dart b/lib/src/widgets/check_box_picker.dart index 7fd0b57a3..30f81e981 100644 --- a/lib/src/widgets/check_box_picker.dart +++ b/lib/src/widgets/check_box_picker.dart @@ -1,7 +1,10 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; class CheckBoxPicker extends StatefulWidget { CheckBoxPicker({ @@ -53,10 +56,7 @@ class CheckBoxPickerState extends State<CheckBoxPicker> { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(30)), child: Container( - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, child: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.65, @@ -90,20 +90,14 @@ class CheckBoxPickerState extends State<CheckBoxPicker> { Widget itemsList() { return Container( - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, child: ListView.separated( padding: EdgeInsets.zero, controller: controller, shrinkWrap: true, separatorBuilder: (context, index) => widget.isSeparated ? Divider( - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, height: 1, ) : const SizedBox(), @@ -122,19 +116,13 @@ class CheckBoxPickerState extends State<CheckBoxPicker> { }, child: Container( height: 55, - color: Theme.of(context) - .accentTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, padding: EdgeInsets.only(left: 24, right: 24), child: CheckboxListTile( value: item.value, activeColor: item.value ? Palette.blueCraiola - : Theme.of(context) - .accentTextTheme! - .titleMedium! - .decorationColor!, + : Theme.of(context).extension<FilterTheme>()!.checkboxBackgroundColor, checkColor: Colors.white, title: widget.displayItem?.call(item) ?? Text( @@ -145,7 +133,7 @@ class CheckBoxPickerState extends State<CheckBoxPicker> { fontWeight: FontWeight.w600, color: item.isDisabled ? Colors.grey.withOpacity(0.5) - : Theme.of(context).primaryTextTheme!.titleLarge!.color!, + : Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), diff --git a/lib/src/widgets/checkbox_widget.dart b/lib/src/widgets/checkbox_widget.dart index 20c900b25..1ea3ee698 100644 --- a/lib/src/widgets/checkbox_widget.dart +++ b/lib/src/widgets/checkbox_widget.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; class CheckboxWidget extends StatefulWidget { CheckboxWidget({required this.value, required this.caption, required this.onChanged}); @@ -37,7 +39,9 @@ class CheckboxWidgetState extends State<CheckboxWidget> { margin: EdgeInsets.only(right: 10.0), decoration: BoxDecoration( border: Border.all( - color: Theme.of(context).primaryTextTheme.bodySmall!.color!, + color: value + ? Palette.blueCraiola + : Theme.of(context).extension<FilterTheme>()!.checkboxBoundsColor, width: 1.0, ), borderRadius: BorderRadius.all( @@ -59,12 +63,12 @@ class CheckboxWidgetState extends State<CheckboxWidget> { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14.0, - color: Theme.of(context).primaryTextTheme.titleLarge!.color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ) ], - ), + ) ); } } diff --git a/lib/src/widgets/collapsible_standart_list.dart b/lib/src/widgets/collapsible_standart_list.dart index 1fef64969..83e4daee2 100644 --- a/lib/src/widgets/collapsible_standart_list.dart +++ b/lib/src/widgets/collapsible_standart_list.dart @@ -3,90 +3,36 @@ import 'package:flutter/material.dart'; class CollapsibleSectionList extends SectionStandardList { CollapsibleSectionList( - {required BuildContext context, - required int sectionCount, - required int Function(int sectionIndex) itemCounter, - required Widget Function(BuildContext context, int sectionIndex, int itemIndex) itemBuilder, - Color? themeColor, - Color? dividerThemeColor, - Widget Function(BuildContext context, int sectionIndex)? sectionTitleBuilder, - bool hasTopSeparator = false}) + {required int sectionCount, + required int Function(int sectionIndex) itemCounter, + required Widget Function(int sectionIndex, int itemIndex) itemBuilder, + Widget Function(int sectionIndex)? sectionTitleBuilder, + bool hasTopSeparator = false}) : super( - context: context, - hasTopSeparator: hasTopSeparator, - sectionCount: sectionCount, - itemCounter: itemCounter, - itemBuilder: itemBuilder, - sectionTitleBuilder: sectionTitleBuilder, - themeColor: themeColor, - dividerThemeColor: dividerThemeColor); + hasTopSeparator: hasTopSeparator, + sectionCount: sectionCount, + itemCounter: itemCounter, + itemBuilder: itemBuilder, + sectionTitleBuilder: sectionTitleBuilder); @override - List<Widget> transform( - bool hasTopSeparator, - BuildContext context, - int sectionCount, - int Function(int sectionIndex) itemCounter, - Widget Function(BuildContext context, int sectionIndex, int itemIndex) itemBuilder, - Widget Function(BuildContext context, int sectionIndex)? sectionTitleBuilder, - Color? themeColor, - Color? dividerThemeColor) { - final items = <Widget>[]; - - for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) { - final itemCount = itemCounter(sectionIndex); - - items.add(Theme( - data: ThemeData( - textTheme: TextTheme(titleMedium: TextStyle(color: themeColor,fontFamily: 'Lato')), - backgroundColor: dividerThemeColor, - unselectedWidgetColor: themeColor, - accentColor: themeColor) - .copyWith(dividerColor: Colors.transparent), - child: Padding( - padding: const EdgeInsets.only(left: 24.0), - child: ListTileTheme( - contentPadding: EdgeInsets.only(right: 16,top:sectionIndex>0?26:0), - child: ExpansionTile( - textColor: themeColor, - iconColor: themeColor, - title: sectionTitleBuilder == null - ? Container() - : Container(child: buildTitle(items, sectionIndex, context)), - initiallyExpanded: true, - children: buildSection(itemCount, items, sectionIndex, context), - ), - ), - ), - )); - - } - - items.add(StandardListSeparator(padding: EdgeInsets.only(left: 24))); - return items; - } - - @override - Widget buildTitle( - List<Widget> items, int sectionIndex, BuildContext context) { + Widget buildTitle(List<Widget> items, int sectionIndex) { if (sectionTitleBuilder == null) { throw Exception('Cannot to build title. sectionTitleBuilder is null'); } - return sectionTitleBuilder!.call(context, sectionIndex); + return sectionTitleBuilder!.call(sectionIndex); } @override - List<Widget> buildSection(int itemCount, List<Widget> items, int sectionIndex, - BuildContext context) { + List<Widget> buildSection(int itemCount, List<Widget> items, int sectionIndex) { final List<Widget> section = []; for (var itemIndex = 0; itemIndex < itemCount; itemIndex++) { - final item = itemBuilder(context, sectionIndex, itemIndex); + final item = itemBuilder(sectionIndex, itemIndex); section.add(StandardListSeparator()); section.add(item); - } return section; } diff --git a/lib/src/widgets/dashboard_card_widget.dart b/lib/src/widgets/dashboard_card_widget.dart index f98e5d68e..b3f92123a 100644 --- a/lib/src/widgets/dashboard_card_widget.dart +++ b/lib/src/widgets/dashboard_card_widget.dart @@ -1,4 +1,7 @@ +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class DashBoardRoundedCardWidget extends StatelessWidget { @@ -26,10 +29,10 @@ class DashBoardRoundedCardWidget extends StatelessWidget { padding: EdgeInsets.all(20), width: double.infinity, decoration: BoxDecoration( - color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, borderRadius: BorderRadius.circular(20), border: Border.all( - color: Colors.white.withOpacity(0.20), + color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor, ), ), child: @@ -39,10 +42,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget { Text( title, style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor, fontSize: 24, fontWeight: FontWeight.w900, ), @@ -51,10 +51,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget { Text( subTitle, style: TextStyle( - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor, fontWeight: FontWeight.w500, fontFamily: 'Lato'), ) diff --git a/lib/src/widgets/gradient_background.dart b/lib/src/widgets/gradient_background.dart new file mode 100644 index 000000000..591e24289 --- /dev/null +++ b/lib/src/widgets/gradient_background.dart @@ -0,0 +1,30 @@ +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:flutter/material.dart'; + +class GradientBackground extends StatelessWidget { + const GradientBackground({required this.scaffold}); + + final Widget scaffold; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Theme.of(context) + .extension<DashboardPageTheme>()! + .firstGradientBackgroundColor, + Theme.of(context) + .extension<DashboardPageTheme>()! + .secondGradientBackgroundColor, + Theme.of(context) + .extension<DashboardPageTheme>()! + .thirdGradientBackgroundColor, + ], + begin: Alignment.topRight, + end: Alignment.bottomLeft, + )), + child: scaffold); + } +} diff --git a/lib/src/widgets/introducing_card.dart b/lib/src/widgets/introducing_card.dart index 0a4a27f36..bd71183fd 100644 --- a/lib/src/widgets/introducing_card.dart +++ b/lib/src/widgets/introducing_card.dart @@ -1,6 +1,8 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/generated/i18n.dart'; class IntroducingCard extends StatelessWidget { @@ -27,7 +29,7 @@ class IntroducingCard extends StatelessWidget { color: borderColor, width: 1, ), - color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!), + color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, @@ -45,10 +47,7 @@ class IntroducingCard extends StatelessWidget { fontSize: 24, fontFamily: 'Lato', fontWeight: FontWeight.bold, - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor, height: 1), maxLines: 1, textAlign: TextAlign.center), @@ -58,10 +57,7 @@ class IntroducingCard extends StatelessWidget { style: TextStyle( fontSize: 12, fontFamily: 'Lato', - color: Theme.of(context) - .accentTextTheme! - .displayMedium! - .backgroundColor!, + color: Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor, height: 1)), ], ), diff --git a/lib/src/widgets/list_row.dart b/lib/src/widgets/list_row.dart index d9d9e2f8d..c404a443b 100644 --- a/lib/src/widgets/list_row.dart +++ b/lib/src/widgets/list_row.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class ListRow extends StatelessWidget { ListRow( @@ -30,10 +32,7 @@ class ListRow extends StatelessWidget { style: TextStyle( fontSize: titleFontSize, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .labelSmall! - .color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), textAlign: TextAlign.left), Padding( padding: const EdgeInsets.only(top: 12), @@ -47,10 +46,7 @@ class ListRow extends StatelessWidget { style: TextStyle( fontSize: valueFontSize, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!)), + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)), ), image != null ? Padding( diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index c9d3be757..6b6543d2f 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -7,6 +7,9 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; import 'package:cw_core/currency.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; class Picker<Item> extends StatefulWidget { Picker({ @@ -40,8 +43,7 @@ class Picker<Item> extends StatefulWidget { final bool Function(Item, String)? matchingCriteria; @override - _PickerState<Item> createState() => - _PickerState<Item>(items, images, onItemSelected); + _PickerState<Item> createState() => _PickerState<Item>(items, images, onItemSelected); } class _PickerState<Item> extends State<Picker<Item>> { @@ -90,8 +92,7 @@ class _PickerState<Item> extends State<Picker<Item>> { setState(() { filteredItems = List.from(items.where((element) { if (widget.selectedAtIndex != items.indexOf(element) && - (widget.matchingCriteria?.call(element, searchController.text) ?? - true)) { + (widget.matchingCriteria?.call(element, searchController.text) ?? true)) { if (images.isNotEmpty) { filteredImages.add(images[items.indexOf(element)]); } @@ -146,9 +147,7 @@ class _PickerState<Item> extends State<Picker<Item>> { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(30)), child: Container( - color: Theme.of(context) - .accentTextTheme.titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, child: ConstrainedBox( constraints: BoxConstraints( maxHeight: containerHeight, @@ -163,13 +162,10 @@ class _PickerState<Item> extends State<Picker<Item>> { child: SearchBarWidget(searchController: searchController), ), Divider( - color: Theme.of(context) - .accentTextTheme.titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, height: 1, ), - if (widget.selectedAtIndex != -1) - buildSelectedItem(widget.selectedAtIndex), + if (widget.selectedAtIndex != -1) buildSelectedItem(widget.selectedAtIndex), Flexible( child: Stack( alignment: Alignment.center, @@ -193,9 +189,8 @@ class _PickerState<Item> extends State<Picker<Item>> { fontWeight: FontWeight.w500, fontFamily: 'Lato', decoration: TextDecoration.none, - color: Theme.of(context) - .primaryTextTheme.titleLarge! - .color!, + color: + Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ) @@ -215,9 +210,7 @@ class _PickerState<Item> extends State<Picker<Item>> { Widget itemsList() { return Container( - color: Theme.of(context) - .accentTextTheme.titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, child: widget.isGridView ? GridView.builder( padding: EdgeInsets.zero, @@ -237,9 +230,7 @@ class _PickerState<Item> extends State<Picker<Item>> { shrinkWrap: true, separatorBuilder: (context, index) => widget.isSeparated ? Divider( - color: Theme.of(context) - .accentTextTheme.titleLarge! - .backgroundColor!, + color: Theme.of(context).extension<PickerTheme>()!.dividerColor, height: 1, ) : const SizedBox(), @@ -264,9 +255,7 @@ class _PickerState<Item> extends State<Picker<Item>> { }, child: Container( height: 55, - color: Theme.of(context) - .accentTextTheme.titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, padding: EdgeInsets.symmetric(horizontal: 24), child: Row( mainAxisSize: MainAxisSize.max, @@ -287,9 +276,7 @@ class _PickerState<Item> extends State<Picker<Item>> { fontSize: 14, fontFamily: 'Lato', fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme.titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -304,19 +291,17 @@ class _PickerState<Item> extends State<Picker<Item>> { child: Text( tag, style: TextStyle( - fontSize: 7.0, - fontFamily: 'Lato', - color: Theme.of(context) - .textTheme.bodyMedium! - .color!), + fontSize: 7.0, + fontFamily: 'Lato', + color: + Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor, + ), ), ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.0), //border: Border.all(color: ), - color: Theme.of(context) - .textTheme.bodyMedium! - .decorationColor!, + color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor, ), ), ), @@ -344,9 +329,7 @@ class _PickerState<Item> extends State<Picker<Item>> { }, child: Container( height: 55, - color: Theme.of(context) - .accentTextTheme.titleLarge! - .color!, + color: Theme.of(context).dialogTheme.backgroundColor, padding: EdgeInsets.symmetric(horizontal: 24), child: Row( mainAxisSize: MainAxisSize.max, @@ -367,9 +350,7 @@ class _PickerState<Item> extends State<Picker<Item>> { fontSize: 16, fontFamily: 'Lato', fontWeight: FontWeight.w700, - color: Theme.of(context) - .primaryTextTheme.titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, decoration: TextDecoration.none, ), ), @@ -384,19 +365,17 @@ class _PickerState<Item> extends State<Picker<Item>> { child: Text( tag, style: TextStyle( - fontSize: 7.0, - fontFamily: 'Lato', - color: Theme.of(context) - .textTheme.bodyMedium! - .color!), + fontSize: 7.0, + fontFamily: 'Lato', + color: + Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor, + ), ), ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.0), //border: Border.all(color: ), - color: Theme.of(context) - .textTheme.bodyMedium! - .decorationColor!, + color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor, ), ), ), @@ -404,10 +383,7 @@ class _PickerState<Item> extends State<Picker<Item>> { ), ), ), - Icon(Icons.check_circle, - color: Theme.of(context) - .accentTextTheme.bodyLarge! - .color!), + Icon(Icons.check_circle, color: Theme.of(context).primaryColor), ], ), ), diff --git a/lib/src/widgets/picker_inner_wrapper_widget.dart b/lib/src/widgets/picker_inner_wrapper_widget.dart index d91789b2a..3d9a289bc 100644 --- a/lib/src/widgets/picker_inner_wrapper_widget.dart +++ b/lib/src/widgets/picker_inner_wrapper_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart'; @@ -44,7 +45,7 @@ class PickerInnerWrapperWidget extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(14)), child: Container( - color: Theme.of(context).textTheme.displayLarge!.decorationColor!, + color: Theme.of(context).dialogTheme.backgroundColor, child: ConstrainedBox( constraints: BoxConstraints( maxHeight: @@ -72,7 +73,7 @@ class PickerInnerWrapperWidget extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(14)), child: Container( - color: Theme.of(context).textTheme.displayLarge!.decorationColor!, + color: Theme.of(context).dialogTheme.backgroundColor, child: ConstrainedBox( constraints: BoxConstraints( maxHeight: containerHeight, diff --git a/lib/src/widgets/search_bar_widget.dart b/lib/src/widgets/search_bar_widget.dart index 04d687cf6..bdb520d55 100644 --- a/lib/src/widgets/search_bar_widget.dart +++ b/lib/src/widgets/search_bar_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -16,12 +17,18 @@ class SearchBarWidget extends StatelessWidget { Widget build(BuildContext context) { return TextFormField( controller: searchController, - style: TextStyle(color: Theme.of(context).primaryTextTheme!.titleLarge!.color!), + style: TextStyle( + color: Theme.of(context).extension<PickerTheme>()!.searchTextColor), decoration: InputDecoration( hintText: hintText ?? S.of(context).search_currency, - prefixIcon: Image.asset("assets/images/search_icon.png"), + hintStyle: TextStyle( + color: Theme.of(context).extension<PickerTheme>()!.searchHintColor), + prefixIcon: Image.asset("assets/images/search_icon.png", + color: Theme.of(context).extension<PickerTheme>()!.searchIconColor), filled: true, - fillColor: Theme.of(context).accentTextTheme!.displaySmall!.color!, + fillColor: Theme.of(context) + .extension<PickerTheme>()! + .searchBackgroundFillColor, alignLabelWithHint: false, contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), enabledBorder: OutlineInputBorder( diff --git a/lib/src/widgets/section_divider.dart b/lib/src/widgets/section_divider.dart index bef85f975..b0beda089 100644 --- a/lib/src/widgets/section_divider.dart +++ b/lib/src/widgets/section_divider.dart @@ -1,13 +1,34 @@ import 'package:flutter/material.dart'; class SectionDivider extends StatelessWidget { - const SectionDivider(); + const SectionDivider({required this.direction}); + + final Axis direction; @override Widget build(BuildContext context) { return Container( - height: 1, + height: direction == Axis.horizontal ? 1 : null, + width: direction == Axis.vertical ? 1 : null, color: Theme.of(context).dividerColor, ); } -} \ No newline at end of file +} + +class HorizontalSectionDivider extends StatelessWidget { + const HorizontalSectionDivider(); + + @override + Widget build(BuildContext context) { + return SectionDivider(direction: Axis.horizontal); + } +} + +class VerticalSectionDivider extends StatelessWidget { + const VerticalSectionDivider(); + + @override + Widget build(BuildContext context) { + return SectionDivider(direction: Axis.vertical); + } +} diff --git a/lib/src/widgets/seed_widget.dart b/lib/src/widgets/seed_widget.dart index 0041f9b79..ddafa924b 100644 --- a/lib/src/widgets/seed_widget.dart +++ b/lib/src/widgets/seed_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart'; import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; @@ -10,6 +11,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/entities/mnemonic_item.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter/widgets.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class SeedWidget extends StatefulWidget { SeedWidget({ @@ -89,10 +91,7 @@ class SeedWidgetState extends State<SeedWidget> { cursorColor: Colors.blue, backgroundCursorColor: Colors.blue, validStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, backgroundColor: Colors.transparent, fontWeight: FontWeight.normal, fontSize: 16), @@ -105,10 +104,7 @@ class SeedWidgetState extends State<SeedWidget> { controller: controller, words: words, textStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, backgroundColor: Colors.transparent, fontWeight: FontWeight.normal, fontSize: 16), @@ -128,19 +124,13 @@ class SeedWidgetState extends State<SeedWidget> { borderRadius: BorderRadius.all(Radius.circular(6))), child: Image.asset('assets/images/paste_ios.png', - color: Theme.of(context) - .primaryTextTheme! - .headlineMedium! - .decorationColor!)), + color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)), ))) ]), Container( margin: EdgeInsets.only(top: 15), height: 1.0, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .backgroundColor!), + color: Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor), ])); } diff --git a/lib/src/widgets/setting_action_button.dart b/lib/src/widgets/setting_action_button.dart index 939e6b857..bebc4b8e1 100644 --- a/lib/src/widgets/setting_action_button.dart +++ b/lib/src/widgets/setting_action_button.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:flutter/material.dart'; class SettingActionButton extends StatelessWidget { @@ -29,15 +30,15 @@ class SettingActionButton extends StatelessWidget { @override Widget build(BuildContext context) { Color? color = isSelected - ? Theme.of(context).textTheme!.displaySmall!.color + ? Theme.of(context).extension<CakeMenuTheme>()!.settingTitleColor : selectionActive ? Palette.darkBlue - : Theme.of(context).textTheme!.displaySmall!.color; + : Theme.of(context).extension<CakeMenuTheme>()!.settingTitleColor; return InkWell( onTap: onTap, hoverColor: Colors.transparent, child: Container( - height: tileHeight, + height: tileHeight, padding: isLastTile ? EdgeInsets.only( left: 24, @@ -54,7 +55,9 @@ class SettingActionButton extends StatelessWidget { image, height: 16, width: 16, - color: Palette.darkBlue, + color: Theme.of(context) + .extension<CakeMenuTheme>()! + .settingActionsIconColor, ), SizedBox(width: 16), Expanded( diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index b1d14cc92..46c5f8a34 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -1,5 +1,5 @@ -import 'dart:ui'; -import 'package:flutter/cupertino.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; import 'package:flutter/material.dart'; class StandardCheckbox extends StatelessWidget { @@ -21,12 +21,12 @@ class StandardCheckbox extends StatelessWidget { @override Widget build(BuildContext context) { final baseGradient = LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleMedium!.color!, - Theme.of(context).primaryTextTheme!.titleMedium!.decorationColor!, + Theme.of(context).extension<FilterTheme>()!.checkboxFirstGradientColor, + Theme.of(context).extension<FilterTheme>()!.checkboxSecondGradientColor, ], begin: Alignment.centerLeft, end: Alignment.centerRight); final boxBorder = Border.all( - color: borderColor ?? Theme.of(context).primaryTextTheme!.bodySmall!.color!, width: 1.0); + color: borderColor ?? Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor, width: 1.0); final checkedBoxDecoration = BoxDecoration( gradient: gradientBackground ? baseGradient : null, @@ -49,7 +49,7 @@ class StandardCheckbox extends StatelessWidget { child: value ? Icon( Icons.check, - color: iconColor ?? Colors.blue, + color: iconColor ?? Theme.of(context).primaryColor, size: 20.0, ) : Offstage(), @@ -60,7 +60,7 @@ class StandardCheckbox extends StatelessWidget { child: Text( caption, style: TextStyle( - fontSize: 16.0, color: Theme.of(context).primaryTextTheme!.titleLarge!.color!), + fontSize: 16.0, color: Theme.of(context).extension<CakeTextTheme>()!.titleColor), )) ], ), diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart index 5fc094755..530d3969c 100644 --- a/lib/src/widgets/standard_list.dart +++ b/lib/src/widgets/standard_list.dart @@ -1,11 +1,10 @@ -import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/standard_list_card.dart'; import 'package:cake_wallet/src/widgets/standard_list_status_row.dart'; import 'package:flutter/material.dart'; class StandardListRow extends StatelessWidget { - StandardListRow( - {required this.title, required this.isSelected, this.onTap, this.decoration}); + StandardListRow({required this.title, required this.isSelected, this.onTap, this.decoration}); final String title; final bool isSelected; @@ -18,50 +17,54 @@ class StandardListRow extends StatelessWidget { final trailing = buildTrailing(context); return InkWell( - onTap: () => onTap?.call(context), - child: Container( - height: 56, - padding: EdgeInsets.only(left: 24, right: 24), - decoration: decoration ?? BoxDecoration( - color: _backgroundColor(context), + onTap: () => onTap?.call(context), + child: Container( + height: 56, + padding: EdgeInsets.only(left: 24, right: 24), + decoration: decoration ?? + BoxDecoration( + color: Theme.of(context).colorScheme.background, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: <Widget>[ - if (leading != null) leading, - buildCenter(context, hasLeftOffset: leading != null), - if (trailing != null) trailing - ]))); + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + if (leading != null) leading, + buildCenter(context, hasLeftOffset: leading != null), + if (trailing != null) trailing, + ], + ), + ), + ); } Widget? buildLeading(BuildContext context) => null; Widget buildCenter(BuildContext context, {required bool hasLeftOffset}) { - // FIXME: find better way for keep text on left side. return Expanded( - child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [ - if (hasLeftOffset) SizedBox(width: 10), - Expanded( - child: Text(title, - style: TextStyle( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (hasLeftOffset) SizedBox(width: 10), + Expanded( + child: Text( + title, + style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, color: titleColor(context), + ), ), - ), - ) - ])); + ) + ], + ), + ); } Widget? buildTrailing(BuildContext context) => null; Color titleColor(BuildContext context) => isSelected - ? Palette.blueCraiola - : Theme.of(context).primaryTextTheme.titleLarge!.color!; - - Color _backgroundColor(BuildContext context) { - return Theme.of(context).colorScheme.background; - } + ? Theme.of(context).primaryColor + : Theme.of(context).extension<CakeTextTheme>()!.titleColor; } class SectionHeaderListRow extends StatelessWidget { @@ -69,15 +72,12 @@ class SectionHeaderListRow extends StatelessWidget { Widget build(BuildContext context) => Column(children: [ StandardListSeparator(padding: EdgeInsets.only(left: 24)), Container( - width: double.infinity, - height: 40, - color: Theme.of(context).colorScheme.background), + width: double.infinity, height: 40, color: Theme.of(context).colorScheme.background), //StandardListSeparator(padding: EdgeInsets.only(left: 24)) ]); } class StandardListSeparator extends StatelessWidget { - const StandardListSeparator({this.padding, this.height = 1}); final EdgeInsets? padding; @@ -90,11 +90,7 @@ class StandardListSeparator extends StatelessWidget { padding: padding, color: Theme.of(context).colorScheme.background, child: Container( - height: height, - color: Theme.of(context) - .primaryTextTheme - .titleLarge - ?.backgroundColor)); + height: height, color: Theme.of(context).primaryTextTheme.titleLarge?.backgroundColor)); } } @@ -107,11 +103,9 @@ class StandardList extends StatelessWidget { @override Widget build(BuildContext context) { return ListView.separated( - separatorBuilder: (_, __) => - StandardListSeparator(padding: EdgeInsets.only(left: 24)), + separatorBuilder: (_, __) => StandardListSeparator(padding: EdgeInsets.only(left: 24)), itemCount: itemCount, itemBuilder: itemBuilder); - } } @@ -123,51 +117,29 @@ class SectionStandardListItem { } class SectionStandardList extends StatelessWidget { - SectionStandardList( - {required this.itemCounter, - required this.itemBuilder, - required this.sectionCount, - required BuildContext context, - this.dividerPadding = const EdgeInsets.only(left: 24), - this.themeColor, - this.dividerThemeColor, - this.sectionTitleBuilder, - this.hasTopSeparator = false,}) - : totalRows = [] { - totalRows.addAll(transform( - hasTopSeparator, - context, - sectionCount, - itemCounter, - itemBuilder, - sectionTitleBuilder, - themeColor, - dividerThemeColor)); - } + SectionStandardList({ + required this.itemCounter, + required this.itemBuilder, + required this.sectionCount, + this.dividerPadding = const EdgeInsets.only(left: 24), + this.sectionTitleBuilder, + this.hasTopSeparator = false, + }) : totalRows = []; final int sectionCount; final bool hasTopSeparator; final int Function(int sectionIndex) itemCounter; - final Widget Function(BuildContext context, int sectionIndex, int itemIndex) - itemBuilder; - final Widget Function(BuildContext context, int sectionIndex)? - sectionTitleBuilder; + final Widget Function(int sectionIndex, int itemIndex) itemBuilder; + final Widget Function(int sectionIndex)? sectionTitleBuilder; final List<Widget> totalRows; - final Color? themeColor; - final Color? dividerThemeColor; final EdgeInsets dividerPadding; List<Widget> transform( bool hasTopSeparator, - BuildContext context, int sectionCount, int Function(int sectionIndex) itemCounter, - Widget Function(BuildContext context, int sectionIndex, int itemIndex) - itemBuilder, - Widget Function(BuildContext context, int sectionIndex)? - sectionTitleBuilder, - Color? themeColor, - Color? dividerThemeColor) { + Widget Function(int sectionIndex, int itemIndex) itemBuilder, + Widget Function(int sectionIndex)? sectionTitleBuilder) { final items = <Widget>[]; for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) { @@ -176,12 +148,12 @@ class SectionStandardList extends StatelessWidget { } if (sectionTitleBuilder != null) { - items.add(buildTitle(items, sectionIndex, context)); + items.add(buildTitle(items, sectionIndex)); } final itemCount = itemCounter(sectionIndex); - items.addAll(buildSection(itemCount, items, sectionIndex, context)); + items.addAll(buildSection(itemCount, items, sectionIndex)); items.add(sectionIndex + 1 != sectionCount ? SectionHeaderListRow() @@ -191,21 +163,19 @@ class SectionStandardList extends StatelessWidget { return items; } - Widget buildTitle( - List<Widget> items, int sectionIndex, BuildContext context) { + Widget buildTitle(List<Widget> items, int sectionIndex) { if (sectionTitleBuilder == null) { throw Exception('Cannot to build title. sectionTitleBuilder is null'); } - return sectionTitleBuilder!.call(context, sectionIndex); + return sectionTitleBuilder!.call(sectionIndex); } - List<Widget> buildSection(int itemCount, List<Widget> items, int sectionIndex, - BuildContext context) { + List<Widget> buildSection(int itemCount, List<Widget> items, int sectionIndex) { final List<Widget> section = []; for (var itemIndex = 0; itemIndex < itemCount; itemIndex++) { - final item = itemBuilder(context, sectionIndex, itemIndex); + final item = itemBuilder(sectionIndex, itemIndex); section.add(item); } @@ -214,29 +184,33 @@ class SectionStandardList extends StatelessWidget { @override Widget build(BuildContext context) { + totalRows.clear(); + totalRows.addAll( + transform(hasTopSeparator, sectionCount, itemCounter, itemBuilder, sectionTitleBuilder)); + return ListView.separated( - separatorBuilder: (_, index) { - final row = totalRows[index]; + separatorBuilder: (_, index) { + final row = totalRows[index]; - if (row is StandardListSeparator || row is SectionHeaderListRow) { - return Container(); - } + if (row is StandardListSeparator || row is SectionHeaderListRow) { + return Container(); + } - if (row is StandardListStatusRow || row is TradeDetailsStandardListCard) { - return Container(); - } + if (row is StandardListStatusRow || row is TradeDetailsStandardListCard) { + return Container(); + } - final nextRow = totalRows[index + 1]; + final nextRow = totalRows[index + 1]; - // If current row is pre last and last row is separator. - if (nextRow is StandardListSeparator || - nextRow is SectionHeaderListRow) { - return Container(); - } + // If current row is pre last and last row is separator. + if (nextRow is StandardListSeparator || nextRow is SectionHeaderListRow) { + return Container(); + } - return StandardListSeparator(padding: dividerPadding); - }, - itemCount: totalRows.length, - itemBuilder: (_, index) => totalRows[index]); + return StandardListSeparator(padding: dividerPadding); + }, + itemCount: totalRows.length, + itemBuilder: (_, index) => totalRows[index], + ); } } diff --git a/lib/src/widgets/standard_list_card.dart b/lib/src/widgets/standard_list_card.dart index 27385bd44..4b16e1ad4 100644 --- a/lib/src/widgets/standard_list_card.dart +++ b/lib/src/widgets/standard_list_card.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/theme_base.dart'; @@ -21,8 +22,8 @@ class TradeDetailsStandardListCard extends StatelessWidget { final darkTheme = currentTheme == ThemeType.dark; final baseGradient = LinearGradient(colors: [ - Theme.of(context).primaryTextTheme!.titleSmall!.color!, - Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor, + Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor, ], begin: Alignment.centerLeft, end: Alignment.centerRight); final gradient = LinearGradient(colors: [ diff --git a/lib/src/widgets/standard_list_status_row.dart b/lib/src/widgets/standard_list_status_row.dart index 5f5970a24..e24010358 100644 --- a/lib/src/widgets/standard_list_status_row.dart +++ b/lib/src/widgets/standard_list_status_row.dart @@ -1,7 +1,10 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class StandardListStatusRow extends StatelessWidget { StandardListStatusRow({required this.title, required this.value}); @@ -24,13 +27,13 @@ class StandardListStatusRow extends StatelessWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme!.labelSmall!.color!), + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), textAlign: TextAlign.left), Padding( padding: const EdgeInsets.only(top: 12), child: Container( decoration: BoxDecoration( - color: Theme.of(context).accentTextTheme!.displaySmall!.color!, + color: Theme.of(context).extension<AddressTheme>()!.actionButtonColor, borderRadius: BorderRadius.circular(30.0), ), child: Padding( @@ -50,10 +53,7 @@ class StandardListStatusRow extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme! - .titleLarge! - .color!)) + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)) ], ), ), diff --git a/lib/src/widgets/standard_switch.dart b/lib/src/widgets/standard_switch.dart index 060e27990..064faea48 100644 --- a/lib/src/widgets/standard_switch.dart +++ b/lib/src/widgets/standard_switch.dart @@ -24,14 +24,8 @@ class StandardSwitchState extends State<StandardSwitch> { height: 28, decoration: BoxDecoration( color: widget.value - ? Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color! - : Theme.of(context) - .accentTextTheme! - .displayLarge! - .color!, + ? Theme.of(context).primaryColor + : Theme.of(context).disabledColor, borderRadius: BorderRadius.all(Radius.circular(14.0))), child: Container( width: 24.0, diff --git a/lib/src/widgets/template_tile.dart b/lib/src/widgets/template_tile.dart index aa285afaf..8f8d5e771 100644 --- a/lib/src/widgets/template_tile.dart +++ b/lib/src/widgets/template_tile.dart @@ -1,5 +1,7 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class TemplateTile extends StatefulWidget { TemplateTile({ @@ -49,7 +51,9 @@ class TemplateTileState extends State<TemplateTile> { @override Widget build(BuildContext context) { - final color = isRemovable ? Colors.white : Theme.of(context).primaryTextTheme!.titleLarge!.color!; + final color = isRemovable + ? Colors.white + : Theme.of(context).extension<SendPageTheme>()!.templateTitleColor; final toIcon = Image.asset('assets/images/to_icon.png', color: color); final content = Row( @@ -109,7 +113,7 @@ class TemplateTileState extends State<TemplateTile> { child: Container( height: 40, padding: EdgeInsets.only(left: 24, right: 24), - color: Theme.of(context).primaryTextTheme!.displayMedium!.decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.templateBackgroundColor, child: content, ), ), @@ -154,4 +158,4 @@ class TemplateTileState extends State<TemplateTile> { return isRemovable ? removableTile : tile; } -} \ No newline at end of file +} diff --git a/lib/src/widgets/trail_button.dart b/lib/src/widgets/trail_button.dart index b9c430d5d..5e4d1bdf6 100644 --- a/lib/src/widgets/trail_button.dart +++ b/lib/src/widgets/trail_button.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -24,10 +25,7 @@ class TrailButton extends StatelessWidget { caption, style: TextStyle( color: textColor ?? - Theme.of(context) - .accentTextTheme! - .displayLarge! - .decorationColor!, + Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor, fontWeight: FontWeight.w600, fontSize: 14), ), diff --git a/lib/themes/bitcoin_dark_theme.dart b/lib/themes/bitcoin_dark_theme.dart new file mode 100644 index 000000000..f8b842ae8 --- /dev/null +++ b/lib/themes/bitcoin_dark_theme.dart @@ -0,0 +1,14 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:flutter/material.dart'; + +class BitcoinDarkTheme extends MoneroDarkTheme { + BitcoinDarkTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.bitcoin_dark_theme; + @override + Color get primaryColor => Palette.bitcoinOrange; +} + diff --git a/lib/themes/bitcoin_light_theme.dart b/lib/themes/bitcoin_light_theme.dart new file mode 100644 index 000000000..14a694221 --- /dev/null +++ b/lib/themes/bitcoin_light_theme.dart @@ -0,0 +1,13 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_light_theme.dart'; +import 'package:flutter/material.dart'; + +class BitcoinLightTheme extends MoneroLightTheme { + BitcoinLightTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.bitcoin_light_theme; + @override + Color get primaryColor => Palette.bitcoinOrange; +} diff --git a/lib/themes/bright_theme.dart b/lib/themes/bright_theme.dart index 4e5437b64..0ea2bb6f2 100644 --- a/lib/themes/bright_theme.dart +++ b/lib/themes/bright_theme.dart @@ -1,275 +1,126 @@ +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; +import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:cake_wallet/themes/light_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; import 'package:flutter/material.dart'; -class BrightTheme extends ThemeBase { +class BrightTheme extends LightTheme { BrightTheme({required int raw}) : super(raw: raw); @override String get title => S.current.bright_theme; - @override ThemeType get type => ThemeType.bright; + @override + Color get primaryColor => Palette.moderateSlateBlue; + @override + Color get containerColor => Palette.moderateLavender; - ThemeData theme = ThemeData( - fontFamily: 'Lato', - brightness: Brightness.light, - scaffoldBackgroundColor: Palette.pinkFlamingo, // second gradient color - primaryColor: Palette.redHat, // third gradient color - indicatorColor: Colors.white.withOpacity(0.5), // page indicator - hoverColor: Colors.white, // amount hint text (receive page) - dividerColor: Palette.paleBlue, - hintColor: Palette.gray, - textTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: Colors.white, // sync_indicator text - backgroundColor: Colors.white.withOpacity(0.2), // synced sync_indicator - decorationColor: Colors.white.withOpacity(0.15), // not synced sync_indicator - ), - bodySmall: TextStyle( - color: Palette.shineOrange, // not synced light - decorationColor: Colors.white, // filter icon - ), - labelSmall: TextStyle( - color: Colors.white.withOpacity(0.2), // filter button - backgroundColor: - Colors.white.withOpacity(0.5), // date section row - decorationColor: Colors.white - .withOpacity(0.2) // icons (transaction and trade rows) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Colors.white.withOpacity(0.2), // address button border - decorationColor: Colors.white.withOpacity(0.4), // copy button (qr widget) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Colors.white, // qr code - decorationColor: Colors.white.withOpacity(0.5), // bottom border of amount (receive page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: PaletteDark.lightBlueGrey, // icons color (receive page) - decorationColor: Palette.lavender, // icons background (receive page) - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: - Palette.darkBlueCraiola, // text color of tiles (receive page) - decorationColor: - Colors.white // background of tiles (receive page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Colors.white, // text color of current tile (receive page), - //decorationColor: Palette.blueCraiola // background of current tile (receive page) - decorationColor: Palette - .moderateSlateBlue // background of current tile (receive page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.violetBlue, // text color of tiles (account list) - decorationColor: - Colors.white // background of tiles (account list) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette - .moderateSlateBlue, // text color of current tile (account list) - decorationColor: - Colors.white // background of current tile (account list) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.moderatePurpleBlue, // scrollbar thumb - decorationColor: Palette.periwinkleCraiola // scrollbar background - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Palette.moderateLavender, // menu header - decorationColor: Colors.white, // menu background - ) - ), - scrollbarTheme: ScrollbarThemeData( - thumbColor: MaterialStateProperty.all(Palette.moderatePurpleBlue), - trackColor: MaterialStateProperty.all(Palette.periwinkleCraiola), - radius: Radius.circular(3), - thickness: MaterialStateProperty.all(6), - thumbVisibility: MaterialStateProperty.all(true), - crossAxisMargin: 6, - ), - primaryTextTheme: TextTheme( - titleLarge: TextStyle( - color: Palette.darkBlueCraiola, // title color - backgroundColor: Palette.wildPeriwinkle // textfield underline - ), - bodySmall: TextStyle( - color: PaletteDark.pigeonBlue, // secondary text - decorationColor: Palette.wildLavender // menu divider - ), - labelSmall: TextStyle( - color: Palette.darkGray, // transaction/trade details titles - decorationColor: Colors.white.withOpacity(0.5), // placeholder - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Palette.blueCraiola, // first gradient color (send page) - decorationColor: - Palette.pinkFlamingo // second gradient color (send page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Colors.white - .withOpacity(0.5), // text field border color (send page) - decorationColor: Colors.white - .withOpacity(0.5), // text field hint color (send page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: Colors.white - .withOpacity(0.2), // text field button color (send page) - decorationColor: - Colors.white // text field button icon color (send page) - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: Colors.white.withOpacity(0.5), // estimated fee (send page) - backgroundColor: PaletteDark.darkCyanBlue - .withOpacity(0.67), // dot color for indicator on send page - decorationColor: - Palette.shadowWhite // template dotted border (send page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Palette.darkBlueCraiola, // template new text (send page) - backgroundColor: PaletteDark - .darkNightBlue, // active dot color for indicator on send page - decorationColor: - Palette.shadowWhite // template background color (send page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.darkBlueCraiola, // template title (send page) - backgroundColor: - Colors.white, // icon color on order row (moonpay) - decorationColor: - Palette.niagara // receive amount text (exchange page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette - .blueCraiola, // first gradient color top panel (exchange page) - decorationColor: Palette - .pinkFlamingo // second gradient color top panel (exchange page) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.blueCraiola.withOpacity( - 0.7), // first gradient color bottom panel (exchange page) - decorationColor: Palette.pinkFlamingo.withOpacity( - 0.7), // second gradient color bottom panel (exchange page) - backgroundColor: - Palette.moderateSlateBlue // alert right button text - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Colors.white.withOpacity( - 0.5), // text field border on top panel (exchange page) - decorationColor: Colors.white.withOpacity( - 0.5), // text field border on bottom panel (exchange page) - backgroundColor: Palette.brightOrange // alert left button text - ) - ), - focusColor: Colors.white.withOpacity(0.2), // text field button (exchange page) - accentTextTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: Colors.white, // picker background - backgroundColor: Palette.periwinkleCraiola, // picker divider - decorationColor: Colors.white // dialog background - ), - bodySmall: TextStyle( - color: Palette.moderateLavender, // container (confirm exchange) - backgroundColor: Palette.moderateLavender, // button background (confirm exchange) - decorationColor: Palette.darkBlueCraiola, // text color (information page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette.darkBlueCraiola, // QR code (exchange trade page) - backgroundColor: Palette.wildPeriwinkle, // divider (exchange trade page) - //decorationColor: Palette.blueCraiola // crete new wallet button background (wallet list page) - decorationColor: Palette - .moderateSlateBlue // crete new wallet button background (wallet list page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Palette - .moderateLavender, // first gradient color of wallet action buttons (wallet list page) - backgroundColor: Palette - .moderateLavender, // second gradient color of wallet action buttons (wallet list page) - decorationColor: Colors - .white // restore wallet button text color (wallet list page) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Palette.darkGray, // titles color (filter widget) - backgroundColor: Palette.periwinkle, // divider color (filter widget) - decorationColor: Colors.white // checkbox background (filter widget) - ), - labelSmall: TextStyle( - color: Palette.wildPeriwinkle, // checkbox bounds (filter widget) - decorationColor: Colors.white, // menu subname - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: Palette.blueCraiola, // first gradient color (menu header) - decorationColor: Palette.pinkFlamingo, // second gradient color(menu header) - backgroundColor: Colors.white // active dot color - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: - Palette.shadowWhite, // action button color (address text field) - decorationColor: Palette.darkGray, // hint text (seed widget) - backgroundColor: - Colors.white.withOpacity(0.5) // text on balance page - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Palette.darkGray, // hint text (new wallet page) - decorationColor: - Palette.periwinkleCraiola, // underline (new wallet page) - backgroundColor: - Colors.white // menu, icons, balance (dashboard page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.darkGray, // switch background (settings page) - backgroundColor: - Colors.black, // icon color on support page (moonpay, github) - decorationColor: - Colors.white.withOpacity(0.4) // hint text (exchange page) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.darkGray, // indicators (PIN code) - decorationColor: Palette.darkGray, // switch (PIN code) - backgroundColor: Colors.white // alert right button - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Palette.moderateSlateBlue, // primary buttons - decorationColor: Colors.white, // alert left button, - backgroundColor: Palette.dullGray // keyboard bar color - ), - ), - cardColor: Palette.moderateSlateBlue // bottom button (action list) + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + firstGradientBackgroundColor: Palette.blueCraiola, + secondGradientBackgroundColor: Palette.pinkFlamingo, + thirdGradientBackgroundColor: Palette.redHat, + pageTitleTextColor: Colors.white, + mainActionsIconColor: Colors.white, + textColor: Colors.white, + cardTextColor: Colors.white, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: Colors.white.withOpacity(0.5), + activeIndicatorColor: Colors.white)); + + @override + SyncIndicatorTheme get syncIndicatorStyle => + super.syncIndicatorStyle.copyWith( + textColor: Colors.white, + syncedBackgroundColor: Colors.white.withOpacity(0.2), + notSyncedBackgroundColor: Colors.white.withOpacity(0.15)); + + @override + ExchangePageTheme get exchangePageTheme => super.exchangePageTheme.copyWith( + secondGradientBottomPanelColor: Palette.pinkFlamingo.withOpacity(0.7), + firstGradientBottomPanelColor: Palette.blueCraiola.withOpacity(0.7), + secondGradientTopPanelColor: Palette.pinkFlamingo, + firstGradientTopPanelColor: Palette.blueCraiola); + + @override + NewWalletTheme get newWalletTheme => super.newWalletTheme.copyWith( + hintTextColor: Palette.darkGray, + underlineColor: Palette.periwinkleCraiola); + + @override + BalancePageTheme get balancePageTheme => super + .balancePageTheme + .copyWith(labelTextColor: Colors.white.withOpacity(0.5)); + + @override + CakeMenuTheme get menuTheme => + super.menuTheme.copyWith(headerSecondGradientColor: Palette.pinkFlamingo); + + @override + FilterTheme get filterTheme => super.filterTheme.copyWith( + checkboxSecondGradientColor: Palette.pinkFlamingo, + checkboxBackgroundColor: Colors.white, + buttonColor: Colors.white.withOpacity(0.2), + iconColor: Colors.white); + + @override + WalletListTheme get walletListTheme => super.walletListTheme.copyWith( + createNewWalletButtonBackgroundColor: Palette.moderateSlateBlue); + + @override + OrderTheme get orderTheme => OrderTheme(iconColor: Colors.white); + + @override + SendPageTheme get sendPageTheme => super.sendPageTheme.copyWith( + templateBackgroundColor: Palette.shadowWhite, + templateDottedBorderColor: Palette.shadowWhite, + secondGradientColor: Palette.pinkFlamingo); + + @override + PlaceholderTheme get placeholderTheme => + PlaceholderTheme(color: Colors.white.withOpacity(0.5)); + + @override + TransactionTradeTheme get transactionTradeTheme => super + .transactionTradeTheme + .copyWith(rowsColor: Colors.white.withOpacity(0.2)); + + @override + ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( + currentTileBackgroundColor: Palette.moderateSlateBlue, + tilesBackgroundColor: Colors.white, + iconsBackgroundColor: Palette.lavender, + amountBottomBorderColor: Colors.white.withOpacity(0.5), + amountHintTextColor: Colors.white, ); @override - ThemeData get themeData => theme.copyWith( - colorScheme: theme.colorScheme - .copyWith(background: Colors.white, secondary: Palette.blueCraiola)); + QRCodeTheme get qrCodeTheme => super + .qrCodeTheme + .copyWith(qrWidgetCopyButtonColor: Colors.white.withOpacity(0.4)); + + @override + CakeTextTheme get cakeTextTheme => super.cakeTextTheme.copyWith( + buttonSecondaryTextColor: super.cakeTextTheme.secondaryTextColor, + buttonTextColor: super.cakeTextTheme.titleColor, + addressButtonBorderColor: Colors.white.withOpacity(0.4), + dateSectionRowColor: Colors.white.withOpacity(0.5)); } diff --git a/lib/themes/dark_theme.dart b/lib/themes/dark_theme.dart index e8cfab633..747dc2527 100644 --- a/lib/themes/dark_theme.dart +++ b/lib/themes/dark_theme.dart @@ -1,3 +1,29 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/info_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/support_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; @@ -8,278 +34,194 @@ class DarkTheme extends ThemeBase { @override String get title => S.current.dark_theme; - @override ThemeType get type => ThemeType.dark; - - ThemeData theme = ThemeData( - fontFamily: 'Lato', - brightness: Brightness.dark, - scaffoldBackgroundColor: - PaletteDark.backgroundColor, // second gradient color - primaryColor: PaletteDark.backgroundColor, // third gradient color - indicatorColor: PaletteDark.cyanBlue, // page indicator - hoverColor: PaletteDark.cyanBlue, // amount hint text (receive page) - dividerColor: PaletteDark.dividerColor, - hintColor: PaletteDark.pigeonBlue, // menu - textTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: PaletteDark.wildBlue, // sync_indicator text - backgroundColor: - PaletteDark.lightNightBlue, // synced sync_indicator - decorationColor: - PaletteDark.oceanBlue // not synced sync_indicator - ), - bodySmall: TextStyle( - color: PaletteDark.orangeYellow, // not synced light - decorationColor: PaletteDark.wildBlue, // filter icon - ), - labelSmall: TextStyle( - color: PaletteDark.oceanBlue, // filter button - backgroundColor: PaletteDark.darkCyanBlue, // date section row - decorationColor: PaletteDark - .wildNightBlue // icons (transaction and trade rows) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: PaletteDark.nightBlue, // address button border - decorationColor: PaletteDark.lightBlueGrey, // copy button (qr widget) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: PaletteDark.lightBlueGrey, // qr code - decorationColor: PaletteDark.darkGrey, // bottom border of amount (receive page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: Colors.white, // icons color (receive page) - decorationColor: PaletteDark.distantNightBlue, // icons background (receive page) - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: Colors.white, // text color of tiles (receive page) - decorationColor: - PaletteDark.nightBlue // background of tiles (receive page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Palette - .blueCraiola, // text color of current tile (receive page) - decorationColor: PaletteDark - .lightOceanBlue // background of current tile (receive page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Colors.white, // text color of tiles (account list) - decorationColor: PaletteDark - .darkOceanBlue // background of tiles (account list) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette - .blueCraiola, // text color of current tile (account list) - decorationColor: PaletteDark - .darkNightBlue // background of current tile (account list) - ), - // body1 -> bodyMedium - bodyMedium: TextStyle( - color: PaletteDark.wildBlueGrey, // scrollbar thumb - decorationColor: PaletteDark.violetBlue // scrollbar background - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: PaletteDark.deepPurpleBlue, // menu header - decorationColor: PaletteDark.deepPurpleBlue, // menu background - ) - ), - scrollbarTheme: ScrollbarThemeData( - thumbColor: MaterialStateProperty.all(PaletteDark.wildBlueGrey), - trackColor: MaterialStateProperty.all(PaletteDark.violetBlue), - radius: Radius.circular(3), - thickness: MaterialStateProperty.all(6), - thumbVisibility: MaterialStateProperty.all(true), - crossAxisMargin: 6, - ), - primaryTextTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: Colors.white, // title color - backgroundColor: PaletteDark.darkOceanBlue // textfield underline - ), - bodySmall: TextStyle( - color: PaletteDark.darkCyanBlue, // secondary text - decorationColor: PaletteDark.darkOceanBlue // menu divider - ), - labelSmall: TextStyle( - color: - PaletteDark.lightBlueGrey, // transaction/trade details titles - decorationColor: Colors.grey, // placeholder - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: - PaletteDark.darkNightBlue, // first gradient color (send page) - decorationColor: - PaletteDark.darkNightBlue // second gradient color (send page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: PaletteDark - .lightVioletBlue, // text field border color (send page) - decorationColor: - PaletteDark.darkCyanBlue, // text field hint color (send page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: PaletteDark - .buttonNightBlue, // text field button color (send page) - decorationColor: - PaletteDark.gray // text field button icon color (send page) - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: Colors.white, // estimated fee (send page) - backgroundColor: - PaletteDark.cyanBlue, // dot color for indicator on send page - decorationColor: - PaletteDark.darkCyanBlue // template dotted border (send page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: PaletteDark.darkCyanBlue, // template new text (send page) - backgroundColor: - Colors.white, // active dot color for indicator on send page - decorationColor: PaletteDark - .darkVioletBlue // template background color (send page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: PaletteDark.cyanBlue, // template title (send page) - backgroundColor: - Colors.white, // icon color on order row (moonpay) - decorationColor: PaletteDark - .darkCyanBlue // receive amount text (exchange page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: PaletteDark - .wildVioletBlue, // first gradient color top panel (exchange page) - decorationColor: PaletteDark - .wildVioletBlue // second gradient color top panel (exchange page) - ), - // body1 -> bodyMedium - bodyMedium: TextStyle( - color: PaletteDark - .darkNightBlue, // first gradient color bottom panel (exchange page) - decorationColor: PaletteDark - .darkNightBlue, // second gradient color bottom panel (exchange page) - backgroundColor: Palette.blueCraiola // alert right button text - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: PaletteDark - .blueGrey, // text field border on top panel (exchange page) - decorationColor: PaletteDark - .moderateVioletBlue, // text field border on bottom panel (exchange page) - backgroundColor: Palette.alizarinRed // alert left button text - ) - ), - focusColor: PaletteDark.moderateBlue, // text field button (exchange page) - accentTextTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: PaletteDark.nightBlue, // picker background - backgroundColor: PaletteDark.dividerColor, // picker divider - decorationColor: PaletteDark.darkNightBlue // dialog background - ), - bodySmall: TextStyle( - color: PaletteDark.nightBlue, // container (confirm exchange) - backgroundColor: PaletteDark.deepVioletBlue, // button background (confirm exchange) - decorationColor: Palette.darkLavender, // text color (information page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - //color: PaletteDark.lightBlueGrey, // QR code (exchange trade page) - color: Colors.white, // QR code (exchange trade page) - backgroundColor: - PaletteDark.deepVioletBlue, // divider (exchange trade page) - decorationColor: Colors - .white // crete new wallet button background (wallet list page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: PaletteDark - .distantBlue, // first gradient color of wallet action buttons (wallet list page) - backgroundColor: PaletteDark - .distantNightBlue, // second gradient color of wallet action buttons (wallet list page) - decorationColor: Palette - .darkBlueCraiola // restore wallet button text color (wallet list page) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Colors.white, // titles color (filter widget) - backgroundColor: - PaletteDark.darkOceanBlue, // divider color (filter widget) - decorationColor: PaletteDark.wildVioletBlue - .withOpacity(0.3) // checkbox background (filter widget) - ), - labelSmall: TextStyle( - color: PaletteDark.wildVioletBlue, // checkbox bounds (filter widget) - decorationColor: PaletteDark.darkCyanBlue, // menu subname - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: PaletteDark - .deepPurpleBlue, // first gradient color (menu header) - decorationColor: PaletteDark - .deepPurpleBlue, // second gradient color(menu header) - backgroundColor: Colors.white // active dot color - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: PaletteDark - .nightBlue, // action button color (address text field) - decorationColor: - PaletteDark.darkCyanBlue, // hint text (seed widget) - backgroundColor: PaletteDark.cyanBlue // text on balance page - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: PaletteDark.cyanBlue, // hint text (new wallet page) - decorationColor: - PaletteDark.darkGrey, // underline (new wallet page) - backgroundColor: - Colors.white // menu, icons, balance (dashboard page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: - PaletteDark.deepVioletBlue, // switch background (settings page) - backgroundColor: - Colors.white, // icon color on support page (moonpay, github) - decorationColor: - PaletteDark.lightBlueGrey // hint text (exchange page) - ), - // body1 -> bodyMedium - bodyMedium: TextStyle( - color: PaletteDark.indicatorVioletBlue, // indicators (PIN code) - decorationColor: PaletteDark.lightPurpleBlue, // switch (PIN code) - backgroundColor: PaletteDark.darkNightBlue // alert right button - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Palette.blueCraiola, // primary buttons - decorationColor: PaletteDark.darkNightBlue, // alert left button - backgroundColor: PaletteDark.granite // keyboard bar color - ), - ), - cardColor: PaletteDark.darkNightBlue // bottom button (action list) - ); + @override + Brightness get brightness => Brightness.dark; + @override + Color get backgroundColor => PaletteDark.backgroundColor; + @override + Color get primaryColor => Palette.blueCraiola; + @override + Color get primaryTextColor => Colors.white; + @override + Color get containerColor => PaletteDark.nightBlue; + @override + Color get dialogBackgroundColor => PaletteDark.darkNightBlue; @override - ThemeData get themeData => theme.copyWith( - colorScheme: theme.colorScheme.copyWith( - background: PaletteDark.backgroundColor, - secondary: PaletteDark.backgroundColor)); + CakeScrollbarTheme get scrollbarTheme => CakeScrollbarTheme( + thumbColor: PaletteDark.wildBlueGrey, trackColor: PaletteDark.violetBlue); + + @override + SyncIndicatorTheme get syncIndicatorStyle => SyncIndicatorTheme( + textColor: PaletteDark.wildBlue, + syncedBackgroundColor: PaletteDark.lightNightBlue, + notSyncedIconColor: PaletteDark.orangeYellow, + notSyncedBackgroundColor: PaletteDark.oceanBlue); + + @override + KeyboardTheme get keyboardTheme => + KeyboardTheme(keyboardBarColor: PaletteDark.granite); + + @override + PinCodeTheme get pinCodeTheme => PinCodeTheme( + indicatorsColor: PaletteDark.indicatorVioletBlue, + switchColor: PaletteDark.lightPurpleBlue); + + @override + SupportPageTheme get supportPageTheme => + SupportPageTheme(iconColor: Colors.white); + + @override + ExchangePageTheme get exchangePageTheme => ExchangePageTheme( + hintTextColor: PaletteDark.lightBlueGrey, + dividerCodeColor: PaletteDark.deepVioletBlue, + qrCodeColor: primaryTextColor, + buttonBackgroundColor: PaletteDark.deepVioletBlue, + textFieldButtonColor: PaletteDark.moderateBlue, + textFieldBorderBottomPanelColor: PaletteDark.moderateVioletBlue, + textFieldBorderTopPanelColor: PaletteDark.blueGrey, + secondGradientBottomPanelColor: PaletteDark.darkNightBlue, + firstGradientBottomPanelColor: PaletteDark.darkNightBlue, + secondGradientTopPanelColor: PaletteDark.wildVioletBlue, + firstGradientTopPanelColor: PaletteDark.wildVioletBlue, + receiveAmountColor: PaletteDark.darkCyanBlue); + + @override + NewWalletTheme get newWalletTheme => NewWalletTheme( + hintTextColor: PaletteDark.cyanBlue, + underlineColor: PaletteDark.darkGrey); + + @override + AddressTheme get addressTheme => + AddressTheme(actionButtonColor: PaletteDark.nightBlue); + + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + cardTextColor: super.dashboardPageTheme.textColor, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: PaletteDark.cyanBlue, + activeIndicatorColor: Colors.white)); + + @override + BalancePageTheme get balancePageTheme => BalancePageTheme( + textColor: dashboardPageTheme.textColor, + labelTextColor: PaletteDark.cyanBlue); + + @override + CakeMenuTheme get menuTheme => CakeMenuTheme( + headerFirstGradientColor: PaletteDark.deepPurpleBlue, + headerSecondGradientColor: PaletteDark.deepPurpleBlue, + backgroundColor: PaletteDark.deepPurpleBlue, + subnameTextColor: PaletteDark.darkCyanBlue, + dividerColor: PaletteDark.darkOceanBlue, + settingTitleColor: receivePageTheme.tilesTextColor, + settingActionsIconColor: PaletteDark.pigeonBlue, + iconColor: PaletteDark.darkCyanBlue); + + @override + FilterTheme get filterTheme => FilterTheme( + checkboxFirstGradientColor: PaletteDark.darkNightBlue, + checkboxSecondGradientColor: PaletteDark.darkNightBlue, + checkboxBoundsColor: PaletteDark.wildVioletBlue, + checkboxBackgroundColor: PaletteDark.wildVioletBlue.withOpacity(0.3), + titlesColor: Colors.white, + buttonColor: PaletteDark.oceanBlue, + iconColor: PaletteDark.wildBlue); + + @override + WalletListTheme get walletListTheme => WalletListTheme( + restoreWalletButtonTextColor: Palette.darkBlueCraiola, + createNewWalletButtonBackgroundColor: Colors.white); + + @override + InfoTheme get infoTheme => InfoTheme(textColor: Palette.darkLavender); + + @override + PickerTheme get pickerTheme => PickerTheme( + dividerColor: PaletteDark.dividerColor, + searchTextColor: cakeTextTheme.textfieldUnderlineColor, + searchBackgroundFillColor: addressTheme.actionButtonColor); + + @override + AlertTheme get alertTheme => AlertTheme( + backdropColor: PaletteDark.darkNightBlue.withOpacity(0.75), + leftButtonTextColor: Palette.alizarinRed); + + @override + OrderTheme get orderTheme => OrderTheme(iconColor: Colors.white); + + @override + SendPageTheme get sendPageTheme => SendPageTheme( + templateTitleColor: PaletteDark.cyanBlue, + templateBackgroundColor: PaletteDark.darkVioletBlue, + templateNewTextColor: PaletteDark.darkCyanBlue, + templateDottedBorderColor: PaletteDark.darkCyanBlue, + templateSelectedCurrencyBackgroundColor: primaryColor, + templateSelectedCurrencyTitleColor: Colors.white, + estimatedFeeColor: Colors.white, + textFieldButtonIconColor: PaletteDark.gray, + textFieldButtonColor: PaletteDark.buttonNightBlue, + textFieldHintColor: PaletteDark.darkCyanBlue, + textFieldBorderColor: PaletteDark.lightVioletBlue, + secondGradientColor: PaletteDark.darkNightBlue, + firstGradientColor: PaletteDark.darkNightBlue, + indicatorDotColor: PaletteDark.cyanBlue); + + @override + SeedWidgetTheme get seedWidgetTheme => + SeedWidgetTheme(hintTextColor: PaletteDark.darkCyanBlue); + + @override + PlaceholderTheme get placeholderTheme => PlaceholderTheme(color: Colors.grey); + + @override + TransactionTradeTheme get transactionTradeTheme => TransactionTradeTheme( + detailsTitlesColor: PaletteDark.lightBlueGrey, + rowsColor: PaletteDark.wildNightBlue); + + @override + CakeTextTheme get cakeTextTheme => CakeTextTheme( + secondaryTextColor: PaletteDark.darkCyanBlue, + textfieldUnderlineColor: PaletteDark.darkOceanBlue, + titleColor: Colors.white, + addressButtonBorderColor: PaletteDark.nightBlue, + dateSectionRowColor: PaletteDark.darkCyanBlue); + + @override + AccountListTheme get accountListTheme => AccountListTheme( + currentAccountBackgroundColor: dialogBackgroundColor, + currentAccountTextColor: primaryColor, + currentAccountAmountColor: receivePageTheme.iconsColor, + tilesAmountColor: receivePageTheme.iconsColor, + tilesBackgroundColor: PaletteDark.darkOceanBlue, + tilesTextColor: Colors.white); + + @override + ReceivePageTheme get receivePageTheme => ReceivePageTheme( + currentTileBackgroundColor: PaletteDark.lightOceanBlue, + currentTileTextColor: Palette.blueCraiola, + tilesBackgroundColor: PaletteDark.nightBlue, + tilesTextColor: Colors.white, + iconsBackgroundColor: PaletteDark.distantNightBlue, + iconsColor: Colors.white, + amountBottomBorderColor: PaletteDark.darkGrey, + amountHintTextColor: PaletteDark.cyanBlue); + + @override + QRCodeTheme get qrCodeTheme => QRCodeTheme( + qrCodeColor: PaletteDark.lightBlueGrey, + qrWidgetCopyButtonColor: PaletteDark.lightBlueGrey); + + @override + ThemeData get themeData => super.themeData.copyWith( + dividerColor: PaletteDark.dividerColor, + hintColor: PaletteDark.pigeonBlue, + disabledColor: PaletteDark.deepVioletBlue, + dialogTheme: super + .themeData + .dialogTheme + .copyWith(backgroundColor: PaletteDark.nightBlue)); } diff --git a/lib/themes/extensions/account_list_theme.dart b/lib/themes/extensions/account_list_theme.dart new file mode 100644 index 000000000..7f2641e33 --- /dev/null +++ b/lib/themes/extensions/account_list_theme.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; + +class AccountListTheme extends ThemeExtension<AccountListTheme> { + final Color tilesTextColor; + final Color tilesAmountColor; + final Color tilesBackgroundColor; + final Color currentAccountBackgroundColor; + final Color currentAccountTextColor; + final Color currentAccountAmountColor; + + AccountListTheme( + {required this.tilesTextColor, + required this.tilesAmountColor, + required this.tilesBackgroundColor, + required this.currentAccountBackgroundColor, + required this.currentAccountTextColor, + required this.currentAccountAmountColor}); + + @override + AccountListTheme copyWith( + {Color? tilesTextColor, + Color? tilesAmountColor, + Color? tilesBackgroundColor, + Color? currentAccountBackgroundColor, + Color? currentAccountTextColor, + Color? currentAccountAmountColor}) => + AccountListTheme( + tilesTextColor: tilesTextColor ?? this.tilesTextColor, + tilesAmountColor: tilesAmountColor ?? this.tilesAmountColor, + tilesBackgroundColor: + tilesBackgroundColor ?? this.tilesBackgroundColor, + currentAccountBackgroundColor: currentAccountBackgroundColor ?? + this.currentAccountBackgroundColor, + currentAccountTextColor: + currentAccountTextColor ?? this.currentAccountTextColor, + currentAccountAmountColor: + currentAccountAmountColor ?? this.currentAccountAmountColor); + + @override + AccountListTheme lerp(ThemeExtension<AccountListTheme>? other, double t) { + if (other is! AccountListTheme) { + return this; + } + + return AccountListTheme( + tilesTextColor: Color.lerp(tilesTextColor, other.tilesTextColor, t)!, + tilesAmountColor: + Color.lerp(tilesAmountColor, other.tilesAmountColor, t)!, + tilesBackgroundColor: + Color.lerp(tilesBackgroundColor, other.tilesBackgroundColor, t)!, + currentAccountBackgroundColor: Color.lerp(currentAccountBackgroundColor, + other.currentAccountBackgroundColor, t)!, + currentAccountTextColor: Color.lerp( + currentAccountTextColor, other.currentAccountTextColor, t)!, + currentAccountAmountColor: Color.lerp( + currentAccountAmountColor, other.currentAccountAmountColor, t)!); + } +} diff --git a/lib/themes/extensions/address_theme.dart b/lib/themes/extensions/address_theme.dart new file mode 100644 index 000000000..cabc8d87f --- /dev/null +++ b/lib/themes/extensions/address_theme.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class AddressTheme extends ThemeExtension<AddressTheme> { + final Color actionButtonColor; + + AddressTheme({required this.actionButtonColor}); + + @override + AddressTheme copyWith({Color? actionButtonColor}) => AddressTheme( + actionButtonColor: actionButtonColor ?? this.actionButtonColor); + + @override + AddressTheme lerp(ThemeExtension<AddressTheme>? other, double t) { + if (other is! AddressTheme) { + return this; + } + + return AddressTheme( + actionButtonColor: + Color.lerp(actionButtonColor, other.actionButtonColor, t) ?? + actionButtonColor, + ); + } +} diff --git a/lib/themes/extensions/alert_theme.dart b/lib/themes/extensions/alert_theme.dart new file mode 100644 index 000000000..3794124f3 --- /dev/null +++ b/lib/themes/extensions/alert_theme.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class AlertTheme extends ThemeExtension<AlertTheme> { + final Color leftButtonTextColor; + final Color backdropColor; + + AlertTheme({required this.leftButtonTextColor, required this.backdropColor}); + + @override + AlertTheme copyWith({Color? leftButtonTextColor, Color? backdropColor}) => + AlertTheme( + leftButtonTextColor: leftButtonTextColor ?? this.leftButtonTextColor, + backdropColor: backdropColor ?? this.backdropColor); + + @override + AlertTheme lerp(ThemeExtension<AlertTheme>? other, double t) { + if (other is! AlertTheme) { + return this; + } + + return AlertTheme( + leftButtonTextColor: + Color.lerp(leftButtonTextColor, other.leftButtonTextColor, t) ?? + leftButtonTextColor, + backdropColor: + Color.lerp(backdropColor, other.backdropColor, t) ?? backdropColor); + } +} diff --git a/lib/themes/extensions/balance_page_theme.dart b/lib/themes/extensions/balance_page_theme.dart new file mode 100644 index 000000000..508514f93 --- /dev/null +++ b/lib/themes/extensions/balance_page_theme.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; + +class BalancePageTheme extends ThemeExtension<BalancePageTheme> { + final Color textColor; + final Color labelTextColor; + final Color balanceAmountColor; + final Color assetTitleColor; + final Color cardBorderColor; + + BalancePageTheme( + {required this.labelTextColor, + required this.textColor, + Color? balanceAmountColor, + Color? assetTitleColor, + this.cardBorderColor = Colors.transparent}) + : this.balanceAmountColor = balanceAmountColor ?? textColor, + this.assetTitleColor = assetTitleColor ?? textColor; + + @override + BalancePageTheme copyWith( + {Color? textColor, + Color? labelTextColor, + Color? balanceAmountColor, + Color? assetTitleColor, + Color? cardBorderColor}) => + BalancePageTheme( + textColor: textColor ?? this.textColor, + labelTextColor: labelTextColor ?? this.labelTextColor, + balanceAmountColor: balanceAmountColor ?? this.balanceAmountColor, + assetTitleColor: assetTitleColor ?? this.assetTitleColor, + cardBorderColor: cardBorderColor ?? this.cardBorderColor); + + @override + BalancePageTheme lerp(ThemeExtension<BalancePageTheme>? other, double t) { + if (other is! BalancePageTheme) { + return this; + } + + return BalancePageTheme( + textColor: Color.lerp(textColor, other.textColor, t) ?? textColor, + labelTextColor: Color.lerp(labelTextColor, other.labelTextColor, t) ?? + labelTextColor, + balanceAmountColor: + Color.lerp(balanceAmountColor, other.balanceAmountColor, t) ?? + balanceAmountColor, + assetTitleColor: + Color.lerp(assetTitleColor, other.assetTitleColor, t) ?? + assetTitleColor, + cardBorderColor: + Color.lerp(cardBorderColor, other.cardBorderColor, t) ?? + cardBorderColor); + } +} diff --git a/lib/themes/extensions/cake_scrollbar_theme.dart b/lib/themes/extensions/cake_scrollbar_theme.dart new file mode 100644 index 000000000..5aeeafa25 --- /dev/null +++ b/lib/themes/extensions/cake_scrollbar_theme.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class CakeScrollbarTheme extends ThemeExtension<CakeScrollbarTheme> { + final Color thumbColor; + final Color trackColor; + + CakeScrollbarTheme({required this.thumbColor, required this.trackColor}); + + @override + Object get type => CakeScrollbarTheme; + + @override + CakeScrollbarTheme copyWith({Color? thumbColor, Color? trackColor}) => + CakeScrollbarTheme( + thumbColor: thumbColor ?? this.thumbColor, + trackColor: trackColor ?? this.trackColor); + + @override + CakeScrollbarTheme lerp(ThemeExtension<CakeScrollbarTheme>? other, double t) { + if (other is! CakeScrollbarTheme) { + return this; + } + + return CakeScrollbarTheme( + thumbColor: Color.lerp(thumbColor, other.thumbColor, t) ?? thumbColor, + trackColor: Color.lerp(trackColor, other.trackColor, t) ?? trackColor); + } +} diff --git a/lib/themes/extensions/cake_text_theme.dart b/lib/themes/extensions/cake_text_theme.dart new file mode 100644 index 000000000..31cd77e44 --- /dev/null +++ b/lib/themes/extensions/cake_text_theme.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +class CakeTextTheme extends ThemeExtension<CakeTextTheme> { + final Color secondaryTextColor; + final Color textfieldUnderlineColor; + final Color titleColor; + final Color addressButtonBorderColor; + final Color dateSectionRowColor; + final Color buttonTextColor; + final Color buttonSecondaryTextColor; + + CakeTextTheme( + {required this.secondaryTextColor, + required this.textfieldUnderlineColor, + required this.titleColor, + required this.addressButtonBorderColor, + required this.dateSectionRowColor, + Color? buttonTextColor, + Color? buttonSecondaryTextColor}) + : buttonTextColor = buttonTextColor ?? titleColor, + buttonSecondaryTextColor = + buttonSecondaryTextColor ?? secondaryTextColor; + + @override + CakeTextTheme copyWith( + {Color? secondaryTextColor, + Color? textfieldUnderlineColor, + Color? titleColor, + Color? addressButtonBorderColor, + Color? dateSectionRowColor, + Color? buttonTextColor, + Color? buttonSecondaryTextColor}) => + CakeTextTheme( + secondaryTextColor: secondaryTextColor ?? this.secondaryTextColor, + textfieldUnderlineColor: + textfieldUnderlineColor ?? this.textfieldUnderlineColor, + titleColor: titleColor ?? this.titleColor, + addressButtonBorderColor: + addressButtonBorderColor ?? this.addressButtonBorderColor, + dateSectionRowColor: dateSectionRowColor ?? this.dateSectionRowColor, + buttonTextColor: buttonTextColor ?? this.buttonTextColor, + buttonSecondaryTextColor: + buttonSecondaryTextColor ?? this.buttonSecondaryTextColor); + + @override + CakeTextTheme lerp(ThemeExtension<CakeTextTheme>? other, double t) { + if (other is! CakeTextTheme) { + return this; + } + + return CakeTextTheme( + secondaryTextColor: + Color.lerp(secondaryTextColor, other.secondaryTextColor, t)!, + textfieldUnderlineColor: Color.lerp( + textfieldUnderlineColor, other.textfieldUnderlineColor, t)!, + titleColor: Color.lerp(titleColor, other.titleColor, t)!, + addressButtonBorderColor: Color.lerp( + addressButtonBorderColor, other.addressButtonBorderColor, t)!, + dateSectionRowColor: + Color.lerp(dateSectionRowColor, other.dateSectionRowColor, t)!, + buttonTextColor: Color.lerp(buttonTextColor, other.buttonTextColor, t)!, + buttonSecondaryTextColor: Color.lerp( + buttonSecondaryTextColor, other.buttonSecondaryTextColor, t)!); + } +} diff --git a/lib/themes/extensions/dashboard_page_theme.dart b/lib/themes/extensions/dashboard_page_theme.dart new file mode 100644 index 000000000..8d0195e62 --- /dev/null +++ b/lib/themes/extensions/dashboard_page_theme.dart @@ -0,0 +1,79 @@ +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:flutter/material.dart'; + +class DashboardPageTheme extends ThemeExtension<DashboardPageTheme> { + final Color firstGradientBackgroundColor; + final Color secondGradientBackgroundColor; + final Color thirdGradientBackgroundColor; + final Color textColor; + final Color cardTextColor; + final Color pageTitleTextColor; + final Color mainActionsIconColor; + + final IndicatorDotTheme indicatorDotTheme; + + DashboardPageTheme( + {required this.firstGradientBackgroundColor, + required this.secondGradientBackgroundColor, + required this.thirdGradientBackgroundColor, + required this.textColor, + required this.indicatorDotTheme, + Color? mainActionsIconColor, + Color? pageTitleTextColor, + Color? cardTextColor}) + : pageTitleTextColor = pageTitleTextColor ?? textColor, + mainActionsIconColor = mainActionsIconColor ?? textColor, + cardTextColor = cardTextColor ?? textColor; + + @override + DashboardPageTheme copyWith( + {Color? firstGradientBackgroundColor, + Color? secondGradientBackgroundColor, + Color? thirdGradientBackgroundColor, + Color? textColor, + IndicatorDotTheme? indicatorDotTheme, + Color? pageTitleTextColor, + Color? mainActionsIconColor, + Color? cardTextColor}) => + DashboardPageTheme( + firstGradientBackgroundColor: + firstGradientBackgroundColor ?? this.firstGradientBackgroundColor, + secondGradientBackgroundColor: secondGradientBackgroundColor ?? + this.secondGradientBackgroundColor, + thirdGradientBackgroundColor: + thirdGradientBackgroundColor ?? this.thirdGradientBackgroundColor, + textColor: textColor ?? this.textColor, + indicatorDotTheme: indicatorDotTheme ?? this.indicatorDotTheme, + pageTitleTextColor: pageTitleTextColor ?? this.pageTitleTextColor, + mainActionsIconColor: + mainActionsIconColor ?? this.mainActionsIconColor, + cardTextColor: cardTextColor ?? this.cardTextColor); + + @override + DashboardPageTheme lerp(ThemeExtension<DashboardPageTheme>? other, double t) { + if (other is! DashboardPageTheme) { + return this; + } + + return DashboardPageTheme( + firstGradientBackgroundColor: Color.lerp(firstGradientBackgroundColor, + other.firstGradientBackgroundColor, t) ?? + firstGradientBackgroundColor, + secondGradientBackgroundColor: Color.lerp(secondGradientBackgroundColor, + other.secondGradientBackgroundColor, t) ?? + secondGradientBackgroundColor, + thirdGradientBackgroundColor: Color.lerp(thirdGradientBackgroundColor, + other.thirdGradientBackgroundColor, t) ?? + thirdGradientBackgroundColor, + textColor: Color.lerp(textColor, other.textColor, t) ?? textColor, + indicatorDotTheme: indicatorDotTheme.lerp(other.indicatorDotTheme, t), + pageTitleTextColor: + Color.lerp(pageTitleTextColor, other.pageTitleTextColor, t) ?? + pageTitleTextColor, + mainActionsIconColor: + Color.lerp(mainActionsIconColor, other.mainActionsIconColor, t) ?? + mainActionsIconColor, + cardTextColor: + Color.lerp(cardTextColor, other.cardTextColor, t) ?? cardTextColor); + } +} diff --git a/lib/themes/extensions/exchange_page_theme.dart b/lib/themes/extensions/exchange_page_theme.dart new file mode 100644 index 000000000..9c35312a1 --- /dev/null +++ b/lib/themes/extensions/exchange_page_theme.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; + +class ExchangePageTheme extends ThemeExtension<ExchangePageTheme> { + final Color hintTextColor; + final Color receiveAmountColor; + final Color firstGradientTopPanelColor; + final Color secondGradientTopPanelColor; + final Color firstGradientBottomPanelColor; + final Color secondGradientBottomPanelColor; + final Color textFieldBorderTopPanelColor; + final Color textFieldBorderBottomPanelColor; + final Color textFieldButtonColor; + final Color buttonBackgroundColor; + final Color qrCodeColor; + final Color dividerCodeColor; + + ExchangePageTheme( + {required this.hintTextColor, + required this.receiveAmountColor, + required this.firstGradientTopPanelColor, + required this.secondGradientTopPanelColor, + required this.firstGradientBottomPanelColor, + required this.secondGradientBottomPanelColor, + required this.textFieldBorderTopPanelColor, + required this.textFieldBorderBottomPanelColor, + required this.textFieldButtonColor, + required this.buttonBackgroundColor, + required this.qrCodeColor, + required this.dividerCodeColor}); + + @override + ExchangePageTheme copyWith({ + Color? hintTextColor, + Color? receiveAmountColor, + Color? firstGradientTopPanelColor, + Color? secondGradientTopPanelColor, + Color? firstGradientBottomPanelColor, + Color? secondGradientBottomPanelColor, + Color? textFieldBorderTopPanelColor, + Color? textFieldBorderBottomPanelColor, + Color? textFieldButtonColor, + Color? buttonBackgroundColor, + Color? qrCodeColor, + Color? dividerCodeColor, + }) => + ExchangePageTheme( + hintTextColor: hintTextColor ?? this.hintTextColor, + receiveAmountColor: receiveAmountColor ?? this.receiveAmountColor, + firstGradientTopPanelColor: + firstGradientTopPanelColor ?? this.firstGradientTopPanelColor, + secondGradientTopPanelColor: + secondGradientTopPanelColor ?? this.secondGradientTopPanelColor, + firstGradientBottomPanelColor: firstGradientBottomPanelColor ?? + this.firstGradientBottomPanelColor, + secondGradientBottomPanelColor: secondGradientBottomPanelColor ?? + this.secondGradientBottomPanelColor, + textFieldBorderTopPanelColor: + textFieldBorderTopPanelColor ?? this.textFieldBorderTopPanelColor, + textFieldBorderBottomPanelColor: textFieldBorderBottomPanelColor ?? + this.textFieldBorderBottomPanelColor, + textFieldButtonColor: + textFieldButtonColor ?? this.textFieldButtonColor, + buttonBackgroundColor: + buttonBackgroundColor ?? this.buttonBackgroundColor, + qrCodeColor: qrCodeColor ?? this.qrCodeColor, + dividerCodeColor: dividerCodeColor ?? this.dividerCodeColor); + + @override + ExchangePageTheme lerp(ThemeExtension<ExchangePageTheme>? other, double t) { + if (other is! ExchangePageTheme) { + return this; + } + + return ExchangePageTheme( + hintTextColor: Color.lerp(hintTextColor, other.hintTextColor, t) ?? hintTextColor, + receiveAmountColor: Color.lerp(receiveAmountColor, other.receiveAmountColor, t) ?? receiveAmountColor, + firstGradientTopPanelColor: Color.lerp(firstGradientTopPanelColor, other.firstGradientTopPanelColor, t) ?? firstGradientTopPanelColor, + secondGradientTopPanelColor: Color.lerp(secondGradientTopPanelColor, other.secondGradientTopPanelColor, t) ?? secondGradientTopPanelColor, + firstGradientBottomPanelColor: Color.lerp(firstGradientBottomPanelColor, other.firstGradientBottomPanelColor, t) ?? firstGradientBottomPanelColor, + secondGradientBottomPanelColor: Color.lerp(secondGradientBottomPanelColor, other.secondGradientBottomPanelColor, t) ?? secondGradientBottomPanelColor, + textFieldBorderTopPanelColor: Color.lerp(textFieldBorderTopPanelColor, other.textFieldBorderTopPanelColor, t) ?? textFieldBorderTopPanelColor, + textFieldBorderBottomPanelColor: Color.lerp(textFieldBorderBottomPanelColor, other.textFieldBorderBottomPanelColor, t) ?? textFieldBorderBottomPanelColor, + textFieldButtonColor: Color.lerp(textFieldButtonColor, other.textFieldButtonColor, t) ?? textFieldButtonColor, + buttonBackgroundColor: Color.lerp(buttonBackgroundColor, other.buttonBackgroundColor, t) ?? buttonBackgroundColor, + qrCodeColor: Color.lerp(qrCodeColor, other.qrCodeColor, t) ?? qrCodeColor, + dividerCodeColor: Color.lerp(dividerCodeColor, other.dividerCodeColor, t) ?? dividerCodeColor); + } +} diff --git a/lib/themes/extensions/filter_theme.dart b/lib/themes/extensions/filter_theme.dart new file mode 100644 index 000000000..a2106f648 --- /dev/null +++ b/lib/themes/extensions/filter_theme.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; + +class FilterTheme extends ThemeExtension<FilterTheme> { + final Color checkboxFirstGradientColor; + final Color checkboxSecondGradientColor; + final Color checkboxBoundsColor; + final Color checkboxBackgroundColor; + final Color titlesColor; + final Color buttonColor; + final Color iconColor; + + FilterTheme( + {required this.checkboxFirstGradientColor, + required this.checkboxSecondGradientColor, + required this.checkboxBoundsColor, + required this.checkboxBackgroundColor, + required this.titlesColor, + required this.buttonColor, + required this.iconColor}); + + @override + FilterTheme copyWith({ + Color? checkboxFirstGradientColor, + Color? checkboxSecondGradientColor, + Color? checkboxBoundsColor, + Color? checkboxBackgroundColor, + Color? titlesColor, + Color? buttonColor, + Color? iconColor, + }) => + FilterTheme( + checkboxFirstGradientColor: + checkboxFirstGradientColor ?? this.checkboxFirstGradientColor, + checkboxSecondGradientColor: + checkboxSecondGradientColor ?? this.checkboxSecondGradientColor, + checkboxBoundsColor: checkboxBoundsColor ?? this.checkboxBoundsColor, + checkboxBackgroundColor: + checkboxBackgroundColor ?? this.checkboxBackgroundColor, + titlesColor: titlesColor ?? this.titlesColor, + buttonColor: buttonColor ?? this.buttonColor, + iconColor: iconColor ?? this.iconColor); + + @override + FilterTheme lerp(ThemeExtension<FilterTheme>? other, double t) { + if (other is! FilterTheme) { + return this; + } + + return FilterTheme( + checkboxFirstGradientColor: Color.lerp(checkboxFirstGradientColor, + other.checkboxFirstGradientColor, t) ?? + this.checkboxFirstGradientColor, + checkboxSecondGradientColor: Color.lerp(checkboxSecondGradientColor, + other.checkboxSecondGradientColor, t) ?? + this.checkboxSecondGradientColor, + checkboxBoundsColor: + Color.lerp(checkboxBoundsColor, other.checkboxBoundsColor, t) ?? + this.checkboxBoundsColor, + checkboxBackgroundColor: Color.lerp( + checkboxBackgroundColor, other.checkboxBackgroundColor, t) ?? + this.checkboxBackgroundColor, + titlesColor: + Color.lerp(titlesColor, other.titlesColor, t) ?? this.titlesColor, + buttonColor: + Color.lerp(buttonColor, other.buttonColor, t) ?? this.buttonColor, + iconColor: Color.lerp(iconColor, other.iconColor, t) ?? this.iconColor); + } +} diff --git a/lib/themes/extensions/indicator_dot_theme.dart b/lib/themes/extensions/indicator_dot_theme.dart new file mode 100644 index 000000000..f7f482ad6 --- /dev/null +++ b/lib/themes/extensions/indicator_dot_theme.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class IndicatorDotTheme extends ThemeExtension<IndicatorDotTheme> { + final Color indicatorColor; + final Color activeIndicatorColor; + + IndicatorDotTheme( + {required this.indicatorColor, required this.activeIndicatorColor}); + + @override + IndicatorDotTheme copyWith( + {Color? indicatorColor, Color? actionButtonColor}) => + IndicatorDotTheme( + indicatorColor: indicatorColor ?? this.indicatorColor, + activeIndicatorColor: actionButtonColor ?? this.activeIndicatorColor); + + @override + IndicatorDotTheme lerp(ThemeExtension<IndicatorDotTheme>? other, double t) { + if (other is! IndicatorDotTheme) { + return this; + } + + return IndicatorDotTheme( + indicatorColor: Color.lerp(indicatorColor, other.indicatorColor, t) ?? + indicatorColor, + activeIndicatorColor: + Color.lerp(activeIndicatorColor, other.activeIndicatorColor, t) ?? + activeIndicatorColor); + } +} diff --git a/lib/themes/extensions/info_theme.dart b/lib/themes/extensions/info_theme.dart new file mode 100644 index 000000000..aaf9952ea --- /dev/null +++ b/lib/themes/extensions/info_theme.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class InfoTheme extends ThemeExtension<InfoTheme> { + final Color textColor; + + InfoTheme({required this.textColor}); + + @override + InfoTheme copyWith({Color? textColor}) => + InfoTheme(textColor: textColor ?? this.textColor); + + @override + InfoTheme lerp(ThemeExtension<InfoTheme>? other, double t) { + if (other is! InfoTheme) { + return this; + } + + return InfoTheme( + textColor: Color.lerp(textColor, other.textColor, t) ?? textColor); + } +} diff --git a/lib/themes/extensions/keyboard_theme.dart b/lib/themes/extensions/keyboard_theme.dart new file mode 100644 index 000000000..316b7a370 --- /dev/null +++ b/lib/themes/extensions/keyboard_theme.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class KeyboardTheme extends ThemeExtension<KeyboardTheme> { + final Color keyboardBarColor; + + KeyboardTheme({required this.keyboardBarColor}); + + @override + Object get type => KeyboardTheme; + + @override + KeyboardTheme copyWith({Color? keyboardBarColor}) => KeyboardTheme( + keyboardBarColor: keyboardBarColor ?? this.keyboardBarColor); + + @override + KeyboardTheme lerp(ThemeExtension<KeyboardTheme>? other, double t) { + if (other is! KeyboardTheme) { + return this; + } + + return KeyboardTheme( + keyboardBarColor: + Color.lerp(keyboardBarColor, other.keyboardBarColor, t) ?? + keyboardBarColor); + } +} diff --git a/lib/themes/extensions/menu_theme.dart b/lib/themes/extensions/menu_theme.dart new file mode 100644 index 000000000..e0a79dac2 --- /dev/null +++ b/lib/themes/extensions/menu_theme.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; + +class CakeMenuTheme extends ThemeExtension<CakeMenuTheme> { + final Color headerFirstGradientColor; + final Color headerSecondGradientColor; + final Color subnameTextColor; + final Color dividerColor; + final Color backgroundColor; + final Color iconColor; + final Color settingActionsIconColor; + final Color settingTitleColor; + + CakeMenuTheme( + {required this.headerFirstGradientColor, + required this.headerSecondGradientColor, + required this.backgroundColor, + required this.subnameTextColor, + required this.dividerColor, + required this.iconColor, + required this.settingActionsIconColor, + required this.settingTitleColor}); + + @override + CakeMenuTheme copyWith( + {Color? headerFirstGradientColor, + Color? headerSecondGradientColor, + Color? backgroundColor, + Color? subnameTextColor, + Color? dividerColor, + Color? iconColor, + Color? settingActionsIconColor, + Color? settingTitleColor}) => + CakeMenuTheme( + headerFirstGradientColor: + headerFirstGradientColor ?? this.headerFirstGradientColor, + headerSecondGradientColor: + headerSecondGradientColor ?? this.headerSecondGradientColor, + backgroundColor: backgroundColor ?? this.backgroundColor, + subnameTextColor: subnameTextColor ?? this.subnameTextColor, + dividerColor: dividerColor ?? this.dividerColor, + iconColor: iconColor ?? this.iconColor, + settingActionsIconColor: + settingActionsIconColor ?? this.settingActionsIconColor, + settingTitleColor: settingTitleColor ?? this.settingTitleColor); + + @override + CakeMenuTheme lerp(ThemeExtension<CakeMenuTheme>? other, double t) { + if (other is! CakeMenuTheme) { + return this; + } + + return CakeMenuTheme( + headerFirstGradientColor: Color.lerp( + headerFirstGradientColor, other.headerFirstGradientColor, t) ?? + headerFirstGradientColor, + headerSecondGradientColor: Color.lerp(headerSecondGradientColor, + other.headerSecondGradientColor, t) ?? + headerSecondGradientColor, + backgroundColor: + Color.lerp(backgroundColor, other.backgroundColor, t) ?? + backgroundColor, + subnameTextColor: + Color.lerp(subnameTextColor, other.subnameTextColor, t) ?? + subnameTextColor, + dividerColor: + Color.lerp(dividerColor, other.dividerColor, t) ?? dividerColor, + iconColor: Color.lerp(iconColor, other.iconColor, t) ?? iconColor, + settingActionsIconColor: Color.lerp( + settingActionsIconColor, other.settingActionsIconColor, t) ?? + settingActionsIconColor, + settingTitleColor: Color.lerp( + settingTitleColor, other.settingTitleColor, t) ?? + settingTitleColor); + } +} diff --git a/lib/themes/extensions/new_wallet_theme.dart b/lib/themes/extensions/new_wallet_theme.dart new file mode 100644 index 000000000..7e06818ff --- /dev/null +++ b/lib/themes/extensions/new_wallet_theme.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class NewWalletTheme extends ThemeExtension<NewWalletTheme> { + final Color hintTextColor; + final Color underlineColor; + + NewWalletTheme({required this.hintTextColor, required this.underlineColor}); + + @override + Object get type => NewWalletTheme; + + @override + NewWalletTheme copyWith({Color? hintTextColor, Color? underlineColor}) => + NewWalletTheme( + hintTextColor: hintTextColor ?? this.hintTextColor, + underlineColor: underlineColor ?? this.underlineColor); + + @override + NewWalletTheme lerp(ThemeExtension<NewWalletTheme>? other, double t) { + if (other is! NewWalletTheme) { + return this; + } + + return NewWalletTheme( + hintTextColor: + Color.lerp(hintTextColor, other.hintTextColor, t) ?? hintTextColor, + underlineColor: Color.lerp(underlineColor, other.underlineColor, t) ?? + underlineColor); + } +} diff --git a/lib/themes/extensions/order_theme.dart b/lib/themes/extensions/order_theme.dart new file mode 100644 index 000000000..2c58fe477 --- /dev/null +++ b/lib/themes/extensions/order_theme.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class OrderTheme extends ThemeExtension<OrderTheme> { + final Color iconColor; + + OrderTheme({required this.iconColor}); + + @override + OrderTheme copyWith({Color? iconColor}) => + OrderTheme(iconColor: iconColor ?? this.iconColor); + + @override + OrderTheme lerp(ThemeExtension<OrderTheme>? other, double t) { + if (other is! OrderTheme) { + return this; + } + + return OrderTheme( + iconColor: Color.lerp(iconColor, other.iconColor, t) ?? iconColor); + } +} diff --git a/lib/themes/extensions/picker_theme.dart b/lib/themes/extensions/picker_theme.dart new file mode 100644 index 000000000..afd2268ec --- /dev/null +++ b/lib/themes/extensions/picker_theme.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +class PickerTheme extends ThemeExtension<PickerTheme> { + final Color dividerColor; + final Color? searchIconColor; + final Color searchBackgroundFillColor; + final Color searchTextColor; + final Color? searchHintColor; + + PickerTheme( + {required this.dividerColor, + this.searchIconColor, + required this.searchBackgroundFillColor, + required this.searchTextColor, + this.searchHintColor}); + + @override + PickerTheme copyWith( + {Color? dividerColor, + Color? searchIconColor, + Color? searchBackgroundFillColor, + Color? searchTextColor, + Color? searchHintColor}) => + PickerTheme( + dividerColor: dividerColor ?? this.dividerColor, + searchIconColor: searchIconColor ?? this.searchIconColor, + searchBackgroundFillColor: + searchBackgroundFillColor ?? this.searchBackgroundFillColor, + searchTextColor: searchTextColor ?? this.searchTextColor, + searchHintColor: searchHintColor ?? this.searchHintColor); + + @override + PickerTheme lerp(ThemeExtension<PickerTheme>? other, double t) { + if (other is! PickerTheme) { + return this; + } + + return PickerTheme( + dividerColor: + Color.lerp(dividerColor, other.dividerColor, t) ?? dividerColor, + searchIconColor: + Color.lerp(searchIconColor, other.searchIconColor, t) ?? + searchIconColor, + searchBackgroundFillColor: Color.lerp(searchBackgroundFillColor, + other.searchBackgroundFillColor, t) ?? + searchBackgroundFillColor, + searchTextColor: + Color.lerp(searchTextColor, other.searchTextColor, t) ?? + searchTextColor, + searchHintColor: + Color.lerp(searchHintColor, other.searchHintColor, t) ?? + searchHintColor); + } +} diff --git a/lib/themes/extensions/pin_code_theme.dart b/lib/themes/extensions/pin_code_theme.dart new file mode 100644 index 000000000..e1b3f005f --- /dev/null +++ b/lib/themes/extensions/pin_code_theme.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class PinCodeTheme extends ThemeExtension<PinCodeTheme> { + final Color indicatorsColor; + final Color switchColor; + + PinCodeTheme({required this.indicatorsColor, required this.switchColor}); + + @override + PinCodeTheme copyWith({Color? indicatorsColor, Color? switchColor}) => + PinCodeTheme( + indicatorsColor: indicatorsColor ?? this.indicatorsColor, + switchColor: switchColor ?? this.switchColor); + + @override + PinCodeTheme lerp(ThemeExtension<PinCodeTheme>? other, double t) { + if (other is! PinCodeTheme) { + return this; + } + + return PinCodeTheme( + indicatorsColor: + Color.lerp(indicatorsColor, other.indicatorsColor, t) ?? + indicatorsColor, + switchColor: + Color.lerp(switchColor, other.switchColor, t) ?? switchColor); + } +} diff --git a/lib/themes/extensions/placeholder_theme.dart b/lib/themes/extensions/placeholder_theme.dart new file mode 100644 index 000000000..14470a9c9 --- /dev/null +++ b/lib/themes/extensions/placeholder_theme.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class PlaceholderTheme extends ThemeExtension<PlaceholderTheme> { + final Color color; + + PlaceholderTheme({required this.color}); + + @override + PlaceholderTheme copyWith({Color? color}) => + PlaceholderTheme(color: color ?? this.color); + + @override + PlaceholderTheme lerp(ThemeExtension<PlaceholderTheme>? other, double t) { + if (other is! PlaceholderTheme) { + return this; + } + + return PlaceholderTheme(color: Color.lerp(color, other.color, t) ?? color); + } +} diff --git a/lib/themes/extensions/qr_code_theme.dart b/lib/themes/extensions/qr_code_theme.dart new file mode 100644 index 000000000..7b6554553 --- /dev/null +++ b/lib/themes/extensions/qr_code_theme.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class QRCodeTheme extends ThemeExtension<QRCodeTheme> { + final Color qrCodeColor; + final Color qrWidgetCopyButtonColor; + + QRCodeTheme( + {required this.qrCodeColor, required this.qrWidgetCopyButtonColor}); + + @override + QRCodeTheme copyWith({Color? qrCodeColor, Color? qrWidgetCopyButtonColor}) => + QRCodeTheme( + qrCodeColor: qrCodeColor ?? this.qrCodeColor, + qrWidgetCopyButtonColor: + qrWidgetCopyButtonColor ?? this.qrWidgetCopyButtonColor); + + @override + QRCodeTheme lerp(ThemeExtension<QRCodeTheme>? other, double t) { + if (other is! QRCodeTheme) { + return this; + } + + return QRCodeTheme( + qrCodeColor: Color.lerp(qrCodeColor, other.qrCodeColor, t)!, + qrWidgetCopyButtonColor: Color.lerp( + qrWidgetCopyButtonColor, other.qrWidgetCopyButtonColor, t)!); + } +} diff --git a/lib/themes/extensions/receive_page_theme.dart b/lib/themes/extensions/receive_page_theme.dart new file mode 100644 index 000000000..0974598d9 --- /dev/null +++ b/lib/themes/extensions/receive_page_theme.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; + +class ReceivePageTheme extends ThemeExtension<ReceivePageTheme> { + final Color currentTileBackgroundColor; + final Color currentTileTextColor; + final Color tilesBackgroundColor; + final Color tilesTextColor; + final Color iconsBackgroundColor; + final Color iconsColor; + final Color amountBottomBorderColor; + final Color amountHintTextColor; + + ReceivePageTheme( + {required this.currentTileBackgroundColor, + required this.currentTileTextColor, + required this.tilesBackgroundColor, + required this.tilesTextColor, + required this.iconsBackgroundColor, + required this.iconsColor, + required this.amountBottomBorderColor, + required this.amountHintTextColor}); + + @override + ReceivePageTheme copyWith( + {Color? currentTileBackgroundColor, + Color? currentTileTextColor, + Color? tilesBackgroundColor, + Color? tilesTextColor, + Color? iconsBackgroundColor, + Color? iconsColor, + Color? amountBottomBorderColor, + Color? amountHintTextColor}) => + ReceivePageTheme( + currentTileBackgroundColor: + currentTileBackgroundColor ?? this.currentTileBackgroundColor, + currentTileTextColor: + currentTileTextColor ?? this.currentTileTextColor, + tilesBackgroundColor: + tilesBackgroundColor ?? this.tilesBackgroundColor, + tilesTextColor: tilesTextColor ?? this.tilesTextColor, + iconsBackgroundColor: + iconsBackgroundColor ?? this.iconsBackgroundColor, + iconsColor: iconsColor ?? this.iconsColor, + amountBottomBorderColor: + amountBottomBorderColor ?? this.amountBottomBorderColor, + amountHintTextColor: amountHintTextColor ?? this.amountHintTextColor); + + @override + ReceivePageTheme lerp(ThemeExtension<ReceivePageTheme>? other, double t) { + if (other is! ReceivePageTheme) { + return this; + } + + return ReceivePageTheme( + currentTileBackgroundColor: Color.lerp( + currentTileBackgroundColor, other.currentTileBackgroundColor, t)!, + currentTileTextColor: + Color.lerp(currentTileTextColor, other.currentTileTextColor, t)!, + tilesBackgroundColor: + Color.lerp(tilesBackgroundColor, other.tilesBackgroundColor, t)!, + tilesTextColor: Color.lerp(tilesTextColor, other.tilesTextColor, t)!, + iconsBackgroundColor: + Color.lerp(iconsBackgroundColor, other.iconsBackgroundColor, t)!, + iconsColor: Color.lerp(iconsColor, other.iconsColor, t)!, + amountBottomBorderColor: Color.lerp( + amountBottomBorderColor, other.amountBottomBorderColor, t)!, + amountHintTextColor: + Color.lerp(amountHintTextColor, other.amountHintTextColor, t)!); + } +} diff --git a/lib/themes/extensions/seed_widget_theme.dart b/lib/themes/extensions/seed_widget_theme.dart new file mode 100644 index 000000000..9ac20db55 --- /dev/null +++ b/lib/themes/extensions/seed_widget_theme.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class SeedWidgetTheme extends ThemeExtension<SeedWidgetTheme> { + final Color hintTextColor; + + SeedWidgetTheme({required this.hintTextColor}); + + @override + SeedWidgetTheme copyWith({Color? hintTextColor}) => + SeedWidgetTheme(hintTextColor: hintTextColor ?? this.hintTextColor); + + @override + SeedWidgetTheme lerp(ThemeExtension<SeedWidgetTheme>? other, double t) { + if (other is! SeedWidgetTheme) { + return this; + } + + return SeedWidgetTheme( + hintTextColor: + Color.lerp(hintTextColor, other.hintTextColor, t) ?? hintTextColor); + } +} diff --git a/lib/themes/extensions/send_page_theme.dart b/lib/themes/extensions/send_page_theme.dart new file mode 100644 index 000000000..79aca77f9 --- /dev/null +++ b/lib/themes/extensions/send_page_theme.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +class SendPageTheme extends ThemeExtension<SendPageTheme> { + final Color templateTitleColor; + final Color templateBackgroundColor; + final Color templateNewTextColor; + final Color templateSelectedCurrencyBackgroundColor; + final Color templateSelectedCurrencyTitleColor; + final Color templateDottedBorderColor; + final Color estimatedFeeColor; + final Color textFieldButtonIconColor; + final Color textFieldButtonColor; + final Color textFieldHintColor; + final Color textFieldBorderColor; + final Color firstGradientColor; + final Color secondGradientColor; + final Color indicatorDotColor; + + SendPageTheme( + {required this.templateTitleColor, + required this.templateBackgroundColor, + required this.templateNewTextColor, + required this.templateSelectedCurrencyBackgroundColor, + required this.templateSelectedCurrencyTitleColor, + required this.templateDottedBorderColor, + required this.estimatedFeeColor, + required this.textFieldButtonIconColor, + required this.textFieldButtonColor, + required this.textFieldHintColor, + required this.textFieldBorderColor, + required this.firstGradientColor, + required this.secondGradientColor, + required this.indicatorDotColor}); + + @override + SendPageTheme copyWith( + {Color? templateTitleColor, + Color? templateBackgroundColor, + Color? templateNewTextColor, + Color? templateSelectedCurrencyBackgroundColor, + Color? templateSelectedCurrencyTitleColor, + Color? templateDottedBorderColor, + Color? estimatedFeeColor, + Color? textFieldButtonIconColor, + Color? textFieldButtonColor, + Color? textFieldHintColor, + Color? textFieldBorderColor, + Color? firstGradientColor, + Color? secondGradientColor, + Color? indicatorDotColor}) => + SendPageTheme( + templateTitleColor: templateTitleColor ?? this.templateTitleColor, + templateBackgroundColor: + templateBackgroundColor ?? this.templateBackgroundColor, + templateNewTextColor: + templateNewTextColor ?? this.templateNewTextColor, + templateSelectedCurrencyBackgroundColor: + templateSelectedCurrencyBackgroundColor ?? + this.templateSelectedCurrencyBackgroundColor, + templateSelectedCurrencyTitleColor: + templateSelectedCurrencyTitleColor ?? + this.templateSelectedCurrencyTitleColor, + templateDottedBorderColor: + templateDottedBorderColor ?? this.templateDottedBorderColor, + estimatedFeeColor: estimatedFeeColor ?? this.estimatedFeeColor, + textFieldButtonIconColor: + textFieldButtonIconColor ?? this.textFieldButtonIconColor, + textFieldButtonColor: + textFieldButtonColor ?? this.textFieldButtonColor, + textFieldHintColor: textFieldHintColor ?? this.textFieldHintColor, + textFieldBorderColor: + textFieldBorderColor ?? this.textFieldBorderColor, + firstGradientColor: firstGradientColor ?? this.firstGradientColor, + secondGradientColor: secondGradientColor ?? this.secondGradientColor, + indicatorDotColor: indicatorDotColor ?? this.indicatorDotColor); + + @override + SendPageTheme lerp(ThemeExtension<SendPageTheme>? other, double t) { + if (other is! SendPageTheme) { + return this; + } + + return SendPageTheme( + templateTitleColor: + Color.lerp(templateTitleColor, other.templateTitleColor, t)!, + templateBackgroundColor: Color.lerp( + templateBackgroundColor, other.templateBackgroundColor, t)!, + templateNewTextColor: + Color.lerp(templateNewTextColor, other.templateNewTextColor, t)!, + templateSelectedCurrencyBackgroundColor: Color.lerp( + templateSelectedCurrencyBackgroundColor, + other.templateSelectedCurrencyBackgroundColor, + t)!, + templateSelectedCurrencyTitleColor: Color.lerp( + templateSelectedCurrencyTitleColor, + other.templateSelectedCurrencyTitleColor, + t)!, + templateDottedBorderColor: Color.lerp( + templateDottedBorderColor, other.templateDottedBorderColor, t)!, + estimatedFeeColor: + Color.lerp(estimatedFeeColor, other.estimatedFeeColor, t)!, + textFieldButtonIconColor: Color.lerp( + textFieldButtonIconColor, other.textFieldButtonIconColor, t)!, + textFieldButtonColor: + Color.lerp(textFieldButtonColor, other.textFieldButtonColor, t)!, + textFieldHintColor: + Color.lerp(textFieldHintColor, other.textFieldHintColor, t)!, + textFieldBorderColor: + Color.lerp(textFieldBorderColor, other.textFieldBorderColor, t)!, + firstGradientColor: + Color.lerp(firstGradientColor, other.firstGradientColor, t)!, + secondGradientColor: + Color.lerp(secondGradientColor, other.secondGradientColor, t)!, + indicatorDotColor: + Color.lerp(indicatorDotColor, other.indicatorDotColor, t)!); + } +} diff --git a/lib/themes/extensions/support_page_theme.dart b/lib/themes/extensions/support_page_theme.dart new file mode 100644 index 000000000..1b4a4117c --- /dev/null +++ b/lib/themes/extensions/support_page_theme.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class SupportPageTheme extends ThemeExtension<SupportPageTheme> { + final Color iconColor; + + SupportPageTheme({required this.iconColor}); + + @override + SupportPageTheme copyWith({Color? iconColor}) => + SupportPageTheme(iconColor: iconColor ?? this.iconColor); + + @override + SupportPageTheme lerp(ThemeExtension<SupportPageTheme>? other, double t) { + if (other is! SupportPageTheme) { + return this; + } + + return SupportPageTheme( + iconColor: Color.lerp(iconColor, other.iconColor, t) ?? iconColor); + } +} diff --git a/lib/themes/extensions/sync_indicator_theme.dart b/lib/themes/extensions/sync_indicator_theme.dart new file mode 100644 index 000000000..b523a646a --- /dev/null +++ b/lib/themes/extensions/sync_indicator_theme.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +class SyncIndicatorTheme extends ThemeExtension<SyncIndicatorTheme> { + final Color textColor; + final Color syncedBackgroundColor; + final Color notSyncedIconColor; + final Color notSyncedBackgroundColor; + + SyncIndicatorTheme( + {required this.textColor, + required this.syncedBackgroundColor, + required this.notSyncedIconColor, + required this.notSyncedBackgroundColor}); + + @override + SyncIndicatorTheme copyWith({ + Color? textColor, + Color? syncedBackgroundColor, + Color? notSyncedIconColor, + Color? notSyncedBackgroundColor, + }) => + SyncIndicatorTheme( + textColor: textColor ?? this.textColor, + syncedBackgroundColor: + syncedBackgroundColor ?? this.syncedBackgroundColor, + notSyncedIconColor: notSyncedIconColor ?? this.notSyncedIconColor, + notSyncedBackgroundColor: + notSyncedBackgroundColor ?? this.notSyncedBackgroundColor); + + @override + SyncIndicatorTheme lerp(ThemeExtension<SyncIndicatorTheme>? other, double t) { + if (other is! SyncIndicatorTheme) { + return this; + } + + return SyncIndicatorTheme( + textColor: Color.lerp(textColor, other.textColor, t) ?? textColor, + syncedBackgroundColor: + Color.lerp(syncedBackgroundColor, other.syncedBackgroundColor, t) ?? + syncedBackgroundColor, + notSyncedIconColor: + Color.lerp(notSyncedIconColor, other.notSyncedIconColor, t) ?? + notSyncedIconColor, + notSyncedBackgroundColor: Color.lerp( + notSyncedBackgroundColor, other.notSyncedBackgroundColor, t) ?? + notSyncedBackgroundColor); + } +} diff --git a/lib/themes/extensions/transaction_trade_theme.dart b/lib/themes/extensions/transaction_trade_theme.dart new file mode 100644 index 000000000..d912a8850 --- /dev/null +++ b/lib/themes/extensions/transaction_trade_theme.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class TransactionTradeTheme extends ThemeExtension<TransactionTradeTheme> { + final Color detailsTitlesColor; + final Color rowsColor; + + TransactionTradeTheme( + {required this.detailsTitlesColor, required this.rowsColor}); + + @override + TransactionTradeTheme copyWith( + {Color? detailsTitlesColor, Color? rowsColor}) => + TransactionTradeTheme( + detailsTitlesColor: detailsTitlesColor ?? this.detailsTitlesColor, + rowsColor: rowsColor ?? this.rowsColor); + + @override + TransactionTradeTheme lerp( + ThemeExtension<TransactionTradeTheme>? other, double t) { + if (other is! TransactionTradeTheme) { + return this; + } + + return TransactionTradeTheme( + detailsTitlesColor: + Color.lerp(detailsTitlesColor, other.detailsTitlesColor, t)!, + rowsColor: Color.lerp(rowsColor, other.rowsColor, t)!); + } +} diff --git a/lib/themes/extensions/wallet_list_theme.dart b/lib/themes/extensions/wallet_list_theme.dart new file mode 100644 index 000000000..aac3a193a --- /dev/null +++ b/lib/themes/extensions/wallet_list_theme.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class WalletListTheme extends ThemeExtension<WalletListTheme> { + final Color restoreWalletButtonTextColor; + final Color createNewWalletButtonBackgroundColor; + + WalletListTheme( + {required this.restoreWalletButtonTextColor, + required this.createNewWalletButtonBackgroundColor}); + + @override + WalletListTheme copyWith( + {Color? restoreWalletButtonTextColor, + Color? createNewWalletButtonBackgroundColor}) => + WalletListTheme( + restoreWalletButtonTextColor: + restoreWalletButtonTextColor ?? this.restoreWalletButtonTextColor, + createNewWalletButtonBackgroundColor: + createNewWalletButtonBackgroundColor ?? + this.createNewWalletButtonBackgroundColor); + + @override + WalletListTheme lerp(ThemeExtension<WalletListTheme>? other, double t) { + if (other is! WalletListTheme) { + return this; + } + + return WalletListTheme( + restoreWalletButtonTextColor: Color.lerp(restoreWalletButtonTextColor, + other.restoreWalletButtonTextColor, t) ?? + restoreWalletButtonTextColor, + createNewWalletButtonBackgroundColor: Color.lerp( + createNewWalletButtonBackgroundColor, + other.createNewWalletButtonBackgroundColor, + t) ?? + createNewWalletButtonBackgroundColor); + } +} diff --git a/lib/themes/high_contrast_theme.dart b/lib/themes/high_contrast_theme.dart new file mode 100644 index 000000000..e43e63020 --- /dev/null +++ b/lib/themes/high_contrast_theme.dart @@ -0,0 +1,118 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/monero_light_theme.dart'; +import 'package:flutter/material.dart'; + +class HighContrastTheme extends MoneroLightTheme { + HighContrastTheme({required int raw}) : super(raw: raw) { + colorScheme = ColorScheme.fromSwatch( + primarySwatch: Colors.grey, + accentColor: primaryColor, + backgroundColor: Colors.white, + cardColor: containerColor, + brightness: Brightness.light); + } + + @override + String get title => S.current.high_contrast_theme; + @override + Color get primaryColor => Colors.black; + @override + Color get containerColor => Palette.highContrastGray; + @override + Color get primaryTextColor => colorScheme.onBackground; + @override + Color get dialogBackgroundColor => Colors.white; + + @override + CakeTextTheme get cakeTextTheme => super.cakeTextTheme.copyWith( + buttonTextColor: Colors.white, + buttonSecondaryTextColor: Colors.white.withOpacity(0.5)); + + @override + SyncIndicatorTheme get syncIndicatorStyle => + super.syncIndicatorStyle.copyWith( + textColor: colorScheme.background, + syncedBackgroundColor: containerColor); + + @override + BalancePageTheme get balancePageTheme => super.balancePageTheme.copyWith( + textColor: Colors.white, + labelTextColor: Colors.grey, + assetTitleColor: Colors.white, + balanceAmountColor: Colors.white); + + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + textColor: Colors.black, + cardTextColor: Colors.white, + mainActionsIconColor: Colors.white, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: Colors.grey, activeIndicatorColor: Colors.black)); + + @override + ExchangePageTheme get exchangePageTheme => super + .exchangePageTheme + .copyWith(firstGradientTopPanelColor: containerColor); + + @override + SendPageTheme get sendPageTheme => super.sendPageTheme.copyWith( + templateTitleColor: Colors.white, + templateBackgroundColor: Colors.black, + firstGradientColor: containerColor); + + @override + AddressTheme get addressTheme => + super.addressTheme.copyWith(actionButtonColor: Colors.grey); + + @override + FilterTheme get filterTheme => + super.filterTheme.copyWith(iconColor: Colors.white); + + @override + CakeMenuTheme get menuTheme => super.menuTheme.copyWith( + settingTitleColor: Colors.black, + headerFirstGradientColor: containerColor, + iconColor: Colors.white); + + @override + PickerTheme get pickerTheme => super.pickerTheme.copyWith( + searchIconColor: Colors.white, + searchHintColor: Colors.white, + searchTextColor: Colors.white, + searchBackgroundFillColor: Colors.grey); + + @override + AccountListTheme get accountListTheme => super.accountListTheme.copyWith( + tilesTextColor: Colors.black, + tilesBackgroundColor: Colors.white, + currentAccountBackgroundColor: containerColor, + currentAccountTextColor: Colors.white, + currentAccountAmountColor: Colors.white); + + @override + ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( + tilesTextColor: Colors.white, + iconsBackgroundColor: Colors.grey, + iconsColor: Colors.black); + + @override + ThemeData get themeData => super.themeData.copyWith( + disabledColor: Colors.grey, + dialogTheme: + super.themeData.dialogTheme.copyWith(backgroundColor: Colors.white)); +} diff --git a/lib/themes/light_theme.dart b/lib/themes/light_theme.dart index ad572c13f..f24551e66 100644 --- a/lib/themes/light_theme.dart +++ b/lib/themes/light_theme.dart @@ -1,3 +1,29 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/info_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/support_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; @@ -8,268 +34,192 @@ class LightTheme extends ThemeBase { @override String get title => S.current.light_theme; - @override ThemeType get type => ThemeType.light; - - ThemeData theme = ThemeData( - fontFamily: 'Lato', - brightness: Brightness.light, - scaffoldBackgroundColor: Colors.white, // second gradient color - primaryColor: Colors.white, // third gradient color - indicatorColor: - PaletteDark.darkCyanBlue.withOpacity(0.67), // page indicator - hoverColor: Palette.darkBlueCraiola, // amount hint text (receive page) - dividerColor: Palette.paleBlue, - hintColor: Palette.gray, - textTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: Palette.darkBlueCraiola, // sync_indicator text - backgroundColor: Palette.blueAlice, // synced sync_indicator - decorationColor: Palette.blueAlice.withOpacity(0.75), // not synced sync_indicator - ), - bodySmall: TextStyle( - color: Palette.shineOrange, // not synced light - decorationColor: PaletteDark.wildBlue, // filter icon - ), - labelSmall: TextStyle( - color: Palette.blueAlice, // filter button - backgroundColor: PaletteDark.darkCyanBlue, // date section row - decorationColor: - Palette.blueAlice // icons (transaction and trade rows) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Palette.blueAlice, // address button border - decorationColor: PaletteDark.lightBlueGrey, // copy button (qr widget) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Colors.white, // qr code - decorationColor: Palette.darkBlueCraiola, // bottom border of amount (receive page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: PaletteDark.lightBlueGrey, // icons color (receive page) - decorationColor: Palette.moderateLavender, // icons background (receive page) - ), - // display2 -> headldisplaySmalline3 - displaySmall: TextStyle( - color: - Palette.darkBlueCraiola, // text color of tiles (receive page) - decorationColor: - Palette.blueAlice // background of tiles (receive page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Colors.white, // text color of current tile (receive page), - //decorationColor: Palette.blueCraiola // background of current tile (receive page) - decorationColor: Palette - .blueCraiola // background of current tile (receive page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.violetBlue, // text color of tiles (account list) - decorationColor: - Colors.white // background of tiles (account list) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette - .protectiveBlue, // text color of current tile (account list) - decorationColor: - Colors.white // background of current tile (account list) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.moderatePurpleBlue, // scrollbar thumb - decorationColor: Palette.periwinkleCraiola // scrollbar background - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Palette.moderateLavender, // menu header - decorationColor: Colors.white, // menu background - ) - ), - scrollbarTheme: ScrollbarThemeData( - thumbColor: MaterialStateProperty.all(Palette.moderatePurpleBlue), - trackColor: MaterialStateProperty.all(Palette.periwinkleCraiola), - radius: Radius.circular(3), - thickness: MaterialStateProperty.all(6), - thumbVisibility: MaterialStateProperty.all(true), - crossAxisMargin: 6, - ), - primaryTextTheme: TextTheme( - // title -> titleLarge - titleLarge: TextStyle( - color: Palette.darkBlueCraiola, // title color - backgroundColor: Palette.wildPeriwinkle // textfield underline - ), - bodySmall: TextStyle( - color: PaletteDark.pigeonBlue, // secondary text - decorationColor: Palette.wildLavender // menu divider - ), - labelSmall: TextStyle( - color: Palette.darkGray, // transaction/trade details titles - decorationColor: PaletteDark.darkCyanBlue, // placeholder - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Palette.blueCraiola, // first gradient color (send page) - decorationColor: - Palette.blueGreyCraiola // second gradient color (send page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Colors.white - .withOpacity(0.5), // text field border color (send page) - decorationColor: Colors.white - .withOpacity(0.5), // text field hint color (send page) - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: Colors.white - .withOpacity(0.2), // text field button color (send page) - decorationColor: - Colors.white // text field button icon color (send page) - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: Colors.white.withOpacity(0.5), // estimated fee (send page) - backgroundColor: PaletteDark.darkCyanBlue - .withOpacity(0.67), // dot color for indicator on send page - decorationColor: - Palette.moderateLavender // template dotted border (send page) - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Palette.darkBlueCraiola, // template new text (send page) - backgroundColor: PaletteDark - .darkNightBlue, // active dot color for indicator on send page - decorationColor: - Palette.blueAlice // template background color (send page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.darkBlueCraiola, // template title (send page) - backgroundColor: - Colors.black, // icon color on order row (moonpay) - decorationColor: - Palette.niagara // receive amount text (exchange page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette - .blueCraiola, // first gradient color top panel (exchange page) - decorationColor: Palette - .blueGreyCraiola // second gradient color top panel (exchange page) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.blueCraiola.withOpacity( - 0.7), // first gradient color bottom panel (exchange page) - decorationColor: Palette.blueGreyCraiola.withOpacity( - 0.7), // second gradient color bottom panel (exchange page) - backgroundColor: Palette.protectiveBlue // alert right button text - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Colors.white.withOpacity( - 0.5), // text field border on top panel (exchange page) - decorationColor: Colors.white.withOpacity( - 0.5), // text field border on bottom panel (exchange page) - backgroundColor: Palette.brightOrange // alert left button text - ) - ), - focusColor: Colors.white.withOpacity(0.2), // text field button (exchange page) - accentTextTheme: TextTheme( - // title -> headlititleLargene6 - titleLarge: TextStyle( - color: Colors.white, // picker background - backgroundColor: Palette.periwinkleCraiola, // picker divider - decorationColor: Colors.white // dialog background - ), - bodySmall: TextStyle( - color: Palette.blueAlice, // container (confirm exchange) - backgroundColor: Palette.blueAlice, // button background (confirm exchange) - decorationColor: Palette.darkBlueCraiola, // text color (information page) - ), - // subtitle -> titleSmall - titleSmall: TextStyle( - color: Palette.darkBlueCraiola, // QR code (exchange trade page) - backgroundColor: - Palette.wildPeriwinkle, // divider (exchange trade page) - decorationColor: Palette - .protectiveBlue // crete new wallet button background (wallet list page) - ), - // headline -> headlineSmall - headlineSmall: TextStyle( - color: Palette - .moderateLavender, // first gradient color of wallet action buttons (wallet list page) - backgroundColor: Palette - .moderateLavender, // second gradient color of wallet action buttons (wallet list page) - decorationColor: Colors - .white // restore wallet button text color (wallet list page) - ), - // subhead -> titleMedium - titleMedium: TextStyle( - color: Palette.darkGray, // titles color (filter widget) - backgroundColor: Palette.periwinkle, // divider color (filter widget) - decorationColor: Colors.white // checkbox background (filter widget) - ), - labelSmall: TextStyle( - color: Palette.wildPeriwinkle, // checkbox bounds (filter widget) - decorationColor: Colors.white, // menu subname - ), - // display1 -> headlineMedium - headlineMedium: TextStyle( - color: Palette.blueCraiola, // first gradient color (menu header) - decorationColor: Palette.blueGreyCraiola, // second gradient color(menu header) - backgroundColor: PaletteDark.darkNightBlue // active dot color - ), - // display2 -> displaySmall - displaySmall: TextStyle( - color: - Palette.shadowWhite, // action button color (address text field) - decorationColor: Palette.darkGray, // hint text (seed widget) - backgroundColor: Palette.darkBlueCraiola - .withOpacity(0.67) // text on balance page - ), - // display3 -> displayMedium - displayMedium: TextStyle( - color: Palette.darkGray, // hint text (new wallet page) - decorationColor: - Palette.periwinkleCraiola, // underline (new wallet page) - backgroundColor: - Palette.darkBlueCraiola // menu, icons, balance (dashboard page) - ), - // display4 -> displayLarge - displayLarge: TextStyle( - color: Palette.darkGray, // switch background (settings page) - backgroundColor: - Colors.black, // icon color on support page (moonpay, github) - decorationColor: - Colors.white.withOpacity(0.4) // hint text (exchange page) - ), - // body -> bodyMedium - bodyMedium: TextStyle( - color: Palette.darkGray, // indicators (PIN code) - decorationColor: Palette.darkGray, // switch (PIN code) - backgroundColor: Colors.white // alert right button - ), - // body2 -> bodyLarge - bodyLarge: TextStyle( - color: Palette.protectiveBlue, // primary buttons - decorationColor: Colors.white, // alert left button, - backgroundColor: Palette.dullGray // keyboard bar color - ), - ), - cardColor: Palette.protectiveBlue // bottom button (action list) - ); + @override + Brightness get brightness => Brightness.light; + @override + Color get backgroundColor => Colors.white; + @override + Color get primaryColor => Palette.protectiveBlue; + @override + Color get primaryTextColor => Palette.darkBlueCraiola; + @override + Color get containerColor => Palette.blueAlice; + @override + Color get dialogBackgroundColor => Colors.white; @override - ThemeData get themeData => theme.copyWith( - colorScheme: theme.colorScheme - .copyWith(background: Colors.white, secondary: Colors.white)); + CakeScrollbarTheme get scrollbarTheme => CakeScrollbarTheme( + thumbColor: Palette.moderatePurpleBlue, + trackColor: Palette.periwinkleCraiola); + + @override + SyncIndicatorTheme get syncIndicatorStyle => SyncIndicatorTheme( + textColor: Palette.darkBlueCraiola, + syncedBackgroundColor: Palette.blueAlice, + notSyncedIconColor: Palette.shineOrange, + notSyncedBackgroundColor: Palette.blueAlice.withOpacity(0.75)); + + @override + KeyboardTheme get keyboardTheme => + KeyboardTheme(keyboardBarColor: Palette.dullGray); + + @override + PinCodeTheme get pinCodeTheme => PinCodeTheme( + indicatorsColor: Palette.darkGray, switchColor: Palette.darkGray); + + @override + SupportPageTheme get supportPageTheme => + SupportPageTheme(iconColor: Colors.black); + + @override + ExchangePageTheme get exchangePageTheme => ExchangePageTheme( + hintTextColor: Colors.white.withOpacity(0.4), + dividerCodeColor: Palette.wildPeriwinkle, + qrCodeColor: primaryTextColor, + buttonBackgroundColor: containerColor, + textFieldButtonColor: Colors.white.withOpacity(0.2), + textFieldBorderBottomPanelColor: Colors.white.withOpacity(0.5), + textFieldBorderTopPanelColor: Colors.white.withOpacity(0.5), + secondGradientBottomPanelColor: Palette.blueGreyCraiola.withOpacity(0.7), + firstGradientBottomPanelColor: Palette.blueCraiola.withOpacity(0.7), + secondGradientTopPanelColor: Palette.blueGreyCraiola, + firstGradientTopPanelColor: Palette.blueCraiola, + receiveAmountColor: Palette.niagara); + + @override + NewWalletTheme get newWalletTheme => NewWalletTheme( + hintTextColor: Palette.darkGray, + underlineColor: Palette.periwinkleCraiola); + + @override + AddressTheme get addressTheme => + AddressTheme(actionButtonColor: Palette.shadowWhite); + + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + cardTextColor: super.dashboardPageTheme.textColor, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: PaletteDark.darkCyanBlue.withOpacity(0.67), + activeIndicatorColor: PaletteDark.darkNightBlue)); + + @override + BalancePageTheme get balancePageTheme => BalancePageTheme( + textColor: dashboardPageTheme.textColor, + labelTextColor: Palette.darkBlueCraiola.withOpacity(0.67)); + + @override + CakeMenuTheme get menuTheme => CakeMenuTheme( + headerFirstGradientColor: Palette.blueCraiola, + headerSecondGradientColor: Palette.blueGreyCraiola, + backgroundColor: Colors.white, + subnameTextColor: Colors.white, + dividerColor: Palette.wildLavender, + iconColor: Colors.white, + settingTitleColor: receivePageTheme.tilesTextColor, + settingActionsIconColor: Palette.gray); + + @override + FilterTheme get filterTheme => FilterTheme( + checkboxFirstGradientColor: Palette.blueCraiola, + checkboxSecondGradientColor: Palette.blueGreyCraiola, + checkboxBoundsColor: Palette.wildPeriwinkle, + checkboxBackgroundColor: Colors.white, + titlesColor: Palette.darkGray, + buttonColor: Palette.blueAlice, + iconColor: PaletteDark.wildBlue); + + @override + WalletListTheme get walletListTheme => WalletListTheme( + restoreWalletButtonTextColor: Colors.white, + createNewWalletButtonBackgroundColor: Palette.protectiveBlue); + + @override + InfoTheme get infoTheme => InfoTheme(textColor: Palette.darkBlueCraiola); + + @override + PickerTheme get pickerTheme => PickerTheme( + dividerColor: Palette.periwinkleCraiola, + searchTextColor: cakeTextTheme.textfieldUnderlineColor, + searchBackgroundFillColor: addressTheme.actionButtonColor); + + @override + AlertTheme get alertTheme => AlertTheme( + backdropColor: PaletteDark.darkNightBlue.withOpacity(0.75), + leftButtonTextColor: Palette.brightOrange); + + @override + OrderTheme get orderTheme => OrderTheme(iconColor: Colors.black); + + @override + SendPageTheme get sendPageTheme => SendPageTheme( + templateTitleColor: Palette.darkBlueCraiola, + templateBackgroundColor: Palette.blueAlice, + templateNewTextColor: Palette.darkBlueCraiola, + templateDottedBorderColor: Palette.moderateLavender, + templateSelectedCurrencyBackgroundColor: Colors.white, + templateSelectedCurrencyTitleColor: primaryColor, + estimatedFeeColor: Colors.white.withOpacity(0.5), + textFieldButtonIconColor: Colors.white, + textFieldButtonColor: Colors.white.withOpacity(0.2), + textFieldHintColor: Colors.white.withOpacity(0.5), + textFieldBorderColor: Colors.white.withOpacity(0.5), + secondGradientColor: Palette.blueGreyCraiola, + firstGradientColor: Palette.blueCraiola, + indicatorDotColor: PaletteDark.darkCyanBlue.withOpacity(0.67)); + + @override + SeedWidgetTheme get seedWidgetTheme => + SeedWidgetTheme(hintTextColor: Palette.darkGray); + + @override + PlaceholderTheme get placeholderTheme => + PlaceholderTheme(color: PaletteDark.darkCyanBlue); + + @override + TransactionTradeTheme get transactionTradeTheme => TransactionTradeTheme( + detailsTitlesColor: Palette.darkGray, rowsColor: Palette.blueAlice); + + @override + CakeTextTheme get cakeTextTheme => CakeTextTheme( + secondaryTextColor: PaletteDark.pigeonBlue, + textfieldUnderlineColor: Palette.wildPeriwinkle, + titleColor: Palette.violetBlue, + addressButtonBorderColor: Palette.blueAlice, + dateSectionRowColor: PaletteDark.darkCyanBlue); + + @override + AccountListTheme get accountListTheme => AccountListTheme( + currentAccountBackgroundColor: dialogBackgroundColor, + currentAccountTextColor: primaryColor, + currentAccountAmountColor: receivePageTheme.iconsColor, + tilesBackgroundColor: Colors.white, + tilesAmountColor: receivePageTheme.iconsColor, + tilesTextColor: Palette.violetBlue); + + @override + ReceivePageTheme get receivePageTheme => ReceivePageTheme( + currentTileBackgroundColor: Palette.blueCraiola, + currentTileTextColor: Colors.white, + tilesBackgroundColor: Palette.blueAlice, + tilesTextColor: Palette.darkBlueCraiola, + iconsBackgroundColor: Palette.moderateLavender, + iconsColor: PaletteDark.lightBlueGrey, + amountBottomBorderColor: Palette.darkBlueCraiola, + amountHintTextColor: Palette.darkBlueCraiola); + + @override + QRCodeTheme get qrCodeTheme => QRCodeTheme( + qrCodeColor: Colors.white, + qrWidgetCopyButtonColor: PaletteDark.lightBlueGrey); + + @override + ThemeData get themeData => super.themeData.copyWith( + dividerColor: Palette.paleBlue, + hintColor: Palette.gray, + disabledColor: Palette.darkGray, + dialogTheme: + super.themeData.dialogTheme.copyWith(backgroundColor: Colors.white)); } diff --git a/lib/themes/matrix_green_theme.dart b/lib/themes/matrix_green_theme.dart new file mode 100644 index 000000000..30e294415 --- /dev/null +++ b/lib/themes/matrix_green_theme.dart @@ -0,0 +1,14 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:flutter/material.dart'; + +class MatrixGreenTheme extends MoneroDarkTheme { + MatrixGreenTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.matrix_green_dark_theme; + @override + Color get primaryColor => PaletteDark.matrixGreen; +} + diff --git a/lib/themes/monero_dark_theme.dart b/lib/themes/monero_dark_theme.dart new file mode 100644 index 000000000..4931d74bc --- /dev/null +++ b/lib/themes/monero_dark_theme.dart @@ -0,0 +1,194 @@ +import 'package:cake_wallet/themes/dark_theme.dart'; +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/info_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:flutter/material.dart'; + +class MoneroDarkTheme extends DarkTheme { + MoneroDarkTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.monero_dark_theme; + @override + Color get backgroundColor => Colors.black; + @override + Color get primaryColor => PaletteDark.moneroOrange; + @override + Color get containerColor => PaletteDark.moneroCard; + @override + Color get dialogBackgroundColor => containerColor; + + @override + CakeScrollbarTheme get scrollbarTheme => + super.scrollbarTheme.copyWith(thumbColor: Colors.grey); + + @override + SyncIndicatorTheme get syncIndicatorStyle => + super.syncIndicatorStyle.copyWith( + textColor: Colors.white, + notSyncedBackgroundColor: Colors.grey.withOpacity(0.2), + syncedBackgroundColor: containerColor); + + @override + PinCodeTheme get pinCodeTheme => super + .pinCodeTheme + .copyWith(indicatorsColor: primaryColor, switchColor: Colors.grey); + + @override + ExchangePageTheme get exchangePageTheme => super.exchangePageTheme.copyWith( + hintTextColor: Colors.grey, + qrCodeColor: primaryTextColor, + buttonBackgroundColor: colorScheme.surfaceVariant, + textFieldButtonColor: colorScheme.onInverseSurface, + textFieldBorderBottomPanelColor: colorScheme.surfaceVariant, + textFieldBorderTopPanelColor: colorScheme.surfaceVariant, + secondGradientBottomPanelColor: containerColor, + firstGradientBottomPanelColor: containerColor, + secondGradientTopPanelColor: colorScheme.surface, + firstGradientTopPanelColor: colorScheme.surface, + receiveAmountColor: colorScheme.surfaceVariant); + + @override + NewWalletTheme get newWalletTheme => super + .newWalletTheme + .copyWith(hintTextColor: Colors.grey, underlineColor: Colors.grey); + + @override + AddressTheme get addressTheme => + super.addressTheme.copyWith(actionButtonColor: containerColor); + + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + pageTitleTextColor: primaryColor, + mainActionsIconColor: primaryColor, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: colorScheme.secondaryContainer, + activeIndicatorColor: colorScheme.inversePrimary)); + @override + BalancePageTheme get balancePageTheme => super.balancePageTheme.copyWith( + cardBorderColor: primaryColor.withOpacity(0.2), + labelTextColor: Colors.grey, + balanceAmountColor: primaryColor, + assetTitleColor: primaryColor); + + @override + CakeMenuTheme get menuTheme => super.menuTheme.copyWith( + headerFirstGradientColor: containerColor, + headerSecondGradientColor: containerColor, + backgroundColor: containerColor, + subnameTextColor: Colors.grey, + dividerColor: colorScheme.secondaryContainer, + iconColor: colorScheme.secondaryContainer, + settingActionsIconColor: colorScheme.secondaryContainer); + + @override + FilterTheme get filterTheme => super.filterTheme.copyWith( + checkboxFirstGradientColor: colorScheme.secondaryContainer, + checkboxSecondGradientColor: colorScheme.inversePrimary, + checkboxBoundsColor: PaletteDark.wildVioletBlue, + checkboxBackgroundColor: PaletteDark.wildVioletBlue.withOpacity(0.3), + buttonColor: containerColor, + iconColor: Colors.grey); + + @override + WalletListTheme get walletListTheme => super.walletListTheme.copyWith( + restoreWalletButtonTextColor: Colors.white, + createNewWalletButtonBackgroundColor: primaryColor); + + @override + InfoTheme get infoTheme => super.infoTheme.copyWith(textColor: Colors.grey); + + @override + PickerTheme get pickerTheme => + super.pickerTheme.copyWith(dividerColor: Colors.grey.withOpacity(0.5)); + + @override + SendPageTheme get sendPageTheme => super.sendPageTheme.copyWith( + templateNewTextColor: + dashboardPageTheme.indicatorDotTheme.activeIndicatorColor, + templateTitleColor: primaryTextColor, + templateBackgroundColor: containerColor, + templateDottedBorderColor: colorScheme.primaryContainer, + templateSelectedCurrencyTitleColor: Colors.black, + textFieldButtonIconColor: colorScheme.inverseSurface, + textFieldButtonColor: colorScheme.onInverseSurface, + textFieldHintColor: Colors.grey.withOpacity(0.5), + textFieldBorderColor: Colors.grey.withOpacity(0.5), + secondGradientColor: containerColor, + firstGradientColor: containerColor, + indicatorDotColor: dashboardPageTheme.indicatorDotTheme.indicatorColor); + + @override + SeedWidgetTheme get seedWidgetTheme => + super.seedWidgetTheme.copyWith(hintTextColor: Colors.grey); + + @override + TransactionTradeTheme get transactionTradeTheme => super + .transactionTradeTheme + .copyWith(detailsTitlesColor: Colors.grey, rowsColor: containerColor); + + @override + CakeTextTheme get cakeTextTheme => super.cakeTextTheme.copyWith( + secondaryTextColor: Colors.grey, + addressButtonBorderColor: primaryColor.withOpacity(0.2), + dateSectionRowColor: Colors.grey, + textfieldUnderlineColor: Colors.grey.withOpacity(0.5)); + + @override + AccountListTheme get accountListTheme => + super.accountListTheme.copyWith(tilesBackgroundColor: containerColor); + + @override + ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( + currentTileBackgroundColor: primaryColor, + currentTileTextColor: Colors.white, + tilesBackgroundColor: containerColor, + iconsBackgroundColor: colorScheme.onInverseSurface, + iconsColor: colorScheme.inverseSurface, + amountBottomBorderColor: Colors.grey, + amountHintTextColor: Colors.grey); + + @override + QRCodeTheme get qrCodeTheme => QRCodeTheme( + qrCodeColor: Colors.grey, qrWidgetCopyButtonColor: Colors.grey); + + @override + AlertTheme get alertTheme => super + .alertTheme + .copyWith(backdropColor: colorScheme.surface.withOpacity(0.75)); + + @override + ThemeData get themeData => super.themeData.copyWith( + dividerColor: pickerTheme.dividerColor, + hintColor: Colors.grey, + dialogTheme: + super.themeData.dialogTheme.copyWith(backgroundColor: containerColor), + appBarTheme: super.themeData.appBarTheme.copyWith( + titleTextStyle: super + .themeData + .appBarTheme + .titleTextStyle! + .copyWith(color: primaryColor))); +} diff --git a/lib/themes/monero_light_theme.dart b/lib/themes/monero_light_theme.dart new file mode 100644 index 000000000..cf046e736 --- /dev/null +++ b/lib/themes/monero_light_theme.dart @@ -0,0 +1,159 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:cake_wallet/themes/light_theme.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter/material.dart'; + +class MoneroLightTheme extends LightTheme { + MoneroLightTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.monero_light_theme; + @override + Color get primaryColor => Palette.moneroOrange; + @override + Color get containerColor => Palette.moneroLightOrange; + @override + Color get primaryTextColor => colorScheme.onPrimaryContainer; + @override + Color get dialogBackgroundColor => containerColor; + + @override + SyncIndicatorTheme get syncIndicatorStyle => + super.syncIndicatorStyle.copyWith( + textColor: primaryTextColor, + syncedBackgroundColor: colorScheme.primaryContainer, + notSyncedBackgroundColor: containerColor.withOpacity(0.75)); + + @override + ExchangePageTheme get exchangePageTheme => super.exchangePageTheme.copyWith( + qrCodeColor: primaryTextColor, + buttonBackgroundColor: containerColor, + secondGradientBottomPanelColor: primaryColor.withOpacity(0.7), + firstGradientBottomPanelColor: colorScheme.primary.withOpacity(0.7), + secondGradientTopPanelColor: primaryColor, + firstGradientTopPanelColor: colorScheme.primary, + textFieldBorderBottomPanelColor: colorScheme.surfaceVariant, + textFieldBorderTopPanelColor: colorScheme.surfaceVariant, + receiveAmountColor: colorScheme.surfaceVariant); + + @override + NewWalletTheme get newWalletTheme => super.newWalletTheme.copyWith( + hintTextColor: colorScheme.secondary, + underlineColor: colorScheme.secondary); + + @override + AddressTheme get addressTheme => + super.addressTheme.copyWith(actionButtonColor: containerColor); + + @override + DashboardPageTheme get dashboardPageTheme => + super.dashboardPageTheme.copyWith( + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: colorScheme.secondaryContainer, + activeIndicatorColor: colorScheme.inversePrimary)); + @override + BalancePageTheme get balancePageTheme => super.balancePageTheme.copyWith( + textColor: primaryTextColor.withOpacity(0.67), + labelTextColor: colorScheme.secondary); + + @override + CakeMenuTheme get menuTheme => super.menuTheme.copyWith( + headerFirstGradientColor: colorScheme.primary, + headerSecondGradientColor: primaryColor, + dividerColor: colorScheme.secondaryContainer, + iconColor: colorScheme.secondaryContainer, + settingActionsIconColor: colorScheme.secondary); + + @override + FilterTheme get filterTheme => super.filterTheme.copyWith( + checkboxFirstGradientColor: colorScheme.secondaryContainer, + checkboxSecondGradientColor: colorScheme.inversePrimary, + checkboxBoundsColor: PaletteDark.wildVioletBlue, + checkboxBackgroundColor: PaletteDark.wildVioletBlue.withOpacity(0.3), + buttonColor: containerColor, + iconColor: colorScheme.secondary); + + @override + WalletListTheme get walletListTheme => super.walletListTheme.copyWith( + restoreWalletButtonTextColor: Colors.white, + createNewWalletButtonBackgroundColor: primaryColor); + + @override + SendPageTheme get sendPageTheme => super.sendPageTheme.copyWith( + templateTitleColor: primaryTextColor, + templateBackgroundColor: containerColor, + templateNewTextColor: primaryTextColor, + templateDottedBorderColor: colorScheme.primaryContainer, + secondGradientColor: primaryColor, + firstGradientColor: colorScheme.primary, + indicatorDotColor: dashboardPageTheme.indicatorDotTheme.indicatorColor); + + @override + SeedWidgetTheme get seedWidgetTheme => + super.seedWidgetTheme.copyWith(hintTextColor: colorScheme.secondary); + + @override + TransactionTradeTheme get transactionTradeTheme => + super.transactionTradeTheme.copyWith( + detailsTitlesColor: colorScheme.secondary, rowsColor: containerColor); + + @override + CakeTextTheme get cakeTextTheme => super.cakeTextTheme.copyWith( + titleColor: primaryTextColor, + secondaryTextColor: colorScheme.secondary, + addressButtonBorderColor: primaryColor.withOpacity(0.2), + dateSectionRowColor: colorScheme.secondary, + textfieldUnderlineColor: colorScheme.secondary.withOpacity(0.5)); + + @override + AccountListTheme get accountListTheme => + super.accountListTheme.copyWith(tilesBackgroundColor: containerColor); + + @override + ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( + currentTileBackgroundColor: primaryColor, + tilesBackgroundColor: containerColor, + tilesTextColor: primaryTextColor, + iconsBackgroundColor: colorScheme.surfaceVariant, + iconsColor: colorScheme.onSurfaceVariant, + amountBottomBorderColor: primaryTextColor, + amountHintTextColor: primaryTextColor, + currentTileTextColor: Colors.white); + + @override + QRCodeTheme get qrCodeTheme => super + .qrCodeTheme + .copyWith(qrWidgetCopyButtonColor: colorScheme.secondary); + + @override + AlertTheme get alertTheme => super + .alertTheme + .copyWith(backdropColor: colorScheme.inverseSurface.withOpacity(0.75)); + + @override + ThemeData get themeData => super.themeData.copyWith( + dividerColor: pickerTheme.dividerColor, + hintColor: colorScheme.secondary, + dialogTheme: super + .themeData + .dialogTheme + .copyWith(backgroundColor: containerColor)); +} diff --git a/lib/themes/theme_base.dart b/lib/themes/theme_base.dart index 50406652a..6151f0e83 100644 --- a/lib/themes/theme_base.dart +++ b/lib/themes/theme_base.dart @@ -1,17 +1,157 @@ +import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/alert_theme.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; +import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; +import 'package:cake_wallet/themes/extensions/info_theme.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/order_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; +import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; +import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/support_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:flutter/material.dart'; -enum ThemeType {light, bright, dark} +enum ThemeType { bright, light, dark } abstract class ThemeBase { - ThemeBase({required this.raw}); + ThemeBase({required this.raw}) { + colorScheme = ColorScheme.fromSeed( + brightness: brightness, + seedColor: primaryColor, + background: backgroundColor); + } final int raw; String get title; - ThemeData get themeData; ThemeType get type; @override String toString() { return title; } -} \ No newline at end of file + + Brightness get brightness; + Color get backgroundColor; + Color get primaryColor; + Color get primaryTextColor; + Color get containerColor; + Color get dialogBackgroundColor; + + ColorScheme colorScheme = ColorScheme.light(); + + ThemeData get generatedThemeData => ThemeData.from( + colorScheme: colorScheme, + textTheme: TextTheme().apply(fontFamily: 'Lato')); + + DashboardPageTheme get dashboardPageTheme => DashboardPageTheme( + firstGradientBackgroundColor: backgroundColor, + secondGradientBackgroundColor: backgroundColor, + thirdGradientBackgroundColor: backgroundColor, + textColor: primaryTextColor, + indicatorDotTheme: IndicatorDotTheme( + indicatorColor: primaryColor, activeIndicatorColor: backgroundColor)); + + CakeScrollbarTheme get scrollbarTheme; + + SyncIndicatorTheme get syncIndicatorStyle; + + KeyboardTheme get keyboardTheme; + + PinCodeTheme get pinCodeTheme; + + SupportPageTheme get supportPageTheme; + + ExchangePageTheme get exchangePageTheme; + + NewWalletTheme get newWalletTheme; + + BalancePageTheme get balancePageTheme; + + AddressTheme get addressTheme; + + CakeMenuTheme get menuTheme; + + FilterTheme get filterTheme; + + WalletListTheme get walletListTheme; + + InfoTheme get infoTheme; + + PickerTheme get pickerTheme; + + AlertTheme get alertTheme; + + OrderTheme get orderTheme; + + SendPageTheme get sendPageTheme; + + SeedWidgetTheme get seedWidgetTheme; + + PlaceholderTheme get placeholderTheme; + + TransactionTradeTheme get transactionTradeTheme; + + CakeTextTheme get cakeTextTheme; + + AccountListTheme get accountListTheme; + + ReceivePageTheme get receivePageTheme; + + QRCodeTheme get qrCodeTheme; + + ThemeData get themeData => generatedThemeData.copyWith( + primaryColor: primaryColor, + cardColor: containerColor, + dialogBackgroundColor: dialogBackgroundColor, + extensions: [ + dashboardPageTheme, + scrollbarTheme, + syncIndicatorStyle, + keyboardTheme, + pinCodeTheme, + supportPageTheme, + exchangePageTheme, + newWalletTheme, + balancePageTheme, + addressTheme, + menuTheme, + filterTheme, + walletListTheme, + infoTheme, + pickerTheme, + alertTheme, + orderTheme, + sendPageTheme, + seedWidgetTheme, + placeholderTheme, + transactionTradeTheme, + cakeTextTheme, + accountListTheme, + receivePageTheme, + qrCodeTheme, + ], + scrollbarTheme: generatedThemeData.scrollbarTheme.copyWith( + thumbColor: MaterialStateProperty.all(scrollbarTheme.thumbColor), + trackColor: MaterialStateProperty.all(scrollbarTheme.trackColor), + radius: Radius.circular(3), + thickness: MaterialStateProperty.all(6), + thumbVisibility: MaterialStateProperty.all(true), + crossAxisMargin: 6), + appBarTheme: generatedThemeData.appBarTheme.copyWith( + titleTextStyle: TextStyle(color: cakeTextTheme.titleColor))); +} diff --git a/lib/themes/theme_list.dart b/lib/themes/theme_list.dart index 941e23f82..cb65dc2b9 100644 --- a/lib/themes/theme_list.dart +++ b/lib/themes/theme_list.dart @@ -1,14 +1,36 @@ import 'package:cake_wallet/themes/bright_theme.dart'; import 'package:cake_wallet/themes/dark_theme.dart'; import 'package:cake_wallet/themes/light_theme.dart'; +import 'package:cake_wallet/themes/monero_light_theme.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:cake_wallet/themes/matrix_green_theme.dart'; +import 'package:cake_wallet/themes/bitcoin_dark_theme.dart'; +import 'package:cake_wallet/themes/bitcoin_light_theme.dart'; +import 'package:cake_wallet/themes/high_contrast_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; class ThemeList { - static final all = [brightTheme, lightTheme, darkTheme]; + static final all = [ + brightTheme, + lightTheme, + darkTheme, + moneroDarkTheme, + moneroLightTheme, + matrixGreenTheme, + bitcoinDarkTheme, + bitcoinLightTheme, + highContrastTheme + ]; static final lightTheme = LightTheme(raw: 0); static final brightTheme = BrightTheme(raw: 1); static final darkTheme = DarkTheme(raw: 2); + static final moneroDarkTheme = MoneroDarkTheme(raw: 3); + static final moneroLightTheme = MoneroLightTheme(raw: 4); + static final matrixGreenTheme = MatrixGreenTheme(raw: 5); + static final bitcoinDarkTheme = BitcoinDarkTheme(raw: 6); + static final bitcoinLightTheme = BitcoinLightTheme(raw: 7); + static final highContrastTheme = HighContrastTheme(raw: 8); static ThemeBase deserialize({required int raw}) { switch (raw) { @@ -18,8 +40,21 @@ class ThemeList { return brightTheme; case 2: return darkTheme; + case 3: + return moneroDarkTheme; + case 4: + return moneroLightTheme; + case 5: + return matrixGreenTheme; + case 6: + return bitcoinDarkTheme; + case 7: + return bitcoinLightTheme; + case 8: + return highContrastTheme; default: - throw Exception('Unexpected token raw: $raw for deserialization of ThemeBase'); + throw Exception( + 'Unexpected token raw: $raw for deserialization of ThemeBase'); } } } \ No newline at end of file diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 63905a94b..573ad120c 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -666,6 +666,12 @@ "balance_page": "صفحة التوازن", "share": "يشارك", "slidable": "قابل للانزلاق", + "monero_dark_theme": "موضوع مونيرو الظلام", + "bitcoin_dark_theme": "موضوع البيتكوين الظلام", + "bitcoin_light_theme": "موضوع البيتكوين الخفيفة", + "high_contrast_theme": "موضوع عالي التباين", + "matrix_green_dark_theme": "موضوع ماتريكس الأخضر الداكن", + "monero_light_theme": " ضوء مونيرو", "etherscan_history": "Etherscan تاريخ", "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", "template_name": "اسم القالب", @@ -675,4 +681,4 @@ "support_description_guides": "توثيق ودعم القضايا المشتركة", "support_title_other_links": "روابط دعم أخرى", "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى" -} \ No newline at end of file +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 5563f0c20..d6ddaf5a6 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -662,6 +662,12 @@ "balance_page": "Страница за баланс", "share": "Дял", "slidable": "Плъзгащ се", + "monero_dark_theme": "Тъмна тема Monero", + "bitcoin_dark_theme": "Тъмна тема за биткойн", + "bitcoin_light_theme": "Лека биткойн тема", + "high_contrast_theme": "Тема с висок контраст", + "matrix_green_dark_theme": "Зелена тъмна тема Matrix", + "monero_light_theme": "Лека тема Monero", "etherscan_history": "История на Etherscan", "manage_nodes": "Управление на възли", "template_name": "Име на шаблон", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index b528d6237..42b69d87a 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -662,6 +662,12 @@ "balance_page": "Stránka zůstatku", "share": "Podíl", "slidable": "Posuvné", + "monero_dark_theme": "Tmavé téma Monero", + "bitcoin_dark_theme": "Tmavé téma bitcoinů", + "bitcoin_light_theme": "Světlé téma bitcoinů", + "high_contrast_theme": "Téma s vysokým kontrastem", + "matrix_green_dark_theme": "Tmavé téma Matrix Green", + "monero_light_theme": "Světlé téma Monero", "manage_nodes": "Spravovat uzly", "etherscan_history": "Historie Etherscanu", "template_name": "Název šablony", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 211708c28..12d03d079 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "TOTP einrichten (empfohlen)", "disable_buy": "Kaufaktion deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", + "monero_dark_theme": "Dunkles Monero-Thema", + "bitcoin_dark_theme": "Dunkles Bitcoin-Thema", + "bitcoin_light_theme": "Bitcoin Light-Thema", + "high_contrast_theme": "Kontrastreiches Thema", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "monero_light_theme": "Monero Light-Thema", "cake_2fa_preset" : "Kuchen 2FA-Voreinstellung", "narrow": "Eng", "normal": "Normal", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4de56de80..3d1ea44fa 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "Set up TOTP (Recommended)", "disable_buy": "Disable buy action", "disable_sell": "Disable sell action", + "monero_dark_theme": "Monero Dark Theme", + "bitcoin_dark_theme": "Bitcoin Dark Theme", + "bitcoin_light_theme": "Bitcoin Light Theme", + "high_contrast_theme": "High Contrast Theme", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "monero_light_theme": "Monero Light Theme", "cake_2fa_preset" : "Cake 2FA Preset", "narrow": "Narrow", "normal": "Normal", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7910e8515..1faa6d78c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "Configurar TOTP (Recomendado)", "disable_buy": "Desactivar acción de compra", "disable_sell": "Desactivar acción de venta", + "monero_dark_theme": "Tema oscuro de Monero", + "bitcoin_dark_theme": "Tema oscuro de Bitcoin", + "bitcoin_light_theme": "Tema de la luz de Bitcoin", + "high_contrast_theme": "Tema de alto contraste", + "matrix_green_dark_theme": "Matrix verde oscuro tema", + "monero_light_theme": "Tema ligero de Monero", "cake_2fa_preset" : "Pastel 2FA preestablecido", "narrow": "Angosto", "normal": "Normal", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 240e5821e..548f74192 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "Configurer TOTP (recommandé)", "disable_buy": "Désactiver l'action d'achat", "disable_sell": "Désactiver l'action de vente", + "monero_dark_theme": "Thème sombre Monero", + "bitcoin_dark_theme": "Thème sombre Bitcoin", + "bitcoin_light_theme": "Thème léger Bitcoin", + "high_contrast_theme": "Thème à contraste élevé", + "matrix_green_dark_theme": "Thème Matrix Green Dark", + "monero_light_theme": "Thème de lumière Monero", "cake_2fa_preset" : "Gâteau 2FA prédéfini", "narrow": "Étroit", "normal": "Normal", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 5a232be2d..20ae66c33 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -612,6 +612,12 @@ "prevent_screenshots": "Fada lambobi da jarrabobi na kayan lambobi", "disable_buy": "Kashe alama", "disable_sell": "Kashe karbuwa", + "monero_dark_theme": "Monero Dark Jigo", + "bitcoin_dark_theme": "Bitcoin Dark Jigo", + "bitcoin_light_theme": "Jigon Hasken Bitcoin", + "high_contrast_theme": "Babban Jigon Kwatance", + "matrix_green_dark_theme": "Matrix Green Dark Jigo", + "monero_light_theme": "Jigon Hasken Monero", "cake_2fa_preset" : "Cake 2FA saiti", "narrow": "kunkuntar", "normal": "Na al'ada", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f60bf7180..afbd3bb47 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "टीओटीपी सेट अप करें (अनुशंसित)", "disable_buy": "खरीद कार्रवाई अक्षम करें", "disable_sell": "बेचने की कार्रवाई अक्षम करें", + "monero_dark_theme": "मोनेरो डार्क थीम", + "bitcoin_dark_theme": "बिटकॉइन डार्क थीम", + "bitcoin_light_theme": "बिटकॉइन लाइट थीम", + "high_contrast_theme": "उच्च कंट्रास्ट थीम", + "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", + "monero_light_theme": "मोनेरो लाइट थीम", "cake_2fa_preset" : "केक 2एफए प्रीसेट", "narrow": "सँकरा", "normal": "सामान्य", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 1b6592102..a014cf8f8 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -634,6 +634,12 @@ "setup_totp_recommended": "Postavite TOTP (preporučeno)", "disable_buy": "Onemogući kupnju", "disable_sell": "Onemogući akciju prodaje", + "monero_dark_theme": "Monero tamna tema", + "bitcoin_dark_theme": "Bitcoin Tamna tema", + "bitcoin_light_theme": "Bitcoin Light Theme", + "high_contrast_theme": "Tema visokog kontrasta", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "monero_light_theme": "Monero lagana tema", "cake_2fa_preset" : "Cake 2FA Preset", "narrow": "Usko", "normal": "Normalno", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 313d0a358..1011a3c6b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -658,6 +658,12 @@ "balance_page": "Halaman Saldo", "share": "Membagikan", "slidable": "Dapat digeser", + "monero_dark_theme": "Tema Gelap Monero", + "bitcoin_dark_theme": "Tema Gelap Bitcoin", + "bitcoin_light_theme": "Tema Cahaya Bitcoin", + "high_contrast_theme": "Tema Kontras Tinggi", + "matrix_green_dark_theme": "Tema Matrix Green Dark", + "monero_light_theme": "Tema Cahaya Monero", "manage_nodes": "Kelola node", "etherscan_history": "Sejarah Etherscan", "template_name": "Nama Templat", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a1cdc676a..e327d7c6d 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -670,6 +670,12 @@ "balance_page": "Pagina di equilibrio", "share": "Condividere", "slidable": "Scorrevole", + "monero_dark_theme": "Tema scuro di Monero", + "bitcoin_dark_theme": "Tema oscuro di Bitcoin", + "bitcoin_light_theme": "Tema luce Bitcoin", + "high_contrast_theme": "Tema ad alto contrasto", + "matrix_green_dark_theme": "Tema Matrix verde scuro", + "monero_light_theme": "Tema leggero Monero", "manage_nodes": "Gestisci i nodi", "etherscan_history": "Storia Etherscan", "template_name": "Nome modello", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 787876204..8d7b2f601 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -670,6 +670,12 @@ "balance_page": "残高ページ", "share": "共有", "slidable": "スライド可能", + "monero_dark_theme": "モネロダークテーマ", + "bitcoin_dark_theme": "ビットコインダークテーマ", + "bitcoin_light_theme": "ビットコインライトテーマ", + "high_contrast_theme": "ハイコントラストテーマ", + "matrix_green_dark_theme": "マトリックスグリーンダークテーマ", + "monero_light_theme": "モネロ ライト テーマ", "manage_nodes": "ノードの管理", "etherscan_history": "イーサスキャンの歴史", "template_name": "テンプレート名", @@ -679,4 +685,4 @@ "support_description_guides": "一般的な問題のドキュメントとサポート", "support_title_other_links": "その他のサポートリンク", "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください" -} \ No newline at end of file +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 76014f54b..16422319d 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -670,6 +670,12 @@ "balance_page": "잔액 페이지", "share": "공유하다", "slidable": "슬라이딩 가능", + "monero_dark_theme": "모네로 다크 테마", + "bitcoin_dark_theme": "비트코인 다크 테마", + "bitcoin_light_theme": "비트코인 라이트 테마", + "high_contrast_theme": "고대비 테마", + "matrix_green_dark_theme": "매트릭스 그린 다크 테마", + "monero_light_theme": "모네로 라이트 테마", "manage_nodes": "노드 관리", "etherscan_history": "이더스캔 역사", "template_name": "템플릿 이름", @@ -679,4 +685,4 @@ "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", "support_title_other_links": "다른 지원 링크", "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오." -} \ No newline at end of file +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index b3ba2a7dd..0a599c16a 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -668,6 +668,12 @@ "balance_page": "လက်ကျန်စာမျက်နှာ", "share": "မျှဝေပါ။", "slidable": "လျှောချနိုင်သည်။", + "monero_dark_theme": "Monero Dark အပြင်အဆင်", + "bitcoin_dark_theme": "Bitcoin Dark Theme", + "bitcoin_light_theme": "Bitcoin Light အပြင်အဆင်", + "high_contrast_theme": "အလင်းအမှောင် မြင့်မားသော အပြင်အဆင်", + "matrix_green_dark_theme": "Matrix Green Dark အပြင်အဆင်", + "monero_light_theme": "Monero Light အပြင်အဆင်", "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", "etherscan_history": "Etherscan သမိုင်း", "template_name": "နမူနာပုံစံ", @@ -677,4 +683,4 @@ "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ" -} \ No newline at end of file +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index aca33d051..00eaf4dc8 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -670,6 +670,12 @@ "balance_page": "Saldo pagina", "share": "Deel", "slidable": "Verschuifbaar", + "monero_dark_theme": "Monero donker thema", + "bitcoin_dark_theme": "Bitcoin donker thema", + "bitcoin_light_theme": "Bitcoin Light-thema", + "high_contrast_theme": "Thema met hoog contrast", + "matrix_green_dark_theme": "Matrix groen donker thema", + "monero_light_theme": "Monero Light-thema", "manage_nodes": "Beheer knooppunten", "etherscan_history": "Etherscan-geschiedenis", "template_name": "Sjabloonnaam", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 56871f242..593f5ae19 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -670,6 +670,12 @@ "balance_page": "Strona salda", "share": "Udział", "slidable": "Przesuwne", + "monero_dark_theme": "Ciemny motyw Monero", + "bitcoin_dark_theme": "Ciemny motyw Bitcoina", + "bitcoin_light_theme": "Lekki motyw Bitcoin", + "high_contrast_theme": "Motyw o wysokim kontraście", + "matrix_green_dark_theme": "Matrix Zielony ciemny motyw", + "monero_light_theme": "Lekki motyw Monero", "manage_nodes": "Zarządzaj węzłami", "etherscan_history": "Historia Etherscanu", "template_name": "Nazwa szablonu", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7cccc3c9e..551c30d01 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -669,6 +669,12 @@ "balance_page": "Página de saldo", "share": "Compartilhar", "slidable": "Deslizável", + "monero_dark_theme": "Monero Tema Escuro", + "bitcoin_dark_theme": "Tema escuro Bitcoin", + "bitcoin_light_theme": "Tema claro de bitcoin", + "high_contrast_theme": "Tema de alto contraste", + "matrix_green_dark_theme": "Tema escuro verde matrix", + "monero_light_theme": "Monero Light Theme", "manage_nodes": "Gerenciar nós", "etherscan_history": "história Etherscan", "template_name": "Nome do modelo", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 40f9447ba..0d4c39570 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -670,6 +670,12 @@ "balance_page": "Страница баланса", "share": "Делиться", "slidable": "Скользящий", + "monero_dark_theme": "Темная тема Monero", + "bitcoin_dark_theme": "Биткойн Темная тема", + "bitcoin_light_theme": "Легкая биткойн-тема", + "high_contrast_theme": "Высококонтрастная тема", + "matrix_green_dark_theme": "Матрица Зеленая Темная Тема", + "monero_light_theme": "Светлая тема Monero", "manage_nodes": "Управление узлами", "etherscan_history": "История Эфириума", "template_name": "Имя Шаблона", @@ -679,4 +685,4 @@ "support_description_guides": "Документация и поддержка общих вопросов", "support_title_other_links": "Другие ссылки на поддержку", "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов" -} \ No newline at end of file +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 9ffd7af11..6522bc3d9 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -668,6 +668,12 @@ "balance_page": "หน้ายอดคงเหลือ", "share": "แบ่งปัน", "slidable": "เลื่อนได้", + "monero_dark_theme": "ธีมมืด Monero", + "bitcoin_dark_theme": "ธีมมืด Bitcoin", + "bitcoin_light_theme": "ธีมแสง Bitcoin", + "high_contrast_theme": "ธีมความคมชัดสูง", + "matrix_green_dark_theme": "ธีมเมทริกซ์สีเขียวเข้ม", + "monero_light_theme": "ธีมแสง Monero", "manage_nodes": "จัดการโหนด", "etherscan_history": "ประวัติอีเธอร์สแกน", "template_name": "ชื่อแม่แบบ", @@ -677,4 +683,4 @@ "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ" -} \ No newline at end of file +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index dedf7cf28..bb87595a4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -669,6 +669,12 @@ "balance_page": "Bakiye Sayfası", "share": "Paylaşmak", "slidable": "kaydırılabilir", + "monero_dark_theme": "Monero Koyu Tema", + "bitcoin_dark_theme": "Bitcoin Karanlık Teması", + "bitcoin_light_theme": "Bitcoin Hafif Tema", + "high_contrast_theme": "Yüksek Kontrastlı Tema", + "matrix_green_dark_theme": "Matrix Yeşil Koyu Tema", + "monero_light_theme": "Monero Hafif Tema", "manage_nodes": "Düğümleri yönet", "etherscan_history": "Etherscan geçmişi", "template_name": "şablon adı", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f8a2777e5..d6e121279 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -670,6 +670,12 @@ "balance_page": "Сторінка балансу", "share": "Поділіться", "slidable": "Розсувний", + "monero_dark_theme": "Темна тема Monero", + "bitcoin_dark_theme": "Темна тема Bitcoin", + "bitcoin_light_theme": "Світла тема Bitcoin", + "high_contrast_theme": "Тема високої контрастності", + "matrix_green_dark_theme": "Зелена темна тема Matrix", + "monero_light_theme": "Легка тема Monero", "manage_nodes": "Керуйте вузлами", "etherscan_history": "Історія Etherscan", "template_name": "Назва шаблону", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 5eed0d35b..a24545501 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -662,6 +662,12 @@ "balance_page": "بیلنس صفحہ", "share": "بانٹیں", "slidable": "سلائیڈ ایبل", + "monero_dark_theme": "مونیرو ڈارک تھیم", + "bitcoin_dark_theme": "بٹ کوائن ڈارک تھیم", + "bitcoin_light_theme": "بٹ کوائن لائٹ تھیم", + "high_contrast_theme": "ہائی کنٹراسٹ تھیم", + "matrix_green_dark_theme": "میٹرکس گرین ڈارک تھیم", + "monero_light_theme": "مونیرو لائٹ تھیم", "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", "template_name": "ٹیمپلیٹ کا نام", @@ -671,4 +677,4 @@ "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", "support_title_other_links": "دوسرے سپورٹ لنکس", "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں" -} \ No newline at end of file +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index c99b00ebd..d406aec86 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -672,5 +672,11 @@ "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", - "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran" -} \ No newline at end of file + "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran", + "monero_dark_theme": "Monero Dudu Akori", + "bitcoin_dark_theme": "Bitcoin Dark Akori", + "bitcoin_light_theme": "Bitcoin Light Akori", + "high_contrast_theme": "Akori Iyatọ giga", + "matrix_green_dark_theme": "Matrix Green Dark Akori", + "monero_light_theme": "Monero Light Akori" +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index dc1cfd139..8e04bf2bc 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -677,5 +677,11 @@ "support_title_guides": "蛋糕钱包指南", "support_description_guides": "对常见问题的文档和支持", "support_title_other_links": "其他支持链接", - "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴" -} \ No newline at end of file + "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴", + "monero_dark_theme": "门罗币深色主题", + "bitcoin_dark_theme": "比特币黑暗主题", + "bitcoin_light_theme": "比特币浅色主题", + "high_contrast_theme": "高对比度主题", + "matrix_green_dark_theme": "矩阵绿暗主题", + "monero_light_theme": "门罗币浅色主题" +} From 9ddab2b4723e94251887d7567ac6367503772be7 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Fri, 18 Aug 2023 18:37:17 +0300 Subject: [PATCH 04/18] Flutter update (#1048) * Update Flutter Update packages * Fix localization issues Fix UI issues Update old packages Update workflow Update how to build guide * Additional UI fixes for merged conflicts --- .github/workflows/cache_dependencies.yml | 2 +- .github/workflows/pr_test_build.yml | 2 +- android/build.gradle | 2 +- cw_bitcoin/pubspec.yaml | 6 +- cw_core/pubspec.yaml | 4 +- cw_ethereum/lib/ethereum_client.dart | 10 +- cw_ethereum/pubspec.yaml | 5 +- cw_haven/pubspec.yaml | 4 +- cw_monero/pubspec.yaml | 4 +- cw_shared_external/pubspec.yaml | 2 +- howto-build-android.md | 6 +- lib/core/generate_wallet_password.dart | 1 - lib/locales/hausa_intl.dart | 18 ++ lib/locales/yoruba_intl.dart | 18 ++ lib/src/screens/dashboard/dashboard_page.dart | 4 +- .../dashboard/widgets/address_page.dart | 19 +- lib/src/screens/exchange/exchange_page.dart | 3 +- .../restore/widgets/restore_button.dart | 25 +- lib/src/screens/seed/pre_seed_page.dart | 4 +- lib/src/screens/send/send_page.dart | 27 +- lib/src/screens/send/widgets/send_card.dart | 13 +- .../widgets/settings_choices_cell.dart | 2 +- .../screens/wallet_list/wallet_list_page.dart | 233 +++++++++--------- lib/src/widgets/standard_list.dart | 16 +- pubspec_base.yaml | 13 +- tool/append_translation.dart | 132 +++++----- tool/localization/localization_constants.dart | 18 ++ 27 files changed, 311 insertions(+), 282 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 4d2dc136c..d57281447 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -18,7 +18,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: '3.3.x' + flutter-version: '3.10.x' channel: stable - name: Install package dependencies diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 47378eef5..7f70ce755 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -28,7 +28,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: '3.7.x' + flutter-version: '3.10.x' channel: stable - name: Install package dependencies diff --git a/android/build.gradle b/android/build.gradle index 692e8dfb1..bd4ebd770 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -27,6 +27,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 481a41ac5..dae0af39b 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -13,16 +13,16 @@ dependencies: flutter: sdk: flutter path_provider: ^2.0.11 - http: ^0.13.4 + http: ^1.1.0 mobx: ^2.0.7+4 flutter_mobx: ^2.0.6+1 - intl: ^0.17.0 + intl: ^0.18.0 cw_core: path: ../cw_core bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v2 + ref: cake-update-v3 rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index e33aeb803..9dcb7eaba 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -12,12 +12,12 @@ environment: dependencies: flutter: sdk: flutter - http: ^0.13.4 + http: ^1.1.0 file: ^6.1.4 path_provider: ^2.0.11 mobx: ^2.0.7+4 flutter_mobx: ^2.0.6+1 - intl: ^0.17.0 + intl: ^0.18.0 encrypt: ^5.0.1 dev_dependencies: diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index f00e2ef7b..7eba43aa7 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -9,7 +9,7 @@ import 'package:cw_ethereum/pending_ethereum_transaction.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart'; import 'package:web3dart/web3dart.dart'; -import 'package:web3dart/contracts/erc20.dart'; +import 'package:erc20/erc20.dart'; import 'package:cw_core/node.dart'; import 'package:cw_ethereum/ethereum_transaction_priority.dart'; import 'package:cw_ethereum/.secrets.g.dart' as secrets; @@ -72,7 +72,7 @@ class EthereumClient { to: EthereumAddress.fromHex(toAddress), maxGas: gas, gasPrice: price, - maxPriorityFeePerGas: EtherAmount.fromUnitAndValue(EtherUnit.gwei, priority.tip), + maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), value: _isEthereum ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), ); @@ -83,7 +83,7 @@ class EthereumClient { if (_isEthereum) { _sendTransaction = () async => await sendTransaction(signedTransaction); } else { - final erc20 = Erc20( + final erc20 = ERC20( client: _client!, address: EthereumAddress.fromHex(contractAddress!), ); @@ -153,7 +153,7 @@ I/flutter ( 4474): Gas Used: 53000 Future<ERC20Balance> fetchERC20Balances( EthereumAddress userAddress, String contractAddress) async { - final erc20 = Erc20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); final balance = await erc20.balanceOf(userAddress); int exponent = (await erc20.decimals()).toInt(); @@ -163,7 +163,7 @@ I/flutter ( 4474): Gas Used: 53000 Future<Erc20Token?> getErc20Token(String contractAddress) async { try { - final erc20 = Erc20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); final name = await erc20.name(); final symbol = await erc20.symbol(); final decimal = await erc20.decimals(); diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index cb1046d5a..5d19589f3 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -12,13 +12,14 @@ environment: dependencies: flutter: sdk: flutter - web3dart: 2.3.5 + web3dart: ^2.7.1 + erc20: ^1.0.1 mobx: ^2.0.7+4 bip39: ^1.0.6 bip32: ^2.0.0 ed25519_hd_key: ^2.2.0 hex: ^0.2.0 - http: ^0.13.4 + http: ^1.1.0 shared_preferences: ^2.0.15 cw_core: path: ../cw_core diff --git a/cw_haven/pubspec.yaml b/cw_haven/pubspec.yaml index 7a5ac6aa4..c215ab779 100644 --- a/cw_haven/pubspec.yaml +++ b/cw_haven/pubspec.yaml @@ -13,11 +13,11 @@ dependencies: flutter: sdk: flutter ffi: ^2.0.1 - http: ^0.13.4 + http: ^1.1.0 path_provider: ^2.0.11 mobx: ^2.0.7+4 flutter_mobx: ^2.0.6+1 - intl: ^0.17.0 + intl: ^0.18.0 cw_core: path: ../cw_core diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index 066a0d4c3..cf2993ef3 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -13,11 +13,11 @@ dependencies: flutter: sdk: flutter ffi: ^2.0.1 - http: ^0.13.4 + http: ^1.1.0 path_provider: ^2.0.11 mobx: ^2.0.7+4 flutter_mobx: ^2.0.6+1 - intl: ^0.17.0 + intl: ^0.18.0 encrypt: ^5.0.1 cw_core: path: ../cw_core diff --git a/cw_shared_external/pubspec.yaml b/cw_shared_external/pubspec.yaml index b9a8ca1e0..71d5fcd5a 100644 --- a/cw_shared_external/pubspec.yaml +++ b/cw_shared_external/pubspec.yaml @@ -5,7 +5,7 @@ author: Cake Walelt homepage: https://cakewallet.com environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" flutter: ">=1.20.0" dependencies: diff --git a/howto-build-android.md b/howto-build-android.md index d37f1b417..a2a4e4d9f 100644 --- a/howto-build-android.md +++ b/howto-build-android.md @@ -5,10 +5,10 @@ The following are the system requirements to build CakeWallet for your Android device. ``` -Ubuntu >= 16.04 +Ubuntu >= 20.04 Android SDK 29 or higher (better to have the latest one 33) Android NDK 17c -Flutter 3.7.x +Flutter 3.10.x or earlier ``` ## Building CakeWallet on Android @@ -66,7 +66,7 @@ Verify that the Android toolchain, Flutter, and Android Studio have been correct The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding. ``` Doctor summary (to see all details, run flutter doctor -v): -[✓] Flutter (Channel stable, 3.7.x, on Linux, locale en_US.UTF-8) +[✓] Flutter (Channel stable, 3.10.x, on Linux, locale en_US.UTF-8) [✓] Android toolchain - develop for Android devices (Android SDK version 29 or higher) [✓] Android Studio (version 4.0 or higher) ``` diff --git a/lib/core/generate_wallet_password.dart b/lib/core/generate_wallet_password.dart index c9a9fac57..93803dd9d 100644 --- a/lib/core/generate_wallet_password.dart +++ b/lib/core/generate_wallet_password.dart @@ -1,4 +1,3 @@ -import 'package:uuid/uuid.dart'; import 'package:cw_core/key.dart'; String generateWalletPassword() { diff --git a/lib/locales/hausa_intl.dart b/lib/locales/hausa_intl.dart index 35a13cdea..749d39a4d 100644 --- a/lib/locales/hausa_intl.dart +++ b/lib/locales/hausa_intl.dart @@ -736,6 +736,21 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations { @override String get keyboardKeySpace => 'Space'; + + @override + String get bottomSheetLabel => "Bottom Sheet"; + + @override + String get currentDateLabel => "Current Date"; + + @override + String get keyboardKeyShift => "Shift"; + + @override + String get scrimLabel => "Scrim"; + + @override + String get scrimOnTapHintRaw => "Scrip on Tap"; } /// Cupertino Support @@ -937,4 +952,7 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations { static const LocalizationsDelegate<CupertinoLocalizations> delegate = _HaCupertinoLocalizationsDelegate(); + + @override + String get noSpellCheckReplacementsLabel => ""; } diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index 974a3d22c..889c21cb7 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -736,6 +736,21 @@ String get keyboardKeyMetaWindows => 'Windows'; @override String get keyboardKeySpace => 'Space'; + + @override + String get bottomSheetLabel => "Bottom Sheet"; + + @override + String get currentDateLabel => "Current Date"; + + @override + String get keyboardKeyShift => "Shift"; + + @override + String get scrimLabel => "Scrim"; + + @override + String get scrimOnTapHintRaw => "Scrip on Tap"; } /// Cupertino Support @@ -937,4 +952,7 @@ String get todayLabel => 'Oyọ'; static const LocalizationsDelegate<CupertinoLocalizations> delegate = _YoCupertinoLocalizationsDelegate(); + + @override + String get noSpellCheckReplacementsLabel => ""; } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index a1db0860b..68f5ca9aa 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -13,7 +13,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -109,7 +108,7 @@ class _DashboardPageView extends BasePage { Widget trailing(BuildContext context) { final menuButton = Image.asset( 'assets/images/menu.png', - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor, + color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor, ); return Container( @@ -128,6 +127,7 @@ class _DashboardPageView extends BasePage { final DashboardViewModel dashboardViewModel; final WalletAddressListViewModel addressListViewModel; + int get initialPage => dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0; ObservableList<Widget> pages = ObservableList<Widget>(); bool _isEffectsInstalled = false; diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 9d97c4e4f..45ac3982e 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; @@ -64,14 +63,6 @@ class AddressPage extends BasePage { @override Widget? leading(BuildContext context) { - final _backButton = Icon( - Icons.arrow_back_ios, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, - size: 16, - ); - final _closeButton = - currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; return MergeSemantics( @@ -119,11 +110,7 @@ class AddressPage extends BasePage { context: context, ); }, - icon: Icon( - Icons.share, - size: 20, - color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!, - ), + icon: Icon(Icons.share, size: 20, color: pageIconColor(context)), ), ); } @@ -160,10 +147,10 @@ class AddressPage extends BasePage { return KeyboardActions( autoScroll: false, disableScroll: true, - tapOutsideToDismiss: true, + tapOutsideBehavior: TapOutsideBehavior.translucentDismiss, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context).accentTextTheme.bodyLarge!.backgroundColor!, + keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor, nextFocus: false, actions: [ KeyboardActionsItem( diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 98929a692..972fa0399 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart'; -import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/debounce.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -250,7 +249,7 @@ class ExchangePage extends BasePage { } } }, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, isDisabled: exchangeViewModel.selectedProviders.isEmpty, isLoading: exchangeViewModel.tradeState is TradeIsCreating)), diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index 221dc37a2..c196de059 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; @@ -24,7 +25,7 @@ class RestoreButton extends StatelessWidget { alignment: Alignment.topLeft, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).accentTextTheme.bodySmall!.color!, + color: Theme.of(context).cardColor, ), child: Row( mainAxisSize: MainAxisSize.max, @@ -43,24 +44,22 @@ class RestoreButton extends StatelessWidget { Text( title, style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .titleLarge! - .color!), + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, + ), ), Padding( padding: EdgeInsets.only(top: 5), child: Text( description, style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .primaryTextTheme - .labelSmall! - .color!), + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context) + .extension<TransactionTradeTheme>()! + .detailsTitlesColor, + ), ), ) ], diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index a2916d642..a73e7bbff 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -6,8 +6,6 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; class PreSeedPage extends BasePage { @@ -62,7 +60,7 @@ class PreSeedPage extends BasePage { onPressed: () => Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true), text: S.of(context).pre_seed_button_text, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white) ], ), diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index dab78f3ef..4a2559902 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -208,14 +208,8 @@ class SendPage extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context) - .primaryTextTheme! - .displaySmall! - .backgroundColor!, - activeDotColor: Theme.of(context) - .primaryTextTheme! - .displayMedium! - .backgroundColor!), + dotColor: Theme.of(context).extension<SendPageTheme>()!.indicatorDotColor, + activeDotColor: Theme.of(context).extension<SendPageTheme>()!.templateBackgroundColor), ) : Offstage(); }, @@ -340,10 +334,7 @@ class SendPage extends BasePage { text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})', color: Colors.transparent, - textColor: Theme.of(context) - .accentTextTheme! - .displaySmall! - .decorationColor!, + textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor, ))), if (sendViewModel.sendTemplateViewModel.hasMultiRecipient) Padding( @@ -358,15 +349,9 @@ class SendPage extends BasePage { }, text: S.of(context).add_receiver, color: Colors.transparent, - textColor: Theme.of(context) - .accentTextTheme! - .displaySmall! - .decorationColor!, + textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor, isDottedBorder: true, - borderColor: Theme.of(context) - .primaryTextTheme! - .displaySmall! - .decorationColor!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.templateDottedBorderColor, )), Observer( builder: (_) { @@ -387,7 +372,7 @@ class SendPage extends BasePage { item.cryptoAmount.isEmpty) .toList(); - if (notValidItems.isNotEmpty ?? false) { + if (notValidItems.isNotEmpty) { showErrorValidationAlert(context); return; } diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 5e5bf44d3..4b2cddeb7 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -167,8 +167,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S AddressTextFieldOption.qrCode, AddressTextFieldOption.addressBook ], - buttonColor: Theme.of(context).primaryTextTheme.headlineMedium!.color!, - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + buttonColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), hintStyle: TextStyle( @@ -403,14 +403,11 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S ), ), hintText: '0.00', - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .headlineSmall! - .decorationColor!, + color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor, fontWeight: FontWeight.w500, fontSize: 14), ), @@ -421,7 +418,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S controller: noteController, keyboardType: TextInputType.multiline, maxLines: null, - borderColor: Theme.of(context).primaryTextTheme.headlineSmall!.color!, + borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor, textStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), hintText: S.of(context).note_optional, diff --git a/lib/src/screens/settings/widgets/settings_choices_cell.dart b/lib/src/screens/settings/widgets/settings_choices_cell.dart index 4d4addb99..aea5ecbb9 100644 --- a/lib/src/screens/settings/widgets/settings_choices_cell.dart +++ b/lib/src/screens/settings/widgets/settings_choices_cell.dart @@ -59,7 +59,7 @@ class SettingsChoicesCell extends StatelessWidget { style: TextStyle( color: isSelected ? Colors.white - : Theme.of(context).primaryTextTheme.bodySmall!.color!, + : Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor, fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal, ), ), diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 2fcc491f0..fd7952628 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,10 +1,8 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:another_flushbar/flushbar.dart'; import 'package:flutter/material.dart'; @@ -66,106 +64,110 @@ class WalletListBodyState extends State<WalletListBody> { return Container( padding: EdgeInsets.only(top: 16), child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 20), - content: Container( - child: Observer( - builder: (_) => ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (_, index) => - Divider(color: Theme.of(context).colorScheme.background, height: 32), - itemCount: widget.walletListViewModel.wallets.length, - itemBuilder: (__, index) { - final wallet = widget.walletListViewModel.wallets[index]; - final currentColor = wallet.isCurrent - ? Theme.of(context) - .extension<WalletListTheme>()! - .createNewWalletButtonBackgroundColor - : Theme.of(context).colorScheme.background; - final row = GestureDetector( - onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), - child: Container( + contentPadding: EdgeInsets.only(bottom: 20), + content: Container( + child: Observer( + builder: (_) => ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (_, index) => + Divider(color: Theme.of(context).colorScheme.background, height: 32), + itemCount: widget.walletListViewModel.wallets.length, + itemBuilder: (__, index) { + final wallet = widget.walletListViewModel.wallets[index]; + final currentColor = wallet.isCurrent + ? Theme.of(context) + .extension<WalletListTheme>()! + .createNewWalletButtonBackgroundColor + : Theme.of(context).colorScheme.background; + final row = GestureDetector( + onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), + child: Container( + height: tileHeight, + width: double.infinity, + child: Row( + children: <Widget>[ + Container( height: tileHeight, - width: double.infinity, - child: Row( - children: <Widget>[ - Container( - height: tileHeight, - width: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topRight: Radius.circular(4), - bottomRight: Radius.circular(4)), - color: currentColor), - ), - Expanded( - child: Container( - height: tileHeight, - padding: EdgeInsets.only(left: 20, right: 20), - color: Theme.of(context).colorScheme.background, - alignment: Alignment.centerLeft, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: <Widget>[ - wallet.isEnabled - ? _imageFor(type: wallet.type) - : nonWalletTypeIcon, - SizedBox(width: 10), - Flexible( - child: Text( - wallet.name, - maxLines: null, - softWrap: true, - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .extension<CakeTextTheme>()! - .titleColor), - )) - ]), - ), - ), - ], - ), - )); - - return wallet.isCurrent - ? row - : Row(children: [ - Expanded(child: row), - GestureDetector( - onTap: () => Navigator.of(context).pushNamed(Routes.walletEdit, - arguments: [widget.walletListViewModel, wallet]), - child: Container( - padding: EdgeInsets.only(right: 20), - child: Center( - child: Container( - height: 40, - width: 44, - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context) - .extension<ReceivePageTheme>()! - .iconsBackgroundColor), - child: Icon( - Icons.edit, - size: 14, - color: Theme.of(context) - .extension<ReceivePageTheme>()! - .iconsColor, + width: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(4), bottomRight: Radius.circular(4)), + color: currentColor), + ), + Expanded( + child: Container( + height: tileHeight, + padding: EdgeInsets.only(left: 20, right: 20), + color: Theme.of(context).colorScheme.background, + alignment: Alignment.centerLeft, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + wallet.isEnabled ? _imageFor(type: wallet.type) : nonWalletTypeIcon, + SizedBox(width: 10), + Flexible( + child: Text( + wallet.name, + maxLines: null, + softWrap: true, + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + color: + Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), ), + ], + ), + ), + ), + ], + ), + ), + ); + + return wallet.isCurrent + ? row + : Row( + children: [ + Expanded(child: row), + GestureDetector( + onTap: () => Navigator.of(context).pushNamed(Routes.walletEdit, + arguments: [widget.walletListViewModel, wallet]), + child: Container( + padding: EdgeInsets.only(right: 20), + child: Center( + child: Container( + height: 40, + width: 44, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context) + .extension<ReceivePageTheme>()! + .iconsBackgroundColor, + ), + child: Icon( + Icons.edit, + size: 14, + color: + Theme.of(context).extension<ReceivePageTheme>()!.iconsColor, + ), + ), ), - ) - ]); - }), + ), + ), + ], + ); + }, ), ), - bottomSectionPadding: EdgeInsets.only(bottom: 24, right: 24, left: 24), - bottomSection: Column(children: <Widget>[ + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24, right: 24, left: 24), + bottomSection: Column( + children: <Widget>[ PrimaryImageButton( onPressed: () { //TODO(David): Find a way to optimize this @@ -199,29 +201,32 @@ class WalletListBodyState extends State<WalletListBody> { }, image: newWalletImage, text: S.of(context).wallet_list_create_new_wallet, - color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), SizedBox(height: 10.0), PrimaryImageButton( - onPressed: () { - if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { - widget.authService.authenticateAction( - context, - route: Routes.restoreOptions, - arguments: false, - conditionToDetermineIfToUse2FA: - widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, - ); - } else { - Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false); - } - }, - image: restoreWalletImage, - text: S.of(context).wallet_list_restore_wallet, - color: Theme.of(context).accentTextTheme.bodySmall!.color!, - textColor: Theme.of(context).primaryTextTheme.titleLarge!.color!) - ])), + onPressed: () { + if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { + widget.authService.authenticateAction( + context, + route: Routes.restoreOptions, + arguments: false, + conditionToDetermineIfToUse2FA: + widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, + ); + } else { + Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false); + } + }, + image: restoreWalletImage, + text: S.of(context).wallet_list_restore_wallet, + color: Theme.of(context).cardColor, + textColor: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor, + ) + ], + ), + ), ); } diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart index 530d3969c..c1fcae052 100644 --- a/lib/src/widgets/standard_list.dart +++ b/lib/src/widgets/standard_list.dart @@ -72,7 +72,10 @@ class SectionHeaderListRow extends StatelessWidget { Widget build(BuildContext context) => Column(children: [ StandardListSeparator(padding: EdgeInsets.only(left: 24)), Container( - width: double.infinity, height: 40, color: Theme.of(context).colorScheme.background), + width: double.infinity, + height: 40, + color: Theme.of(context).colorScheme.background, + ), //StandardListSeparator(padding: EdgeInsets.only(left: 24)) ]); } @@ -86,11 +89,14 @@ class StandardListSeparator extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + height: height, + padding: padding, + color: Theme.of(context).colorScheme.background, + child: Container( height: height, - padding: padding, - color: Theme.of(context).colorScheme.background, - child: Container( - height: height, color: Theme.of(context).primaryTextTheme.titleLarge?.backgroundColor)); + color: Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor, + ), + ); } } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index ce7d04b3f..51cfe4b26 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -3,14 +3,13 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - intl: ^0.17.0 + intl: ^0.18.0 url_launcher: ^6.1.4 qr_flutter: git: url: https://github.com/cake-tech/qr.flutter.git ref: cake-4.0.2 version: 4.0.2 - uuid: 3.0.6 shared_preferences: ^2.0.15 flutter_secure_storage: git: @@ -23,7 +22,7 @@ dependencies: yaml: ^3.1.1 #barcode_scan: any barcode_scan2: ^4.2.1 - http: ^0.13.4 + http: ^1.1.0 path_provider: ^2.0.11 mobx: ^2.1.4 flutter_mobx: ^2.0.6+5 @@ -53,7 +52,7 @@ dependencies: encrypt: ^5.0.1 crypto: ^3.0.2 # password: ^1.0.0 - basic_utils: ^4.3.0 + basic_utils: ^5.6.1 get_it: ^7.2.0 # connectivity: ^3.0.3 connectivity_plus: ^2.3.5 @@ -86,13 +85,13 @@ dependencies: bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v2 + ref: cake-update-v3 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.3.3 - logging: 1.1.1 + logging: ^1.2.0 mobx_codegen: ^2.1.1 build_resolvers: ^2.0.9 hive_generator: ^1.1.3 @@ -100,7 +99,7 @@ dev_dependencies: # check flutter_launcher_icons for usage pedantic: ^1.8.0 # replace https://github.com/dart-lang/lints#migrating-from-packagepedantic - translator: ^0.1.7 +# translator: ^0.1.7 flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/tool/append_translation.dart b/tool/append_translation.dart index e56ad89d6..080b2c5e7 100644 --- a/tool/append_translation.dart +++ b/tool/append_translation.dart @@ -1,66 +1,66 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:translator/translator.dart'; - -const defaultLang = "en"; -const langs = [ - "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", - "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", - "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) -]; -final translator = GoogleTranslator(); - -void main(List<String> args) async { - if (args.length != 2) { - throw Exception( - 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); - } - - final name = args.first; - final text = args.last; - - print('Appending "$name": "$text"'); - - for (var lang in langs) { - final fileName = getFileName(lang); - final translation = await getTranslation(text, lang); - - appendArbFile(fileName, name, translation); - } -} - -void appendArbFile(String fileName, String name, String text) { - final file = File(fileName); - final inputContent = file.readAsStringSync(); - final arbObj = json.decode(inputContent) as Map<String, dynamic>; - - if (arbObj.containsKey(name)) { - print("String $name already exists in $fileName!"); - return; - } - - arbObj.addAll({name: text}); - - final outputContent = json - .encode(arbObj) - .replaceAll('","', '",\n "') - .replaceAll('{"', '{\n "') - .replaceAll('"}', '"\n}') - .replaceAll('":"', '": "'); - - file.writeAsStringSync(outputContent); -} - - -Future<String> getTranslation(String text, String lang) async { - if (lang == defaultLang) return text; - return (await translator.translate(text, from: defaultLang, to: lang)).text; -} - -String getFileName(String lang) { - final shortLang = lang - .split("-") - .first; - return "./res/values/strings_$shortLang.arb"; -} +// import 'dart:convert'; +// import 'dart:io'; +// +// import 'package:translator/translator.dart'; +// +// const defaultLang = "en"; +// const langs = [ +// "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", +// "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", +// "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) +// ]; +// final translator = GoogleTranslator(); +// +// void main(List<String> args) async { +// if (args.length != 2) { +// throw Exception( +// 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); +// } +// +// final name = args.first; +// final text = args.last; +// +// print('Appending "$name": "$text"'); +// +// for (var lang in langs) { +// final fileName = getFileName(lang); +// final translation = await getTranslation(text, lang); +// +// appendArbFile(fileName, name, translation); +// } +// } +// +// void appendArbFile(String fileName, String name, String text) { +// final file = File(fileName); +// final inputContent = file.readAsStringSync(); +// final arbObj = json.decode(inputContent) as Map<String, dynamic>; +// +// if (arbObj.containsKey(name)) { +// print("String $name already exists in $fileName!"); +// return; +// } +// +// arbObj.addAll({name: text}); +// +// final outputContent = json +// .encode(arbObj) +// .replaceAll('","', '",\n "') +// .replaceAll('{"', '{\n "') +// .replaceAll('"}', '"\n}') +// .replaceAll('":"', '": "'); +// +// file.writeAsStringSync(outputContent); +// } +// +// +// Future<String> getTranslation(String text, String lang) async { +// if (lang == defaultLang) return text; +// return (await translator.translate(text, from: defaultLang, to: lang)).text; +// } +// +// String getFileName(String lang) { +// final shortLang = lang +// .split("-") +// .first; +// return "./res/values/strings_$shortLang.arb"; +// } diff --git a/tool/localization/localization_constants.dart b/tool/localization/localization_constants.dart index 0ccbd380b..326ff2c13 100644 --- a/tool/localization/localization_constants.dart +++ b/tool/localization/localization_constants.dart @@ -27,6 +27,24 @@ class S implements WidgetsLocalizations { GeneratedLocalizationsDelegate(); static S of(BuildContext context) => Localizations.of<S>(context, S)!; + + @override + String get reorderItemToStart => "reorderItemToStart"; + + @override + String get reorderItemToEnd => "reorderItemToEnd"; + + @override + String get reorderItemUp => "reorderItemUp"; + + @override + String get reorderItemDown => "reorderItemDown"; + + @override + String get reorderItemLeft => "reorderItemLeft"; + + @override + String get reorderItemRight => "reorderItemRight"; """; const part2 = """ From 5556d9ef965ad5c476aa32bf46f8710d77fd48ac Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Sat, 19 Aug 2023 00:55:18 +0300 Subject: [PATCH 05/18] Fix Ethereum network for anonpay invoice (#1051) --- lib/anonpay/anonpay_api.dart | 2 ++ lib/src/screens/receive/anonpay_invoice_page.dart | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/anonpay/anonpay_api.dart b/lib/anonpay/anonpay_api.dart index bc6abc6e2..e46499407 100644 --- a/lib/anonpay/anonpay_api.dart +++ b/lib/anonpay/anonpay_api.dart @@ -182,6 +182,8 @@ class AnonPayApi { switch (currency) { case CryptoCurrency.usdt: return CryptoCurrency.btc.title.toLowerCase(); + case CryptoCurrency.eth: + return 'ERC20'; default: return currency.tag != null ? _normalizeTag(currency.tag!) : 'Mainnet'; } diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index 606383faa..deda679c5 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -154,6 +154,7 @@ class AnonPayInvoicePage extends BasePage { ? S.of(context).create_invoice : S.of(context).create_donation_link, onPressed: () { + FocusScope.of(context).unfocus(); anonInvoicePageViewModel.setRequestParams( inputAmount: _amountController.text, inputName: _nameController.text, From ee586ab5148498da7d9bdbe2edd3c87e23a51be6 Mon Sep 17 00:00:00 2001 From: Rafael Saes <76502841+saltrafael@users.noreply.github.com> Date: Tue, 22 Aug 2023 15:49:37 -0300 Subject: [PATCH 06/18] Cw 470 additional theming fixes (#1052) * fix: revert theme order (bright-purple as default) * fix: missing card borders * fix: high contrast gradients (send/exchange) * fix: contact list page * feat: add picker search border and change high contrast search fill * fix: balance page txts * fix: accounts_subaddresses button * fix: exchange page buttons * Revert "fix: revert theme order (bright-purple as default)" This reverts commit 8e13b2241cfe62223b4d094aba1dcae130aebad7. * fix: themetype enum * feat: add localized strings to backup dialog * fix: onramper flow --- lib/buy/onramper/onramper_buy_provider.dart | 45 +++++++--------- lib/entities/main_actions.dart | 2 +- lib/src/screens/backup/backup_page.dart | 6 +-- .../screens/contact/contact_list_page.dart | 8 +-- .../dashboard/widgets/address_page.dart | 12 ++--- .../dashboard/widgets/balance_page.dart | 13 ++--- lib/src/screens/exchange/exchange_page.dart | 5 +- lib/src/widgets/search_bar_widget.dart | 15 +++--- lib/themes/extensions/picker_theme.dart | 36 ++++++------- lib/themes/high_contrast_theme.dart | 52 ++++++++----------- lib/themes/theme_base.dart | 2 +- res/values/strings_ar.arb | 4 +- res/values/strings_bg.arb | 20 +++---- res/values/strings_cs.arb | 20 +++---- res/values/strings_de.arb | 20 +++---- res/values/strings_en.arb | 20 +++---- res/values/strings_es.arb | 20 +++---- res/values/strings_fr.arb | 20 +++---- res/values/strings_ha.arb | 20 +++---- res/values/strings_hi.arb | 20 +++---- res/values/strings_hr.arb | 20 +++---- res/values/strings_id.arb | 20 +++---- res/values/strings_it.arb | 20 +++---- res/values/strings_ja.arb | 4 +- res/values/strings_ko.arb | 4 +- res/values/strings_my.arb | 4 +- res/values/strings_nl.arb | 20 +++---- res/values/strings_pl.arb | 20 +++---- res/values/strings_pt.arb | 20 +++---- res/values/strings_ru.arb | 4 +- res/values/strings_th.arb | 4 +- res/values/strings_tr.arb | 21 ++++---- res/values/strings_uk.arb | 20 +++---- res/values/strings_ur.arb | 4 +- res/values/strings_yo.arb | 4 +- res/values/strings_zh.arb | 4 +- 36 files changed, 288 insertions(+), 265 deletions(-) diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 68be59f4e..cf4cbd124 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:flutter/material.dart'; class OnRamperBuyProvider { OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet}) @@ -27,7 +29,11 @@ class OnRamperBuyProvider { } } - Uri requestUrl() { + String getColorStr(Color color) { + return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), ""); + } + + Uri requestUrl(BuildContext context) { String primaryColor, secondaryColor, primaryTextColor, @@ -35,31 +41,16 @@ class OnRamperBuyProvider { containerColor, cardColor; - switch (_settingsStore.currentTheme.type) { - case ThemeType.bright: - primaryColor = '815dfbff'; - secondaryColor = 'ffffff'; - primaryTextColor = '141519'; - secondaryTextColor = '6b6f80'; - containerColor = 'ffffff'; - cardColor = 'f2f0faff'; - break; - case ThemeType.light: - primaryColor = '2194ffff'; - secondaryColor = 'ffffff'; - primaryTextColor = '141519'; - secondaryTextColor = '6b6f80'; - containerColor = 'ffffff'; - cardColor = 'e5f7ff'; - break; - case ThemeType.dark: - primaryColor = '456effff'; - secondaryColor = '1b2747ff'; - primaryTextColor = 'ffffff'; - secondaryTextColor = 'ffffff'; - containerColor = '19233C'; - cardColor = '232f4fff'; - break; + primaryColor = getColorStr(Theme.of(context).primaryColor); + secondaryColor = getColorStr(Theme.of(context).colorScheme.background); + primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor); + secondaryTextColor = + getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor); + containerColor = getColorStr(Theme.of(context).colorScheme.background); + cardColor = getColorStr(Theme.of(context).cardColor); + + if (_settingsStore.currentTheme.title == S.current.high_contrast_theme) { + cardColor = getColorStr(Colors.white); } final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", ""); diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 912269d8e..2d91983d4 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -49,7 +49,7 @@ class MainActions { case WalletType.ethereum: case WalletType.monero: if (viewModel.isEnabledBuyAction) { - final uri = getIt.get<OnRamperBuyProvider>().requestUrl(); + final uri = getIt.get<OnRamperBuyProvider>().requestUrl(context); if (DeviceInfo.instance.isMobile) { Navigator.of(context) .pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); diff --git a/lib/src/screens/backup/backup_page.dart b/lib/src/screens/backup/backup_page.dart index f7a224aac..5995e71c4 100644 --- a/lib/src/screens/backup/backup_page.dart +++ b/lib/src/screens/backup/backup_page.dart @@ -127,9 +127,9 @@ class BackupPage extends BasePage { builder: (dialogContext) { return AlertWithTwoActions( alertTitle: S.of(context).export_backup, - alertContent: 'Please select destination for the backup file.', - rightButtonText: 'Save to Downloads', - leftButtonText: 'Share', + alertContent: S.of(context).select_destination, + rightButtonText: S.of(context).save_to_downloads, + leftButtonText:S.of(context).share, actionRightButton: () async { final permission = await Permission.storage.request(); diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 6c00b64f9..b551875f9 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/entities/contact_record.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -39,7 +40,7 @@ class ContactListPage extends BasePage { children: <Widget>[ Icon( Icons.add, - color: Theme.of(context).dialogTheme.backgroundColor, + color: Theme.of(context).appBarTheme.titleTextStyle!.color, size: 22.0, ), ButtonTheme( @@ -71,7 +72,7 @@ class ContactListPage extends BasePage { @override Widget body(BuildContext context) { return Container( - padding: EdgeInsets.only(top: 20.0, bottom: 20.0), + padding: EdgeInsets.all(20.0), child: Observer(builder: (_) { final contacts = contactListViewModel.contactsToShow; final walletContacts = contactListViewModel.walletContactsToShow; @@ -131,7 +132,6 @@ class ContactListPage extends BasePage { } }, child: Container( - color: Colors.transparent, padding: const EdgeInsets.only(top: 16, bottom: 16, right: 24), child: Row( mainAxisSize: MainAxisSize.min, @@ -146,7 +146,7 @@ class ContactListPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).dialogTheme.backgroundColor, + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor, ), ), )) diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 45ac3982e..236087595 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -182,9 +182,8 @@ class AddressPage extends BasePage { decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(25)), border: Border.all( - color: Theme.of(context) - .extension<ReceivePageTheme>()! - .iconsBackgroundColor, + color: + Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor, width: 1), color: Theme.of(context) .extension<SyncIndicatorTheme>()! @@ -201,13 +200,14 @@ class AddressPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Theme.of(context).extension<DashboardPageTheme>()!.textColor), + color: Theme.of(context) + .extension<SyncIndicatorTheme>()! + .textColor), )), Icon( Icons.arrow_forward_ios, size: 14, - color: - Theme.of(context).extension<DashboardPageTheme>()!.textColor, + color: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor, ) ], ), diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart index f799950ea..c8d7faf11 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -2,7 +2,6 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -77,9 +76,7 @@ class BalancePage extends StatelessWidget { return IntroducingCard( title: S.of(context).introducing_cake_pay, subTitle: S.of(context).cake_pay_learn_more, - borderColor: settingsStore.currentTheme.type == ThemeType.bright - ? Color.fromRGBO(255, 255, 255, 0.2) - : Colors.transparent, + borderColor: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor, closeCard: dashboardViewModel.balanceViewModel.disableIntroCakePayCard); } return Container(); @@ -139,9 +136,7 @@ class BalancePage extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(30.0), border: Border.all( - color: settingsStore.currentTheme.type == ThemeType.bright - ? Color.fromRGBO(255, 255, 255, 0.2) - : Colors.transparent, + color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor, width: 1, ), color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor, @@ -282,7 +277,7 @@ class BalancePage extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, + color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor, height: 1, ), maxLines: 1, @@ -296,7 +291,7 @@ class BalancePage extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).extension<DashboardPageTheme>()!.textColor, + color: Theme.of(context).extension<BalancePageTheme>()!.textColor, height: 1, ), ), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 972fa0399..7ff9e6c30 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/debounce.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -629,7 +630,7 @@ class ExchangePage extends BasePage { }, imageArrow: arrowBottomPurple, currencyButtonColor: Colors.transparent, - addressButtonsColor: Theme.of(context).focusColor, + addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor, currencyValueValidator: (value) { return !exchangeViewModel.isFixedRateMode @@ -677,7 +678,7 @@ class ExchangePage extends BasePage { exchangeViewModel.changeReceiveCurrency(currency: currency), imageArrow: arrowBottomCakeGreen, currencyButtonColor: Colors.transparent, - addressButtonsColor: Theme.of(context).focusColor, + addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor, borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor, currencyValueValidator: (value) { return exchangeViewModel.isFixedRateMode diff --git a/lib/src/widgets/search_bar_widget.dart b/lib/src/widgets/search_bar_widget.dart index bdb520d55..731fbf632 100644 --- a/lib/src/widgets/search_bar_widget.dart +++ b/lib/src/widgets/search_bar_widget.dart @@ -17,24 +17,21 @@ class SearchBarWidget extends StatelessWidget { Widget build(BuildContext context) { return TextFormField( controller: searchController, - style: TextStyle( - color: Theme.of(context).extension<PickerTheme>()!.searchTextColor), + style: TextStyle(color: Theme.of(context).extension<PickerTheme>()!.searchTextColor), decoration: InputDecoration( hintText: hintText ?? S.of(context).search_currency, - hintStyle: TextStyle( - color: Theme.of(context).extension<PickerTheme>()!.searchHintColor), + hintStyle: TextStyle(color: Theme.of(context).extension<PickerTheme>()!.searchHintColor), prefixIcon: Image.asset("assets/images/search_icon.png", color: Theme.of(context).extension<PickerTheme>()!.searchIconColor), filled: true, - fillColor: Theme.of(context) - .extension<PickerTheme>()! - .searchBackgroundFillColor, + fillColor: Theme.of(context).extension<PickerTheme>()!.searchBackgroundFillColor, alignLabelWithHint: false, contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(borderRadius), - borderSide: const BorderSide( - color: Colors.transparent, + borderSide: BorderSide( + color: Theme.of(context).extension<PickerTheme>()!.searchBorderColor ?? + Colors.transparent, )), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(borderRadius), diff --git a/lib/themes/extensions/picker_theme.dart b/lib/themes/extensions/picker_theme.dart index afd2268ec..58c7fa3ff 100644 --- a/lib/themes/extensions/picker_theme.dart +++ b/lib/themes/extensions/picker_theme.dart @@ -6,13 +6,15 @@ class PickerTheme extends ThemeExtension<PickerTheme> { final Color searchBackgroundFillColor; final Color searchTextColor; final Color? searchHintColor; + final Color? searchBorderColor; PickerTheme( {required this.dividerColor, this.searchIconColor, required this.searchBackgroundFillColor, required this.searchTextColor, - this.searchHintColor}); + this.searchHintColor, + this.searchBorderColor}); @override PickerTheme copyWith( @@ -20,14 +22,15 @@ class PickerTheme extends ThemeExtension<PickerTheme> { Color? searchIconColor, Color? searchBackgroundFillColor, Color? searchTextColor, - Color? searchHintColor}) => + Color? searchHintColor, + Color? searchBorderColor}) => PickerTheme( dividerColor: dividerColor ?? this.dividerColor, searchIconColor: searchIconColor ?? this.searchIconColor, - searchBackgroundFillColor: - searchBackgroundFillColor ?? this.searchBackgroundFillColor, + searchBackgroundFillColor: searchBackgroundFillColor ?? this.searchBackgroundFillColor, searchTextColor: searchTextColor ?? this.searchTextColor, - searchHintColor: searchHintColor ?? this.searchHintColor); + searchHintColor: searchHintColor ?? this.searchHintColor, + searchBorderColor: searchBorderColor ?? this.searchBorderColor); @override PickerTheme lerp(ThemeExtension<PickerTheme>? other, double t) { @@ -36,19 +39,14 @@ class PickerTheme extends ThemeExtension<PickerTheme> { } return PickerTheme( - dividerColor: - Color.lerp(dividerColor, other.dividerColor, t) ?? dividerColor, - searchIconColor: - Color.lerp(searchIconColor, other.searchIconColor, t) ?? - searchIconColor, - searchBackgroundFillColor: Color.lerp(searchBackgroundFillColor, - other.searchBackgroundFillColor, t) ?? - searchBackgroundFillColor, - searchTextColor: - Color.lerp(searchTextColor, other.searchTextColor, t) ?? - searchTextColor, - searchHintColor: - Color.lerp(searchHintColor, other.searchHintColor, t) ?? - searchHintColor); + dividerColor: Color.lerp(dividerColor, other.dividerColor, t) ?? dividerColor, + searchIconColor: Color.lerp(searchIconColor, other.searchIconColor, t) ?? searchIconColor, + searchBackgroundFillColor: + Color.lerp(searchBackgroundFillColor, other.searchBackgroundFillColor, t) ?? + searchBackgroundFillColor, + searchTextColor: Color.lerp(searchTextColor, other.searchTextColor, t) ?? searchTextColor, + searchHintColor: Color.lerp(searchHintColor, other.searchHintColor, t) ?? searchHintColor, + searchBorderColor: + Color.lerp(searchBorderColor, other.searchBorderColor, t) ?? searchBorderColor); } } diff --git a/lib/themes/high_contrast_theme.dart b/lib/themes/high_contrast_theme.dart index e43e63020..0483adb38 100644 --- a/lib/themes/high_contrast_theme.dart +++ b/lib/themes/high_contrast_theme.dart @@ -39,14 +39,12 @@ class HighContrastTheme extends MoneroLightTheme { @override CakeTextTheme get cakeTextTheme => super.cakeTextTheme.copyWith( - buttonTextColor: Colors.white, - buttonSecondaryTextColor: Colors.white.withOpacity(0.5)); + buttonTextColor: Colors.white, buttonSecondaryTextColor: Colors.white.withOpacity(0.5)); @override - SyncIndicatorTheme get syncIndicatorStyle => - super.syncIndicatorStyle.copyWith( - textColor: colorScheme.background, - syncedBackgroundColor: containerColor); + SyncIndicatorTheme get syncIndicatorStyle => super + .syncIndicatorStyle + .copyWith(textColor: colorScheme.background, syncedBackgroundColor: containerColor); @override BalancePageTheme get balancePageTheme => super.balancePageTheme.copyWith( @@ -56,32 +54,28 @@ class HighContrastTheme extends MoneroLightTheme { balanceAmountColor: Colors.white); @override - DashboardPageTheme get dashboardPageTheme => - super.dashboardPageTheme.copyWith( - textColor: Colors.black, - cardTextColor: Colors.white, - mainActionsIconColor: Colors.white, - indicatorDotTheme: IndicatorDotTheme( - indicatorColor: Colors.grey, activeIndicatorColor: Colors.black)); + DashboardPageTheme get dashboardPageTheme => super.dashboardPageTheme.copyWith( + textColor: Colors.black, + cardTextColor: Colors.white, + mainActionsIconColor: Colors.white, + indicatorDotTheme: + IndicatorDotTheme(indicatorColor: Colors.grey, activeIndicatorColor: Colors.black)); @override - ExchangePageTheme get exchangePageTheme => super - .exchangePageTheme - .copyWith(firstGradientTopPanelColor: containerColor); + ExchangePageTheme get exchangePageTheme => super.exchangePageTheme.copyWith( + firstGradientTopPanelColor: primaryColor, firstGradientBottomPanelColor: containerColor); @override SendPageTheme get sendPageTheme => super.sendPageTheme.copyWith( templateTitleColor: Colors.white, templateBackgroundColor: Colors.black, - firstGradientColor: containerColor); + firstGradientColor: primaryColor); @override - AddressTheme get addressTheme => - super.addressTheme.copyWith(actionButtonColor: Colors.grey); + AddressTheme get addressTheme => super.addressTheme.copyWith(actionButtonColor: Colors.grey); @override - FilterTheme get filterTheme => - super.filterTheme.copyWith(iconColor: Colors.white); + FilterTheme get filterTheme => super.filterTheme.copyWith(iconColor: Colors.white); @override CakeMenuTheme get menuTheme => super.menuTheme.copyWith( @@ -91,10 +85,11 @@ class HighContrastTheme extends MoneroLightTheme { @override PickerTheme get pickerTheme => super.pickerTheme.copyWith( - searchIconColor: Colors.white, - searchHintColor: Colors.white, - searchTextColor: Colors.white, - searchBackgroundFillColor: Colors.grey); + searchIconColor: primaryColor, + searchHintColor: primaryColor, + searchTextColor: primaryColor, + searchBackgroundFillColor: Colors.white, + searchBorderColor: primaryColor); @override AccountListTheme get accountListTheme => super.accountListTheme.copyWith( @@ -106,13 +101,10 @@ class HighContrastTheme extends MoneroLightTheme { @override ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( - tilesTextColor: Colors.white, - iconsBackgroundColor: Colors.grey, - iconsColor: Colors.black); + tilesTextColor: Colors.white, iconsBackgroundColor: Colors.grey, iconsColor: Colors.black); @override ThemeData get themeData => super.themeData.copyWith( disabledColor: Colors.grey, - dialogTheme: - super.themeData.dialogTheme.copyWith(backgroundColor: Colors.white)); + dialogTheme: super.themeData.dialogTheme.copyWith(backgroundColor: Colors.white)); } diff --git a/lib/themes/theme_base.dart b/lib/themes/theme_base.dart index 6151f0e83..b5f42e7de 100644 --- a/lib/themes/theme_base.dart +++ b/lib/themes/theme_base.dart @@ -26,7 +26,7 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:flutter/material.dart'; -enum ThemeType { bright, light, dark } +enum ThemeType { light, bright, dark } abstract class ThemeBase { ThemeBase({required this.raw}) { diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 573ad120c..5bd8906fe 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -680,5 +680,7 @@ "support_title_guides": "أدلة محفظة كعكة", "support_description_guides": "توثيق ودعم القضايا المشتركة", "support_title_other_links": "روابط دعم أخرى", - "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى" + "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", + "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", + "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d6ddaf5a6..325057aa4 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -626,18 +626,18 @@ "setup_totp_recommended": "Настройка на TOTP (препоръчително)", "disable_buy": "Деактивирайте действието за покупка", "disable_sell": "Деактивирайте действието за продажба", - "cake_2fa_preset" : "Торта 2FA Preset", + "cake_2fa_preset": "Торта 2FA Preset", "narrow": "Тесен", "normal": "нормално", "aggressive": "Прекалено усърден", "require_for_assessing_wallet": "Изискване за достъп до портфейла", - "require_for_sends_to_non_contacts" : "Изискване за изпращане до лица без контакт", - "require_for_sends_to_contacts" : "Изискване за изпращане до контакти", - "require_for_sends_to_internal_wallets" : "Изискване за изпращане до вътрешни портфейли", - "require_for_exchanges_to_internal_wallets" : "Изискване за обмен към вътрешни портфейли", - "require_for_adding_contacts" : "Изисква се за добавяне на контакти", - "require_for_creating_new_wallets" : "Изискване за създаване на нови портфейли", - "require_for_all_security_and_backup_settings" : "Изисква се за всички настройки за сигурност и архивиране", + "require_for_sends_to_non_contacts": "Изискване за изпращане до лица без контакт", + "require_for_sends_to_contacts": "Изискване за изпращане до контакти", + "require_for_sends_to_internal_wallets": "Изискване за изпращане до вътрешни портфейли", + "require_for_exchanges_to_internal_wallets": "Изискване за обмен към вътрешни портфейли", + "require_for_adding_contacts": "Изисква се за добавяне на контакти", + "require_for_creating_new_wallets": "Изискване за създаване на нови портфейли", + "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", "available_balance_description": "Това е балансът, който можете да използвате за покупка на криптовалути. Това не включва замразените средства.", "syncing_wallet_alert_title": "Вашият портфейл се синхронизира", "syncing_wallet_alert_content": "Списъкът ви с баланс и транзакции може да не е пълен, докато в горната част не пише „СИНХРОНИЗИРАН“. Кликнете/докоснете, за да научите повече.", @@ -676,5 +676,7 @@ "support_title_guides": "Ръководства за портфейл за торта", "support_description_guides": "Документация и подкрепа за общи проблеми", "support_title_other_links": "Други връзки за поддръжка", - "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи" + "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", + "select_destination": "Моля, изберете дестинация за архивния файл.", + "save_to_downloads": "Запазване в Изтегляния" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 42b69d87a..a258eaa40 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -626,18 +626,18 @@ "setup_totp_recommended": "Nastavit TOTP (doporučeno)", "disable_buy": "Zakázat akci nákupu", "disable_sell": "Zakázat akci prodeje", - "cake_2fa_preset" : "Předvolba Cake 2FA", + "cake_2fa_preset": "Předvolba Cake 2FA", "narrow": "Úzký", "normal": "Normální", "aggressive": "Agresivní", "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", - "require_for_sends_to_non_contacts" : "Vyžadovat pro odesílání nekontaktním osobám", - "require_for_sends_to_contacts" : "Vyžadovat pro odeslání kontaktům", - "require_for_sends_to_internal_wallets" : "Vyžadovat pro odesílání do interních peněženek", - "require_for_exchanges_to_internal_wallets" : "Vyžadovat pro výměny do interních peněženek", - "require_for_adding_contacts" : "Vyžadovat pro přidání kontaktů", - "require_for_creating_new_wallets" : "Vyžadovat pro vytváření nových peněženek", - "require_for_all_security_and_backup_settings" : "Vyžadovat všechna nastavení zabezpečení a zálohování", + "require_for_sends_to_non_contacts": "Vyžadovat pro odesílání nekontaktním osobám", + "require_for_sends_to_contacts": "Vyžadovat pro odeslání kontaktům", + "require_for_sends_to_internal_wallets": "Vyžadovat pro odesílání do interních peněženek", + "require_for_exchanges_to_internal_wallets": "Vyžadovat pro výměny do interních peněženek", + "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", + "require_for_creating_new_wallets": "Vyžadovat pro vytváření nových peněženek", + "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", "available_balance_description": "Dostupná částka je částka, kterou můžete okamžitě utratit. Zmrazená částka je částka, která ještě není k dispozici, protože ještě nebyla potvrzena síťovým protokolem.", "syncing_wallet_alert_title": "Vaše peněženka se synchronizuje", "syncing_wallet_alert_content": "Váš seznam zůstatků a transakcí nemusí být úplný, dokud nebude nahoře uvedeno „SYNCHRONIZOVANÉ“. Kliknutím/klepnutím se dozvíte více.", @@ -676,5 +676,7 @@ "support_title_guides": "Průvodce peněženkami dortu", "support_description_guides": "Dokumentace a podpora běžných otázek", "support_title_other_links": "Další odkazy na podporu", - "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody" + "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody", + "select_destination": "Vyberte cíl pro záložní soubor.", + "save_to_downloads": "Uložit do Stažených souborů" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 12d03d079..06450a315 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "Kontrastreiches Thema", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero Light-Thema", - "cake_2fa_preset" : "Kuchen 2FA-Voreinstellung", + "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", "narrow": "Eng", "normal": "Normal", "aggressive": "Übereifrig", "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", - "require_for_sends_to_non_contacts" : "Erforderlich für Versendungen an Nichtkontakte", - "require_for_sends_to_contacts" : "Erforderlich für Versendungen an Kontakte", - "require_for_sends_to_internal_wallets" : "Erforderlich für Sendungen an interne Wallets", - "require_for_exchanges_to_internal_wallets" : "Erforderlich für den Umtausch in interne Wallets", - "require_for_adding_contacts" : "Erforderlich zum Hinzufügen von Kontakten", - "require_for_creating_new_wallets" : "Erforderlich zum Erstellen neuer Wallets", - "require_for_all_security_and_backup_settings" : "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", + "require_for_sends_to_non_contacts": "Erforderlich für Versendungen an Nichtkontakte", + "require_for_sends_to_contacts": "Erforderlich für Versendungen an Kontakte", + "require_for_sends_to_internal_wallets": "Erforderlich für Sendungen an interne Wallets", + "require_for_exchanges_to_internal_wallets": "Erforderlich für den Umtausch in interne Wallets", + "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", + "require_for_creating_new_wallets": "Erforderlich zum Erstellen neuer Wallets", + "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", "available_balance_description": "Verfügbarer Saldo ist der Betrag, den Sie sofort ausgeben können. Dieser Betrag kann sich ändern, wenn Sie eine Transaktion senden oder empfangen.", "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert", "syncing_wallet_alert_content": "Ihr Kontostand und Ihre Transaktionsliste sind möglicherweise erst vollständig, wenn oben „SYNCHRONISIERT“ steht. Klicken/tippen Sie, um mehr zu erfahren.", @@ -684,5 +684,7 @@ "support_title_guides": "Cake Wallet Guides", "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", "support_title_other_links": "Andere Support-Links", - "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden" + "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden", + "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.", + "save_to_downloads": "Unter „Downloads“ speichern" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3d1ea44fa..9e8e3788c 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "High Contrast Theme", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero Light Theme", - "cake_2fa_preset" : "Cake 2FA Preset", + "cake_2fa_preset": "Cake 2FA Preset", "narrow": "Narrow", "normal": "Normal", "aggressive": "Aggressive", "require_for_assessing_wallet": "Require for accessing wallet", - "require_for_sends_to_non_contacts" : "Require for sends to non-contacts", - "require_for_sends_to_contacts" : "Require for sends to contacts", - "require_for_sends_to_internal_wallets" : "Require for sends to internal wallets", - "require_for_exchanges_to_internal_wallets" : "Require for exchanges to internal wallets", - "require_for_adding_contacts" : "Require for adding contacts", - "require_for_creating_new_wallets" : "Require for creating new wallets", - "require_for_all_security_and_backup_settings" : "Require for all security and backup settings", + "require_for_sends_to_non_contacts": "Require for sends to non-contacts", + "require_for_sends_to_contacts": "Require for sends to contacts", + "require_for_sends_to_internal_wallets": "Require for sends to internal wallets", + "require_for_exchanges_to_internal_wallets": "Require for exchanges to internal wallets", + "require_for_adding_contacts": "Require for adding contacts", + "require_for_creating_new_wallets": "Require for creating new wallets", + "require_for_all_security_and_backup_settings": "Require for all security and backup settings", "available_balance_description": "The “Available Balance” or “Confirmed Balance” are funds that can be spent immediately. If funds appear in the lower balance but not the top balance, then you must wait a few minutes for the incoming funds to get more network confirmations. After they get more confirmations, they will be spendable.", "syncing_wallet_alert_title": "Your wallet is syncing", "syncing_wallet_alert_content": "Your balance and transaction list may not be complete until it says “SYNCHRONIZED” at the top. Click/tap to learn more.", @@ -684,5 +684,7 @@ "support_title_guides": "Cake Wallet guides", "support_description_guides": "Documentation and support for common issues", "support_title_other_links": "Other support links", - "support_description_other_links": "Join our communities or reach us our our partners through other methods" + "support_description_other_links": "Join our communities or reach us our our partners through other methods", + "select_destination": "Please select destination for the backup file.", + "save_to_downloads": "Save to Downloads" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 1faa6d78c..3c0abce48 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "Tema de alto contraste", "matrix_green_dark_theme": "Matrix verde oscuro tema", "monero_light_theme": "Tema ligero de Monero", - "cake_2fa_preset" : "Pastel 2FA preestablecido", + "cake_2fa_preset": "Pastel 2FA preestablecido", "narrow": "Angosto", "normal": "Normal", "aggressive": "Demasiado entusiasta", "require_for_assessing_wallet": "Requerido para acceder a la billetera", - "require_for_sends_to_non_contacts" : "Requerido para envíos a no contactos", - "require_for_sends_to_contacts" : "Requerir para envíos a contactos", - "require_for_sends_to_internal_wallets" : "Requerido para envíos a billeteras internas", - "require_for_exchanges_to_internal_wallets" : "Requerido para intercambios a billeteras internas", - "require_for_adding_contacts" : "Requerido para agregar contactos", - "require_for_creating_new_wallets" : "Requerido para crear nuevas billeteras", - "require_for_all_security_and_backup_settings" : "Requerido para todas las configuraciones de seguridad y copia de seguridad", + "require_for_sends_to_non_contacts": "Requerido para envíos a no contactos", + "require_for_sends_to_contacts": "Requerir para envíos a contactos", + "require_for_sends_to_internal_wallets": "Requerido para envíos a billeteras internas", + "require_for_exchanges_to_internal_wallets": "Requerido para intercambios a billeteras internas", + "require_for_adding_contacts": "Requerido para agregar contactos", + "require_for_creating_new_wallets": "Requerido para crear nuevas billeteras", + "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", "available_balance_description": "Su saldo disponible es la cantidad de fondos que puede gastar. Los fondos que se muestran aquí se pueden gastar inmediatamente.", "syncing_wallet_alert_title": "Tu billetera se está sincronizando", "syncing_wallet_alert_content": "Es posible que su lista de saldo y transacciones no esté completa hasta que diga \"SINCRONIZADO\" en la parte superior. Haga clic/toque para obtener más información.", @@ -684,5 +684,7 @@ "support_title_guides": "Guías de billetera para pastel", "support_description_guides": "Documentación y apoyo para problemas comunes", "support_title_other_links": "Otros enlaces de soporte", - "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos" + "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos", + "select_destination": "Seleccione el destino del archivo de copia de seguridad.", + "save_to_downloads": "Guardar en Descargas" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 548f74192..1449d6370 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "Thème à contraste élevé", "matrix_green_dark_theme": "Thème Matrix Green Dark", "monero_light_theme": "Thème de lumière Monero", - "cake_2fa_preset" : "Gâteau 2FA prédéfini", + "cake_2fa_preset": "Gâteau 2FA prédéfini", "narrow": "Étroit", "normal": "Normal", "aggressive": "Trop zélé", "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", - "require_for_sends_to_non_contacts" : "Exiger pour les envois à des non-contacts", - "require_for_sends_to_contacts" : "Exiger pour les envois aux contacts", - "require_for_sends_to_internal_wallets" : "Exiger pour les envois vers des portefeuilles internes", - "require_for_exchanges_to_internal_wallets" : "Exiger pour les échanges vers des portefeuilles internes", - "require_for_adding_contacts" : "Requis pour ajouter des contacts", - "require_for_creating_new_wallets" : "Nécessaire pour créer de nouveaux portefeuilles", - "require_for_all_security_and_backup_settings" : "Exiger pour tous les paramètres de sécurité et de sauvegarde", + "require_for_sends_to_non_contacts": "Exiger pour les envois à des non-contacts", + "require_for_sends_to_contacts": "Exiger pour les envois aux contacts", + "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles internes", + "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles internes", + "require_for_adding_contacts": "Requis pour ajouter des contacts", + "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles", + "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", "available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.", "syncing_wallet_alert_title": "Votre portefeuille est en cours de synchronisation", "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être complets tant qu'il n'y a pas « SYNCHRONISÉ » en haut. Cliquez/appuyez pour en savoir plus.", @@ -684,5 +684,7 @@ "support_title_guides": "Guides de portefeuille à gâteau", "support_description_guides": "Documentation et soutien aux problèmes communs", "support_title_other_links": "Autres liens d'assistance", - "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes" + "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes", + "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", + "save_to_downloads": "Enregistrer dans les téléchargements" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 20ae66c33..e3542e9ac 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -618,18 +618,18 @@ "high_contrast_theme": "Babban Jigon Kwatance", "matrix_green_dark_theme": "Matrix Green Dark Jigo", "monero_light_theme": "Jigon Hasken Monero", - "cake_2fa_preset" : "Cake 2FA saiti", + "cake_2fa_preset": "Cake 2FA saiti", "narrow": "kunkuntar", "normal": "Na al'ada", "aggressive": "Mai tsananin kishi", "require_for_assessing_wallet": "Bukatar samun damar walat", - "require_for_sends_to_non_contacts" : "Bukatar aika zuwa waɗanda ba lambobin sadarwa ba", - "require_for_sends_to_contacts" : "Bukatar aika zuwa lambobin sadarwa", - "require_for_sends_to_internal_wallets" : "Bukatar aika zuwa wallet na ciki", - "require_for_exchanges_to_internal_wallets" : "Bukatar musanya zuwa wallet na ciki", - "require_for_adding_contacts" : "Bukatar ƙara lambobin sadarwa", - "require_for_creating_new_wallets" : "Bukatar ƙirƙirar sabbin wallet", - "require_for_all_security_and_backup_settings" : "Bukatar duk tsaro da saitunan wariyar ajiya", + "require_for_sends_to_non_contacts": "Bukatar aika zuwa waɗanda ba lambobin sadarwa ba", + "require_for_sends_to_contacts": "Bukatar aika zuwa lambobin sadarwa", + "require_for_sends_to_internal_wallets": "Bukatar aika zuwa wallet na ciki", + "require_for_exchanges_to_internal_wallets": "Bukatar musanya zuwa wallet na ciki", + "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", + "require_for_creating_new_wallets": "Bukatar ƙirƙirar sabbin wallet", + "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", "available_balance_description": "Ma'auni mai samuwa” ko ”,Tabbataccen Ma'auni”, kudade ne da za a iya kashewa nan da nan. Idan kudade sun bayyana a cikin ƙananan ma'auni amma ba babban ma'auni ba, to dole ne ku jira 'yan mintoci kaɗan don kudaden shiga don samun ƙarin tabbaci na hanyar sadarwa. Bayan sun sami ƙarin tabbaci, za a kashe su.", "syncing_wallet_alert_title": "Walat ɗin ku yana aiki tare", "syncing_wallet_alert_content": "Ma'aunin ku da lissafin ma'amala bazai cika ba har sai an ce \"SYNCHRONIZED\" a saman. Danna/matsa don ƙarin koyo.", @@ -662,5 +662,7 @@ "support_title_guides": "Jagorar Cake", "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", "support_title_other_links": "Sauran hanyoyin tallafi", - "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi" + "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi", + "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.", + "save_to_downloads": "Ajiye zuwa Zazzagewa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index afbd3bb47..ca3e79bd0 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "उच्च कंट्रास्ट थीम", "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", "monero_light_theme": "मोनेरो लाइट थीम", - "cake_2fa_preset" : "केक 2एफए प्रीसेट", + "cake_2fa_preset": "केक 2एफए प्रीसेट", "narrow": "सँकरा", "normal": "सामान्य", "aggressive": "ज्यादा", "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", - "require_for_sends_to_non_contacts" : "गैर-संपर्कों को भेजने की आवश्यकता", - "require_for_sends_to_contacts" : "संपर्कों को भेजने के लिए आवश्यक है", - "require_for_sends_to_internal_wallets" : "आंतरिक वॉलेट में भेजने की आवश्यकता है", - "require_for_exchanges_to_internal_wallets" : "आंतरिक वॉलेट में आदान-प्रदान की आवश्यकता है", - "require_for_adding_contacts" : "संपर्क जोड़ने के लिए आवश्यकता है", - "require_for_creating_new_wallets" : "नए वॉलेट बनाने की आवश्यकता है", - "require_for_all_security_and_backup_settings" : "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", + "require_for_sends_to_non_contacts": "गैर-संपर्कों को भेजने की आवश्यकता", + "require_for_sends_to_contacts": "संपर्कों को भेजने के लिए आवश्यक है", + "require_for_sends_to_internal_wallets": "आंतरिक वॉलेट में भेजने की आवश्यकता है", + "require_for_exchanges_to_internal_wallets": "आंतरिक वॉलेट में आदान-प्रदान की आवश्यकता है", + "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", + "require_for_creating_new_wallets": "नए वॉलेट बनाने की आवश्यकता है", + "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", "available_balance_description": "उपलब्ध शेष या ”पुष्टिकृत शेष”, वे धनराशि हैं जिन्हें तुरंत खर्च किया जा सकता है। यदि फंड निचले बैलेंस में दिखाई देते हैं, लेकिन शीर्ष बैलेंस में नहीं, तो आपको आने वाले फंड के लिए अधिक नेटवर्क पुष्टिकरण प्राप्त करने के लिए कुछ मिनट इंतजार करना होगा। अधिक पुष्टि मिलने के बाद, वे खर्च करने योग्य हो जाएंगे।", "syncing_wallet_alert_title": "आपका वॉलेट सिंक हो रहा है", "syncing_wallet_alert_content": "आपकी शेष राशि और लेनदेन सूची तब तक पूरी नहीं हो सकती जब तक कि शीर्ष पर \"सिंक्रनाइज़्ड\" न लिखा हो। अधिक जानने के लिए क्लिक/टैप करें।", @@ -684,5 +684,7 @@ "support_title_guides": "केक वॉलेट गाइड", "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", "support_title_other_links": "अन्य समर्थन लिंक", - "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें" + "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", + "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।", + "save_to_downloads": "डाउनलोड में सहेजें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index a014cf8f8..e19d32ea1 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -640,18 +640,18 @@ "high_contrast_theme": "Tema visokog kontrasta", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero lagana tema", - "cake_2fa_preset" : "Cake 2FA Preset", + "cake_2fa_preset": "Cake 2FA Preset", "narrow": "Usko", "normal": "Normalno", "aggressive": "Preterano", "require_for_assessing_wallet": "Potreban za pristup novčaniku", - "require_for_sends_to_non_contacts" : "Zahtijeva za slanje nekontaktima", - "require_for_sends_to_contacts" : "Zahtijeva za slanje kontaktima", - "require_for_sends_to_internal_wallets" : "Zahtijeva za slanje u interne novčanike", - "require_for_exchanges_to_internal_wallets" : "Potreban za razmjenu na interne novčanike", - "require_for_adding_contacts" : "Zahtijeva za dodavanje kontakata", - "require_for_creating_new_wallets" : "Potreban za kreiranje novih novčanika", - "require_for_all_security_and_backup_settings" : "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", + "require_for_sends_to_non_contacts": "Zahtijeva za slanje nekontaktima", + "require_for_sends_to_contacts": "Zahtijeva za slanje kontaktima", + "require_for_sends_to_internal_wallets": "Zahtijeva za slanje u interne novčanike", + "require_for_exchanges_to_internal_wallets": "Potreban za razmjenu na interne novčanike", + "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", + "require_for_creating_new_wallets": "Potreban za kreiranje novih novčanika", + "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", "available_balance_description": "Dostupno stanje je iznos koji možete potrošiti. To je vaš saldo minus bilo kakve transakcije koje su još uvijek u tijeku.", "syncing_wallet_alert_title": "Vaš novčanik se sinkronizira", "syncing_wallet_alert_content": "Vaš saldo i popis transakcija možda neće biti potpuni sve dok na vrhu ne piše \"SINKRONIZIRANO\". Kliknite/dodirnite da biste saznali više.", @@ -684,5 +684,7 @@ "support_title_guides": "Vodiči za torte", "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", "support_title_other_links": "Ostale veze za podršku", - "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama" + "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama", + "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.", + "save_to_downloads": "Spremi u Preuzimanja" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 1011a3c6b..3f62f968c 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -622,18 +622,18 @@ "setup_totp_recommended": "Siapkan TOTP (Disarankan)", "disable_buy": "Nonaktifkan tindakan beli", "disable_sell": "Nonaktifkan aksi jual", - "cake_2fa_preset" : "Preset Kue 2FA", + "cake_2fa_preset": "Preset Kue 2FA", "narrow": "Sempit", "normal": "Normal", "aggressive": "Terlalu bersemangat", "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", - "require_for_sends_to_non_contacts" : "Wajibkan untuk mengirim ke non-kontak", - "require_for_sends_to_contacts" : "Membutuhkan untuk mengirim ke kontak", - "require_for_sends_to_internal_wallets" : "Diperlukan untuk mengirim ke dompet internal", - "require_for_exchanges_to_internal_wallets" : "Diperlukan untuk pertukaran ke dompet internal", - "require_for_adding_contacts" : "Membutuhkan untuk menambahkan kontak", - "require_for_creating_new_wallets" : "Diperlukan untuk membuat dompet baru", - "require_for_all_security_and_backup_settings" : "Memerlukan untuk semua pengaturan keamanan dan pencadangan", + "require_for_sends_to_non_contacts": "Wajibkan untuk mengirim ke non-kontak", + "require_for_sends_to_contacts": "Membutuhkan untuk mengirim ke kontak", + "require_for_sends_to_internal_wallets": "Diperlukan untuk mengirim ke dompet internal", + "require_for_exchanges_to_internal_wallets": "Diperlukan untuk pertukaran ke dompet internal", + "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", + "require_for_creating_new_wallets": "Diperlukan untuk membuat dompet baru", + "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", "available_balance_description": "“Saldo yang Tersedia” atau “Saldo yang Dikonfirmasi” adalah dana yang dapat langsung dibelanjakan. Jika dana muncul di saldo bawah tetapi tidak di saldo atas, maka Anda harus menunggu beberapa menit agar dana masuk mendapatkan konfirmasi jaringan lainnya. Setelah mereka mendapatkan lebih banyak konfirmasi, mereka akan dapat dibelanjakan.", "syncing_wallet_alert_title": "Dompet Anda sedang disinkronkan", "syncing_wallet_alert_content": "Saldo dan daftar transaksi Anda mungkin belum lengkap sampai tertulis “SYNCHRONIZED” di bagian atas. Klik/ketuk untuk mempelajari lebih lanjut.", @@ -672,5 +672,7 @@ "support_title_guides": "Panduan Dompet Kue", "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", "support_title_other_links": "Tautan dukungan lainnya", - "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain" + "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain", + "select_destination": "Silakan pilih tujuan untuk file cadangan.", + "save_to_downloads": "Simpan ke Unduhan" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index e327d7c6d..8ad7502fd 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "Imposta TOTP (consigliato)", "disable_buy": "Disabilita l'azione di acquisto", "disable_sell": "Disabilita l'azione di vendita", - "cake_2fa_preset" : "Torta 2FA Preset", + "cake_2fa_preset": "Torta 2FA Preset", "narrow": "Stretto", "normal": "Normale", "aggressive": "Fervente", "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", - "require_for_sends_to_non_contacts" : "Richiesto per invii a non contatti", - "require_for_sends_to_contacts" : "Richiedi per gli invii ai contatti", - "require_for_sends_to_internal_wallets" : "Richiesto per invii a portafogli interni", - "require_for_exchanges_to_internal_wallets" : "Richiedi per gli scambi ai portafogli interni", - "require_for_adding_contacts" : "Richiesto per l'aggiunta di contatti", - "require_for_creating_new_wallets" : "Richiesto per la creazione di nuovi portafogli", - "require_for_all_security_and_backup_settings" : "Richiedi per tutte le impostazioni di sicurezza e backup", + "require_for_sends_to_non_contacts": "Richiesto per invii a non contatti", + "require_for_sends_to_contacts": "Richiedi per gli invii ai contatti", + "require_for_sends_to_internal_wallets": "Richiesto per invii a portafogli interni", + "require_for_exchanges_to_internal_wallets": "Richiedi per gli scambi ai portafogli interni", + "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", + "require_for_creating_new_wallets": "Richiesto per la creazione di nuovi portafogli", + "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", "available_balance_description": "Il saldo disponibile è il saldo totale meno i fondi congelati. I fondi congelati sono fondi che sono stati inviati ma non sono ancora stati confermati.", "syncing_wallet_alert_title": "Il tuo portafoglio si sta sincronizzando", "syncing_wallet_alert_content": "Il saldo e l'elenco delle transazioni potrebbero non essere completi fino a quando non viene visualizzato \"SYNCHRONIZED\" in alto. Clicca/tocca per saperne di più.", @@ -684,5 +684,7 @@ "support_title_guides": "Guide del portafoglio per torte", "support_description_guides": "Documentazione e supporto per problemi comuni", "support_title_other_links": "Altri collegamenti di supporto", - "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi" + "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi", + "select_destination": "Seleziona la destinazione per il file di backup.", + "save_to_downloads": "Salva in Download" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 8d7b2f601..3fe586279 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -684,5 +684,7 @@ "support_title_guides": "ケーキウォレットガイド", "support_description_guides": "一般的な問題のドキュメントとサポート", "support_title_other_links": "その他のサポートリンク", - "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください" + "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", + "select_destination": "バックアップファイルの保存先を選択してください。", + "save_to_downloads": "ダウンロードに保存" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 16422319d..1b7116e90 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -684,5 +684,7 @@ "support_title_guides": "케이크 지갑 가이드", "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", "support_title_other_links": "다른 지원 링크", - "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오." + "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", + "select_destination": "백업 파일의 대상을 선택하십시오.", + "save_to_downloads": "다운로드에 저장" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 0a599c16a..c12adb5ac 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -682,5 +682,7 @@ "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", - "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ" + "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", + "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", + "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 00eaf4dc8..18b3b5e5b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "TOTP instellen (aanbevolen)", "disable_buy": "Koopactie uitschakelen", "disable_sell": "Verkoopactie uitschakelen", - "cake_2fa_preset" : "Taart 2FA Voorinstelling", + "cake_2fa_preset": "Taart 2FA Voorinstelling", "narrow": "Smal", "normal": "Normaal", "aggressive": "Overijverig", "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", - "require_for_sends_to_non_contacts" : "Vereist voor verzendingen naar niet-contacten", - "require_for_sends_to_contacts" : "Vereist voor verzending naar contacten", - "require_for_sends_to_internal_wallets" : "Vereist voor verzendingen naar interne portefeuilles", - "require_for_exchanges_to_internal_wallets" : "Vereist voor uitwisselingen naar interne portefeuilles", - "require_for_adding_contacts" : "Vereist voor het toevoegen van contacten", - "require_for_creating_new_wallets" : "Vereist voor het maken van nieuwe portefeuilles", - "require_for_all_security_and_backup_settings" : "Vereist voor alle beveiligings- en back-upinstellingen", + "require_for_sends_to_non_contacts": "Vereist voor verzendingen naar niet-contacten", + "require_for_sends_to_contacts": "Vereist voor verzending naar contacten", + "require_for_sends_to_internal_wallets": "Vereist voor verzendingen naar interne portefeuilles", + "require_for_exchanges_to_internal_wallets": "Vereist voor uitwisselingen naar interne portefeuilles", + "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", + "require_for_creating_new_wallets": "Vereist voor het maken van nieuwe portefeuilles", + "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", "available_balance_description": "Beschikbaar saldo is het saldo dat u kunt uitgeven. Het kan lager zijn dan uw totale saldo als u onlangs geld hebt verzonden.", "syncing_wallet_alert_title": "Uw portemonnee wordt gesynchroniseerd", "syncing_wallet_alert_content": "Uw saldo- en transactielijst is mogelijk pas compleet als er bovenaan 'GESYNCHRONISEERD' staat. Klik/tik voor meer informatie.", @@ -684,5 +684,7 @@ "support_title_guides": "Cake -portemonnee gidsen", "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", "support_title_other_links": "Andere ondersteuningslinks", - "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden" + "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden", + "select_destination": "Selecteer de bestemming voor het back-upbestand.", + "save_to_downloads": "Opslaan in downloads" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 593f5ae19..e458339ba 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "Skonfiguruj TOTP (zalecane)", "disable_buy": "Wyłącz akcję kupna", "disable_sell": "Wyłącz akcję sprzedaży", - "cake_2fa_preset" : "Ciasto 2FA Preset", + "cake_2fa_preset": "Ciasto 2FA Preset", "narrow": "Wąski", "normal": "Normalna", "aggressive": "Nadgorliwy", "require_for_assessing_wallet": "Wymagaj dostępu do portfela", - "require_for_sends_to_non_contacts" : "Wymagaj wysyłania do osób niekontaktowych", - "require_for_sends_to_contacts" : "Wymagaj wysyłania do kontaktów", - "require_for_sends_to_internal_wallets" : "Wymagaj wysyłania do portfeli wewnętrznych", - "require_for_exchanges_to_internal_wallets" : "Wymagaj wymiany do portfeli wewnętrznych", - "require_for_adding_contacts" : "Wymagane do dodania kontaktów", - "require_for_creating_new_wallets" : "Wymagane do tworzenia nowych portfeli", - "require_for_all_security_and_backup_settings" : "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", + "require_for_sends_to_non_contacts": "Wymagaj wysyłania do osób niekontaktowych", + "require_for_sends_to_contacts": "Wymagaj wysyłania do kontaktów", + "require_for_sends_to_internal_wallets": "Wymagaj wysyłania do portfeli wewnętrznych", + "require_for_exchanges_to_internal_wallets": "Wymagaj wymiany do portfeli wewnętrznych", + "require_for_adding_contacts": "Wymagane do dodania kontaktów", + "require_for_creating_new_wallets": "Wymagane do tworzenia nowych portfeli", + "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", "available_balance_description": "Dostępne saldo jest równoważne z saldem portfela minus zamrożone saldo.", "syncing_wallet_alert_title": "Twój portfel się synchronizuje", "syncing_wallet_alert_content": "Twoje saldo i lista transakcji mogą nie być kompletne, dopóki u góry nie pojawi się napis „SYNCHRONIZOWANY”. Kliknij/stuknij, aby dowiedzieć się więcej.", @@ -684,5 +684,7 @@ "support_title_guides": "Przewodniki portfela ciasta", "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", "support_title_other_links": "Inne linki wsparcia", - "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod" + "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod", + "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", + "save_to_downloads": "Zapisz w Pobranych" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 551c30d01..aa06cd095 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -633,18 +633,18 @@ "setup_totp_recommended": "Configurar TOTP (recomendado)", "disable_buy": "Desativar ação de compra", "disable_sell": "Desativar ação de venda", - "cake_2fa_preset" : "Predefinição de bolo 2FA", + "cake_2fa_preset": "Predefinição de bolo 2FA", "narrow": "Estreito", "normal": "Normal", "aggressive": "excessivamente zeloso", "require_for_assessing_wallet": "Requer para acessar a carteira", - "require_for_sends_to_non_contacts" : "Exigir para envios para não-contatos", - "require_for_sends_to_contacts" : "Exigir para envios para contatos", - "require_for_sends_to_internal_wallets" : "Exigir envios para carteiras internas", - "require_for_exchanges_to_internal_wallets" : "Requer trocas para carteiras internas", - "require_for_adding_contacts" : "Requer para adicionar contatos", - "require_for_creating_new_wallets" : "Requer para criar novas carteiras", - "require_for_all_security_and_backup_settings" : "Exigir todas as configurações de segurança e backup", + "require_for_sends_to_non_contacts": "Exigir para envios para não-contatos", + "require_for_sends_to_contacts": "Exigir para envios para contatos", + "require_for_sends_to_internal_wallets": "Exigir envios para carteiras internas", + "require_for_exchanges_to_internal_wallets": "Requer trocas para carteiras internas", + "require_for_adding_contacts": "Requer para adicionar contatos", + "require_for_creating_new_wallets": "Requer para criar novas carteiras", + "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", "available_balance_description": "Seu saldo disponível é o saldo total menos o saldo congelado. O saldo congelado é o saldo que você não pode gastar, mas que ainda não foi confirmado na blockchain. O saldo congelado é geralmente o resultado de transações recentes.", "syncing_wallet_alert_title": "Sua carteira está sincronizando", "syncing_wallet_alert_content": "Seu saldo e lista de transações podem não estar completos até que diga “SYNCHRONIZED” no topo. Clique/toque para saber mais.", @@ -683,5 +683,7 @@ "support_title_guides": "Guias da carteira de bolo", "support_description_guides": "Documentação e suporte para problemas comuns", "support_title_other_links": "Outros links de suporte", - "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos" + "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos", + "select_destination": "Selecione o destino para o arquivo de backup.", + "save_to_downloads": "Salvar em Downloads" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 0d4c39570..533ca431d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -684,5 +684,7 @@ "support_title_guides": "Корт -гиды", "support_description_guides": "Документация и поддержка общих вопросов", "support_title_other_links": "Другие ссылки на поддержку", - "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов" + "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", + "select_destination": "Пожалуйста, выберите место для файла резервной копии.", + "save_to_downloads": "Сохранить в загрузках" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 6522bc3d9..f54194617 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -682,5 +682,7 @@ "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", - "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ" + "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", + "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", + "save_to_downloads": "บันทึกลงดาวน์โหลด" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index bb87595a4..fa835912a 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -632,19 +632,18 @@ "setup_totp_recommended": "TOTP'yi kurun (Önerilir)", "disable_buy": "Satın alma işlemini devre dışı bırak", "disable_sell": "Satış işlemini devre dışı bırak", - "cake_2fa_preset" : "Kek 2FA Ön Ayarı", + "cake_2fa_preset": "Kek 2FA Ön Ayarı", "narrow": "Dar", "normal": "Normal", "aggressive": "Aşırı duyarlı", "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", - "require_for_sends_to_non_contacts" : "Kişi olmayan kişilere göndermeler için gerekli kıl", - "require_for_sends_to_contacts" : "Kişilere göndermeler için gerekli kıl", - "require_for_sends_to_internal_wallets" : "Dahili cüzdanlara yapılan gönderimler için gereklilik", - "require_for_exchanges_to_internal_wallets" : "Dahili cüzdanlara değişim gerektir", - "require_for_adding_contacts" : "Kişi eklemek için gerekli", - "require_for_creating_new_wallets" : "Yeni cüzdan oluşturmak için gerekli", - "require_for_all_security_and_backup_settings" : "Tüm güvenlik ve yedekleme ayarları için iste", - "disable_sell": "Satış işlemini devre dışı bırak", + "require_for_sends_to_non_contacts": "Kişi olmayan kişilere göndermeler için gerekli kıl", + "require_for_sends_to_contacts": "Kişilere göndermeler için gerekli kıl", + "require_for_sends_to_internal_wallets": "Dahili cüzdanlara yapılan gönderimler için gereklilik", + "require_for_exchanges_to_internal_wallets": "Dahili cüzdanlara değişim gerektir", + "require_for_adding_contacts": "Kişi eklemek için gerekli", + "require_for_creating_new_wallets": "Yeni cüzdan oluşturmak için gerekli", + "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", "available_balance_description": "Bu, cüzdanınızda harcayabileceğiniz miktar. Bu miktar, cüzdanınızdan çekilebilecek toplam bakiyeden daha düşük olabilir, çünkü bazı fonlar henüz kullanılamaz durumda olabilir.", "syncing_wallet_alert_title": "Cüzdanınız senkronize ediliyor", "syncing_wallet_alert_content": "Bakiyeniz ve işlem listeniz, en üstte \"SENKRONİZE EDİLDİ\" yazana kadar tamamlanmamış olabilir. Daha fazla bilgi edinmek için tıklayın/dokunun.", @@ -683,5 +682,7 @@ "support_title_guides": "Kek Cüzdan Kılavuzları", "support_description_guides": "Ortak sorunlara belge ve destek", "support_title_other_links": "Diğer destek bağlantıları", - "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın" + "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın", + "select_destination": "Lütfen yedekleme dosyası için hedef seçin.", + "save_to_downloads": "İndirilenlere Kaydet" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index d6e121279..6d9a648fa 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -634,18 +634,18 @@ "setup_totp_recommended": "Налаштувати TOTP (рекомендовано)", "disable_buy": "Вимкнути дію покупки", "disable_sell": "Вимкнути дію продажу", - "cake_2fa_preset" : "Торт 2FA Preset", + "cake_2fa_preset": "Торт 2FA Preset", "narrow": "вузькі", "normal": "нормальний", "aggressive": "Надто старанний", "require_for_assessing_wallet": "Потрібен доступ до гаманця", - "require_for_sends_to_non_contacts" : "Вимагати для надсилання неконтактним особам", - "require_for_sends_to_contacts" : "Вимагати для надсилання контактам", - "require_for_sends_to_internal_wallets" : "Вимагати надсилання на внутрішні гаманці", - "require_for_exchanges_to_internal_wallets" : "Вимагати обміну на внутрішні гаманці", - "require_for_adding_contacts" : "Потрібен для додавання контактів", - "require_for_creating_new_wallets" : "Потрібно для створення нових гаманців", - "require_for_all_security_and_backup_settings" : "Вимагати всіх налаштувань безпеки та резервного копіювання", + "require_for_sends_to_non_contacts": "Вимагати для надсилання неконтактним особам", + "require_for_sends_to_contacts": "Вимагати для надсилання контактам", + "require_for_sends_to_internal_wallets": "Вимагати надсилання на внутрішні гаманці", + "require_for_exchanges_to_internal_wallets": "Вимагати обміну на внутрішні гаманці", + "require_for_adding_contacts": "Потрібен для додавання контактів", + "require_for_creating_new_wallets": "Потрібно для створення нових гаманців", + "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", "available_balance_description": "Це сума, яку ви можете витратити, не включаючи невизначені кошти. Це може бути менше, ніж загальний баланс, якщо ви витратили кошти, які ще не підтверджені.", "syncing_wallet_alert_title": "Ваш гаманець синхронізується", "syncing_wallet_alert_content": "Ваш баланс та список транзакцій може бути неповним, доки вгорі не буде написано «СИНХРОНІЗОВАНО». Натисніть/торкніться, щоб дізнатися більше.", @@ -684,5 +684,7 @@ "support_title_guides": "Поклики для гаманців тортів", "support_description_guides": "Документація та підтримка загальних питань", "support_title_other_links": "Інші посилання на підтримку", - "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами" + "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", + "select_destination": "Виберіть місце призначення для файлу резервної копії.", + "save_to_downloads": "Зберегти до завантажень" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a24545501..39cae33d0 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -676,5 +676,7 @@ "support_title_guides": "کیک پرس گائڈز", "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", "support_title_other_links": "دوسرے سپورٹ لنکس", - "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں" + "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", + "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", + "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index d406aec86..75df8de6b 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -678,5 +678,7 @@ "bitcoin_light_theme": "Bitcoin Light Akori", "high_contrast_theme": "Akori Iyatọ giga", "matrix_green_dark_theme": "Matrix Green Dark Akori", - "monero_light_theme": "Monero Light Akori" + "monero_light_theme": "Monero Light Akori", + "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", + "save_to_downloads": "Fipamọ si Awọn igbasilẹ" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8e04bf2bc..3fa31bb10 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -683,5 +683,7 @@ "bitcoin_light_theme": "比特币浅色主题", "high_contrast_theme": "高对比度主题", "matrix_green_dark_theme": "矩阵绿暗主题", - "monero_light_theme": "门罗币浅色主题" + "monero_light_theme": "门罗币浅色主题", + "select_destination": "请选择备份文件的目的地。", + "save_to_downloads": "保存到下载" } From 43cf8a896eeac53f71b11bcd468dd453c4acbcbb Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 23 Aug 2023 00:05:48 +0100 Subject: [PATCH 07/18] fix: Rotate TOTP Secret (#1056) --- lib/view_model/set_up_2fa_viewmodel.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/view_model/set_up_2fa_viewmodel.dart b/lib/view_model/set_up_2fa_viewmodel.dart index 96a0c4a20..0b4b614ab 100644 --- a/lib/view_model/set_up_2fa_viewmodel.dart +++ b/lib/view_model/set_up_2fa_viewmodel.dart @@ -96,9 +96,7 @@ abstract class Setup2FAViewModelBase with Store { @action void _setBase32SecretKey(String value) { - if (_settingsStore.totpSecretKey == '') { - _settingsStore.totpSecretKey = value; - } + _settingsStore.totpSecretKey = value; } @action From 3577730de8cd84cec50f0b1722615218f90b1a82 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Wed, 23 Aug 2023 15:33:20 +0300 Subject: [PATCH 08/18] Add restore from private key to Ethereum (#1055) * Add restore from private key to Ethereum Add restore from QR code for Ethereum in both seeds/keys * Add node network issue to ignored errors [skip ci] --- cw_core/lib/wallet_base.dart | 4 +- cw_ethereum/lib/ethereum_wallet.dart | 53 +++++-- .../ethereum_wallet_creation_credentials.dart | 16 +- cw_ethereum/lib/ethereum_wallet_service.dart | 16 +- ios/Podfile.lock | 8 +- lib/di.dart | 21 --- lib/ethereum/cw_ethereum.dart | 8 + lib/router.dart | 12 -- lib/routes.dart | 1 - .../restore_wallet_from_seed_details.dart | 145 ------------------ .../wallet_restore_from_keys_form.dart | 132 +++++++++++----- .../screens/restore/wallet_restore_page.dart | 33 ++-- lib/src/widgets/seed_widget.dart | 7 - lib/utils/exception_handler.dart | 1 + .../dashboard/dashboard_view_model.dart | 4 +- .../restore/restore_from_qr_vm.dart | 3 + lib/view_model/restore/restore_wallet.dart | 5 +- .../restore/wallet_restore_from_qr_code.dart | 14 ++ lib/view_model/wallet_keys_view_model.dart | 21 ++- .../wallet_restoration_from_keys_vm.dart | 77 ---------- .../wallet_restoration_from_seed_vm.dart | 58 ------- lib/view_model/wallet_restore_view_model.dart | 41 +++-- lib/view_model/wallet_seed_view_model.dart | 2 +- tool/configure.dart | 1 + 24 files changed, 250 insertions(+), 433 deletions(-) delete mode 100644 lib/src/screens/restore/restore_wallet_from_seed_details.dart delete mode 100644 lib/view_model/wallet_restoration_from_keys_vm.dart delete mode 100644 lib/view_model/wallet_restoration_from_seed_vm.dart diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 019f87631..5bc5ef914 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -42,7 +42,9 @@ abstract class WalletBase< set syncStatus(SyncStatus status); - String get seed; + String? get seed; + + String? get privateKey => null; Object get keys; diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 404b78ca2..8d7c477e1 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -44,12 +44,14 @@ abstract class EthereumWalletBase with Store { EthereumWalletBase({ required WalletInfo walletInfo, - required String mnemonic, + String? mnemonic, + String? privateKey, required String password, ERC20Balance? initialBalance, }) : syncStatus = NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, + _hexPrivateKey = privateKey, _isTransactionUpdating = false, _client = EthereumClient(), walletAddresses = EthereumWalletAddresses(walletInfo), @@ -66,12 +68,13 @@ abstract class EthereumWalletBase _sharedPrefs.complete(SharedPreferences.getInstance()); } - final String _mnemonic; + final String? _mnemonic; + final String? _hexPrivateKey; final String _password; late final Box<Erc20Token> erc20TokensBox; - late final EthPrivateKey _privateKey; + late final EthPrivateKey _ethPrivateKey; late EthereumClient _client; @@ -99,8 +102,12 @@ abstract class EthereumWalletBase erc20TokensBox = await CakeHive.openBox<Erc20Token>(Erc20Token.boxName); await walletAddresses.init(); await transactionHistory.init(); - _privateKey = await getPrivateKey(_mnemonic, _password); - walletAddresses.address = _privateKey.address.toString(); + _ethPrivateKey = await getPrivateKey( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + password: _password, + ); + walletAddresses.address = _ethPrivateKey.address.toString(); await save(); } @@ -108,8 +115,7 @@ abstract class EthereumWalletBase int calculateEstimatedFee(TransactionPriority priority, int? amount) { try { if (priority is EthereumTransactionPriority) { - final priorityFee = - EtherAmount.fromUnitAndValue(EtherUnit.gwei, priority.tip).getInWei.toInt(); + final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); } @@ -142,7 +148,7 @@ abstract class EthereumWalletBase throw Exception("Ethereum Node connection failed"); } - _client.setListeners(_privateKey.address, _onNewTransaction); + _client.setListeners(_ethPrivateKey.address, _onNewTransaction); _setTransactionUpdateTimer(); @@ -202,7 +208,7 @@ abstract class EthereumWalletBase } final pendingEthereumTransaction = await _client.signTransaction( - privateKey: _privateKey, + privateKey: _ethPrivateKey, toAddress: _credentials.outputs.first.isParsedAddress ? _credentials.outputs.first.extractedAddress! : _credentials.outputs.first.address, @@ -240,7 +246,7 @@ abstract class EthereumWalletBase @override Future<Map<String, EthereumTransactionInfo>> fetchTransactions() async { - final address = _privateKey.address.hex; + final address = _ethPrivateKey.address.hex; final transactions = await _client.fetchTransactions(address); final List<Future<List<EthereumTransactionModel>>> erc20TokensTransactions = []; @@ -300,7 +306,10 @@ abstract class EthereumWalletBase } @override - String get seed => _mnemonic; + String? get seed => _mnemonic; + + @override + String get privateKey => HEX.encode(_ethPrivateKey.privateKey); @action @override @@ -327,6 +336,7 @@ abstract class EthereumWalletBase String toJSON() => json.encode({ 'mnemonic': _mnemonic, + 'private_key': privateKey, 'balance': balance[currency]!.toJSON(), }); @@ -338,13 +348,15 @@ abstract class EthereumWalletBase final path = await pathForWallet(name: name, type: walletInfo.type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; - final mnemonic = data['mnemonic'] as String; + final mnemonic = data['mnemonic'] as String?; + final privateKey = data['private_key'] as String?; final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero); return EthereumWallet( walletInfo: walletInfo, password: password, mnemonic: mnemonic, + privateKey: privateKey, initialBalance: balance, ); } @@ -357,7 +369,7 @@ abstract class EthereumWalletBase } Future<ERC20Balance> _fetchEthBalance() async { - final balance = await _client.getBalance(_privateKey.address); + final balance = await _client.getBalance(_ethPrivateKey.address); return ERC20Balance(balance.getInWei); } @@ -366,7 +378,7 @@ abstract class EthereumWalletBase try { if (token.enabled) { balance[token] = await _client.fetchERC20Balances( - _privateKey.address, + _ethPrivateKey.address, token.contractAddress, ); } else { @@ -376,8 +388,15 @@ abstract class EthereumWalletBase } } - Future<EthPrivateKey> getPrivateKey(String mnemonic, String password) async { - final seed = bip39.mnemonicToSeed(mnemonic); + Future<EthPrivateKey> getPrivateKey( + {String? mnemonic, String? privateKey, required String password}) async { + assert(mnemonic != null || privateKey != null); + + if (privateKey != null) { + return EthPrivateKey.fromHex(privateKey); + } + + final seed = bip39.mnemonicToSeed(mnemonic!); final root = bip32.BIP32.fromSeed(seed); @@ -413,7 +432,7 @@ abstract class EthereumWalletBase if (_token.enabled) { balance[_token] = await _client.fetchERC20Balances( - _privateKey.address, + _ethPrivateKey.address, _token.contractAddress, ); } else { diff --git a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart b/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart index 12d0d53e2..6546f2fae 100644 --- a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart +++ b/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart @@ -8,16 +8,22 @@ class EthereumNewWalletCredentials extends WalletCredentials { class EthereumRestoreWalletFromSeedCredentials extends WalletCredentials { EthereumRestoreWalletFromSeedCredentials( - {required String name, required String password, required this.mnemonic, WalletInfo? walletInfo}) + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) : super(name: name, password: password, walletInfo: walletInfo); final String mnemonic; } -class EthereumRestoreWalletFromWIFCredentials extends WalletCredentials { - EthereumRestoreWalletFromWIFCredentials( - {required String name, required String password, required this.wif, WalletInfo? walletInfo}) +class EthereumRestoreWalletFromPrivateKey extends WalletCredentials { + EthereumRestoreWalletFromPrivateKey( + {required String name, + required String password, + required this.privateKey, + WalletInfo? walletInfo}) : super(name: name, password: password, walletInfo: walletInfo); - final String wif; + final String privateKey; } diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 318f287fc..16dbc0b04 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -13,7 +13,7 @@ import 'package:bip39/bip39.dart' as bip39; import 'package:collection/collection.dart'; class EthereumWalletService extends WalletService<EthereumNewWalletCredentials, - EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> { + EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromPrivateKey> { EthereumWalletService(this.walletInfoSource); final Box<WalletInfo> walletInfoSource; @@ -66,8 +66,18 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials, } @override - Future<EthereumWallet> restoreFromKeys(credentials) { - throw UnimplementedError(); + Future<EthereumWallet> restoreFromKeys(EthereumRestoreWalletFromPrivateKey credentials) async { + final wallet = EthereumWallet( + password: credentials.password!, + privateKey: credentials.privateKey, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; } @override diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f13c68629..6f441c587 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -174,12 +174,12 @@ DEPENDENCIES: - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - platform_device_id (from `.symlinks/plugins/platform_device_id/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -236,7 +236,7 @@ EXTERNAL SOURCES: package_info: :path: ".symlinks/plugins/package_info/ios" path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/ios" + :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" platform_device_id: @@ -246,7 +246,7 @@ EXTERNAL SOURCES: share_plus: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/ios" + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: diff --git a/lib/di.dart b/lib/di.dart index 2a54c85a3..c37575337 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -177,8 +177,6 @@ import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; -import 'package:cake_wallet/view_model/wallet_restoration_from_keys_vm.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/wallet_type.dart'; @@ -320,25 +318,6 @@ Future setup({ getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource, type: type)); - getIt.registerFactoryParam<WalletRestorationFromSeedVM, List, void>((args, _) { - final type = args.first as WalletType; - final language = args[1] as String; - final mnemonic = args[2] as String; - - return WalletRestorationFromSeedVM( - getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource, - type: type, language: language, seed: mnemonic); - }); - - getIt.registerFactoryParam<WalletRestorationFromKeysVM, List, void>((args, _) { - final type = args.first as WalletType; - final language = args[1] as String; - - return WalletRestorationFromKeysVM( - getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource, - type: type, language: language); - }); - getIt.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource, type); diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index f38cafbbd..f2db7741e 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -22,6 +22,14 @@ class CWEthereum extends Ethereum { }) => EthereumRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + @override + WalletCredentials createEthereumRestoreWalletFromPrivateKey({ + required String name, + required String privateKey, + required String password, + }) => + EthereumRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + @override String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address; diff --git a/lib/router.dart b/lib/router.dart index 7d63ad1ea..0ef91e16f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -57,7 +57,6 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; -import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -80,7 +79,6 @@ import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_c import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; import 'package:cake_wallet/src/screens/contact/contact_page.dart'; import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; -import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; import 'package:cake_wallet/src/screens/faq/faq_page.dart'; @@ -398,16 +396,6 @@ Route<dynamic> createRoute(RouteSettings settings) { builder: (_) => getIt.get<BuyWebViewPage>(param1: args)); - case Routes.restoreWalletFromSeedDetails: - final args = settings.arguments as List; - final walletRestorationFromSeedVM = - getIt.get<WalletRestorationFromSeedVM>(param1: args); - - return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => RestoreWalletFromSeedDetailsPage( - walletRestorationFromSeedVM: walletRestorationFromSeedVM)); - case Routes.exchange: return CupertinoPageRoute<void>( fullscreenDialog: true, diff --git a/lib/routes.dart b/lib/routes.dart index 62c303ce8..bcb4c38b5 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -30,7 +30,6 @@ class Routes { static const tradeDetails = '/trade_details'; static const exchangeFunds = '/exchange_funds'; static const exchangeTrade = '/exchange_trade'; - static const restoreWalletFromSeedDetails = '/restore_from_seed_details'; static const exchange = '/exchange'; static const settings = '/settings'; static const desktop_settings_page = '/desktop_settings_page'; diff --git a/lib/src/screens/restore/restore_wallet_from_seed_details.dart b/lib/src/screens/restore/restore_wallet_from_seed_details.dart deleted file mode 100644 index 8d08c441d..000000000 --- a/lib/src/screens/restore/restore_wallet_from_seed_details.dart +++ /dev/null @@ -1,145 +0,0 @@ -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:mobx/mobx.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/wallet_name_validator.dart'; -import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; - -class RestoreWalletFromSeedDetailsPage extends BasePage { - RestoreWalletFromSeedDetailsPage( - {required this.walletRestorationFromSeedVM}); - - final WalletRestorationFromSeedVM walletRestorationFromSeedVM; - - @override - String get title => S.current.restore_wallet_restore_description; - - @override - Widget body(BuildContext context) => RestoreFromSeedDetailsForm( - walletRestorationFromSeedVM: walletRestorationFromSeedVM); -} - -class RestoreFromSeedDetailsForm extends StatefulWidget { - RestoreFromSeedDetailsForm({required this.walletRestorationFromSeedVM}); - - final WalletRestorationFromSeedVM walletRestorationFromSeedVM; - - @override - _RestoreFromSeedDetailsFormState createState() => - _RestoreFromSeedDetailsFormState(); -} - -class _RestoreFromSeedDetailsFormState - extends State<RestoreFromSeedDetailsForm> { - final _formKey = GlobalKey<FormState>(); - final _blockchainHeightKey = GlobalKey<BlockchainHeightState>(); - final _nameController = TextEditingController(); - ReactionDisposer? _stateReaction; - - @override - void initState() { - _stateReaction = reaction((_) => widget.walletRestorationFromSeedVM.state, - (ExecutionState state) { - if (state is ExecutedSuccessfullyState) { - Navigator.of(context).popUntil((route) => route.isFirst); - } - - if (state is FailureState) { - WidgetsBinding.instance.addPostFrameCallback((_) { - showPopUp<void>( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.current.restore_title_from_seed, - alertContent: state.error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - }); - } - }); - - _nameController.addListener( - () => widget.walletRestorationFromSeedVM.name = _nameController.text); - super.initState(); - } - - @override - void dispose() { - _nameController.dispose(); - _stateReaction?.reaction.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24.0), - content: Form( - key: _formKey, - child: Column(children: <Widget>[ - Row( - children: <Widget>[ - Flexible( - child: Container( - padding: EdgeInsets.only(top: 20.0), - child: BaseTextFormField( - controller: _nameController, - hintText: S.of(context).restore_wallet_name, - validator: WalletNameValidator(), - ), - )) - ], - ), - if (widget.walletRestorationFromSeedVM.hasRestorationHeight) ... [ - BlockchainHeightWidget( - key: _blockchainHeightKey, - onHeightChange: (height) { - widget.walletRestorationFromSeedVM.height = height; - print(height); - }), - Padding( - padding: EdgeInsets.only(left: 40, right: 40, top: 24), - child: Text( - S.of(context).restore_from_date_or_blockheight, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.normal, - color: Theme.of(context).hintColor - ), - ), - ) - ] - ]), - ), - bottomSectionPadding: EdgeInsets.only(bottom: 24), - bottomSection: Observer(builder: (_) { - return LoadingPrimaryButton( - onPressed: () { - if (_formKey.currentState != null && _formKey.currentState!.validate()) { - widget.walletRestorationFromSeedVM.create(); - } - }, - isLoading: - widget.walletRestorationFromSeedVM.state is IsExecutingState, - text: S.of(context).restore_recover, - color: Theme.of(context).primaryColor, - textColor: Colors.white, - isDisabled: _nameController.text.isNotEmpty, - ); - }), - ), - ); - } -} diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index 4712cfb10..a1e2a82f0 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -1,30 +1,29 @@ +import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_name_validator.dart'; import 'package:cake_wallet/entities/generate_name.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:flutter/services.dart'; class WalletRestoreFromKeysFrom extends StatefulWidget { WalletRestoreFromKeysFrom({ required this.walletRestoreViewModel, + required this.displayPrivateKeyField, + required this.onHeightOrDateEntered, Key? key, - this.onHeightOrDateEntered,}) - : super(key: key); + }) : super(key: key); - final Function(bool)? onHeightOrDateEntered; + final Function(bool) onHeightOrDateEntered; final WalletRestoreViewModel walletRestoreViewModel; + final bool displayPrivateKeyField; @override - WalletRestoreFromKeysFromState createState() => - WalletRestoreFromKeysFromState(); + WalletRestoreFromKeysFromState createState() => WalletRestoreFromKeysFromState(); } class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { @@ -35,6 +34,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { addressController = TextEditingController(), viewKeyController = TextEditingController(), spendKeyController = TextEditingController(), + privateKeyController = TextEditingController(), nameTextEditingController = TextEditingController(); final GlobalKey<FormState> formKey; @@ -44,6 +44,18 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { final TextEditingController viewKeyController; final TextEditingController spendKeyController; final TextEditingController nameTextEditingController; + final TextEditingController privateKeyController; + + @override + void initState() { + super.initState(); + + privateKeyController.addListener(() { + if (privateKeyController.text.isNotEmpty) { + widget.onHeightOrDateEntered(true); + } + }); + } @override void dispose() { @@ -51,16 +63,18 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { addressController.dispose(); viewKeyController.dispose(); spendKeyController.dispose(); + privateKeyController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: Form( - key: formKey, - child: Column(children: <Widget>[ + padding: EdgeInsets.only(left: 24, right: 24), + child: Form( + key: formKey, + child: Column( + children: <Widget>[ Stack( alignment: Alignment.centerRight, children: [ @@ -75,9 +89,8 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { setState(() { nameTextEditingController.text = rName; - nameTextEditingController.selection = - TextSelection.fromPosition(TextPosition( - offset: nameTextEditingController.text.length)); + nameTextEditingController.selection = TextSelection.fromPosition( + TextPosition(offset: nameTextEditingController.text.length)); }); }, icon: Container( @@ -90,7 +103,8 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { height: 34, child: Image.asset( 'assets/images/refresh_icon.png', - color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, + color: + Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor, ), ), ), @@ -98,29 +112,65 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { ], ), Container(height: 20), - BaseTextFormField( - controller: addressController, - keyboardType: TextInputType.multiline, - maxLines: null, - hintText: S.of(context).restore_address), - Container( - padding: EdgeInsets.only(top: 20.0), - child: BaseTextFormField( - controller: viewKeyController, - hintText: S.of(context).restore_view_key_private, - maxLines: null)), - Container( - padding: EdgeInsets.only(top: 20.0), - child: BaseTextFormField( - controller: spendKeyController, - hintText: S.of(context).restore_spend_key_private, - maxLines: null)), - BlockchainHeightWidget( - key: blockchainHeightKey, - hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven, - onHeightChange: (_) => null, - onHeightOrDateEntered: widget.onHeightOrDateEntered) - ]), - )); + _restoreFromKeysFormFields(), + ], + ), + ), + ); + } + + Widget _restoreFromKeysFormFields() { + if (widget.displayPrivateKeyField) { + return AddressTextField( + controller: privateKeyController, + placeholder: S.of(context).private_key, + options: [AddressTextFieldOption.paste], + buttonColor: Theme.of(context).hintColor, + onPushPasteButton: (_) { + _pasteText(); + }, + ); + } + + return Column( + children: [ + BaseTextFormField( + controller: addressController, + keyboardType: TextInputType.multiline, + maxLines: null, + hintText: S.of(context).restore_address, + ), + Container( + padding: EdgeInsets.only(top: 20.0), + child: BaseTextFormField( + controller: viewKeyController, + hintText: S.of(context).restore_view_key_private, + maxLines: null, + ), + ), + Container( + padding: EdgeInsets.only(top: 20.0), + child: BaseTextFormField( + controller: spendKeyController, + hintText: S.of(context).restore_spend_key_private, + maxLines: null, + ), + ), + BlockchainHeightWidget( + key: blockchainHeightKey, + hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven, + onHeightChange: (_) => null, + onHeightOrDateEntered: widget.onHeightOrDateEntered, + ), + ], + ); + } + + Future<void> _pasteText() async { + final value = await Clipboard.getData('text/plain'); + + if (value?.text?.isNotEmpty ?? false) { + privateKeyController.text = value!.text!; + } } } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 10b5a521d..bea84a7c9 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -1,10 +1,7 @@ import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; @@ -19,10 +16,6 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.da import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/core/validator.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/core/seed_validator.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; @@ -76,6 +69,7 @@ class WalletRestorePage extends BasePage { _pages.add(WalletRestoreFromKeysFrom( key: walletRestoreFromKeysFormKey, walletRestoreViewModel: walletRestoreViewModel, + displayPrivateKeyField: walletRestoreViewModel.hasRestoreFromPrivateKey, onHeightOrDateEntered: (value) => walletRestoreViewModel.isButtonEnabled = value)); break; default: @@ -193,8 +187,12 @@ class WalletRestorePage extends BasePage { return LoadingPrimaryButton( onPressed: _confirmForm, text: S.of(context).restore_recover, - color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor, - textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor, + color: Theme.of(context) + .extension<WalletListTheme>()! + .createNewWalletButtonBackgroundColor, + textColor: Theme.of(context) + .extension<WalletListTheme>()! + .restoreWalletButtonTextColor, isLoading: walletRestoreViewModel.state is IsExecutingState, isDisabled: !walletRestoreViewModel.isButtonEnabled, ); @@ -246,11 +244,18 @@ class WalletRestorePage extends BasePage { credentials['name'] = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text; } else { - credentials['address'] = walletRestoreFromKeysFormKey.currentState!.addressController.text; - credentials['viewKey'] = walletRestoreFromKeysFormKey.currentState!.viewKeyController.text; - credentials['spendKey'] = walletRestoreFromKeysFormKey.currentState!.spendKeyController.text; - credentials['height'] = - walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState!.height; + if (walletRestoreViewModel.hasRestoreFromPrivateKey) { + credentials['private_key'] = + walletRestoreFromKeysFormKey.currentState!.privateKeyController.text; + } else { + credentials['address'] = walletRestoreFromKeysFormKey.currentState!.addressController.text; + credentials['viewKey'] = walletRestoreFromKeysFormKey.currentState!.viewKeyController.text; + credentials['spendKey'] = + walletRestoreFromKeysFormKey.currentState!.spendKeyController.text; + credentials['height'] = + walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState!.height; + } + credentials['name'] = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.text; } diff --git a/lib/src/widgets/seed_widget.dart b/lib/src/widgets/seed_widget.dart index ddafa924b..7015e0acf 100644 --- a/lib/src/widgets/seed_widget.dart +++ b/lib/src/widgets/seed_widget.dart @@ -1,16 +1,9 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart'; -import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/core/seed_validator.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/entities/mnemonic_item.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:flutter/widgets.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; class SeedWidget extends StatefulWidget { diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index 9d9328879..e8e7702fa 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -148,6 +148,7 @@ class ExceptionHandler { "CERTIFICATE_VERIFY_FAILED", "Handshake error in client", "Error while launching http", + "OS Error: Network is unreachable", ]; static Future<void> _addDeviceInfo(File file) async { diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 49bb5304e..7035130c0 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -107,7 +107,7 @@ abstract class DashboardViewModelBase with Store { name = wallet.name; type = wallet.type; isOutdatedElectrumWallet = - wallet.type == WalletType.bitcoin && wallet.seed.split(' ').length < 24; + wallet.type == WalletType.bitcoin && wallet.seed!.split(' ').length < 24; isShowFirstYatIntroduction = false; isShowSecondYatIntroduction = false; isShowThirdYatIntroduction = false; @@ -327,7 +327,7 @@ abstract class DashboardViewModelBase with Store { type = wallet.type; name = wallet.name; isOutdatedElectrumWallet = - wallet.type == WalletType.bitcoin && wallet.seed.split(' ').length < 24; + wallet.type == WalletType.bitcoin && wallet.seed!.split(' ').length < 24; updateActions(); if (wallet.type == WalletType.monero) { diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 996b3b3fb..39a7b682f 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -66,6 +66,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromWIFCredentials( name: name, password: password, wif: wif); + case WalletType.ethereum: + return ethereum!.createEthereumRestoreWalletFromPrivateKey( + name: name, password: password, privateKey: restoreWallet.privateKey!); default: throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); } diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart index 0f872d8cc..264b3d421 100644 --- a/lib/view_model/restore/restore_wallet.dart +++ b/lib/view_model/restore/restore_wallet.dart @@ -13,7 +13,8 @@ class RestoredWallet { this.txAmount, this.txDescription, this.recipientName, - this.height}); + this.height, + this.privateKey}); final WalletRestoreMode restoreMode; final WalletType type; @@ -26,6 +27,7 @@ class RestoredWallet { final String? txDescription; final String? recipientName; final int? height; + final String? privateKey; factory RestoredWallet.fromKey(Map<String, dynamic> json) { final height = json['height'] as String?; @@ -36,6 +38,7 @@ class RestoredWallet { spendKey: json['spend_key'] as String?, viewKey: json['view_key'] as String?, height: height != null ? int.parse(height) : 0, + privateKey: json['private_key'] as String?, ); } diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index c4b772f9c..e9aed55c6 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -33,7 +33,10 @@ class WalletRestoreFromQRCode { getSeedPhraseFromUrl(queryParameters.toString(), credentials['type'] as WalletType); if (seed != null) { credentials['seed'] = seed; + } else { + credentials['private_key'] = queryParameters['private_key']; } + credentials.addAll(queryParameters); credentials['mode'] = getWalletRestoreMode(credentials); @@ -69,6 +72,8 @@ class WalletRestoreFromQRCode { case 'litecoin': case 'litecoin-wallet': return WalletType.litecoin; + case 'ethereum-wallet': + return WalletType.ethereum; default: throw Exception('Unexpected wallet type: ${scheme.toString()}'); } @@ -101,6 +106,7 @@ class WalletRestoreFromQRCode { } case WalletType.bitcoin: case WalletType.litecoin: + case WalletType.ethereum: RegExp regex24 = RegExp(r'\b(\S+\b\s+){23}\S+\b'); RegExp regex18 = RegExp(r'\b(\S+\b\s+){17}\S+\b'); RegExp regex12 = RegExp(r'\b(\S+\b\s+){11}\S+\b'); @@ -152,6 +158,14 @@ class WalletRestoreFromQRCode { : throw Exception('Unexpected restore mode: spend_key or view_key is invalid'); } + if (type == WalletType.ethereum && credentials.containsKey('private_key')) { + final privateKey = credentials['private_key'] as String; + if (privateKey.isEmpty) { + throw Exception('Unexpected restore mode: private_key'); + } + return WalletRestoreMode.keys; + } + throw Exception('Unexpected restore mode: restore params are invalid'); } } diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index 0a758ccfb..0233e13e9 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -69,7 +69,7 @@ abstract class WalletKeysViewModelBase with Store { StandartListItem(title: S.current.view_key_public, value: keys['publicViewKey']!), if (keys['privateViewKey'] != null) StandartListItem(title: S.current.view_key_private, value: keys['privateViewKey']!), - StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed), + StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); } @@ -85,15 +85,23 @@ abstract class WalletKeysViewModelBase with Store { StandartListItem(title: S.current.view_key_public, value: keys['publicViewKey']!), if (keys['privateViewKey'] != null) StandartListItem(title: S.current.view_key_private, value: keys['privateViewKey']!), - StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed), + StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); } if (_appStore.wallet!.type == WalletType.bitcoin || - _appStore.wallet!.type == WalletType.litecoin || - _appStore.wallet!.type == WalletType.ethereum) { + _appStore.wallet!.type == WalletType.litecoin) { items.addAll([ - StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed), + StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), + ]); + } + + if (_appStore.wallet!.type == WalletType.ethereum) { + items.addAll([ + if (_appStore.wallet!.privateKey != null) + StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!), + if (_appStore.wallet!.seed != null) + StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); } } @@ -139,7 +147,8 @@ abstract class WalletKeysViewModelBase with Store { Future<Map<String, String>> get _queryParams async { final restoreHeightResult = await restoreHeight; return { - 'seed': _appStore.wallet!.seed, + if (_appStore.wallet!.seed != null) 'seed': _appStore.wallet!.seed!, + if (_appStore.wallet!.privateKey != null) 'private_key': _appStore.wallet!.privateKey!, if (restoreHeightResult != null) ...{'height': restoreHeightResult} }; } diff --git a/lib/view_model/wallet_restoration_from_keys_vm.dart b/lib/view_model/wallet_restoration_from_keys_vm.dart deleted file mode 100644 index 97cb8d519..000000000 --- a/lib/view_model/wallet_restoration_from_keys_vm.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cake_wallet/core/generate_wallet_password.dart'; -import 'package:cake_wallet/core/wallet_creation_service.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; - -part 'wallet_restoration_from_keys_vm.g.dart'; - -class WalletRestorationFromKeysVM = WalletRestorationFromKeysVMBase - with _$WalletRestorationFromKeysVM; - -abstract class WalletRestorationFromKeysVMBase extends WalletCreationVM - with Store { - WalletRestorationFromKeysVMBase(AppStore appStore, - WalletCreationService walletCreationService, Box<WalletInfo> walletInfoSource, - {required WalletType type, required this.language}) - : height = 0, - viewKey = '', - spendKey = '', - wif = '', - address = '', - super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true); - - @observable - int height; - - @observable - String viewKey; - - @observable - String spendKey; - - @observable - String wif; - - @observable - String address; - - bool get hasRestorationHeight => type == WalletType.monero; - - final String language; - - @override - WalletCredentials getCredentials(dynamic options) { - final password = generateWalletPassword(); - - switch (type) { - case WalletType.monero: - return monero!.createMoneroRestoreWalletFromKeysCredentials( - name: name, - password: password, - language: language, - address: address, - viewKey: viewKey, - spendKey: spendKey, - height: height); - case WalletType.bitcoin: - return bitcoin!.createBitcoinRestoreWalletFromWIFCredentials( - name: name, password: password, wif: wif); - default: - throw Exception('Unexpected type: ${type.toString()}'); - } - } - - @override - Future<WalletBase> process(WalletCredentials credentials) async => - walletCreationService.restoreFromKeys(credentials); -} diff --git a/lib/view_model/wallet_restoration_from_seed_vm.dart b/lib/view_model/wallet_restoration_from_seed_vm.dart deleted file mode 100644 index 0caa7f37d..000000000 --- a/lib/view_model/wallet_restoration_from_seed_vm.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cake_wallet/core/generate_wallet_password.dart'; -import 'package:cake_wallet/core/wallet_creation_service.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; -import 'package:cw_core/wallet_info.dart'; - -part 'wallet_restoration_from_seed_vm.g.dart'; - -class WalletRestorationFromSeedVM = WalletRestorationFromSeedVMBase - with _$WalletRestorationFromSeedVM; - -abstract class WalletRestorationFromSeedVMBase extends WalletCreationVM - with Store { - WalletRestorationFromSeedVMBase(AppStore appStore, - WalletCreationService walletCreationService, Box<WalletInfo> walletInfoSource, - {required WalletType type, required this.language, this.seed = ''}) - : height = 0, - super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true); - - @observable - String seed; - - @observable - int height; - - bool get hasRestorationHeight => type == WalletType.monero; - - final String language; - - @override - WalletCredentials getCredentials(dynamic options) { - final password = generateWalletPassword(); - - switch (type) { - case WalletType.monero: - return monero!.createMoneroRestoreWalletFromSeedCredentials( - name: name, height: height, mnemonic: seed, password: password); - case WalletType.bitcoin: - return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password); - default: - throw Exception('Unexpected type: ${type.toString()}'); - } - } - - @override - Future<WalletBase> process(WalletCredentials credentials) async => - walletCreationService.restoreFromSeed(credentials); -} diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 6bf87f22c..65f122bf0 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -1,7 +1,4 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/core/mnemonic_length.dart'; -import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -19,7 +16,6 @@ import 'package:cake_wallet/view_model/restore/restore_mode.dart'; part 'wallet_restore_view_model.g.dart'; - class WalletRestoreViewModel = WalletRestoreViewModelBase with _$WalletRestoreViewModel; @@ -27,11 +23,13 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { WalletRestoreViewModelBase(AppStore appStore, WalletCreationService walletCreationService, Box<WalletInfo> walletInfoSource, {required WalletType type}) - : availableModes = (type == WalletType.monero || type == WalletType.haven) - ? WalletRestoreMode.values - : [WalletRestoreMode.seed], + : availableModes = + (type == WalletType.monero || type == WalletType.haven || type == WalletType.ethereum) + ? WalletRestoreMode.values + : [WalletRestoreMode.seed], hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven, hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven, + hasRestoreFromPrivateKey = type == WalletType.ethereum, isButtonEnabled = false, mode = WalletRestoreMode.seed, super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) { @@ -47,13 +45,14 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { final List<WalletRestoreMode> availableModes; final bool hasSeedLanguageSelector; final bool hasBlockchainHeightLanguageSelector; + final bool hasRestoreFromPrivateKey; @observable WalletRestoreMode mode; @observable bool isButtonEnabled; - + @override WalletCredentials getCredentials(dynamic options) { final password = generateWalletPassword(); @@ -97,17 +96,17 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { } if (mode == WalletRestoreMode.keys) { - final viewKey = options['viewKey'] as String; - final spendKey = options['spendKey'] as String; - final address = options['address'] as String; + final viewKey = options['viewKey'] as String?; + final spendKey = options['spendKey'] as String?; + final address = options['address'] as String?; if (type == WalletType.monero) { return monero!.createMoneroRestoreWalletFromKeysCredentials( name: name, height: height, - spendKey: spendKey, - viewKey: viewKey, - address: address, + spendKey: spendKey!, + viewKey: viewKey!, + address: address!, password: password, language: 'English'); } @@ -116,12 +115,20 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { return haven!.createHavenRestoreWalletFromKeysCredentials( name: name, height: height, - spendKey: spendKey, - viewKey: viewKey, - address: address, + spendKey: spendKey!, + viewKey: viewKey!, + address: address!, password: password, language: 'English'); } + + if (type == WalletType.ethereum) { + return ethereum!.createEthereumRestoreWalletFromPrivateKey( + name: name, + privateKey: options['private_key'] as String, + password: password, + ); + } } throw Exception('Unexpected type: ${type.toString()}'); diff --git a/lib/view_model/wallet_seed_view_model.dart b/lib/view_model/wallet_seed_view_model.dart index 4a9c0009b..8923a99da 100644 --- a/lib/view_model/wallet_seed_view_model.dart +++ b/lib/view_model/wallet_seed_view_model.dart @@ -8,7 +8,7 @@ class WalletSeedViewModel = WalletSeedViewModelBase with _$WalletSeedViewModel; abstract class WalletSeedViewModelBase with Store { WalletSeedViewModelBase(WalletBase wallet) : name = wallet.name, - seed = wallet.seed; + seed = wallet.seed!; @observable String name; diff --git a/tool/configure.dart b/tool/configure.dart index 3d846e8a6..3893847e2 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -507,6 +507,7 @@ abstract class Ethereum { WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource); WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo}); WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); String getAddress(WalletBase wallet); TransactionPriority getDefaultTransactionPriority(); List<TransactionPriority> getTransactionPriorities(); From f6670c0236f1e5efaf124c9f2570df92d4563e46 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo <41484542+godilite@users.noreply.github.com> Date: Thu, 24 Aug 2023 16:54:05 +0300 Subject: [PATCH 09/18] CW-415 add coin control for xmr (#985) * Added CoinsInfo to monero_api_cpp * Add struct on dart * Add struct on dart * Set coins value * CW-415 Use add-coin-to-monero branch * CW-415 Add get Coin and build Monero Deps using Docker * CW-415 Fix Typo * CW-415 add debug log info * CW-415 Add preferred key Images for coin control to Monero * CW-415 Fix generation * CW-415 Skip GA Cache Externals * CW-415 Skip GA Cache Externals * CW-415 Coin Control: remove Block Explorer for Monero, Add Tx hash, save note on field exit * CW-415 Coin Control: Throw Exception when all outputs are deselected * CW-415 Coin Control: Show Frozen Balance on Dashboard * CW-415 Coin Control: Show Frozen Balance on Dashboard * CW-415 Ignore cached Monero deps in Workflow * CW-415 Fix displaying frozen Balance * Use own Translator with http 1.1.0 * CW-415 Resolve requested Changes * CW-415 Resolve requested Changes * CW-415 Resolve requested Changes * CW-415 Apply requested Changes * CW-415 Apply requested Changes * CW-415 Ensure opening of UnspentCoinsInfo Box, even for Monero.com --------- Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com> --- .github/workflows/pr_test_build.yml | 2 +- ...tcoin_transaction_no_inputs_exception.dart | 2 +- cw_core/lib/monero_balance.dart | 15 +- cw_core/lib/unspent_coins_info.dart | 7 +- cw_monero/ios/Classes/monero_api.cpp | 180 +++++- cw_monero/lib/api/coins_info.dart | 23 + cw_monero/lib/api/signatures.dart | 29 +- cw_monero/lib/api/structs/coins_info_row.dart | 73 +++ cw_monero/lib/api/transaction_history.dart | 101 ++-- cw_monero/lib/api/types.dart | 13 +- ...monero_transaction_creation_exception.dart | 0 ...onero_transaction_no_inputs_exception.dart | 4 + cw_monero/lib/monero_subaddress_list.dart | 4 +- cw_monero/lib/monero_unspent.dart | 28 + cw_monero/lib/monero_wallet.dart | 209 +++++-- cw_monero/lib/monero_wallet_service.dart | 33 +- lib/bitcoin/cw_bitcoin.dart | 5 +- lib/di.dart | 12 +- lib/entities/unspent_transaction_output.dart | 18 + lib/main.dart | 8 +- lib/monero/cw_monero.dart | 542 +++++++++--------- lib/src/screens/send/send_page.dart | 2 +- lib/src/screens/send/widgets/send_card.dart | 2 +- .../transaction_details_page.dart | 1 - .../widgets/textfield_list_row.dart | 13 +- .../unspent_coins_details_page.dart | 2 +- .../widgets/unspent_coins_list_item.dart | 2 +- lib/view_model/send/send_view_model.dart | 8 +- .../unspent_coins_details_view_model.dart | 26 +- .../unspent_coins/unspent_coins_item.dart | 9 +- .../unspent_coins_list_view_model.dart | 64 ++- pubspec_base.yaml | 5 +- res/values/strings_de.arb | 34 +- scripts/docker/.gitignore | 1 + scripts/docker/Dockerfile | 26 + scripts/docker/build_all.sh | 1 + scripts/docker/build_boost.sh | 16 + scripts/docker/build_haven.sh | 1 + scripts/docker/build_haven_all.sh | 1 + scripts/docker/build_iconv.sh | 38 ++ scripts/docker/build_monero.sh | 69 +++ scripts/docker/build_openssl.sh | 55 ++ scripts/docker/build_sodium.sh | 30 + scripts/docker/build_unbound.sh | 65 +++ scripts/docker/build_zmq.sh | 32 ++ scripts/docker/config.sh | 11 + scripts/docker/copy_haven_deps.sh | 45 ++ scripts/docker/copy_monero_deps.sh | 37 ++ scripts/docker/docker-compose.yml | 9 + scripts/docker/entrypoint.sh | 4 + scripts/docker/finish_boost.sh | 9 + scripts/docker/init_boost.sh | 22 + scripts/docker/install_ndk.sh | 18 + scripts/ios/build_monero.sh | 2 +- tool/append_translation.dart | 132 ++--- tool/configure.dart | 29 +- 56 files changed, 1584 insertions(+), 545 deletions(-) create mode 100644 cw_monero/lib/api/coins_info.dart create mode 100644 cw_monero/lib/api/structs/coins_info_row.dart rename cw_monero/lib/{ => exceptions}/monero_transaction_creation_exception.dart (100%) create mode 100644 cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart create mode 100644 cw_monero/lib/monero_unspent.dart create mode 100644 lib/entities/unspent_transaction_output.dart create mode 100644 scripts/docker/.gitignore create mode 100644 scripts/docker/Dockerfile create mode 100644 scripts/docker/build_all.sh create mode 100644 scripts/docker/build_boost.sh create mode 100644 scripts/docker/build_haven.sh create mode 100644 scripts/docker/build_haven_all.sh create mode 100644 scripts/docker/build_iconv.sh create mode 100644 scripts/docker/build_monero.sh create mode 100644 scripts/docker/build_openssl.sh create mode 100644 scripts/docker/build_sodium.sh create mode 100644 scripts/docker/build_unbound.sh create mode 100644 scripts/docker/build_zmq.sh create mode 100644 scripts/docker/config.sh create mode 100644 scripts/docker/copy_haven_deps.sh create mode 100644 scripts/docker/copy_monero_deps.sh create mode 100644 scripts/docker/docker-compose.yml create mode 100644 scripts/docker/entrypoint.sh create mode 100644 scripts/docker/finish_boost.sh create mode 100644 scripts/docker/init_boost.sh create mode 100644 scripts/docker/install_ndk.sh diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 7f70ce755..80d5d74aa 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -55,7 +55,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }} + key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh', '**/monero_api.cpp') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals diff --git a/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart b/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart index d4397dead..fac7e93c4 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart @@ -1,4 +1,4 @@ class BitcoinTransactionNoInputsException implements Exception { @override - String toString() => 'Not enough inputs available'; + String toString() => 'Not enough inputs available. Please select more under Coin Control'; } diff --git a/cw_core/lib/monero_balance.dart b/cw_core/lib/monero_balance.dart index 7d569ef2f..bf30110a3 100644 --- a/cw_core/lib/monero_balance.dart +++ b/cw_core/lib/monero_balance.dart @@ -2,24 +2,31 @@ import 'package:cw_core/balance.dart'; import 'package:cw_core/monero_amount_format.dart'; class MoneroBalance extends Balance { - MoneroBalance({required this.fullBalance, required this.unlockedBalance}) + MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0}) : formattedFullBalance = moneroAmountToString(amount: fullBalance), - formattedUnlockedBalance = - moneroAmountToString(amount: unlockedBalance), + formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance), + frozenFormatted = moneroAmountToString(amount: frozenBalance), super(unlockedBalance, fullBalance); MoneroBalance.fromString( {required this.formattedFullBalance, - required this.formattedUnlockedBalance}) + required this.formattedUnlockedBalance, + this.frozenFormatted = '0.0'}) : fullBalance = moneroParseAmount(amount: formattedFullBalance), unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance), + frozenBalance = moneroParseAmount(amount: frozenFormatted), super(moneroParseAmount(amount: formattedUnlockedBalance), moneroParseAmount(amount: formattedFullBalance)); final int fullBalance; final int unlockedBalance; + final int frozenBalance; final String formattedFullBalance; final String formattedUnlockedBalance; + final String frozenFormatted; + + @override + String get formattedFrozenBalance => frozenFormatted == '0.0' ? '' : frozenFormatted; @override String get formattedAvailableBalance => formattedUnlockedBalance; diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 33be2eb2c..68bbcbfd2 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -13,7 +13,9 @@ class UnspentCoinsInfo extends HiveObject { required this.noteRaw, required this.address, required this.vout, - required this.value}); + required this.value, + this.keyImage = null + }); static const typeId = UNSPENT_COINS_INFO_TYPE_ID; static const boxName = 'Unspent'; @@ -43,6 +45,9 @@ class UnspentCoinsInfo extends HiveObject { @HiveField(7, defaultValue: 0) int vout; + @HiveField(8, defaultValue: null) + String? keyImage; + String get note => noteRaw ?? ''; set note(String value) => noteRaw = value; diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 780fc5b14..66b8605c6 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -6,6 +6,7 @@ #include <fstream> #include <unistd.h> #include <mutex> +#include <list> #include "thread" #include "CwWalletListener.h" #if __APPLE__ @@ -182,6 +183,62 @@ extern "C" } }; + struct CoinsInfoRow + { + uint64_t blockHeight; + char *hash; + uint64_t internalOutputIndex; + uint64_t globalOutputIndex; + bool spent; + bool frozen; + uint64_t spentHeight; + uint64_t amount; + bool rct; + bool keyImageKnown; + uint64_t pkIndex; + uint32_t subaddrIndex; + uint32_t subaddrAccount; + char *address; + char *addressLabel; + char *keyImage; + uint64_t unlockTime; + bool unlocked; + char *pubKey; + bool coinbase; + char *description; + + CoinsInfoRow(Monero::CoinsInfo *coinsInfo) + { + blockHeight = coinsInfo->blockHeight(); + std::string *hash_str = new std::string(coinsInfo->hash()); + hash = strdup(hash_str->c_str()); + internalOutputIndex = coinsInfo->internalOutputIndex(); + globalOutputIndex = coinsInfo->globalOutputIndex(); + spent = coinsInfo->spent(); + frozen = coinsInfo->frozen(); + spentHeight = coinsInfo->spentHeight(); + amount = coinsInfo->amount(); + rct = coinsInfo->rct(); + keyImageKnown = coinsInfo->keyImageKnown(); + pkIndex = coinsInfo->pkIndex(); + subaddrIndex = coinsInfo->subaddrIndex(); + subaddrAccount = coinsInfo->subaddrAccount(); + address = strdup(coinsInfo->address().c_str()) ; + addressLabel = strdup(coinsInfo->addressLabel().c_str()); + keyImage = strdup(coinsInfo->keyImage().c_str()); + unlockTime = coinsInfo->unlockTime(); + unlocked = coinsInfo->unlocked(); + pubKey = strdup(coinsInfo->pubKey().c_str()); + coinbase = coinsInfo->coinbase(); + description = strdup(coinsInfo->description().c_str()); + } + + void setUnlocked(bool unlocked); + + }; + + Monero::Coins *m_coins; + Monero::Wallet *m_wallet; Monero::TransactionHistory *m_transaction_history; MoneroWalletListener *m_listener; @@ -189,6 +246,7 @@ extern "C" Monero::SubaddressAccount *m_account; uint64_t m_last_known_wallet_height; uint64_t m_cached_syncing_blockchain_height = 0; + std::list<Monero::CoinsInfo*> m_coins_info; std::mutex store_lock; bool is_storing = false; @@ -224,6 +282,17 @@ extern "C" { m_subaddress = nullptr; } + + m_coins_info = std::list<Monero::CoinsInfo*>(); + + if (wallet != nullptr) + { + m_coins = wallet->coins(); + } + else + { + m_coins = nullptr; + } } Monero::Wallet *get_current_wallet() @@ -487,9 +556,18 @@ extern "C" } bool transaction_create(char *address, char *payment_id, char *amount, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); + + std::set<std::string> _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw); std::string _payment_id; @@ -503,11 +581,11 @@ extern "C" if (amount != nullptr) { uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount)); - transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } else { - transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } int status = transaction->status(); @@ -527,7 +605,9 @@ extern "C" } bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); @@ -541,6 +621,13 @@ extern "C" amounts++; } + std::set<std::string> _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } + auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -800,6 +887,91 @@ extern "C" return m_wallet->trustedDaemon(); } + CoinsInfoRow* coin(int index) + { + if (index >= 0 && index < m_coins_info.size()) { + std::list<Monero::CoinsInfo*>::iterator it = m_coins_info.begin(); + std::advance(it, index); + Monero::CoinsInfo* element = *it; + std::cout << "Element at index " << index << ": " << element << std::endl; + return new CoinsInfoRow(element); + } else { + std::cout << "Invalid index." << std::endl; + return nullptr; // Return a default value (nullptr) for invalid index + } + } + + void refresh_coins(uint32_t accountIndex) + { + m_coins_info.clear(); + + m_coins->refresh(); + for (const auto i : m_coins->getAll()) { + if (i->subaddrAccount() == accountIndex && !(i->spent())) { + m_coins_info.push_back(i); + } + } + } + + uint64_t coins_count() + { + return m_coins_info.size(); + } + + CoinsInfoRow** coins_from_account(uint32_t accountIndex) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (coinInfo->subaddrAccount == accountIndex) { + matchingCoins.push_back(coinInfo); + } + } + + CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_txid(const char* txid, size_t* count) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (std::string(coinInfo->hash) == txid) { + matchingCoins.push_back(coinInfo); + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinsInfoRow = coin(i); + for (size_t j = 0; j < keyimageCount; j++) { + if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) { + matchingCoins.push_back(coinsInfoRow); + break; + } + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + #ifdef __cplusplus } #endif diff --git a/cw_monero/lib/api/coins_info.dart b/cw_monero/lib/api/coins_info.dart new file mode 100644 index 000000000..9a5303f9d --- /dev/null +++ b/cw_monero/lib/api/coins_info.dart @@ -0,0 +1,23 @@ +import 'dart:ffi'; +import 'package:cw_monero/api/signatures.dart'; +import 'package:cw_monero/api/structs/coins_info_row.dart'; +import 'package:cw_monero/api/types.dart'; +import 'package:cw_monero/api/monero_api.dart'; + +final refreshCoinsNative = moneroApi + .lookup<NativeFunction<refresh_coins>>('refresh_coins') + .asFunction<RefreshCoins>(); + +final coinsCountNative = moneroApi + .lookup<NativeFunction<coins_count>>('coins_count') + .asFunction<CoinsCount>(); + +final coinNative = moneroApi + .lookup<NativeFunction<coin>>('coin') + .asFunction<GetCoin>(); + +void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex); + +int countOfCoins() => coinsCountNative(); + +CoinsInfoRow getCoin(int index) => coinNative(index).ref; diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index 82bc7801e..e208414c8 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -1,4 +1,5 @@ import 'dart:ffi'; +import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -9,8 +10,8 @@ typedef create_wallet = Int8 Function( typedef restore_wallet_from_seed = Int8 Function( Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>); -typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, - Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>); +typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, + Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>); typedef is_wallet_exist = Int8 Function(Pointer<Utf8>); @@ -63,8 +64,7 @@ typedef subaddrress_refresh = Void Function(Int32); typedef subaddress_get_all = Pointer<Int64> Function(); -typedef subaddress_add_new = Void Function( - Int32 accountIndex, Pointer<Utf8> label); +typedef subaddress_add_new = Void Function(Int32 accountIndex, Pointer<Utf8> label); typedef subaddress_set_label = Void Function( Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label); @@ -77,8 +77,7 @@ typedef account_get_all = Pointer<Int64> Function(); typedef account_add_new = Void Function(Pointer<Utf8> label); -typedef account_set_label = Void Function( - Int32 accountIndex, Pointer<Utf8> label); +typedef account_set_label = Void Function(Int32 accountIndex, Pointer<Utf8> label); typedef transactions_refresh = Void Function(); @@ -94,6 +93,8 @@ typedef transaction_create = Int8 Function( Pointer<Utf8> amount, Int8 priorityRaw, Int32 subaddrAccount, + Pointer<Pointer<Utf8>> preferredInputs, + Int32 preferredInputsSize, Pointer<Utf8Box> error, Pointer<PendingTransactionRaw> pendingTransaction); @@ -104,6 +105,8 @@ typedef transaction_create_mult_dest = Int8 Function( Int32 size, Int8 priorityRaw, Int32 subaddrAccount, + Pointer<Pointer<Utf8>> preferredInputs, + Int32 preferredInputsSize, Pointer<Utf8Box> error, Pointer<PendingTransactionRaw> pendingTransaction); @@ -123,10 +126,16 @@ typedef on_startup = Void Function(); typedef rescan_blockchain = Void Function(); -typedef get_subaddress_label = Pointer<Utf8> Function( - Int32 accountIndex, - Int32 addressIndex); +typedef get_subaddress_label = Pointer<Utf8> Function(Int32 accountIndex, Int32 addressIndex); typedef set_trusted_daemon = Void Function(Int8 trusted); -typedef trusted_daemon = Int8 Function(); \ No newline at end of file +typedef trusted_daemon = Int8 Function(); + +typedef refresh_coins = Void Function(Int32 accountIndex); + +typedef coins_count = Int64 Function(); + +// typedef coins_from_txid = Pointer<CoinsInfoRow> Function(Pointer<Utf8> txid); + +typedef coin = Pointer<CoinsInfoRow> Function(Int32 index); diff --git a/cw_monero/lib/api/structs/coins_info_row.dart b/cw_monero/lib/api/structs/coins_info_row.dart new file mode 100644 index 000000000..ff6f6ce73 --- /dev/null +++ b/cw_monero/lib/api/structs/coins_info_row.dart @@ -0,0 +1,73 @@ +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; + +class CoinsInfoRow extends Struct { + @Int64() + external int blockHeight; + + external Pointer<Utf8> hash; + + @Uint64() + external int internalOutputIndex; + + @Uint64() + external int globalOutputIndex; + + @Int8() + external int spent; + + @Int8() + external int frozen; + + @Uint64() + external int spentHeight; + + @Uint64() + external int amount; + + @Int8() + external int rct; + + @Int8() + external int keyImageKnown; + + @Uint64() + external int pkIndex; + + @Uint32() + external int subaddrIndex; + + @Uint32() + external int subaddrAccount; + + external Pointer<Utf8> address; + + external Pointer<Utf8> addressLabel; + + external Pointer<Utf8> keyImage; + + @Uint64() + external int unlockTime; + + @Int8() + external int unlocked; + + external Pointer<Utf8> pubKey; + + @Int8() + external int coinbase; + + external Pointer<Utf8> description; + + String getHash() => hash.toDartString(); + + String getAddress() => address.toDartString(); + + String getAddressLabel() => addressLabel.toDartString(); + + String getKeyImage() => keyImage.toDartString(); + + String getPubKey() => pubKey.toDartString(); + + String getDescription() => description.toDartString(); +} diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index 0fc507500..6f848cb3d 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -35,9 +35,8 @@ final transactionCommitNative = moneroApi .lookup<NativeFunction<transaction_commit>>('transaction_commit') .asFunction<TransactionCommit>(); -final getTxKeyNative = moneroApi - .lookup<NativeFunction<get_tx_key>>('get_tx_key') - .asFunction<GetTxKey>(); +final getTxKeyNative = + moneroApi.lookup<NativeFunction<get_tx_key>>('get_tx_key').asFunction<GetTxKey>(); String getTxKey(String txId) { final txIdPointer = txId.toNativeUtf8(); @@ -71,10 +70,21 @@ PendingTransactionDescription createTransactionSync( required String paymentId, required int priorityRaw, String? amount, - int accountIndex = 0}) { + int accountIndex = 0, + List<String> preferredInputs = const []}) { final addressPointer = address.toNativeUtf8(); final paymentIdPointer = paymentId.toNativeUtf8(); final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr; + + final int preferredInputsSize = preferredInputs.length; + final List<Pointer<Utf8>> preferredInputsPointers = + preferredInputs.map((output) => output.toNativeUtf8()).toList(); + final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize); + + for (int i = 0; i < preferredInputsSize; i++) { + preferredInputsPointerPointer[i] = preferredInputsPointers[i]; + } + final errorMessagePointer = calloc<Utf8Box>(); final pendingTransactionRawPointer = calloc<PendingTransactionRaw>(); final created = transactionCreateNative( @@ -83,10 +93,16 @@ PendingTransactionDescription createTransactionSync( amountPointer, priorityRaw, accountIndex, + preferredInputsPointerPointer, + preferredInputsSize, errorMessagePointer, pendingTransactionRawPointer) != 0; + calloc.free(preferredInputsPointerPointer); + + preferredInputsPointers.forEach((element) => calloc.free(element)); + calloc.free(addressPointer); calloc.free(paymentIdPointer); @@ -111,15 +127,16 @@ PendingTransactionDescription createTransactionSync( PendingTransactionDescription createTransactionMultDestSync( {required List<MoneroOutput> outputs, - required String paymentId, - required int priorityRaw, - int accountIndex = 0}) { + required String paymentId, + required int priorityRaw, + int accountIndex = 0, + List<String> preferredInputs = const []}) { final int size = outputs.length; - final List<Pointer<Utf8>> addressesPointers = outputs.map((output) => - output.address.toNativeUtf8()).toList(); + final List<Pointer<Utf8>> addressesPointers = + outputs.map((output) => output.address.toNativeUtf8()).toList(); final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size); - final List<Pointer<Utf8>> amountsPointers = outputs.map((output) => - output.amount.toNativeUtf8()).toList(); + final List<Pointer<Utf8>> amountsPointers = + outputs.map((output) => output.amount.toNativeUtf8()).toList(); final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc(size); for (int i = 0; i < size; i++) { @@ -127,25 +144,38 @@ PendingTransactionDescription createTransactionMultDestSync( amountsPointerPointer[i] = amountsPointers[i]; } + final int preferredInputsSize = preferredInputs.length; + final List<Pointer<Utf8>> preferredInputsPointers = + preferredInputs.map((output) => output.toNativeUtf8()).toList(); + final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize); + + for (int i = 0; i < preferredInputsSize; i++) { + preferredInputsPointerPointer[i] = preferredInputsPointers[i]; + } + final paymentIdPointer = paymentId.toNativeUtf8(); final errorMessagePointer = calloc<Utf8Box>(); final pendingTransactionRawPointer = calloc<PendingTransactionRaw>(); final created = transactionCreateMultDestNative( - addressesPointerPointer, - paymentIdPointer, - amountsPointerPointer, - size, - priorityRaw, - accountIndex, - errorMessagePointer, - pendingTransactionRawPointer) != + addressesPointerPointer, + paymentIdPointer, + amountsPointerPointer, + size, + priorityRaw, + accountIndex, + preferredInputsPointerPointer, + preferredInputsSize, + errorMessagePointer, + pendingTransactionRawPointer) != 0; calloc.free(addressesPointerPointer); calloc.free(amountsPointerPointer); + calloc.free(preferredInputsPointerPointer); addressesPointers.forEach((element) => calloc.free(element)); amountsPointers.forEach((element) => calloc.free(element)); + preferredInputsPointers.forEach((element) => calloc.free(element)); calloc.free(paymentIdPointer); @@ -164,13 +194,12 @@ PendingTransactionDescription createTransactionMultDestSync( pointerAddress: pendingTransactionRawPointer.address); } -void commitTransactionFromPointerAddress({required int address}) => commitTransaction( - transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address)); +void commitTransactionFromPointerAddress({required int address}) => + commitTransaction(transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address)); void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) { final errorMessagePointer = calloc<Utf8Box>(); - final isCommited = - transactionCommitNative(transactionPointer, errorMessagePointer) != 0; + final isCommited = transactionCommitNative(transactionPointer, errorMessagePointer) != 0; if (!isCommited) { final message = errorMessagePointer.ref.getValue(); @@ -185,13 +214,15 @@ PendingTransactionDescription _createTransactionSync(Map args) { final amount = args['amount'] as String?; final priorityRaw = args['priorityRaw'] as int; final accountIndex = args['accountIndex'] as int; + final preferredInputs = args['preferredInputs'] as List<String>; return createTransactionSync( address: address, paymentId: paymentId, amount: amount, priorityRaw: priorityRaw, - accountIndex: accountIndex); + accountIndex: accountIndex, + preferredInputs: preferredInputs); } PendingTransactionDescription _createTransactionMultDestSync(Map args) { @@ -199,12 +230,14 @@ PendingTransactionDescription _createTransactionMultDestSync(Map args) { final paymentId = args['paymentId'] as String; final priorityRaw = args['priorityRaw'] as int; final accountIndex = args['accountIndex'] as int; + final preferredInputs = args['preferredInputs'] as List<String>; return createTransactionMultDestSync( outputs: outputs, paymentId: paymentId, priorityRaw: priorityRaw, - accountIndex: accountIndex); + accountIndex: accountIndex, + preferredInputs: preferredInputs); } Future<PendingTransactionDescription> createTransaction( @@ -212,23 +245,27 @@ Future<PendingTransactionDescription> createTransaction( required int priorityRaw, String? amount, String paymentId = '', - int accountIndex = 0}) => + int accountIndex = 0, + List<String> preferredInputs = const []}) => compute(_createTransactionSync, { 'address': address, 'paymentId': paymentId, 'amount': amount, 'priorityRaw': priorityRaw, - 'accountIndex': accountIndex + 'accountIndex': accountIndex, + 'preferredInputs': preferredInputs }); Future<PendingTransactionDescription> createTransactionMultDest( - {required List<MoneroOutput> outputs, - required int priorityRaw, - String paymentId = '', - int accountIndex = 0}) => + {required List<MoneroOutput> outputs, + required int priorityRaw, + String paymentId = '', + int accountIndex = 0, + List<String> preferredInputs = const []}) => compute(_createTransactionMultDestSync, { 'outputs': outputs, 'paymentId': paymentId, 'priorityRaw': priorityRaw, - 'accountIndex': accountIndex + 'accountIndex': accountIndex, + 'preferredInputs': preferredInputs }); diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 051f317c9..2c92f2d80 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -1,4 +1,5 @@ import 'dart:ffi'; +import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -92,6 +93,8 @@ typedef TransactionCreate = int Function( Pointer<Utf8> amount, int priorityRaw, int subaddrAccount, + Pointer<Pointer<Utf8>> preferredInputs, + int preferredInputsSize, Pointer<Utf8Box> error, Pointer<PendingTransactionRaw> pendingTransaction); @@ -102,6 +105,8 @@ typedef TransactionCreateMultDest = int Function( int size, int priorityRaw, int subaddrAccount, + Pointer<Pointer<Utf8>> preferredInputs, + int preferredInputsSize, Pointer<Utf8Box> error, Pointer<PendingTransactionRaw> pendingTransaction); @@ -127,4 +132,10 @@ typedef GetSubaddressLabel = Pointer<Utf8> Function( typedef SetTrustedDaemon = void Function(int); -typedef TrustedDaemon = int Function(); \ No newline at end of file +typedef TrustedDaemon = int Function(); + +typedef RefreshCoins = void Function(int); + +typedef CoinsCount = int Function(); + +typedef GetCoin = Pointer<CoinsInfoRow> Function(int); diff --git a/cw_monero/lib/monero_transaction_creation_exception.dart b/cw_monero/lib/exceptions/monero_transaction_creation_exception.dart similarity index 100% rename from cw_monero/lib/monero_transaction_creation_exception.dart rename to cw_monero/lib/exceptions/monero_transaction_creation_exception.dart diff --git a/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart new file mode 100644 index 000000000..5d808be8f --- /dev/null +++ b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart @@ -0,0 +1,4 @@ +class MoneroTransactionNoInputsException implements Exception { + @override + String toString() => 'Not enough inputs available. Please select more under Coin Control'; +} diff --git a/cw_monero/lib/monero_subaddress_list.dart b/cw_monero/lib/monero_subaddress_list.dart index 8d8eeb469..53efc1251 100644 --- a/cw_monero/lib/monero_subaddress_list.dart +++ b/cw_monero/lib/monero_subaddress_list.dart @@ -1,6 +1,6 @@ -import 'package:cw_monero/api/structs/subaddress_row.dart'; import 'package:flutter/services.dart'; import 'package:mobx/mobx.dart'; +import 'package:cw_monero/api/coins_info.dart'; import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list; import 'package:cw_core/subaddress.dart'; @@ -22,6 +22,8 @@ abstract class MoneroSubaddressListBase with Store { bool _isUpdating; void update({required int accountIndex}) { + refreshCoins(accountIndex); + if (_isUpdating) { return; } diff --git a/cw_monero/lib/monero_unspent.dart b/cw_monero/lib/monero_unspent.dart new file mode 100644 index 000000000..c2ff9f9db --- /dev/null +++ b/cw_monero/lib/monero_unspent.dart @@ -0,0 +1,28 @@ +import 'package:cw_monero/api/structs/coins_info_row.dart'; + +class MoneroUnspent { + MoneroUnspent(this.address, this.hash, this.keyImage, this.value, this.isFrozen, this.isUnlocked) + : isSending = true, + note = ''; + + MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) + : address = coinsInfoRow.getAddress(), + hash = coinsInfoRow.getHash(), + keyImage = coinsInfoRow.getKeyImage(), + value = coinsInfoRow.amount, + isFrozen = coinsInfoRow.frozen == 1, + isUnlocked = coinsInfoRow.unlocked == 1, + isSending = true, + note = ''; + + final String address; + final String hash; + final String keyImage; + final int value; + + final bool isUnlocked; + + bool isFrozen; + bool isSending; + String note; +} diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index ef25b6b93..76563310e 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -1,33 +1,35 @@ import 'dart:async'; import 'dart:io'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/monero_amount_format.dart'; -import 'package:cw_monero/monero_transaction_creation_exception.dart'; -import 'package:cw_monero/monero_transaction_info.dart'; -import 'package:cw_monero/monero_wallet_addresses.dart'; -import 'package:cw_core/monero_wallet_utils.dart'; -import 'package:cw_monero/api/structs/pending_transaction.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_monero/api/transaction_history.dart' - as monero_transaction_history; -import 'package:cw_monero/api/wallet.dart'; -import 'package:cw_monero/api/wallet.dart' as monero_wallet; -import 'package:cw_monero/api/transaction_history.dart' as transaction_history; -import 'package:cw_monero/api/monero_output.dart'; -import 'package:cw_monero/monero_transaction_creation_credentials.dart'; -import 'package:cw_monero/pending_monero_transaction.dart'; -import 'package:cw_core/monero_wallet_keys.dart'; -import 'package:cw_core/monero_balance.dart'; -import 'package:cw_monero/monero_transaction_history.dart'; import 'package:cw_core/account.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/monero_amount_format.dart'; +import 'package:cw_core/monero_balance.dart'; +import 'package:cw_core/monero_transaction_priority.dart'; +import 'package:cw_core/monero_wallet_keys.dart'; +import 'package:cw_core/monero_wallet_utils.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_monero/api/coins_info.dart'; +import 'package:cw_monero/api/monero_output.dart'; +import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/transaction_history.dart' as transaction_history; +import 'package:cw_monero/api/wallet.dart' as monero_wallet; +import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart'; +import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart'; +import 'package:cw_monero/pending_monero_transaction.dart'; +import 'package:cw_monero/monero_transaction_creation_credentials.dart'; +import 'package:cw_monero/monero_transaction_history.dart'; +import 'package:cw_monero/monero_transaction_info.dart'; +import 'package:cw_monero/monero_unspent.dart'; +import 'package:cw_monero/monero_wallet_addresses.dart'; +import 'package:mobx/mobx.dart'; +import 'package:hive/hive.dart'; part 'monero_wallet.g.dart'; @@ -37,37 +39,39 @@ class MoneroWallet = MoneroWalletBase with _$MoneroWallet; abstract class MoneroWalletBase extends WalletBase<MoneroBalance, MoneroTransactionHistory, MoneroTransactionInfo> with Store { - MoneroWalletBase({required WalletInfo walletInfo}) + MoneroWalletBase({required WalletInfo walletInfo, + required Box<UnspentCoinsInfo> unspentCoinsInfo}) : balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({ - CryptoCurrency.xmr: MoneroBalance( + CryptoCurrency.xmr: MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: 0), unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0)) - }), + }), _isTransactionUpdating = false, _hasSyncAfterStartup = false, walletAddresses = MoneroWalletAddresses(walletInfo), syncStatus = NotConnectedSyncStatus(), + unspentCoins = [], + this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { transactionHistory = MoneroTransactionHistory(); - _onAccountChangeReaction = reaction((_) => walletAddresses.account, - (Account? account) { + _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) { if (account == null) { return; } - balance = ObservableMap<CryptoCurrency, MoneroBalance>.of( - <CryptoCurrency, MoneroBalance>{ - currency: MoneroBalance( + balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{ + currency: MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), - unlockedBalance: - monero_wallet.getUnlockedBalance(accountIndex: account.id)) - }); + unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id)) + }); walletAddresses.updateSubaddressList(accountIndex: account.id); }); } static const int _autoSaveInterval = 30; + Box<UnspentCoinsInfo> unspentCoinsInfo; + @override MoneroWalletAddresses walletAddresses; @@ -89,11 +93,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, publicSpendKey: monero_wallet.getPublicSpendKey(), publicViewKey: monero_wallet.getPublicViewKey()); - SyncListener? _listener; + monero_wallet.SyncListener? _listener; ReactionDisposer? _onAccountChangeReaction; bool _isTransactionUpdating; bool _hasSyncAfterStartup; Timer? _autoSaveTimer; + List<MoneroUnspent> unspentCoins; Future<void> init() async { await walletAddresses.init(); @@ -170,10 +175,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, @override Future<PendingTransaction> createTransaction(Object credentials) async { final _credentials = credentials as MoneroTransactionCreationCredentials; + final inputs = <String>[]; final outputs = _credentials.outputs; final hasMultiDestination = outputs.length > 1; final unlockedBalance = monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id); + var allInputsAmount = 0; PendingTransactionDescription pendingTransactionDescription; @@ -181,6 +188,21 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, throw MoneroTransactionCreationException('The wallet is not synced.'); } + if (unspentCoins.isEmpty) { + await updateUnspent(); + } + + for (final utx in unspentCoins) { + if (utx.isSending) { + allInputsAmount += utx.value; + inputs.add(utx.keyImage); + } + } + + if (inputs.isEmpty) { + throw MoneroTransactionNoInputsException(); + } + if (hasMultiDestination) { if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { @@ -208,7 +230,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, await transaction_history.createTransactionMultDest( outputs: moneroOutputs, priorityRaw: _credentials.priority.serialize(), - accountIndex: walletAddresses.account!.id); + accountIndex: walletAddresses.account!.id, + preferredInputs: inputs); } else { final output = outputs.first; final address = output.isParsedAddress @@ -229,12 +252,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, 'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.'); } - pendingTransactionDescription = - await transaction_history.createTransaction( + pendingTransactionDescription = await transaction_history.createTransaction( address: address!, amount: amount, priorityRaw: _credentials.priority.serialize(), - accountIndex: walletAddresses.account!.id); + accountIndex: walletAddresses.account!.id, + preferredInputs: inputs); } return PendingMoneroTransaction(pendingTransactionDescription); @@ -354,6 +377,85 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, await walletInfo.save(); } + Future<void> updateUnspent() async { + refreshCoins(walletAddresses.account!.id); + + unspentCoins.clear(); + + final coinCount = countOfCoins(); + for (var i = 0; i < coinCount; i++) { + final coin = getCoin(i); + if (coin.spent == 0) { + unspentCoins.add(MoneroUnspent.fromCoinsInfoRow(coin)); + } + } + + if (unspentCoinsInfo.isEmpty) { + unspentCoins.forEach((coin) => _addCoinInfo(coin)); + return; + } + + if (unspentCoins.isNotEmpty) { + unspentCoins.forEach((coin) { + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && element.hash.contains(coin.hash)); + + if (coinInfoList.isNotEmpty) { + final coinInfo = coinInfoList.first; + + coin.isFrozen = coinInfo.isFrozen; + coin.isSending = coinInfo.isSending; + coin.note = coinInfo.note; + } else { + _addCoinInfo(coin); + } + }); + } + + await _refreshUnspentCoinsInfo(); + _askForUpdateBalance(); + } + + Future<void> _addCoinInfo(MoneroUnspent coin) async { + final newInfo = UnspentCoinsInfo( + walletId: id, + hash: coin.hash, + isFrozen: coin.isFrozen, + isSending: coin.isSending, + noteRaw: coin.note, + address: coin.address, + value: coin.value, + vout: 0, + keyImage: coin.keyImage + ); + + await unspentCoinsInfo.add(newInfo); + } + + Future<void> _refreshUnspentCoinsInfo() async { + try { + final List<dynamic> keys = <dynamic>[]; + final currentWalletUnspentCoins = unspentCoinsInfo.values + .where((element) => element.walletId.contains(id)); + + if (currentWalletUnspentCoins.isNotEmpty) { + currentWalletUnspentCoins.forEach((element) { + final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash)); + + if (existUnspentCoins.isEmpty) { + keys.add(element.key); + } + }); + } + + if (keys.isNotEmpty) { + await unspentCoinsInfo.deleteAll(keys); + } + } catch (e) { + print(e.toString()); + } + } + String getTransactionAddress(int accountIndex, int addressIndex) => monero_wallet.getAddress( accountIndex: accountIndex, @@ -361,7 +463,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, @override Future<Map<String, MoneroTransactionInfo>> fetchTransactions() async { - monero_transaction_history.refreshTransactions(); + transaction_history.refreshTransactions(); return _getAllTransactions(null).fold<Map<String, MoneroTransactionInfo>>( <String, MoneroTransactionInfo>{}, (Map<String, MoneroTransactionInfo> acc, MoneroTransactionInfo tx) { @@ -392,7 +494,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, } List<MoneroTransactionInfo> _getAllTransactions(dynamic _) => - monero_transaction_history + transaction_history .getAllTransations() .map((row) => MoneroTransactionInfo.fromRow(row)) .toList(); @@ -407,7 +509,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, return; } - final currentHeight = getCurrentHeight(); + final currentHeight = monero_wallet.getCurrentHeight(); if (currentHeight <= 1) { final height = _getHeightByDate(walletInfo.date); @@ -439,11 +541,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, void _askForUpdateBalance() { final unlockedBalance = _getUnlockedBalance(); final fullBalance = _getFullBalance(); + final frozenBalance = _getFrozenBalance(); if (balance[currency]!.fullBalance != fullBalance || - balance[currency]!.unlockedBalance != unlockedBalance) { + balance[currency]!.unlockedBalance != unlockedBalance || + balance[currency]!.frozenBalance != frozenBalance) { balance[currency] = MoneroBalance( - fullBalance: fullBalance, unlockedBalance: unlockedBalance); + fullBalance: fullBalance, unlockedBalance: unlockedBalance, frozenBalance: frozenBalance); } } @@ -456,6 +560,17 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, int _getUnlockedBalance() => monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id); + int _getFrozenBalance() { + var frozenBalance = 0; + + for (var coin in unspentCoinsInfo.values) { + if (coin.isFrozen) + frozenBalance += coin.value; + } + + return frozenBalance; + } + void _onNewBlock(int height, int blocksLeft, double ptc) async { try { if (walletInfo.isRecovery) { diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 6539d58a5..90c63fb72 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -1,16 +1,16 @@ import 'dart:io'; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/monero_wallet_utils.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; -import 'package:cw_monero/api/wallet.dart' as monero_wallet; -import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; -import 'package:cw_monero/monero_wallet.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; +import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; +import 'package:cw_monero/monero_wallet.dart'; +import 'package:hive/hive.dart'; class MoneroNewWalletCredentials extends WalletCredentials { MoneroNewWalletCredentials({required String name, required this.language, String? password}) @@ -53,9 +53,10 @@ class MoneroWalletService extends WalletService< MoneroNewWalletCredentials, MoneroRestoreWalletFromSeedCredentials, MoneroRestoreWalletFromKeysCredentials> { - MoneroWalletService(this.walletInfoSource); + MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box<WalletInfo> walletInfoSource; + final Box<UnspentCoinsInfo> unspentCoinsInfoSource; static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -71,7 +72,8 @@ class MoneroWalletService extends WalletService< path: path, password: credentials.password!, language: credentials.language); - final wallet = MoneroWallet(walletInfo: credentials.walletInfo!); + final wallet = MoneroWallet( + walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -107,7 +109,7 @@ class MoneroWalletService extends WalletService< .openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(name, getType())); - final wallet = MoneroWallet(walletInfo: walletInfo); + final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); final isValid = wallet.walletAddresses.validate(); if (!isValid) { @@ -157,7 +159,8 @@ class MoneroWalletService extends WalletService< String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(currentName, getType())); - final currentWallet = MoneroWallet(walletInfo: currentWalletInfo); + final currentWallet = + MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await currentWallet.renameWalletFiles(newName); @@ -181,7 +184,8 @@ class MoneroWalletService extends WalletService< address: credentials.address, viewKey: credentials.viewKey, spendKey: credentials.spendKey); - final wallet = MoneroWallet(walletInfo: credentials.walletInfo!); + final wallet = MoneroWallet( + walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -202,7 +206,8 @@ class MoneroWalletService extends WalletService< password: credentials.password!, seed: credentials.mnemonic, restoreHeight: credentials.height!); - final wallet = MoneroWallet(walletInfo: credentials.walletInfo!); + final wallet = MoneroWallet( + walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index dfd3b1538..3164aacaa 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -128,7 +128,8 @@ class CWBitcoin extends Bitcoin { bitcoinUnspent.address.address, bitcoinUnspent.hash, bitcoinUnspent.value, - bitcoinUnspent.vout)) + bitcoinUnspent.vout, + null)) .toList(); } @@ -160,4 +161,4 @@ class CWBitcoin extends Bitcoin { @override TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow; -} \ No newline at end of file +} diff --git a/lib/di.dart b/lib/di.dart index c37575337..80a55e1c6 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -216,10 +216,10 @@ late Box<Template> _templates; late Box<ExchangeTemplate> _exchangeTemplates; late Box<TransactionDescription> _transactionDescriptionBox; late Box<Order> _ordersSource; -late Box<UnspentCoinsInfo>? _unspentCoinsInfoSource; +late Box<UnspentCoinsInfo> _unspentCoinsInfoSource; late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource; -Future setup({ +Future<void> setup({ required Box<WalletInfo> walletInfoSource, required Box<Node> nodeSource, required Box<Contact> contactSource, @@ -228,7 +228,7 @@ Future setup({ required Box<ExchangeTemplate> exchangeTemplates, required Box<TransactionDescription> transactionDescriptionBox, required Box<Order> ordersSource, - Box<UnspentCoinsInfo>? unspentCoinsInfoSource, + required Box<UnspentCoinsInfo> unspentCoinsInfoSource, required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource, }) async { _walletInfoSource = walletInfoSource; @@ -731,11 +731,11 @@ Future setup({ case WalletType.haven: return haven!.createHavenWalletService(_walletInfoSource); case WalletType.monero: - return monero!.createMoneroWalletService(_walletInfoSource); + return monero!.createMoneroWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.bitcoin: - return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.litecoin: - return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.ethereum: return ethereum!.createEthereumWalletService(_walletInfoSource); default: diff --git a/lib/entities/unspent_transaction_output.dart b/lib/entities/unspent_transaction_output.dart new file mode 100644 index 000000000..6827f4c01 --- /dev/null +++ b/lib/entities/unspent_transaction_output.dart @@ -0,0 +1,18 @@ +class Unspent { + Unspent(this.address, this.hash, this.value, this.vout, this.keyImage) + : isSending = true, + isFrozen = false, + note = ''; + + final String address; + final String hash; + final int value; + final int vout; + final String? keyImage; + + bool isSending; + bool isFrozen; + String note; + + bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); +} diff --git a/lib/main.dart b/lib/main.dart index 62a0bfc9c..db5335ac1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -133,11 +133,7 @@ Future<void> initializeAppConfigs() async { final templates = await CakeHive.openBox<Template>(Template.boxName); final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName); final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName); - Box<UnspentCoinsInfo>? unspentCoinsInfoSource; - - if (!isMoneroOnly) { - unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); - } + final unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName); await initialSetup( sharedPreferences: await SharedPreferences.getInstance(), @@ -169,7 +165,7 @@ Future<void> initialSetup( required Box<TransactionDescription> transactionDescriptions, required FlutterSecureStorage secureStorage, required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo, - Box<UnspentCoinsInfo>? unspentCoinsInfoSource, + required Box<UnspentCoinsInfo> unspentCoinsInfoSource, int initialMigrationVersion = 15}) async { LanguageService.loadLocaleList(); await defaultSettingsMigration( diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 5dfe2e467..4f45bc974 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -1,361 +1,363 @@ part of 'monero.dart'; class CWMoneroAccountList extends MoneroAccountList { - CWMoneroAccountList(this._wallet); - final Object _wallet; + CWMoneroAccountList(this._wallet); - @override - @computed + final Object _wallet; + + @override + @computed ObservableList<Account> get accounts { - final moneroWallet = _wallet as MoneroWallet; - final accounts = moneroWallet.walletAddresses.accountList - .accounts - .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance)) - .toList(); - return ObservableList<Account>.of(accounts); + final moneroWallet = _wallet as MoneroWallet; + final accounts = moneroWallet.walletAddresses.accountList.accounts + .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance)) + .toList(); + return ObservableList<Account>.of(accounts); } @override void update(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - moneroWallet.walletAddresses.accountList.update(); + final moneroWallet = wallet as MoneroWallet; + moneroWallet.walletAddresses.accountList.update(); } @override - void refresh(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - moneroWallet.walletAddresses.accountList.refresh(); - } + void refresh(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + moneroWallet.walletAddresses.accountList.refresh(); + } - @override + @override List<Account> getAll(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - return moneroWallet.walletAddresses.accountList - .getAll() - .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance)) - .toList(); + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.walletAddresses.accountList + .getAll() + .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance)) + .toList(); } @override Future<void> addAccount(Object wallet, {required String label}) async { - final moneroWallet = wallet as MoneroWallet; - await moneroWallet.walletAddresses.accountList.addAccount(label: label); + final moneroWallet = wallet as MoneroWallet; + await moneroWallet.walletAddresses.accountList.addAccount(label: label); } @override - Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label}) async { - final moneroWallet = wallet as MoneroWallet; - await moneroWallet.walletAddresses.accountList - .setLabelAccount( - accountIndex: accountIndex, - label: label); + Future<void> setLabelAccount(Object wallet, + {required int accountIndex, required String label}) async { + final moneroWallet = wallet as MoneroWallet; + await moneroWallet.walletAddresses.accountList + .setLabelAccount(accountIndex: accountIndex, label: label); } } class CWMoneroSubaddressList extends MoneroSubaddressList { - CWMoneroSubaddressList(this._wallet); - final Object _wallet; + CWMoneroSubaddressList(this._wallet); - @override - @computed + final Object _wallet; + + @override + @computed ObservableList<Subaddress> get subaddresses { - final moneroWallet = _wallet as MoneroWallet; - final subAddresses = moneroWallet.walletAddresses.subaddressList - .subaddresses - .map((sub) => Subaddress( - id: sub.id, - address: sub.address, - label: sub.label)) - .toList(); - return ObservableList<Subaddress>.of(subAddresses); + final moneroWallet = _wallet as MoneroWallet; + final subAddresses = moneroWallet.walletAddresses.subaddressList.subaddresses + .map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label)) + .toList(); + return ObservableList<Subaddress>.of(subAddresses); } @override void update(Object wallet, {required int accountIndex}) { - final moneroWallet = wallet as MoneroWallet; - moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex); + final moneroWallet = wallet as MoneroWallet; + moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex); } @override void refresh(Object wallet, {required int accountIndex}) { - final moneroWallet = wallet as MoneroWallet; - moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex); + final moneroWallet = wallet as MoneroWallet; + moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex); } @override List<Subaddress> getAll(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - return moneroWallet.walletAddresses - .subaddressList - .getAll() - .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address)) - .toList(); + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.walletAddresses.subaddressList + .getAll() + .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address)) + .toList(); } @override - Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label}) async { - final moneroWallet = wallet as MoneroWallet; - await moneroWallet.walletAddresses.subaddressList - .addSubaddress( - accountIndex: accountIndex, - label: label); + Future<void> addSubaddress(Object wallet, + {required int accountIndex, required String label}) async { + final moneroWallet = wallet as MoneroWallet; + await moneroWallet.walletAddresses.subaddressList + .addSubaddress(accountIndex: accountIndex, label: label); } @override Future<void> setLabelSubaddress(Object wallet, {required int accountIndex, required int addressIndex, required String label}) async { - final moneroWallet = wallet as MoneroWallet; - await moneroWallet.walletAddresses.subaddressList - .setLabelSubaddress( - accountIndex: accountIndex, - addressIndex: addressIndex, - label: label); + final moneroWallet = wallet as MoneroWallet; + await moneroWallet.walletAddresses.subaddressList + .setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label); } } class CWMoneroWalletDetails extends MoneroWalletDetails { - CWMoneroWalletDetails(this._wallet); - final Object _wallet; + CWMoneroWalletDetails(this._wallet); - @computed + final Object _wallet; + + @computed @override Account get account { - final moneroWallet = _wallet as MoneroWallet; - final acc = moneroWallet.walletAddresses.account; - return Account(id: acc!.id, label: acc.label, balance: acc.balance); + final moneroWallet = _wallet as MoneroWallet; + final acc = moneroWallet.walletAddresses.account; + return Account(id: acc!.id, label: acc.label, balance: acc.balance); } @computed @override - MoneroBalance get balance { - final moneroWallet = _wallet as MoneroWallet; - final balance = moneroWallet.balance; + MoneroBalance get balance { + final moneroWallet = _wallet as MoneroWallet; + final balance = moneroWallet.balance; throw Exception('Unimplemented'); - // return MoneroBalance(); - //return MoneroBalance( - // fullBalance: balance.fullBalance, - // unlockedBalance: balance.unlockedBalance); - } + // return MoneroBalance(); + //return MoneroBalance( + // fullBalance: balance.fullBalance, + // unlockedBalance: balance.unlockedBalance); + } } class CWMonero extends Monero { @override - MoneroAccountList getAccountList(Object wallet) { - return CWMoneroAccountList(wallet); - } - - @override - MoneroSubaddressList getSubaddressList(Object wallet) { - return CWMoneroSubaddressList(wallet); - } - - @override - TransactionHistoryBase getTransactionHistory(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - return moneroWallet.transactionHistory; - } - - @override - MoneroWalletDetails getMoneroWalletDetails(Object wallet) { - return CWMoneroWalletDetails(wallet); - } - - @override - int getHeigthByDate({required DateTime date}) { - return getMoneroHeigthByDate(date: date); - } - - @override - TransactionPriority getDefaultTransactionPriority() { - return MoneroTransactionPriority.automatic; - } + MoneroAccountList getAccountList(Object wallet) { + return CWMoneroAccountList(wallet); + } @override - TransactionPriority getMoneroTransactionPrioritySlow() - => MoneroTransactionPriority.slow; + MoneroSubaddressList getSubaddressList(Object wallet) { + return CWMoneroSubaddressList(wallet); + } @override - TransactionPriority getMoneroTransactionPriorityAutomatic() - => MoneroTransactionPriority.automatic; + TransactionHistoryBase getTransactionHistory(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.transactionHistory; + } - @override - TransactionPriority deserializeMoneroTransactionPriority({required int raw}) { - return MoneroTransactionPriority.deserialize(raw: raw); - } + @override + MoneroWalletDetails getMoneroWalletDetails(Object wallet) { + return CWMoneroWalletDetails(wallet); + } - @override - List<TransactionPriority> getTransactionPriorities() { - return MoneroTransactionPriority.all; - } + @override + int getHeigthByDate({required DateTime date}) { + return getMoneroHeigthByDate(date: date); + } - @override - List<String> getMoneroWordList(String language) { - switch (language.toLowerCase()) { - case 'english': - return EnglishMnemonics.words; - case 'chinese (simplified)': - return ChineseSimplifiedMnemonics.words; - case 'dutch': - return DutchMnemonics.words; - case 'german': - return GermanMnemonics.words; - case 'japanese': - return JapaneseMnemonics.words; - case 'portuguese': - return PortugueseMnemonics.words; - case 'russian': - return RussianMnemonics.words; - case 'spanish': - return SpanishMnemonics.words; - case 'french': - return FrenchMnemonics.words; - case 'italian': - return ItalianMnemonics.words; - default: - return EnglishMnemonics.words; - } - } + @override + TransactionPriority getDefaultTransactionPriority() { + return MoneroTransactionPriority.automatic; + } - @override - WalletCredentials createMoneroRestoreWalletFromKeysCredentials({ - required String name, - required String spendKey, - required String viewKey, - required String address, - required String password, - required String language, - required int height}) { - return MoneroRestoreWalletFromKeysCredentials( - name: name, - spendKey: spendKey, - viewKey: viewKey, - address: address, - password: password, - language: language, - height: height); - } - - @override - WalletCredentials createMoneroRestoreWalletFromSeedCredentials({ - required String name, - required String password, - required int height, - required String mnemonic}) { - return MoneroRestoreWalletFromSeedCredentials( - name: name, - password: password, - height: height, - mnemonic: mnemonic); - } + @override + TransactionPriority getMoneroTransactionPrioritySlow() => MoneroTransactionPriority.slow; - @override - WalletCredentials createMoneroNewWalletCredentials({ + @override + TransactionPriority getMoneroTransactionPriorityAutomatic() => + MoneroTransactionPriority.automatic; + + @override + TransactionPriority deserializeMoneroTransactionPriority({required int raw}) { + return MoneroTransactionPriority.deserialize(raw: raw); + } + + @override + List<TransactionPriority> getTransactionPriorities() { + return MoneroTransactionPriority.all; + } + + @override + List<String> getMoneroWordList(String language) { + switch (language.toLowerCase()) { + case 'english': + return EnglishMnemonics.words; + case 'chinese (simplified)': + return ChineseSimplifiedMnemonics.words; + case 'dutch': + return DutchMnemonics.words; + case 'german': + return GermanMnemonics.words; + case 'japanese': + return JapaneseMnemonics.words; + case 'portuguese': + return PortugueseMnemonics.words; + case 'russian': + return RussianMnemonics.words; + case 'spanish': + return SpanishMnemonics.words; + case 'french': + return FrenchMnemonics.words; + case 'italian': + return ItalianMnemonics.words; + default: + return EnglishMnemonics.words; + } + } + + @override + WalletCredentials createMoneroRestoreWalletFromKeysCredentials( + {required String name, + required String spendKey, + required String viewKey, + required String address, + required String password, + required String language, + required int height}) { + return MoneroRestoreWalletFromKeysCredentials( + name: name, + spendKey: spendKey, + viewKey: viewKey, + address: address, + password: password, + language: language, + height: height); + } + + @override + WalletCredentials createMoneroRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required int height, + required String mnemonic}) { + return MoneroRestoreWalletFromSeedCredentials( + name: name, password: password, height: height, mnemonic: mnemonic); + } + + @override + WalletCredentials createMoneroNewWalletCredentials({ required String name, required String language, - String? password,}) { - return MoneroNewWalletCredentials( - name: name, - password: password, - language: language); - } + String? password, + }) { + return MoneroNewWalletCredentials(name: name, password: password, language: language); + } - @override - Map<String, String> getKeys(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - final keys = moneroWallet.keys; - return <String, String>{ - 'privateSpendKey': keys.privateSpendKey, + @override + Map<String, String> getKeys(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + final keys = moneroWallet.keys; + return <String, String>{ + 'privateSpendKey': keys.privateSpendKey, 'privateViewKey': keys.privateViewKey, 'publicSpendKey': keys.publicSpendKey, - 'publicViewKey': keys.publicViewKey}; - } + 'publicViewKey': keys.publicViewKey + }; + } - @override - Object createMoneroTransactionCreationCredentials({ - required List<Output> outputs, - required TransactionPriority priority}) { - return MoneroTransactionCreationCredentials( - outputs: outputs.map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as MoneroTransactionPriority); - } + @override + Object createMoneroTransactionCreationCredentials( + {required List<Output> outputs, required TransactionPriority priority}) { + return MoneroTransactionCreationCredentials( + outputs: outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as MoneroTransactionPriority); + } - @override - Object createMoneroTransactionCreationCredentialsRaw({ - required List<OutputInfo> outputs, - required TransactionPriority priority}) { - return MoneroTransactionCreationCredentials( - outputs: outputs, - priority: priority as MoneroTransactionPriority); - } + @override + Object createMoneroTransactionCreationCredentialsRaw( + {required List<OutputInfo> outputs, required TransactionPriority priority}) { + return MoneroTransactionCreationCredentials( + outputs: outputs, priority: priority as MoneroTransactionPriority); + } - @override - String formatterMoneroAmountToString({required int amount}) { - return moneroAmountToString(amount: amount); - } + @override + String formatterMoneroAmountToString({required int amount}) { + return moneroAmountToString(amount: amount); + } - @override - double formatterMoneroAmountToDouble({required int amount}) { - return moneroAmountToDouble(amount: amount); - } + @override + double formatterMoneroAmountToDouble({required int amount}) { + return moneroAmountToDouble(amount: amount); + } - @override - int formatterMoneroParseAmount({required String amount}) { - return moneroParseAmount(amount: amount); - } + @override + int formatterMoneroParseAmount({required String amount}) { + return moneroParseAmount(amount: amount); + } - @override - Account getCurrentAccount(Object wallet) { - final moneroWallet = wallet as MoneroWallet; - final acc = moneroWallet.walletAddresses.account; - return Account(id: acc!.id, label: acc.label, balance: acc.balance); - } + @override + Account getCurrentAccount(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + final acc = moneroWallet.walletAddresses.account; + return Account(id: acc!.id, label: acc.label, balance: acc.balance); + } - @override - void setCurrentAccount(Object wallet, int id, String label, String? balance) { - final moneroWallet = wallet as MoneroWallet; - moneroWallet.walletAddresses.account = monero_account.Account(id: id, label: label, balance: balance); - } + @override + void setCurrentAccount(Object wallet, int id, String label, String? balance) { + final moneroWallet = wallet as MoneroWallet; + moneroWallet.walletAddresses.account = + monero_account.Account(id: id, label: label, balance: balance); + } - @override - void onStartup() { - monero_wallet_api.onStartup(); - } + @override + void onStartup() { + monero_wallet_api.onStartup(); + } - @override - int getTransactionInfoAccountId(TransactionInfo tx) { - final moneroTransactionInfo = tx as MoneroTransactionInfo; - return moneroTransactionInfo.accountIndex; - } + @override + int getTransactionInfoAccountId(TransactionInfo tx) { + final moneroTransactionInfo = tx as MoneroTransactionInfo; + return moneroTransactionInfo.accountIndex; + } - @override - WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource) { - return MoneroWalletService(walletInfoSource); - } + @override + WalletService createMoneroWalletService( + Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) { + return MoneroWalletService(walletInfoSource, unspentCoinSource); + } - @override - String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { - final moneroWallet = wallet as MoneroWallet; - return moneroWallet.getTransactionAddress(accountIndex, addressIndex); - } + @override + String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.getTransactionAddress(accountIndex, addressIndex); + } - @override - String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) { - final moneroWallet = wallet as MoneroWallet; - return moneroWallet.getSubaddressLabel(accountIndex, addressIndex); - } + @override + String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) { + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.getSubaddressLabel(accountIndex, addressIndex); + } - @override - Map<String, String> pendingTransactionInfo(Object transaction) { - final ptx = transaction as PendingMoneroTransaction; - return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey}; - } + @override + Map<String, String> pendingTransactionInfo(Object transaction) { + final ptx = transaction as PendingMoneroTransaction; + return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey}; + } + + @override + List<Unspent> getUnspents(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.unspentCoins + .map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash, + moneroUnspent.value, 0, moneroUnspent.keyImage)) + .toList(); + } + + @override + void updateUnspents(Object wallet) async { + final moneroWallet = wallet as MoneroWallet; + await moneroWallet.updateUnspent(); + } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 4a2559902..b24e9b01f 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -100,7 +100,7 @@ class SendPage extends BasePage { AppBarStyle get appBarStyle => AppBarStyle.transparent; double _sendCardHeight(BuildContext context) { - final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465; + final double initialHeight = sendViewModel.hasCoinControl ? 490 : 465; if (!ResponsiveLayoutUtil.instance.isMobile) { return initialHeight - 66; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 4b2cddeb7..04fded5c8 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -496,7 +496,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S ), ), ), - if (sendViewModel.isElectrumWallet) + if (sendViewModel.hasCoinControl) Padding( padding: EdgeInsets.only(top: 6), child: GestureDetector( diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 96f67424c..a6f60a52d 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -21,7 +21,6 @@ class TransactionDetailsPage extends BasePage { @override Widget body(BuildContext context) { - // FIX-ME: Added `context` it was not used here before, maby bug ? return SectionStandardList( sectionCount: 1, itemCounter: (int _) => transactionDetailsViewModel.items.length, diff --git a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart index 2c7934d19..ff5513502 100644 --- a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart +++ b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart @@ -6,11 +6,12 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; class TextFieldListRow extends StatelessWidget { TextFieldListRow( {required this.title, - required this.value, - this.titleFontSize = 14, - this.valueFontSize = 16, - this.onSubmitted}) - : _textController = TextEditingController() { + required this.value, + this.titleFontSize = 14, + this.valueFontSize = 16, + this.onSubmitted, + this.onTapOutside}) + : _textController = TextEditingController() { _textController.text = value; } @@ -19,6 +20,7 @@ class TextFieldListRow extends StatelessWidget { final double titleFontSize; final double valueFontSize; final Function(String value)? onSubmitted; + final Function(String value)? onTapOutside; final TextEditingController _textController; @override @@ -58,6 +60,7 @@ class TextFieldListRow extends StatelessWidget { fontWeight: FontWeight.w500, color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor), border: InputBorder.none), + onTapOutside: (_) => onTapOutside?.call(_textController.text), onSubmitted: (value) => onSubmitted?.call(value), ) ]), diff --git a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart index dfa8e8435..61689b52a 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_details_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_details_page.dart @@ -24,7 +24,6 @@ class UnspentCoinsDetailsPage extends BasePage { @override Widget body(BuildContext context) { - // FIX-ME: Added `context` it was not used here before, maby bug ? return SectionStandardList( sectionCount: 1, itemCounter: (int _) => unspentCoinsDetailsViewModel.items.length, @@ -45,6 +44,7 @@ class UnspentCoinsDetailsPage extends BasePage { return TextFieldListRow( title: item.title, value: item.value, + onTapOutside: item.onSubmitted, onSubmitted: item.onSubmitted, ); } diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index 154c3a2f5..93cf27af1 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -94,7 +94,7 @@ class UnspentCoinsListItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ AutoSizeText( - address, + '${address.substring(0, 5)}...${address.substring(address.length-5)}', // ToDo: Maybe use address label style: TextStyle( color: addressColor, fontSize: 12, diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index dfec89f43..9a04b5ea7 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -172,6 +172,10 @@ abstract class SendViewModelBase with Store { .where((template) => _isEqualCurrency(template.cryptoCurrency)) .toList(); + @computed + bool get hasCoinControl => + _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin || _wallet.type == WalletType.monero; + @computed bool get isElectrumWallet => _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin; @@ -206,12 +210,12 @@ abstract class SendViewModelBase with Store { @computed List<ContactRecord> get contactsToShow => contactListViewModel.contacts - .where((element) => selectedCryptoCurrency == null || element.type == selectedCryptoCurrency) + .where((element) => element.type == selectedCryptoCurrency) .toList(); @computed List<WalletContact> get walletContactsToShow => contactListViewModel.walletContacts - .where((element) => selectedCryptoCurrency == null || element.type == selectedCryptoCurrency) + .where((element) => element.type == selectedCryptoCurrency) .toList(); @action diff --git a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart index 098296036..992991147 100644 --- a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart @@ -23,6 +23,7 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { note = unspentCoinsItem.note { items = [ StandartListItem(title: S.current.transaction_details_amount, value: unspentCoinsItem.amount), + StandartListItem(title: S.current.transaction_details_transaction_id, value: unspentCoinsItem.hash), StandartListItem(title: S.current.widgets_address, value: unspentCoinsItem.address), TextFieldListItem( title: S.current.note_tap_to_change, @@ -42,19 +43,22 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { unspentCoinsItem.isSending = !value; } await unspentCoinsListViewModel.saveUnspentCoinInfo(unspentCoinsItem); - }), - BlockExplorerListItem( - title: S.current.view_in_block_explorer, - value: _explorerDescription(unspentCoinsListViewModel.wallet.type), - onTap: () { - try { - final url = Uri.parse( - _explorerUrl(unspentCoinsListViewModel.wallet.type, unspentCoinsItem.hash)); - return launchUrl(url); - } catch (e) {} - }) ]; + + if ([WalletType.bitcoin, WalletType.litecoin].contains(unspentCoinsListViewModel.wallet.type)) { + items.add(BlockExplorerListItem( + title: S.current.view_in_block_explorer, + value: _explorerDescription(unspentCoinsListViewModel.wallet.type), + onTap: () { + try { + final url = Uri.parse( + _explorerUrl(unspentCoinsListViewModel.wallet.type, unspentCoinsItem.hash)); + return launchUrl(url); + } catch (e) {} + }, + )); + } } String _explorerUrl(WalletType type, String txId) { diff --git a/lib/view_model/unspent_coins/unspent_coins_item.dart b/lib/view_model/unspent_coins/unspent_coins_item.dart index 2f0d75571..9d1f6c71c 100644 --- a/lib/view_model/unspent_coins/unspent_coins_item.dart +++ b/lib/view_model/unspent_coins/unspent_coins_item.dart @@ -13,7 +13,9 @@ abstract class UnspentCoinsItemBase with Store { required this.note, required this.isSending, required this.amountRaw, - required this.vout}); + required this.vout, + required this.keyImage + }); @observable String address; @@ -38,4 +40,7 @@ abstract class UnspentCoinsItemBase with Store { @observable int vout; -} \ No newline at end of file + + @observable + String? keyImage; +} diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 4df4b9a66..9ecb381fd 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -1,10 +1,15 @@ -import 'package:cw_core/unspent_coins_info.dart'; +import 'package:collection/collection.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cake_wallet/entities/unspent_transaction_output.dart'; +import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; +import 'package:cw_bitcoin/bitcoin_wallet.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:cw_monero/monero_wallet.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:collection/collection.dart'; part 'unspent_coins_list_view_model.g.dart'; @@ -14,7 +19,7 @@ abstract class UnspentCoinsListViewModelBase with Store { UnspentCoinsListViewModelBase( {required this.wallet, required Box<UnspentCoinsInfo> unspentCoinsInfo}) : _unspentCoinsInfo = unspentCoinsInfo { - bitcoin!.updateUnspents(wallet); + _updateUnspents(); } WalletBase wallet; @@ -22,11 +27,10 @@ abstract class UnspentCoinsListViewModelBase with Store { @computed ObservableList<UnspentCoinsItem> get items => - ObservableList.of(bitcoin!.getUnspents(wallet).map((elem) { - final amount = bitcoin!.formatterBitcoinAmountToString(amount: elem.value) + - ' ${wallet.currency.title}'; + ObservableList.of(_getUnspents().map((elem) { + final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}'; - final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout); + final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); return UnspentCoinsItem( address: elem.address, @@ -36,12 +40,14 @@ abstract class UnspentCoinsListViewModelBase with Store { note: info?.note ?? '', isSending: info?.isSending ?? true, amountRaw: elem.value, - vout: elem.vout); + vout: elem.vout, + keyImage: elem.keyImage + ); })); Future<void> saveUnspentCoinInfo(UnspentCoinsItem item) async { try { - final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout); + final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage); if (info == null) { final newInfo = UnspentCoinsInfo( walletId: wallet.id, @@ -51,10 +57,12 @@ abstract class UnspentCoinsListViewModelBase with Store { vout: item.vout, isFrozen: item.isFrozen, isSending: item.isSending, - noteRaw: item.note); + noteRaw: item.note, + keyImage: item.keyImage + ); await _unspentCoinsInfo.add(newInfo); - bitcoin!.updateUnspents(wallet); + _updateUnspents(); wallet.updateBalance(); return; } @@ -63,19 +71,45 @@ abstract class UnspentCoinsListViewModelBase with Store { info.note = item.note; await info.save(); - bitcoin!.updateUnspents(wallet); + _updateUnspents(); wallet.updateBalance(); } catch (e) { print(e.toString()); } } - UnspentCoinsInfo? getUnspentCoinInfo(String hash, String address, int value, int vout) { + UnspentCoinsInfo? getUnspentCoinInfo(String hash, String address, int value, int vout, String? keyImage) { return _unspentCoinsInfo.values.firstWhereOrNull((element) => element.walletId == wallet.id && element.hash == hash && element.address == address && element.value == value && - element.vout == vout); + element.vout == vout && + element.keyImage == keyImage + ); + } + + String formatAmountToString(int fullBalance) { + if (wallet.type == WalletType.monero) + return monero!.formatterMoneroAmountToString(amount: fullBalance); + if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + return bitcoin!.formatterBitcoinAmountToString(amount: fullBalance); + return ''; + } + + + void _updateUnspents() { + if (wallet.type == WalletType.monero) + return monero!.updateUnspents(wallet); + if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + return bitcoin!.updateUnspents(wallet); + } + + List<Unspent> _getUnspents() { + if (wallet.type == WalletType.monero) + return monero!.getUnspents(wallet); + if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + return bitcoin!.getUnspents(wallet); + return List.empty(); } } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 51cfe4b26..4655a70b5 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -99,7 +99,10 @@ dev_dependencies: # check flutter_launcher_icons for usage pedantic: ^1.8.0 # replace https://github.com/dart-lang/lints#migrating-from-packagepedantic -# translator: ^0.1.7 + translator: + git: + url: https://github.com/cake-tech/google-translator.git + version: 1.0.0 flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 06450a315..b315ddb56 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -5,10 +5,10 @@ "please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.", "create_new": "Neue Wallet erstellen", "restore_wallet": "Wallet wiederherstellen", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", + "monero_com": "Monero.com von Cake Wallet", + "monero_com_wallet_text": "Eine großartige Wallet für Monero", + "haven_app": "Haven von Cake Wallet", + "haven_app_wallet_text": "Eine großartige Wallet für Haven", "accounts": "Konten", "edit": "Bearbeiten", "account": "Konto", @@ -152,10 +152,10 @@ "restore_wallet_restore_description": "Beschreibung zur Wallet-Wiederherstellung", "restore_new_seed": "Neuer Seed", "restore_active_seed": "Aktiver Seed", - "restore_bitcoin_description_from_seed": "Stellen Sie Ihre Brieftasche aus dem 24-Wort-Kombinationscode wieder her", - "restore_bitcoin_description_from_keys": "Stellen Sie Ihre Brieftasche aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her", + "restore_bitcoin_description_from_seed": "Stellen Sie Ihre Wallet aus dem 24-Wort-Kombinationscode wieder her", + "restore_bitcoin_description_from_keys": "Stellen Sie Ihre Wallet aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her", "restore_bitcoin_title_from_keys": "Aus WIF wiederherstellen", - "restore_from_date_or_blockheight": "Bitte geben Sie ein Datum ein, das einige Tage vor dem Erstellen dieser Brieftasche liegt. Oder wenn Sie die Blockhöhe kennen, geben Sie stattdessen diese ein", + "restore_from_date_or_blockheight": "Bitte geben Sie ein Datum ein, das einige Tage vor dem Erstellen dieser Wallet liegt. Oder wenn Sie die Blockhöhe kennen, geben Sie stattdessen diese ein", "seed_reminder": "Bitte notieren Sie diese für den Fall, dass Sie Ihr Telefon verlieren oder es kaputtgeht", "seed_title": "Seed", "seed_share": "Seed teilen", @@ -403,7 +403,7 @@ "buy_bitcoin": "Bitcoin kaufen", "buy_with": "Kaufen mit", "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", - "outdated_electrum_wallet_receive_warning": "Wenn diese Brieftasche einen 12-Wort-Seed hat und in Cake erstellt wurde, zahlen Sie KEINE Bitcoins in diese Brieftasche ein. Alle auf diese Wallet übertragenen BTC können verloren gehen. Erstellen Sie eine neue 24-Wort-Wallet (tippen Sie auf das Menü oben rechts, wählen Sie Wallets, wählen Sie Neue Wallet erstellen und dann Bitcoin) und verschieben Sie Ihre BTC SOFORT dorthin. Neue (24-Wort-)BTC-Wallets von Cake sind sicher", + "outdated_electrum_wallet_receive_warning": "Wenn diese Wallet einen 12-Wort-Seed hat und in Cake erstellt wurde, zahlen Sie KEINE Bitcoins in diese Wallet ein. Alle auf diese Wallet übertragenen BTC können verloren gehen. Erstellen Sie eine neue 24-Wort-Wallet (tippen Sie auf das Menü oben rechts, wählen Sie Wallets, wählen Sie Neue Wallet erstellen und dann Bitcoin) und verschieben Sie Ihre BTC SOFORT dorthin. Neue (24-Wort-)BTC-Wallets von Cake sind sicher", "do_not_show_me": "Zeig mir das nicht noch einmal", "unspent_coins_title": "Nicht ausgegebene Münzen", "unspent_coins_details_title": "Details zu nicht ausgegebenen Münzen", @@ -596,10 +596,10 @@ "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE SWEPT-GELDER VERLOREN GEHEN", "decimal_places_error": "Zu viele Nachkommastellen", "edit_node": "Knoten bearbeiten", - "frozen_balance": "Gefrorenes Gleichgewicht", + "frozen_balance": "Gefrorenes Guthaben", "invoice_details": "Rechnungs-Details", "donation_link_details": "Details zum Spendenlink", - "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Brieftasche.", + "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", "create_invoice": "Rechnung erstellen", "create_donation_link": "Spendenlink erstellen", "optional_email_hint": "Optionale Benachrichtigungs-E-Mail für den Zahlungsempfänger", @@ -615,22 +615,22 @@ "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen", "profile": "Profil", "close": "Schließen", - "modify_2fa": "Kuchen 2FA ändern", - "disable_cake_2fa": "Kuchen 2FA deaktivieren", - "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Brieftasche und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", + "modify_2fa": "Cake 2FA ändern", + "disable_cake_2fa": "Cake 2FA deaktivieren", + "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Wallet und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", "disable": "Deaktivieren", - "setup_2fa": "Setup-Kuchen 2FA", + "setup_2fa": "Setup-Cake 2FA", "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", "totp_code": "TOTP-Code", "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", - "totp_2fa_success": "Erfolg! Cake 2FA für dieses Wallet aktiviert. Denken Sie daran, Ihren mnemonischen Seed zu speichern, falls Sie den Zugriff auf die Brieftasche verlieren.", + "totp_2fa_success": "Erfolg! Cake 2FA für dieses Wallet aktiviert. Denken Sie daran, Ihren mnemonischen Seed zu speichern, falls Sie den Zugriff auf die Wallet verlieren.", "totp_verification_success": "Verifizierung erfolgreich!", "totp_2fa_failure": "Falscher Code. Bitte versuchen Sie es mit einem anderen Code oder generieren Sie einen neuen geheimen Schlüssel. Verwenden Sie eine kompatible 2FA-App, die 8-stellige Codes und SHA512 unterstützt.", "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", "add_secret_code": "Fügen Sie diesen Geheimcode einem anderen Gerät hinzu", "totp_secret_code": "TOTP-Geheimcode", "important_note": "Wichtiger Hinweis", - "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Kühllagerung. 2FA schützt vor grundlegenden Arten von Angriffen, z. B. wenn Ihr Freund Ihren Fingerabdruck bereitstellt, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Brieftasche aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake ein Brieftasche ohne Verwahrung.", + "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Kühllagerung. 2FA schützt vor grundlegenden Arten von Angriffen, z. B. wenn Ihr Freund Ihren Fingerabdruck bereitstellt, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Wallet aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake Wallet eine Wallet ohne treuhänderische Verwahrung ist.", "setup_totp_recommended": "TOTP einrichten (empfohlen)", "disable_buy": "Kaufaktion deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", @@ -640,7 +640,7 @@ "high_contrast_theme": "Kontrastreiches Thema", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero Light-Thema", - "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", + "cake_2fa_preset" : "Cake 2FA-Voreinstellung", "narrow": "Eng", "normal": "Normal", "aggressive": "Übereifrig", diff --git a/scripts/docker/.gitignore b/scripts/docker/.gitignore new file mode 100644 index 000000000..ea1472ec1 --- /dev/null +++ b/scripts/docker/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile new file mode 100644 index 000000000..eef09a323 --- /dev/null +++ b/scripts/docker/Dockerfile @@ -0,0 +1,26 @@ +FROM ubuntu:20.04 +LABEL authors="konsti" + +ENV MONERO_BRANCH=release-v0.18.2.2-android +RUN apt-get update && \ + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections && \ + apt-get install -y dialog apt-utils curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + +RUN mkdir /opt/android/ + +COPY . /opt/android/cakewallet/ + +WORKDIR /opt/android/cakewallet/ + + +RUN ./install_ndk.sh + +RUN ./build_iconv.sh +RUN ./build_boost.sh +RUN ./build_openssl.sh +RUN ./build_sodium.sh +RUN ./build_unbound.sh +RUN ./build_zmq.sh + + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/scripts/docker/build_all.sh b/scripts/docker/build_all.sh new file mode 100644 index 000000000..0acb7fcde --- /dev/null +++ b/scripts/docker/build_all.sh @@ -0,0 +1 @@ +#!/bin/sh if [ -z "$APP_ANDROID_TYPE" ]; then echo "Please set APP_ANDROID_TYPE" exit 1 fi DIR=$(dirname "$0") case $APP_ANDROID_TYPE in "monero.com") $DIR/build_monero_all.sh ;; "cakewallet") $DIR/build_monero_all.sh $DIR/build_haven.sh ;; "haven") $DIR/build_haven_all.sh ;; esac \ No newline at end of file diff --git a/scripts/docker/build_boost.sh b/scripts/docker/build_boost.sh new file mode 100644 index 000000000..2c98afab5 --- /dev/null +++ b/scripts/docker/build_boost.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +. ./config.sh +BOOST_SRC_DIR=$WORKDIR/boost_1_72_0 +BOOST_FILENAME=boost_1_72_0.tar.bz2 +BOOST_VERSION=1.72.0 + +for arch in "aarch" "aarch64" "i686" "x86_64" +do + +PREFIX=$WORKDIR/prefix_${arch} +PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" +./init_boost.sh $arch $PREFIX $BOOST_SRC_DIR $BOOST_FILENAME $BOOST_VERSION +./finish_boost.sh $arch $PREFIX $BOOST_SRC_DIR $BOOST_SRC_DIR + +done diff --git a/scripts/docker/build_haven.sh b/scripts/docker/build_haven.sh new file mode 100644 index 000000000..7927c5102 --- /dev/null +++ b/scripts/docker/build_haven.sh @@ -0,0 +1 @@ +#!/bin/sh . ./config.sh HAVEN_VERSION=tags/v3.0.7 HAVEN_SRC_DIR=${WORKDIR}/haven git clone https://github.com/haven-protocol-org/haven-main.git ${HAVEN_SRC_DIR} git checkout ${HAVEN_VERSION} cd $HAVEN_SRC_DIR git submodule init git submodule update for arch in "aarch" "aarch64" "i686" "x86_64" do FLAGS="" PREFIX=${WORKDIR}/prefix_${arch} DEST_LIB_DIR=${PREFIX}/lib/haven DEST_INCLUDE_DIR=${PREFIX}/include/haven export CMAKE_INCLUDE_PATH="${PREFIX}/include" export CMAKE_LIBRARY_PATH="${PREFIX}/lib" ANDROID_STANDALONE_TOOLCHAIN_PATH="${TOOLCHAIN_BASE_DIR}_${arch}" PATH="${ANDROID_STANDALONE_TOOLCHAIN_PATH}/bin:${ORIGINAL_PATH}" mkdir -p $DEST_LIB_DIR mkdir -p $DEST_INCLUDE_DIR case $arch in "aarch" ) CLANG=arm-linux-androideabi-clang CXXLANG=arm-linux-androideabi-clang++ BUILD_64=OFF TAG="android-armv7" ARCH="armv7-a" ARCH_ABI="armeabi-v7a" FLAGS="-D CMAKE_ANDROID_ARM_MODE=ON -D NO_AES=true";; "aarch64" ) CLANG=aarch64-linux-androideabi-clang CXXLANG=aarch64-linux-androideabi-clang++ BUILD_64=ON TAG="android-armv8" ARCH="armv8-a" ARCH_ABI="arm64-v8a";; "i686" ) CLANG=i686-linux-androideabi-clang CXXLANG=i686-linux-androideabi-clang++ BUILD_64=OFF TAG="android-x86" ARCH="i686" ARCH_ABI="x86";; "x86_64" ) CLANG=x86_64-linux-androideabi-clang CXXLANG=x86_64-linux-androideabi-clang++ BUILD_64=ON TAG="android-x86_64" ARCH="x86-64" ARCH_ABI="x86_64";; esac cd $HAVEN_SRC_DIR rm -rf ./build/release mkdir -p ./build/release cd ./build/release CC=${CLANG} CXX=${CXXLANG} cmake -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} $FLAGS ../.. make wallet_api -j$THREADS find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; cp -r ./lib/* $DEST_LIB_DIR cp ../../src/wallet/api/wallet2_api.h $DEST_INCLUDE_DIR done \ No newline at end of file diff --git a/scripts/docker/build_haven_all.sh b/scripts/docker/build_haven_all.sh new file mode 100644 index 000000000..4b33ad077 --- /dev/null +++ b/scripts/docker/build_haven_all.sh @@ -0,0 +1 @@ +#!/bin/bash ./build_iconv.sh ./build_boost.sh ./build_openssl.sh ./build_sodium.sh ./build_zmq.sh ./build_haven.sh \ No newline at end of file diff --git a/scripts/docker/build_iconv.sh b/scripts/docker/build_iconv.sh new file mode 100644 index 000000000..9edac26b3 --- /dev/null +++ b/scripts/docker/build_iconv.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +. ./config.sh +export ICONV_FILENAME=libiconv-1.16.tar.gz +export ICONV_FILE_PATH=$WORKDIR/$ICONV_FILENAME +export ICONV_SRC_DIR=$WORKDIR/libiconv-1.16 +ICONV_SHA256="e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04" + +curl http://ftp.gnu.org/pub/gnu/libiconv/$ICONV_FILENAME -o $ICONV_FILE_PATH +echo $ICONV_SHA256 $ICONV_FILE_PATH | sha256sum -c - || exit 1 + +for arch in aarch aarch64 i686 x86_64 +do + +PREFIX=${WORKDIR}/prefix_${arch} +PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" + +case $arch in + "aarch" ) + CLANG=arm-linux-androideabi-clang + CXXLANG=arm-linux-androideabi-clang++ + HOST="arm-linux-android";; + * ) + CLANG=${arch}-linux-android-clang + CXXLANG=${arch}-linux-android-clang++ + HOST="${arch}-linux-android";; +esac + +cd $WORKDIR +rm -rf $ICONV_SRC_DIR +tar -xzf $ICONV_FILE_PATH -C $WORKDIR +cd $ICONV_SRC_DIR +CC=${CLANG} CXX=${CXXLANG} ./configure --build=x86_64-linux-gnu --host=${HOST} --prefix=${PREFIX} --disable-rpath +make -j$THREADS +make install + +done + diff --git a/scripts/docker/build_monero.sh b/scripts/docker/build_monero.sh new file mode 100644 index 000000000..d663f5288 --- /dev/null +++ b/scripts/docker/build_monero.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +. ./config.sh + +MONERO_SRC_DIR=${WORKDIR}/monero + +git clone https://github.com/cake-tech/monero.git ${MONERO_SRC_DIR} --branch ${MONERO_BRANCH} +cd $MONERO_SRC_DIR +git submodule init +git submodule update + +for arch in "aarch" "aarch64" "i686" "x86_64" +do +FLAGS="" +PREFIX=${WORKDIR}/prefix_${arch} +DEST_LIB_DIR=${PREFIX}/lib/monero +DEST_INCLUDE_DIR=${PREFIX}/include/monero +export CMAKE_INCLUDE_PATH="${PREFIX}/include" +export CMAKE_LIBRARY_PATH="${PREFIX}/lib" +ANDROID_STANDALONE_TOOLCHAIN_PATH="${TOOLCHAIN_BASE_DIR}_${arch}" +PATH="${ANDROID_STANDALONE_TOOLCHAIN_PATH}/bin:${ORIGINAL_PATH}" + +mkdir -p $DEST_LIB_DIR +mkdir -p $DEST_INCLUDE_DIR + +case $arch in + "aarch" ) + CLANG=arm-linux-androideabi-clang + CXXLANG=arm-linux-androideabi-clang++ + BUILD_64=OFF + TAG="android-armv7" + ARCH="armv7-a" + ARCH_ABI="armeabi-v7a" + FLAGS="-D CMAKE_ANDROID_ARM_MODE=ON -D NO_AES=true";; + "aarch64" ) + CLANG=aarch64-linux-androideabi-clang + CXXLANG=aarch64-linux-androideabi-clang++ + BUILD_64=ON + TAG="android-armv8" + ARCH="armv8-a" + ARCH_ABI="arm64-v8a";; + "i686" ) + CLANG=i686-linux-androideabi-clang + CXXLANG=i686-linux-androideabi-clang++ + BUILD_64=OFF + TAG="android-x86" + ARCH="i686" + ARCH_ABI="x86";; + "x86_64" ) + CLANG=x86_64-linux-androideabi-clang + CXXLANG=x86_64-linux-androideabi-clang++ + BUILD_64=ON + TAG="android-x86_64" + ARCH="x86-64" + ARCH_ABI="x86_64";; +esac + +cd $MONERO_SRC_DIR +rm -rf ./build/release +mkdir -p ./build/release +cd ./build/release +CC=${CLANG} CXX=${CXXLANG} cmake -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} $FLAGS ../.. + +make wallet_api -j$THREADS +find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; + +cp -r ./lib/* $DEST_LIB_DIR +cp ../../src/wallet/api/wallet2_api.h $DEST_INCLUDE_DIR +done diff --git a/scripts/docker/build_openssl.sh b/scripts/docker/build_openssl.sh new file mode 100644 index 000000000..685d0a1be --- /dev/null +++ b/scripts/docker/build_openssl.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +set -e + +. ./config.sh +OPENSSL_FILENAME=openssl-1.1.1q.tar.gz +OPENSSL_FILE_PATH=$WORKDIR/$OPENSSL_FILENAME +OPENSSL_SRC_DIR=$WORKDIR/openssl-1.1.1q +OPENSSL_SHA256="d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca" +ZLIB_DIR=$WORKDIR/zlib +ZLIB_TAG=v1.2.11 +ZLIB_COMMIT_HASH="cacf7f1d4e3d44d871b605da3b647f07d718623f" + +rm -rf $ZLIB_DIR +git clone -b $ZLIB_TAG --depth 1 https://github.com/madler/zlib $ZLIB_DIR +cd $ZLIB_DIR +git reset --hard $ZLIB_COMMIT_HASH +CC=clang CXX=clang++ ./configure --static +make + +curl https://www.openssl.org/source/$OPENSSL_FILENAME -o $OPENSSL_FILE_PATH +echo $OPENSSL_SHA256 $OPENSSL_FILE_PATH | sha256sum -c - || exit 1 + +for arch in "aarch" "aarch64" "i686" "x86_64" +do +PREFIX=$WORKDIR/prefix_${arch} +TOOLCHAIN=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 +PATH="${TOOLCHAIN}/bin:${ORIGINAL_PATH}" + +case $arch in + "aarch") X_ARCH="android-arm";; + "aarch64") X_ARCH="android-arm64";; + "i686") X_ARCH="android-x86";; + "x86_64") X_ARCH="android-x86_64";; + *) X_ARCH="android-${arch}";; +esac + +cd $WORKDIR +rm -rf $OPENSSL_SRC_DIR +tar -xzf $OPENSSL_FILE_PATH -C $WORKDIR +cd $OPENSSL_SRC_DIR + +CC=clang ANDROID_NDK=$TOOLCHAIN \ + ./Configure ${X_ARCH} \ + no-shared no-tests \ + --with-zlib-include=${PREFIX}/include \ + --with-zlib-lib=${PREFIX}/lib \ + --prefix=${PREFIX} \ + --openssldir=${PREFIX} \ + -D__ANDROID_API__=$API +make -j$THREADS +make -j$THREADS install_sw + +done + diff --git a/scripts/docker/build_sodium.sh b/scripts/docker/build_sodium.sh new file mode 100644 index 000000000..a934d641b --- /dev/null +++ b/scripts/docker/build_sodium.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +. ./config.sh +SODIUM_SRC_DIR=${WORKDIR}/libsodium +SODIUM_BRANCH=1.0.16 + +for arch in "aarch" "aarch64" "i686" "x86_64" +do + +PREFIX=${WORKDIR}/prefix_${arch} +PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" + +case $arch in + "aarch" ) TARGET="arm";; + "i686" ) TARGET="x86";; + * ) TARGET="${arch}";; +esac + +HOST="${TARGET}-linux-android" +cd $WORKDIR +rm -rf $SODIUM_SRC_DIR +git clone https://github.com/jedisct1/libsodium.git $SODIUM_SRC_DIR -b $SODIUM_BRANCH +cd $SODIUM_SRC_DIR +./autogen.sh +CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=${HOST} --enable-static --disable-shared +make -j$THREADS +make install + +done + diff --git a/scripts/docker/build_unbound.sh b/scripts/docker/build_unbound.sh new file mode 100644 index 000000000..8786b0f2b --- /dev/null +++ b/scripts/docker/build_unbound.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +. ./config.sh + +EXPAT_VERSION=R_2_4_8 +EXPAT_HASH="3bab6c09bbe8bf42d84b81563ddbcf4cca4be838" +EXPAT_SRC_DIR=$WORKDIR/libexpat + +for arch in "aarch" "aarch64" "i686" "x86_64" +do +PREFIX=$WORKDIR/prefix_${arch} +TOOLCHAIN=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 +PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" + +cd $WORKDIR +rm -rf $EXPAT_SRC_DIR +git clone https://github.com/libexpat/libexpat.git -b ${EXPAT_VERSION} ${EXPAT_SRC_DIR} +cd $EXPAT_SRC_DIR +test `git rev-parse HEAD` = ${EXPAT_HASH} || exit 1 +cd $EXPAT_SRC_DIR/expat + +case $arch in + "aarch") HOST="arm-linux-androideabi";; + "i686") HOST="x86-linux-android";; + *) HOST="${arch}-linux-android";; +esac + +./buildconf.sh +CC=clang CXX=clang++ ./configure --enable-static --disable-shared --prefix=${PREFIX} --host=${HOST} +make -j$THREADS +make -j$THREADS install +done + +UNBOUND_VERSION=release-1.16.2 +UNBOUND_HASH="cbed768b8ff9bfcf11089a5f1699b7e5707f1ea5" +UNBOUND_SRC_DIR=$WORKDIR/unbound-1.16.2 + +for arch in "aarch" "aarch64" "i686" "x86_64" +do +PREFIX=$WORKDIR/prefix_${arch} +TOOLCHAIN=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 + +case $arch in + "aarch") TOOLCHAIN_BIN_PATH=${TOOLCHAIN_BASE_DIR}_${arch}/arm-linux-androideabi/bin;; + *) TOOLCHAIN_BIN_PATH=${TOOLCHAIN_BASE_DIR}_${arch}/${arch}-linux-android/bin;; +esac + +PATH="${TOOLCHAIN_BIN_PATH}:${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" +echo $PATH +cd $WORKDIR +rm -rf $UNBOUND_SRC_DIR +git clone https://github.com/NLnetLabs/unbound.git -b ${UNBOUND_VERSION} ${UNBOUND_SRC_DIR} +cd $UNBOUND_SRC_DIR +test `git rev-parse HEAD` = ${UNBOUND_HASH} || exit 1 + +case $arch in + "aarch") HOST="arm-linux-androideabi";; + "i686") HOST="x86-linux-android";; + *) HOST="${arch}-linux-android";; +esac + +CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=${HOST} --enable-static --disable-shared --disable-flto --with-ssl=${PREFIX} --with-libexpat=${PREFIX} +make -j$THREADS +make -j$THREADS install +done diff --git a/scripts/docker/build_zmq.sh b/scripts/docker/build_zmq.sh new file mode 100644 index 000000000..bbff9e41b --- /dev/null +++ b/scripts/docker/build_zmq.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +. ./config.sh +ZMQ_SRC_DIR=$WORKDIR/libzmq +ZMQ_BRANCH=v4.3.3 +ZMQ_COMMIT_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3 + +for arch in "aarch" "aarch64" "i686" "x86_64" +do + +PREFIX=$WORKDIR/prefix_${arch} +PATH="${TOOLCHAIN_BASE_DIR}_${arch}/bin:${ORIGINAL_PATH}" + +case $arch in + "aarch" ) TARGET="arm";; + "i686" ) TARGET="x86";; + * ) TARGET="${arch}";; +esac + + +HOST="${TARGET}-linux-android" +cd $WORKDIR +rm -rf $ZMQ_SRC_DIR +git clone https://github.com/zeromq/libzmq.git ${ZMQ_SRC_DIR} -b ${ZMQ_BRANCH} +cd $ZMQ_SRC_DIR +git checkout ${ZMQ_COMMIT_HASH} +./autogen.sh +CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=${HOST} --enable-static --disable-shared +make -j$THREADS +make install + +done diff --git a/scripts/docker/config.sh b/scripts/docker/config.sh new file mode 100644 index 000000000..c5067f2c3 --- /dev/null +++ b/scripts/docker/config.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +export API=21 +export WORKDIR=/opt/android +export ANDROID_NDK_ZIP=${WORKDIR}/android-ndk-r17c.zip +export ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r17c +export ANDROID_NDK_HOME=$ANDROID_NDK_ROOT +export TOOLCHAIN_DIR="${WORKDIR}/toolchain" +export TOOLCHAIN_BASE_DIR=$TOOLCHAIN_DIR +export ORIGINAL_PATH=$PATH +export THREADS=4 diff --git a/scripts/docker/copy_haven_deps.sh b/scripts/docker/copy_haven_deps.sh new file mode 100644 index 000000000..d59e9d7f0 --- /dev/null +++ b/scripts/docker/copy_haven_deps.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +WORKDIR=/opt/android +CW_DIR=${WORKDIR}/cake_wallet +CW_EXRTERNAL_DIR=${CW_DIR}/cw_shared_external/ios/External/android +CW_HAVEN_EXTERNAL_DIR=${CW_DIR}/cw_haven/ios/External/android +CW_MONERO_EXTERNAL_DIR=${CW_DIR}/cw_monero/ios/External/android +for arch in "aarch" "aarch64" "i686" "x86_64" +do + +PREFIX=${WORKDIR}/prefix_${arch} +ABI="" + +case $arch in + "aarch" ) + ABI="armeabi-v7a";; + "aarch64" ) + ABI="arm64-v8a";; + "i686" ) + ABI="x86";; + "x86_64" ) + ABI="x86_64";; +esac + +LIB_DIR=${CW_EXRTERNAL_DIR}/${ABI}/lib +INCLUDE_DIR=${CW_EXRTERNAL_DIR}/${ABI}/include +LIBANBOUND_PATH=${PREFIX}/lib/libunbound.a + +mkdir -p $LIB_DIR +mkdir -p $INCLUDE_DIR + +cp -r ${PREFIX}/lib/* $LIB_DIR +cp -r ${PREFIX}/include/* $INCLUDE_DIR + +if [ -f "$LIBANBOUND_PATH" ]; then + cp $LIBANBOUND_PATH ${LIB_DIR}/monero +fi + +done + +mkdir -p ${CW_HAVEN_EXTERNAL_DIR}/include +mkdir -p ${CW_MONERO_EXTERNAL_DIR}/include + +cp $CW_EXRTERNAL_DIR/x86/include/monero/wallet2_api.h ${CW_MONERO_EXTERNAL_DIR}/include +cp $CW_EXRTERNAL_DIR/x86/include/haven/wallet2_api.h ${CW_HAVEN_EXTERNAL_DIR}/include diff --git a/scripts/docker/copy_monero_deps.sh b/scripts/docker/copy_monero_deps.sh new file mode 100644 index 000000000..e4392186c --- /dev/null +++ b/scripts/docker/copy_monero_deps.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +WORKDIR=/opt/android +CW_EXRTERNAL_DIR=${WORKDIR}/output/android + +for arch in "aarch" "aarch64" "i686" "x86_64" +do + +PREFIX=${WORKDIR}/prefix_${arch} +ABI="" + +case $arch in + "aarch" ) + ABI="armeabi-v7a";; + "aarch64" ) + ABI="arm64-v8a";; + "i686" ) + ABI="x86";; + "x86_64" ) + ABI="x86_64";; +esac + +LIB_DIR=${CW_EXRTERNAL_DIR}/${ABI}/lib +INCLUDE_DIR=${CW_EXRTERNAL_DIR}/${ABI}/include +LIBANBOUND_PATH=${PREFIX}/lib/libunbound.a + +mkdir -p $LIB_DIR +mkdir -p $INCLUDE_DIR + +cp -r ${PREFIX}/lib/* $LIB_DIR +cp -r ${PREFIX}/include/* $INCLUDE_DIR + +if [ -f "$LIBANBOUND_PATH" ]; then + cp $LIBANBOUND_PATH ${LIB_DIR}/monero +fi + +done diff --git a/scripts/docker/docker-compose.yml b/scripts/docker/docker-compose.yml new file mode 100644 index 000000000..eaeea0f5b --- /dev/null +++ b/scripts/docker/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3.6' + +services: + build_deps: + image: build_monero_deps + environment: + MONERO_BRANCH: release-v0.18.2.2-android + volumes: + - ./output:/opt/android/output diff --git a/scripts/docker/entrypoint.sh b/scripts/docker/entrypoint.sh new file mode 100644 index 000000000..e4bdc017c --- /dev/null +++ b/scripts/docker/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./build_monero.sh +./copy_monero_deps.sh diff --git a/scripts/docker/finish_boost.sh b/scripts/docker/finish_boost.sh new file mode 100644 index 000000000..e3f195276 --- /dev/null +++ b/scripts/docker/finish_boost.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +ARCH=$1 +PREFIX=$2 +BOOST_SRC_DIR=$3 + +cd $BOOST_SRC_DIR + +./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} -j$THREADS install diff --git a/scripts/docker/init_boost.sh b/scripts/docker/init_boost.sh new file mode 100644 index 000000000..ffb7a1416 --- /dev/null +++ b/scripts/docker/init_boost.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +ARCH=$1 +PREFIX=$2 +BOOST_SRC_DIR=$3 +BOOST_FILENAME=$4 +BOOST_VERSION=$5 +BOOST_FILE_PATH=$WORKDIR/$BOOST_FILENAME +BOOST_SHA256="59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722" + +if [ ! -e "$BOOST_FILE_PATH" ]; then + curl -L http://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION}/${BOOST_FILENAME} > $BOOST_FILE_PATH +fi + +echo $BOOST_SHA256 $BOOST_FILE_PATH | sha256sum -c - || exit 1 + +cd $WORKDIR +rm -rf $BOOST_SRC_DIR +rm -rf $PREFIX/include/boost +tar -xvf $BOOST_FILE_PATH -C $WORKDIR +cd $BOOST_SRC_DIR +./bootstrap.sh --prefix=${PREFIX} diff --git a/scripts/docker/install_ndk.sh b/scripts/docker/install_ndk.sh new file mode 100644 index 000000000..5f97751e3 --- /dev/null +++ b/scripts/docker/install_ndk.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +. ./config.sh +TOOLCHAIN_DIR=${WORKDIR}/toolchain +TOOLCHAIN_A32_DIR=${TOOLCHAIN_DIR}_aarch +TOOLCHAIN_A64_DIR=${TOOLCHAIN_DIR}_aarch64 +TOOLCHAIN_x86_DIR=${TOOLCHAIN_DIR}_i686 +TOOLCHAIN_x86_64_DIR=${TOOLCHAIN_DIR}_x86_64 +ANDROID_NDK_SHA256="3f541adbd0330a9205ba12697f6d04ec90752c53d6b622101a2a8a856e816589" + +curl https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip -o ${ANDROID_NDK_ZIP} +echo $ANDROID_NDK_SHA256 $ANDROID_NDK_ZIP | sha256sum -c || exit 1 +unzip $ANDROID_NDK_ZIP -d $WORKDIR + +${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py --arch arm64 --api $API --install-dir ${TOOLCHAIN_A64_DIR} --stl=libc++ +${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py --arch arm --api $API --install-dir ${TOOLCHAIN_A32_DIR} --stl=libc++ +${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py --arch x86 --api $API --install-dir ${TOOLCHAIN_x86_DIR} --stl=libc++ +${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py --arch x86_64 --api $API --install-dir ${TOOLCHAIN_x86_64_DIR} --stl=libc++ diff --git a/scripts/ios/build_monero.sh b/scripts/ios/build_monero.sh index 9a892d8c5..54dda546f 100755 --- a/scripts/ios/build_monero.sh +++ b/scripts/ios/build_monero.sh @@ -59,4 +59,4 @@ cp -r ./lib/* $DEST_LIB_DIR cp ../../src/wallet/api/wallet2_api.h $DEST_INCLUDE_DIR popd -done \ No newline at end of file +done diff --git a/tool/append_translation.dart b/tool/append_translation.dart index 080b2c5e7..e56ad89d6 100644 --- a/tool/append_translation.dart +++ b/tool/append_translation.dart @@ -1,66 +1,66 @@ -// import 'dart:convert'; -// import 'dart:io'; -// -// import 'package:translator/translator.dart'; -// -// const defaultLang = "en"; -// const langs = [ -// "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", -// "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", -// "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) -// ]; -// final translator = GoogleTranslator(); -// -// void main(List<String> args) async { -// if (args.length != 2) { -// throw Exception( -// 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); -// } -// -// final name = args.first; -// final text = args.last; -// -// print('Appending "$name": "$text"'); -// -// for (var lang in langs) { -// final fileName = getFileName(lang); -// final translation = await getTranslation(text, lang); -// -// appendArbFile(fileName, name, translation); -// } -// } -// -// void appendArbFile(String fileName, String name, String text) { -// final file = File(fileName); -// final inputContent = file.readAsStringSync(); -// final arbObj = json.decode(inputContent) as Map<String, dynamic>; -// -// if (arbObj.containsKey(name)) { -// print("String $name already exists in $fileName!"); -// return; -// } -// -// arbObj.addAll({name: text}); -// -// final outputContent = json -// .encode(arbObj) -// .replaceAll('","', '",\n "') -// .replaceAll('{"', '{\n "') -// .replaceAll('"}', '"\n}') -// .replaceAll('":"', '": "'); -// -// file.writeAsStringSync(outputContent); -// } -// -// -// Future<String> getTranslation(String text, String lang) async { -// if (lang == defaultLang) return text; -// return (await translator.translate(text, from: defaultLang, to: lang)).text; -// } -// -// String getFileName(String lang) { -// final shortLang = lang -// .split("-") -// .first; -// return "./res/values/strings_$shortLang.arb"; -// } +import 'dart:convert'; +import 'dart:io'; + +import 'package:translator/translator.dart'; + +const defaultLang = "en"; +const langs = [ + "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", + "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", + "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) +]; +final translator = GoogleTranslator(); + +void main(List<String> args) async { + if (args.length != 2) { + throw Exception( + 'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`'); + } + + final name = args.first; + final text = args.last; + + print('Appending "$name": "$text"'); + + for (var lang in langs) { + final fileName = getFileName(lang); + final translation = await getTranslation(text, lang); + + appendArbFile(fileName, name, translation); + } +} + +void appendArbFile(String fileName, String name, String text) { + final file = File(fileName); + final inputContent = file.readAsStringSync(); + final arbObj = json.decode(inputContent) as Map<String, dynamic>; + + if (arbObj.containsKey(name)) { + print("String $name already exists in $fileName!"); + return; + } + + arbObj.addAll({name: text}); + + final outputContent = json + .encode(arbObj) + .replaceAll('","', '",\n "') + .replaceAll('{"', '{\n "') + .replaceAll('"}', '"\n}') + .replaceAll('":"', '": "'); + + file.writeAsStringSync(outputContent); +} + + +Future<String> getTranslation(String text, String lang) async { + if (lang == defaultLang) return text; + return (await translator.translate(text, from: defaultLang, to: lang)).text; +} + +String getFileName(String lang) { + final shortLang = lang + .split("-") + .first; + return "./res/values/strings_$shortLang.arb"; +} diff --git a/tool/configure.dart b/tool/configure.dart index 3893847e2..5172f4244 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -25,6 +25,7 @@ Future<void> main(List<String> args) async { Future<void> generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ +import 'package:cake_wallet/entities/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -48,24 +49,6 @@ import 'package:cw_bitcoin/litecoin_wallet_service.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinContent = """ -class Unspent { - Unspent(this.address, this.hash, this.value, this.vout) - : isSending = true, - isFrozen = false, - note = ''; - - final String address; - final String hash; - final int value; - final int vout; - - bool isSending; - bool isFrozen; - String note; - - bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); -} - abstract class Bitcoin { TransactionPriority getMediumTransactionPriority(); @@ -122,6 +105,9 @@ abstract class Bitcoin { Future<void> generateMonero(bool hasImplementation) async { final outputFile = File(moneroOutputPath); const moneroCommonHeaders = """ +import 'package:cake_wallet/entities/unspent_transaction_output.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_monero/monero_unspent.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -231,6 +217,9 @@ abstract class Monero { TransactionPriority deserializeMoneroTransactionPriority({required int raw}); List<TransactionPriority> getTransactionPriorities(); List<String> getMoneroWordList(String language); + + List<Unspent> getUnspents(Object wallet); + void updateUnspents(Object wallet); WalletCredentials createMoneroRestoreWalletFromKeysCredentials({ required String name, @@ -252,7 +241,7 @@ abstract class Monero { void setCurrentAccount(Object wallet, int id, String label, String? balance); void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); - WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource); + WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource); Map<String, String> pendingTransactionInfo(Object transaction); } @@ -650,4 +639,4 @@ Future<void> generateWalletTypes({required bool hasMonero, required bool hasBitc outputContent += '];\n'; await walletTypesFile.writeAsString(outputContent); -} \ No newline at end of file +} From 9999816850560da68040f3150ead330fc92e1518 Mon Sep 17 00:00:00 2001 From: Justin Ehrenhofer <justin.ehrenhofer@gmail.com> Date: Thu, 24 Aug 2023 16:30:53 -0500 Subject: [PATCH 10/18] Improve ChangeNOW and Trocador network mapping (#1058) * Improve ChangeNOW network mapping Follows Trocador code to use the title instead of the const name, and to allow normalizing across the tag level instead of needing to map the `legacyTicker` I will test * Missing `}` * Remove `:` * Add normalizeTitle for zec * Missing `;` * Make functions private and fix zec for Trocador * Add supported assets [skip ci] * Change name [skip ci] --- .../changenow_exchange_provider.dart | 65 ++++++++++--------- .../sideshift_exchange_provider.dart | 1 - .../trocador/trocador_exchange_provider.dart | 20 ++++-- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index ecfe888e7..6166a8875 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -68,14 +68,12 @@ class ChangeNowExchangeProvider extends ExchangeProvider { required CryptoCurrency to, required bool isFixedRateMode}) async { final headers = {apiHeaderKey: apiKey}; - final normalizedFrom = normalizeCryptoCurrency(from); - final normalizedTo = normalizeCryptoCurrency(to); final flow = getFlow(isFixedRateMode); final params = <String, String>{ - 'fromCurrency': normalizedFrom, - 'toCurrency': normalizedTo, - 'fromNetwork': networkFor(from), - 'toNetwork': networkFor(to), + 'fromCurrency': _normalizeCurrency(from), + 'toCurrency': _normalizeCurrency(to), + 'fromNetwork': _networkFor(from), + 'toNetwork': _networkFor(to), 'flow': flow }; final uri = Uri.https(apiAuthority, rangePath, params); @@ -112,10 +110,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final flow = getFlow(isFixedRateMode); final type = isFixedRateMode ? 'reverse' : 'direct'; final body = <String, dynamic>{ - 'fromCurrency': normalizeCryptoCurrency(_request.from), - 'toCurrency': normalizeCryptoCurrency(_request.to), - 'fromNetwork': networkFor(_request.from), - 'toNetwork': networkFor(_request.to), + 'fromCurrency': _normalizeCurrency(_request.from), + 'toCurrency': _normalizeCurrency(_request.to), + 'fromNetwork': _networkFor(_request.from), + 'toNetwork': _networkFor(_request.to), if (!isFixedRateMode) 'fromAmount': _request.fromAmount, if (isFixedRateMode) 'toAmount': _request.toAmount, 'address': _request.address, @@ -241,10 +239,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final type = isReverse ? 'reverse' : 'direct'; final flow = getFlow(isFixedRateMode); final params = <String, String>{ - 'fromCurrency': normalizeCryptoCurrency(from), - 'toCurrency': normalizeCryptoCurrency(to), - 'fromNetwork': networkFor(from), - 'toNetwork': networkFor(to), + 'fromCurrency': _normalizeCurrency(from), + 'toCurrency': _normalizeCurrency(to), + 'fromNetwork': _networkFor(from), + 'toNetwork': _networkFor(to), 'type': type, 'flow': flow }; @@ -273,25 +271,34 @@ class ChangeNowExchangeProvider extends ExchangeProvider { } } - String networkFor(CryptoCurrency currency) { + String _networkFor(CryptoCurrency currency) { switch (currency) { case CryptoCurrency.usdt: - return CryptoCurrency.btc.title.toLowerCase(); + return 'btc'; default: - return currency.tag != null ? currency.tag!.toLowerCase() : currency.title.toLowerCase(); + return currency.tag != null ? _normalizeTag(currency.tag!) : currency.title.toLowerCase(); } } -} -String normalizeCryptoCurrency(CryptoCurrency currency) { - switch (currency) { - case CryptoCurrency.zec: - return 'zec'; - case CryptoCurrency.usdcpoly: - return 'usdcmatic'; - case CryptoCurrency.maticpoly: - return 'maticmainnet'; - default: - return currency.title.toLowerCase(); + String _normalizeCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.zec: + return 'zec'; + default: + return currency.title.toLowerCase(); + } } -} + + String _normalizeTag(String tag) { + switch (tag) { + case 'POLY': + return 'matic'; + case 'LN': + return 'lightning'; + case 'AVAXC': + return 'cchain'; + default: + return tag.toLowerCase(); + } + } +} \ No newline at end of file diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 26575f2c1..257d339cf 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -28,7 +28,6 @@ class SideShiftExchangeProvider extends ExchangeProvider { CryptoCurrency.xhv, CryptoCurrency.dcr, CryptoCurrency.kmd, - CryptoCurrency.mkr, CryptoCurrency.oxt, CryptoCurrency.pivx, CryptoCurrency.rune, diff --git a/lib/exchange/trocador/trocador_exchange_provider.dart b/lib/exchange/trocador/trocador_exchange_provider.dart index fb6109bdf..b42291ed7 100644 --- a/lib/exchange/trocador/trocador_exchange_provider.dart +++ b/lib/exchange/trocador/trocador_exchange_provider.dart @@ -20,7 +20,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { bool useTorOnly; static const List<CryptoCurrency> _notSupported = [ - CryptoCurrency.scrt, CryptoCurrency.stx, CryptoCurrency.zaddr, ]; @@ -60,8 +59,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { }) async { final params = <String, String>{ 'api_key': apiKey, - 'ticker_from': request.from.title.toLowerCase(), - 'ticker_to': request.to.title.toLowerCase(), + 'ticker_from': _normalizeCurrency(request.from), + 'ticker_to': _normalizeCurrency(request.to), 'network_from': _networkFor(request.from), 'network_to': _networkFor(request.to), 'payment': isFixedRateMode ? 'True' : 'False', @@ -137,7 +136,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { required bool isFixedRateMode}) async { final params = <String, String>{ 'api_key': apiKey, - 'ticker': from.title.toLowerCase(), + 'ticker': _normalizeCurrency(from), 'name': from.name, }; @@ -177,8 +176,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { final params = <String, String>{ 'api_key': apiKey, - 'ticker_from': from.title.toLowerCase(), - 'ticker_to': to.title.toLowerCase(), + 'ticker_from': _normalizeCurrency(from), + 'ticker_to': _normalizeCurrency(to), 'network_from': _networkFor(from), 'network_to': _networkFor(to), if (!isFixedRateMode) 'amount_from': amount.toString(), @@ -279,6 +278,15 @@ class TrocadorExchangeProvider extends ExchangeProvider { } } + String _normalizeCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.zec: + return 'zec'; + default: + return currency.title.toLowerCase(); + } + } + String _normalizeTag(String tag) { switch (tag) { case 'ETH': From fff5a1c41982ba449132bd20e5f6d71d2318acda Mon Sep 17 00:00:00 2001 From: Godwin Asuquo <41484542+godilite@users.noreply.github.com> Date: Tue, 29 Aug 2023 19:11:51 +0300 Subject: [PATCH 11/18] CW-228 Auto generate monero subaddress (#902) * Add UI and setting logic for subaddresses * Enable auto generate subaddresses * Rename variable * Add comment to unused code * Fix issue with initial state change * Fix observable for isAppSecure * Filter sub account contacts * Fix select account use unused address * Use add address if last address is unused * Fix auto generate wallet issues * Fix button color * Add translation and refactored naming * Fix PR review * Remove unused code * Remove unused overrides in electrum * Fix address info null check * CW-228 Fix ContactListViewModel condition * CW-228 Fix Account Tile; Rework updateAddressesInBox; Fix _getAllUnusedAddresses * CW-228 Fix unintentional address_page.dart regression * CW-228 Fix Merge Conflicts * CW-228 Add more translation Tools * CW-228 More merge conflict fixes * CW-228 Fix Merge Conflicts * CW-228 Auto Translation improvements * CW-228 Resolve requested Changes --------- Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com> --- cw_core/lib/address_info.dart | 21 +++++ cw_core/lib/hive_type_ids.dart | 2 +- cw_core/lib/wallet_addresses.dart | 10 ++- cw_core/lib/wallet_base.dart | 4 + cw_core/lib/wallet_info.dart | 7 ++ cw_haven/lib/haven_wallet.dart | 82 +++++++---------- cw_monero/lib/monero_subaddress_list.dart | 88 ++++++++++++++++--- cw_monero/lib/monero_wallet.dart | 35 +++++++- cw_monero/lib/monero_wallet_addresses.dart | 52 ++++++++--- lib/core/backup_service.dart | 6 ++ lib/di.dart | 2 +- .../auto_generate_subaddress_status.dart | 13 +++ lib/entities/preferences_key.dart | 1 + lib/main.dart | 5 ++ lib/reactions/on_current_wallet_change.dart | 81 ++++++++++------- .../dashboard/widgets/address_page.dart | 40 ++++++--- .../monero_accounts/widgets/account_tile.dart | 15 ++-- .../screens/restore/restore_options_page.dart | 2 +- .../restore/widgets/backup_file_button.dart | 0 lib/src/screens/settings/privacy_page.dart | 8 ++ lib/store/settings_store.dart | 27 +++++- .../contact_list/contact_list_view_model.dart | 31 +++++-- .../dashboard/dashboard_view_model.dart | 5 ++ .../settings/privacy_settings_view_model.dart | 22 ++++- res/values/strings_ar.arb | 4 +- res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- tool/append_translation.dart | 54 ++---------- tool/translation_consistence.dart | 37 ++++++++ tool/utils/translation/arb_file_utils.dart | 66 ++++++++++++++ .../translation/translation_constants.dart | 6 ++ tool/utils/translation/translation_utils.dart | 37 ++++++++ 54 files changed, 603 insertions(+), 200 deletions(-) create mode 100644 cw_core/lib/address_info.dart create mode 100644 lib/entities/auto_generate_subaddress_status.dart create mode 100644 lib/src/screens/restore/widgets/backup_file_button.dart create mode 100644 tool/translation_consistence.dart create mode 100644 tool/utils/translation/arb_file_utils.dart create mode 100644 tool/utils/translation/translation_constants.dart create mode 100644 tool/utils/translation/translation_utils.dart diff --git a/cw_core/lib/address_info.dart b/cw_core/lib/address_info.dart new file mode 100644 index 000000000..63dc023ab --- /dev/null +++ b/cw_core/lib/address_info.dart @@ -0,0 +1,21 @@ +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; + +part 'address_info.g.dart'; + +@HiveType(typeId: ADDRESS_INFO_TYPE_ID) +class AddressInfo extends HiveObject { + AddressInfo({required this.address, this.accountIndex, required this.label}); + + static const typeId = ADDRESS_INFO_TYPE_ID; + static const boxName = 'AddressInfo'; + + @HiveField(0) + int? accountIndex; + + @HiveField(1, defaultValue: '') + String address; + + @HiveField(2, defaultValue: '') + String label; +} diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index 0961182bc..950f39e1f 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -9,5 +9,5 @@ const EXCHANGE_TEMPLATE_TYPE_ID = 7; const ORDER_TYPE_ID = 8; const UNSPENT_COINS_INFO_TYPE_ID = 9; const ANONPAY_INVOICE_INFO_TYPE_ID = 10; - +const ADDRESS_INFO_TYPE_ID = 11; const ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index a34101a88..27b5468c5 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -1,8 +1,10 @@ +import 'package:cw_core/address_info.dart'; import 'package:cw_core/wallet_info.dart'; abstract class WalletAddresses { WalletAddresses(this.walletInfo) - : addressesMap = {}; + : addressesMap = {}, + addressInfos = {}; final WalletInfo walletInfo; @@ -12,6 +14,10 @@ abstract class WalletAddresses { Map<String, String> addressesMap; + Map<int, List<AddressInfo>> addressInfos; + + Set<String> usedAddresses = {}; + Future<void> init(); Future<void> updateAddressesInBox(); @@ -20,6 +26,8 @@ abstract class WalletAddresses { try { walletInfo.address = address; walletInfo.addresses = addressesMap; + walletInfo.addressInfos = addressInfos; + walletInfo.usedAddresses = usedAddresses.toList(); if (walletInfo.isInBox) { await walletInfo.save(); diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 5bc5ef914..e24fdb4b0 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -52,6 +52,10 @@ abstract class WalletBase< late HistoryType transactionHistory; + set isEnabledAutoGenerateSubaddress(bool value) {} + + bool get isEnabledAutoGenerateSubaddress => false; + Future<void> connectToNode({required Node node}); Future<void> startSync(); diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 6b3fa9e98..210adb9a4 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cw_core/address_info.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; @@ -72,6 +73,12 @@ class WalletInfo extends HiveObject { @HiveField(13) bool? showIntroCakePayCard; + @HiveField(14) + Map<int, List<AddressInfo>>? addressInfos; + + @HiveField(15) + List<String>? usedAddresses; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 226ace6a1..e639be4b9 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -12,8 +12,7 @@ import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_haven/api/structs/pending_transaction.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_haven/api/transaction_history.dart' - as haven_transaction_history; +import 'package:cw_haven/api/transaction_history.dart' as haven_transaction_history; //import 'package:cw_haven/wallet.dart'; import 'package:cw_haven/api/wallet.dart' as haven_wallet; import 'package:cw_haven/api/transaction_history.dart' as transaction_history; @@ -37,8 +36,8 @@ const moneroBlockSize = 1000; class HavenWallet = HavenWalletBase with _$HavenWallet; -abstract class HavenWalletBase extends WalletBase<MoneroBalance, - HavenTransactionHistory, HavenTransactionInfo> with Store { +abstract class HavenWalletBase + extends WalletBase<MoneroBalance, HavenTransactionHistory, HavenTransactionInfo> with Store { HavenWalletBase({required WalletInfo walletInfo}) : balance = ObservableMap.of(getHavenBalance(accountIndex: 0)), _isTransactionUpdating = false, @@ -47,8 +46,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, syncStatus = NotConnectedSyncStatus(), super(walletInfo) { transactionHistory = HavenTransactionHistory(); - _onAccountChangeReaction = reaction((_) => walletAddresses.account, - (Account? account) { + _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) { if (account == null) { return; } @@ -96,14 +94,12 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, haven_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery); if (haven_wallet.getCurrentHeight() <= 1) { - haven_wallet.setRefreshFromBlockHeight( - height: walletInfo.restoreHeight); + haven_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight); } } - _autoSaveTimer = Timer.periodic( - Duration(seconds: _autoSaveInterval), - (_) async => await save()); + _autoSaveTimer = + Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save()); } @override @@ -115,7 +111,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, _onAccountChangeReaction?.reaction.dispose(); _autoSaveTimer?.cancel(); } - + @override Future<void> connectToNode({required Node node}) async { try { @@ -170,26 +166,25 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, } if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll - || (item.formattedCryptoAmount ?? 0) <= 0)) { - throw HavenTransactionCreationException('You do not have enough coins to send this amount.'); + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw HavenTransactionCreationException( + 'You do not have enough coins to send this amount.'); } - final int totalAmount = outputs.fold(0, (acc, value) => - acc + (value.formattedCryptoAmount ?? 0)); + final int totalAmount = + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)); if (unlockedBalance < totalAmount) { - throw HavenTransactionCreationException('You do not have enough coins to send this amount.'); + throw HavenTransactionCreationException( + 'You do not have enough coins to send this amount.'); } - final moneroOutputs = outputs.map((output) => - MoneroOutput( - address: output.address, - amount: output.cryptoAmount!.replaceAll(',', '.'))) + final moneroOutputs = outputs + .map((output) => MoneroOutput( + address: output.address, amount: output.cryptoAmount!.replaceAll(',', '.'))) .toList(); - pendingTransactionDescription = - await transaction_history.createTransactionMultDest( + pendingTransactionDescription = await transaction_history.createTransactionMultDest( outputs: moneroOutputs, priorityRaw: _credentials.priority.serialize(), accountIndex: walletAddresses.account!.id); @@ -198,12 +193,8 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, final address = output.isParsedAddress && (output.extractedAddress?.isNotEmpty ?? false) ? output.extractedAddress! : output.address; - final amount = output.sendAll - ? null - : output.cryptoAmount!.replaceAll(',', '.'); - final int? formattedAmount = output.sendAll - ? null - : output.formattedCryptoAmount; + final amount = output.sendAll ? null : output.cryptoAmount!.replaceAll(',', '.'); + final int? formattedAmount = output.sendAll ? null : output.formattedCryptoAmount; if ((formattedAmount != null && unlockedBalance < formattedAmount) || (formattedAmount == null && unlockedBalance <= 0)) { @@ -213,8 +204,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, 'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.'); } - pendingTransactionDescription = - await transaction_history.createTransaction( + pendingTransactionDescription = await transaction_history.createTransaction( address: address, assetType: _credentials.assetType, amount: amount, @@ -307,16 +297,14 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, } String getTransactionAddress(int accountIndex, int addressIndex) => - haven_wallet.getAddress( - accountIndex: accountIndex, - addressIndex: addressIndex); + haven_wallet.getAddress(accountIndex: accountIndex, addressIndex: addressIndex); @override Future<Map<String, HavenTransactionInfo>> fetchTransactions() async { haven_transaction_history.refreshTransactions(); - return _getAllTransactions(null).fold<Map<String, HavenTransactionInfo>>( - <String, HavenTransactionInfo>{}, - (Map<String, HavenTransactionInfo> acc, HavenTransactionInfo tx) { + return _getAllTransactions(null) + .fold<Map<String, HavenTransactionInfo>>(<String, HavenTransactionInfo>{}, + (Map<String, HavenTransactionInfo> acc, HavenTransactionInfo tx) { acc[tx.id] = tx; return acc; }); @@ -340,9 +328,9 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, } List<HavenTransactionInfo> _getAllTransactions(dynamic _) => haven_transaction_history - .getAllTransations() - .map((row) => HavenTransactionInfo.fromRow(row)) - .toList(); + .getAllTransations() + .map((row) => HavenTransactionInfo.fromRow(row)) + .toList(); void _setListeners() { _listener?.stop(); @@ -364,8 +352,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, } int _getHeightDistance(DateTime date) { - final distance = - DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch; + final distance = DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch; final daysTmp = (distance / 86400).round(); final days = daysTmp < 1 ? 1 : daysTmp; @@ -386,8 +373,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, void _askForUpdateBalance() => balance.addAll(getHavenBalance(accountIndex: walletAddresses.account!.id)); - Future<void> _askForUpdateTransactionHistory() async => - await updateTransactions(); + Future<void> _askForUpdateTransactionHistory() async => await updateTransactions(); void _onNewBlock(int height, int blocksLeft, double ptc) async { try { @@ -404,9 +390,9 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance, syncStatus = SyncedSyncStatus(); if (!_hasSyncAfterStartup) { - _hasSyncAfterStartup = true; - await save(); - } + _hasSyncAfterStartup = true; + await save(); + } if (walletInfo.isRecovery) { await setAsRecovered(); diff --git a/cw_monero/lib/monero_subaddress_list.dart b/cw_monero/lib/monero_subaddress_list.dart index 53efc1251..dbd1a89ae 100644 --- a/cw_monero/lib/monero_subaddress_list.dart +++ b/cw_monero/lib/monero_subaddress_list.dart @@ -6,14 +6,15 @@ import 'package:cw_core/subaddress.dart'; part 'monero_subaddress_list.g.dart'; -class MoneroSubaddressList = MoneroSubaddressListBase - with _$MoneroSubaddressList; +class MoneroSubaddressList = MoneroSubaddressListBase with _$MoneroSubaddressList; abstract class MoneroSubaddressListBase with Store { MoneroSubaddressListBase() - : _isRefreshing = false, - _isUpdating = false, - subaddresses = ObservableList<Subaddress>(); + : _isRefreshing = false, + _isUpdating = false, + subaddresses = ObservableList<Subaddress>(); + + final List<String> _usedAddresses = []; @observable ObservableList<Subaddress> subaddresses; @@ -49,20 +50,24 @@ abstract class MoneroSubaddressListBase with Store { subaddresses = [primary] + rest.toList(); } - return subaddresses - .map((subaddressRow) => Subaddress( + return subaddresses.map((subaddressRow) { + final hasDefaultAddressName = + subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() || + subaddressRow.getLabel().toLowerCase() == 'Untitled account'.toLowerCase(); + final isPrimaryAddress = subaddressRow.getId() == 0 && hasDefaultAddressName; + return Subaddress( id: subaddressRow.getId(), address: subaddressRow.getAddress(), - label: subaddressRow.getId() == 0 && - subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() - ? 'Primary address' - : subaddressRow.getLabel())) - .toList(); + label: isPrimaryAddress + ? 'Primary address' + : hasDefaultAddressName + ? '' + : subaddressRow.getLabel()); + }).toList(); } Future<void> addSubaddress({required int accountIndex, required String label}) async { - await subaddress_list.addSubaddress( - accountIndex: accountIndex, label: label); + await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label); update(accountIndex: accountIndex); } @@ -88,4 +93,59 @@ abstract class MoneroSubaddressListBase with Store { rethrow; } } + + Future<void> updateWithAutoGenerate({ + required int accountIndex, + required String defaultLabel, + required List<String> usedAddresses, + }) async { + _usedAddresses.addAll(usedAddresses); + if (_isUpdating) { + return; + } + + try { + _isUpdating = true; + refresh(accountIndex: accountIndex); + subaddresses.clear(); + final newSubAddresses = + await _getAllUnusedAddresses(accountIndex: accountIndex, label: defaultLabel); + subaddresses.addAll(newSubAddresses); + } catch (e) { + rethrow; + } finally { + _isUpdating = false; + } + } + + Future<List<Subaddress>> _getAllUnusedAddresses( + {required int accountIndex, required String label}) async { + final allAddresses = subaddress_list.getAllSubaddresses(); + + if (allAddresses.isEmpty || _usedAddresses.contains(allAddresses.last.getAddress())) { + final isAddressUnused = await _newSubaddress(accountIndex: accountIndex, label: label); + if (!isAddressUnused) { + return await _getAllUnusedAddresses(accountIndex: accountIndex, label: label); + } + } + + return allAddresses + .map((subaddressRow) => Subaddress( + id: subaddressRow.getId(), + address: subaddressRow.getAddress(), + label: subaddressRow.getId() == 0 && + subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() + ? 'Primary address' + : subaddressRow.getLabel())) + .toList(); + } + + Future<bool> _newSubaddress({required int accountIndex, required String label}) async { + await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label); + + return subaddress_list + .getAllSubaddresses() + .where((subaddressRow) => !_usedAddresses.contains(subaddressRow.getAddress())) + .isNotEmpty; + } } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 76563310e..39c0604a3 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -48,12 +48,14 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, }), _isTransactionUpdating = false, _hasSyncAfterStartup = false, - walletAddresses = MoneroWalletAddresses(walletInfo), + isEnabledAutoGenerateSubaddress = false, syncStatus = NotConnectedSyncStatus(), unspentCoins = [], this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { transactionHistory = MoneroTransactionHistory(); + walletAddresses = MoneroWalletAddresses(walletInfo, transactionHistory); + _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) { if (account == null) { return; @@ -64,7 +66,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id)) }); - walletAddresses.updateSubaddressList(accountIndex: account.id); + _updateSubAddress(isEnabledAutoGenerateSubaddress, account: account); + }); + + reaction((_) => isEnabledAutoGenerateSubaddress, (bool enabled) { + _updateSubAddress(enabled, account: walletAddresses.account); }); } @@ -73,7 +79,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, Box<UnspentCoinsInfo> unspentCoinsInfo; @override - MoneroWalletAddresses walletAddresses; + late MoneroWalletAddresses walletAddresses; + + @override + @observable + bool isEnabledAutoGenerateSubaddress; @override @observable @@ -287,6 +297,14 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, @override Future<void> save() async { + await walletAddresses.updateUsedSubaddress(); + + if (isEnabledAutoGenerateSubaddress) { + walletAddresses.updateUnusedSubaddress( + accountIndex: walletAddresses.account?.id ?? 0, + defaultLabel: walletAddresses.account?.label ?? ''); + } + await walletAddresses.updateAddressesInBox(); await backupWalletFiles(name); await monero_wallet.store(); @@ -610,4 +628,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, print(e.toString()); } } + + void _updateSubAddress(bool enableAutoGenerate, {Account? account}) { + if (enableAutoGenerate) { + walletAddresses.updateUnusedSubaddress( + accountIndex: account?.id ?? 0, + defaultLabel: account?.label ?? '', + ); + } else { + walletAddresses.updateSubaddressList(accountIndex: account?.id ?? 0); + } + } } diff --git a/cw_monero/lib/monero_wallet_addresses.dart b/cw_monero/lib/monero_wallet_addresses.dart index 2002e789a..fcc3576f4 100644 --- a/cw_monero/lib/monero_wallet_addresses.dart +++ b/cw_monero/lib/monero_wallet_addresses.dart @@ -1,27 +1,32 @@ +import 'package:cw_core/address_info.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/account.dart'; +import 'package:cw_monero/api/wallet.dart'; import 'package:cw_monero/monero_account_list.dart'; import 'package:cw_monero/monero_subaddress_list.dart'; import 'package:cw_core/subaddress.dart'; +import 'package:cw_monero/monero_transaction_history.dart'; import 'package:mobx/mobx.dart'; part 'monero_wallet_addresses.g.dart'; -class MoneroWalletAddresses = MoneroWalletAddressesBase - with _$MoneroWalletAddresses; +class MoneroWalletAddresses = MoneroWalletAddressesBase with _$MoneroWalletAddresses; abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { - MoneroWalletAddressesBase(WalletInfo walletInfo) - : accountList = MoneroAccountList(), - subaddressList = MoneroSubaddressList(), - address = '', - super(walletInfo); + MoneroWalletAddressesBase( + WalletInfo walletInfo, MoneroTransactionHistory moneroTransactionHistory) + : accountList = MoneroAccountList(), + _moneroTransactionHistory = moneroTransactionHistory, + subaddressList = MoneroSubaddressList(), + address = '', + super(walletInfo); + final MoneroTransactionHistory _moneroTransactionHistory; @override @observable String address; - + @observable Account? account; @@ -36,7 +41,6 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { Future<void> init() async { accountList.update(); account = accountList.accounts.first; - updateSubaddressList(accountIndex: account?.id ?? 0); await updateAddressesInBox(); } @@ -46,11 +50,15 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { final _subaddressList = MoneroSubaddressList(); addressesMap.clear(); + addressInfos.clear(); accountList.accounts.forEach((account) { _subaddressList.update(accountIndex: account.id); _subaddressList.subaddresses.forEach((subaddress) { addressesMap[subaddress.address] = subaddress.label; + addressInfos[account.id] ??= []; + addressInfos[account.id]?.add(AddressInfo( + address: subaddress.address, label: subaddress.label, accountIndex: account.id)); }); }); @@ -62,14 +70,14 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { bool validate() { accountList.update(); - final accountListLength = accountList.accounts.length ?? 0; + final accountListLength = accountList.accounts.length; if (accountListLength <= 0) { return false; } subaddressList.update(accountIndex: accountList.accounts.first.id); - final subaddressListLength = subaddressList.subaddresses.length ?? 0; + final subaddressListLength = subaddressList.subaddresses.length; if (subaddressListLength <= 0) { return false; @@ -83,4 +91,24 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { subaddress = subaddressList.subaddresses.first; address = subaddress!.address; } -} \ No newline at end of file + + Future<void> updateUsedSubaddress() async { + final transactions = _moneroTransactionHistory.transactions.values.toList(); + + transactions.forEach((element) { + final accountIndex = element.accountIndex; + final addressIndex = element.addressIndex; + usedAddresses.add(getAddress(accountIndex: accountIndex, addressIndex: addressIndex)); + }); + } + + Future<void> updateUnusedSubaddress( + {required int accountIndex, required String defaultLabel}) async { + await subaddressList.updateWithAutoGenerate( + accountIndex: accountIndex, + defaultLabel: defaultLabel, + usedAddresses: usedAddresses.toList()); + subaddress = subaddressList.subaddresses.last; + address = subaddress!.address; + } +} diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 6476891ed..3f430b7e9 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -246,6 +246,7 @@ class BackupService { final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncMode = data[PreferencesKey.syncModeKey] as int?; + final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName); @@ -296,6 +297,9 @@ class BackupService { if (fiatApiMode != null) await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode); + if (autoGenerateSubaddressStatus != null) + await _sharedPreferences.setInt(PreferencesKey.autoGenerateSubaddressStatusKey, + autoGenerateSubaddressStatus); if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); @@ -523,6 +527,8 @@ class BackupService { _sharedPreferences.getInt(PreferencesKey.syncModeKey), PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey), + PreferencesKey.autoGenerateSubaddressStatusKey: + _sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey), }; return json.encode(preferences); diff --git a/lib/di.dart b/lib/di.dart index 80a55e1c6..d32576836 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; @@ -245,7 +246,6 @@ Future<void> setup({ if (!_isSetupFinished) { getIt.registerSingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance()); } - if (!_isSetupFinished) { getIt.registerFactory(() => BackgroundTasks()); } diff --git a/lib/entities/auto_generate_subaddress_status.dart b/lib/entities/auto_generate_subaddress_status.dart new file mode 100644 index 000000000..6d6cc406c --- /dev/null +++ b/lib/entities/auto_generate_subaddress_status.dart @@ -0,0 +1,13 @@ + +enum AutoGenerateSubaddressStatus { + initialized(1), + enabled(2), + disabled(3); + + const AutoGenerateSubaddressStatus(this.value); + final int value; + + static AutoGenerateSubaddressStatus deserialize({required int raw}) => + AutoGenerateSubaddressStatus.values.firstWhere((e) => e.value == raw); + +} \ No newline at end of file diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index c50629c1b..7b4d3d0dc 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -50,6 +50,7 @@ class PreferencesKey { '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}'; static const exchangeProvidersSelection = 'exchange-providers-selection'; + static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status'; static const clearnetDonationLink = 'clearnet_donation_link'; static const onionDonationLink = 'onion_donation_link'; static const lastSeenAppVersion = 'last_seen_app_version'; diff --git a/lib/main.dart b/lib/main.dart index db5335ac1..62d18708e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; +import 'package:cw_core/address_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:flutter/foundation.dart'; @@ -89,6 +90,10 @@ Future<void> initializeAppConfigs() async { CakeHive.registerAdapter(TradeAdapter()); } + if (!CakeHive.isAdapterRegistered(AddressInfo.typeId)) { + CakeHive.registerAdapter(AddressInfoAdapter()); + } + if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { CakeHive.registerAdapter(WalletInfoAdapter()); } diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index 89f39d5f9..95406fb40 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; @@ -21,36 +22,36 @@ ReactionDisposer? _onCurrentWalletChangeReaction; ReactionDisposer? _onCurrentWalletChangeFiatRateUpdateReaction; //ReactionDisposer _onCurrentWalletAddressChangeReaction; -void startCurrentWalletChangeReaction(AppStore appStore, - SettingsStore settingsStore, FiatConversionStore fiatConversionStore) { +void startCurrentWalletChangeReaction( + AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) { _onCurrentWalletChangeReaction?.reaction.dispose(); _onCurrentWalletChangeFiatRateUpdateReaction?.reaction.dispose(); //_onCurrentWalletAddressChangeReaction?.reaction?dispose(); //_onCurrentWalletAddressChangeReaction = reaction((_) => appStore.wallet.walletAddresses.address, - //(String address) async { - //if (address == appStore.wallet.walletInfo.yatLastUsedAddress) { - // return; - //} + //(String address) async { + //if (address == appStore.wallet.walletInfo.yatLastUsedAddress) { + // return; + //} - //try { - // final yatStore = getIt.get<YatStore>(); - // await updateEmojiIdAddress( - // appStore.wallet.walletInfo.yatEmojiId, - // appStore.wallet.walletAddresses.address, - // yatStore.apiKey, - // appStore.wallet.type - // ); - // appStore.wallet.walletInfo.yatLastUsedAddress = address; - // await appStore.wallet.walletInfo.save(); - //} catch (e) { - // print(e.toString()); - //} + //try { + // final yatStore = getIt.get<YatStore>(); + // await updateEmojiIdAddress( + // appStore.wallet.walletInfo.yatEmojiId, + // appStore.wallet.walletAddresses.address, + // yatStore.apiKey, + // appStore.wallet.type + // ); + // appStore.wallet.walletInfo.yatLastUsedAddress = address; + // await appStore.wallet.walletInfo.save(); + //} catch (e) { + // print(e.toString()); + //} //}); - _onCurrentWalletChangeReaction = reaction((_) => appStore.wallet, (WalletBase< - Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? - wallet) async { + _onCurrentWalletChangeReaction = reaction((_) => appStore.wallet, + (WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? + wallet) async { try { if (wallet == null) { return; @@ -59,11 +60,13 @@ void startCurrentWalletChangeReaction(AppStore appStore, final node = settingsStore.getCurrentNode(wallet.type); startWalletSyncStatusChangeReaction(wallet, fiatConversionStore); startCheckConnectionReaction(wallet, settingsStore); + await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name); await getIt .get<SharedPreferences>() - .setString(PreferencesKey.currentWalletName, wallet.name); - await getIt.get<SharedPreferences>().setInt( - PreferencesKey.currentWalletType, serializeToInt(wallet.type)); + .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type)); + if (wallet.type == WalletType.monero) { + _setAutoGenerateSubaddressStatus(wallet, settingsStore); + } await wallet.connectToNode(node: node); if (wallet.type == WalletType.haven) { @@ -82,9 +85,8 @@ void startCurrentWalletChangeReaction(AppStore appStore, } }); - _onCurrentWalletChangeFiatRateUpdateReaction = - reaction((_) => appStore.wallet, (WalletBase<Balance, - TransactionHistoryBase<TransactionInfo>, TransactionInfo>? + _onCurrentWalletChangeFiatRateUpdateReaction = reaction((_) => appStore.wallet, + (WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet) async { try { if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) { @@ -92,11 +94,10 @@ void startCurrentWalletChangeReaction(AppStore appStore, } fiatConversionStore.prices[wallet.currency] = 0; - fiatConversionStore.prices[wallet.currency] = - await FiatConversionService.fetchPrice( - crypto: wallet.currency, - fiat: settingsStore.fiatCurrency, - torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); + fiatConversionStore.prices[wallet.currency] = await FiatConversionService.fetchPrice( + crypto: wallet.currency, + fiat: settingsStore.fiatCurrency, + torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); if (wallet.type == WalletType.ethereum) { final currencies = @@ -116,3 +117,17 @@ void startCurrentWalletChangeReaction(AppStore appStore, } }); } + +void _setAutoGenerateSubaddressStatus( + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet, + SettingsStore settingsStore, +) async { + final walletHasAddresses = await wallet.walletAddresses.addressesMap.length > 1; + if (settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.initialized && + walletHasAddresses) { + settingsStore.autoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.disabled; + } + wallet.isEnabledAutoGenerateSubaddress = + settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled || + settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.initialized; +} diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 236087595..2f18ef634 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; @@ -24,7 +26,6 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; @@ -174,7 +175,11 @@ class AddressPage extends BasePage { Observer(builder: (_) { if (addressListViewModel.hasAddressList) { return GestureDetector( - onTap: () => Navigator.of(context).pushNamed(Routes.receive), + onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled + ? await showPopUp<void>( + context: context, + builder: (_) => getIt.get<MoneroAccountListPage>()) + : Navigator.of(context).pushNamed(Routes.receive), child: Container( height: 50, padding: EdgeInsets.only(left: 24, right: 12), @@ -193,17 +198,26 @@ class AddressPage extends BasePage { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Observer( - builder: (_) => Text( - addressListViewModel.hasAccounts - ? S.of(context).accounts_subaddresses - : S.of(context).addresses, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) + builder: (_) { + String label = addressListViewModel.hasAccounts + ? S.of(context).accounts_subaddresses + : S.of(context).addresses; + + if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { + label = addressListViewModel.hasAccounts + ? S.of(context).accounts + : S.of(context).account; + } + return Text( + label, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context) .extension<SyncIndicatorTheme>()! .textColor), - )), + ); + },), Icon( Icons.arrow_forward_ios, size: 14, @@ -213,7 +227,7 @@ class AddressPage extends BasePage { ), ), ); - } else if (addressListViewModel.showElectrumAddressDisclaimer) { + } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || addressListViewModel.showElectrumAddressDisclaimer) { return Text(S.of(context).electrum_address_disclaimer, textAlign: TextAlign.center, style: TextStyle( diff --git a/lib/src/screens/monero_accounts/widgets/account_tile.dart b/lib/src/screens/monero_accounts/widgets/account_tile.dart index fa8221513..3e428f355 100644 --- a/lib/src/screens/monero_accounts/widgets/account_tile.dart +++ b/lib/src/screens/monero_accounts/widgets/account_tile.dart @@ -5,13 +5,14 @@ import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/generated/i18n.dart'; class AccountTile extends StatelessWidget { - AccountTile( - {required this.isCurrent, - required this.accountName, - this.accountBalance, - required this.currency, - required this.onTap, - required this.onEdit}); + AccountTile({ + required this.isCurrent, + required this.accountName, + this.accountBalance, + required this.currency, + required this.onTap, + required this.onEdit, + }); final bool isCurrent; final String accountName; diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 74e33b87a..3adad4379 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -73,7 +73,7 @@ class RestoreOptionsPage extends BasePage { await restoreFromQRViewModel.create(restoreWallet: restoreWallet); if (restoreFromQRViewModel.state is FailureState) { _onWalletCreateFailure(context, - 'Create wallet state: ${restoreFromQRViewModel.state.runtimeType.toString()}'); + 'Create wallet state: ${(restoreFromQRViewModel.state as FailureState).error}'); } } catch (e) { _onWalletCreateFailure(context, e.toString()); diff --git a/lib/src/screens/restore/widgets/backup_file_button.dart b/lib/src/screens/restore/widgets/backup_file_button.dart new file mode 100644 index 000000000..e69de29bb diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index ae6bfe6c8..e953fd4ee 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -50,6 +50,14 @@ class PrivacyPage extends BasePage { onValueChange: (BuildContext _, bool value) { _privacySettingsViewModel.setShouldSaveRecipientAddress(value); }), + if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) + SettingsSwitcherCell( + title: S.current.auto_generate_subaddresses, + value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setAutoGenerateSubaddresses(value); + }, + ), if (DeviceInfo.instance.isMobile) SettingsSwitcherCell( title: S.current.prevent_screenshots, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 703c7d73e..f512063a4 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; @@ -42,6 +43,7 @@ abstract class SettingsStoreBase with Store { required FiatCurrency initialFiatCurrency, required BalanceDisplayMode initialBalanceDisplayMode, required bool initialSaveRecipientAddress, + required AutoGenerateSubaddressStatus initialAutoGenerateSubaddressStatus, required bool initialAppSecure, required bool initialDisableBuy, required bool initialDisableSell, @@ -87,6 +89,7 @@ abstract class SettingsStoreBase with Store { fiatCurrency = initialFiatCurrency, balanceDisplayMode = initialBalanceDisplayMode, shouldSaveRecipientAddress = initialSaveRecipientAddress, + autoGenerateSubaddressStatus = initialAutoGenerateSubaddressStatus, fiatApiMode = initialFiatMode, allowBiometricalAuthentication = initialAllowBiometricalAuthentication, selectedCake2FAPreset = initialCake2FAPresetOptions, @@ -197,6 +200,11 @@ abstract class SettingsStoreBase with Store { (bool disableSell) => sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell)); + reaction( + (_) => autoGenerateSubaddressStatus, + (AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt( + PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus.value)); + reaction( (_) => fiatApiMode, (FiatApiMode mode) => @@ -337,6 +345,7 @@ abstract class SettingsStoreBase with Store { static const defaultPinLength = 4; static const defaultActionsMode = 11; static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes; + static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized; @observable FiatCurrency fiatCurrency; @@ -359,6 +368,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldSaveRecipientAddress; + @observable + AutoGenerateSubaddressStatus autoGenerateSubaddressStatus; + @observable bool isAppSecure; @@ -602,7 +614,12 @@ abstract class SettingsStoreBase with Store { final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; + final generateSubaddresses = + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + final autoGenerateSubaddressStatus = generateSubaddresses != null + ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) + : defaultAutoGenerateSubaddressStatus; final nodes = <WalletType, Node>{}; if (moneroNode != null) { @@ -640,6 +657,7 @@ abstract class SettingsStoreBase with Store { initialFiatCurrency: currentFiatCurrency, initialBalanceDisplayMode: currentBalanceDisplayMode, initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, initialAppSecure: isAppSecure, initialDisableBuy: disableBuy, initialDisableSell: disableSell, @@ -709,6 +727,13 @@ abstract class SettingsStoreBase with Store { priority[WalletType.ethereum]!; } + final generateSubaddresses = + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + + autoGenerateSubaddressStatus = generateSubaddresses != null + ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) + : defaultAutoGenerateSubaddressStatus; + balanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!); shouldSaveRecipientAddress = @@ -719,8 +744,6 @@ abstract class SettingsStoreBase with Store { numberOfFailedTokenTrials = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials; - sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? - shouldSaveRecipientAddress; isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index c99984ebc..93b06c378 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -10,6 +11,7 @@ import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/utils/mobx.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:collection/collection.dart'; part 'contact_list_view_model.g.dart'; @@ -20,12 +22,26 @@ abstract class ContactListViewModelBase with Store { ContactListViewModelBase(this.contactSource, this.walletInfoSource, this._currency, this.settingsStore) : contacts = ObservableList<ContactRecord>(), - walletContacts = [] { + walletContacts = [], + isAutoGenerateEnabled = + settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled { walletInfoSource.values.forEach((info) { - if (info.addresses?.isNotEmpty ?? false) { - info.addresses?.forEach((address, label) { - final name = label.isNotEmpty ? info.name + ' ($label)' : info.name; - + if (isAutoGenerateEnabled && info.type == WalletType.monero && info.addressInfos != null) { + info.addressInfos!.forEach((key, value) { + final nextUnusedAddress = value.firstWhereOrNull( + (addressInfo) => !(info.usedAddresses?.contains(addressInfo.address) ?? false)); + if (nextUnusedAddress != null) { + final name = _createName(info.name, nextUnusedAddress.label); + walletContacts.add(WalletContact( + nextUnusedAddress.address, + name, + walletTypeToCryptoCurrency(info.type), + )); + } + }); + } else if (info.addresses?.isNotEmpty == true) { + info.addresses!.forEach((address, label) { + final name = _createName(info.name, label); walletContacts.add(WalletContact( address, name, @@ -40,6 +56,11 @@ abstract class ContactListViewModelBase with Store { initialFire: true); } + String _createName(String walletName, String label) { + return label.isNotEmpty ? '$walletName ($label)' : walletName; + } + + final bool isAutoGenerateEnabled; final Box<Contact> contactSource; final Box<WalletInfo> walletInfoSource; final ObservableList<ContactRecord> contacts; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 7035130c0..009fe0350 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; @@ -235,6 +236,10 @@ abstract class DashboardViewModelBase with Store { @computed double get price => balanceViewModel.price; + @computed + bool get isAutoGenerateSubaddressesEnabled => + settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled; + @computed List<ActionListItem> get items { final _items = <ActionListItem>[]; diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 5dbfd61dd..27ce919df 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -1,6 +1,10 @@ +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -14,11 +18,27 @@ abstract class PrivacySettingsViewModelBase with Store { PrivacySettingsViewModelBase(this._settingsStore, this._wallet); final SettingsStore _settingsStore; - final WalletBase _wallet; + final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet; @computed ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus; + @computed + bool get isAutoGenerateSubaddressesEnabled => + _settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled; + + @action + void setAutoGenerateSubaddresses(bool value) { + _wallet.isEnabledAutoGenerateSubaddress = value; + if (value) { + _settingsStore.autoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.enabled; + } else { + _settingsStore.autoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.disabled; + } + } + + bool get isAutoGenerateSubaddressesVisible => _wallet.type == WalletType.monero; + @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 5bd8906fe..ae3f669ca 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -682,5 +682,7 @@ "support_title_other_links": "روابط دعم أخرى", "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", - "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ" + "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ", + "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", + "auto_generate_subaddresses": "تلقائي توليد subddresses" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 325057aa4..ac2a08088 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -626,6 +626,7 @@ "setup_totp_recommended": "Настройка на TOTP (препоръчително)", "disable_buy": "Деактивирайте действието за покупка", "disable_sell": "Деактивирайте действието за продажба", + "auto_generate_subaddresses": "Автоматично генериране на подадреси", "cake_2fa_preset": "Торта 2FA Preset", "narrow": "Тесен", "normal": "нормално", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index a258eaa40..38e01ca6b 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -626,6 +626,7 @@ "setup_totp_recommended": "Nastavit TOTP (doporučeno)", "disable_buy": "Zakázat akci nákupu", "disable_sell": "Zakázat akci prodeje", + "auto_generate_subaddresses": "Automaticky generovat podadresy", "cake_2fa_preset": "Předvolba Cake 2FA", "narrow": "Úzký", "normal": "Normální", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index b315ddb56..afc5fba82 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -640,6 +640,7 @@ "high_contrast_theme": "Kontrastreiches Thema", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero Light-Thema", + "auto_generate_subaddresses": "Unteradressen automatisch generieren", "cake_2fa_preset" : "Cake 2FA-Voreinstellung", "narrow": "Eng", "normal": "Normal", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9e8e3788c..4698701de 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -568,6 +568,7 @@ "privacy": "Privacy", "display_settings": "Display settings", "other_settings": "Other settings", + "auto_generate_subaddresses": "Auto generate subaddresses", "require_pin_after": "Require PIN after", "always": "Always", "minutes_to_pin_code": "${minute} minutes", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3c0abce48..8a4519255 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -640,6 +640,7 @@ "high_contrast_theme": "Tema de alto contraste", "matrix_green_dark_theme": "Matrix verde oscuro tema", "monero_light_theme": "Tema ligero de Monero", + "auto_generate_subaddresses": "Generar subdirecciones automáticamente", "cake_2fa_preset": "Pastel 2FA preestablecido", "narrow": "Angosto", "normal": "Normal", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 1449d6370..357a73110 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -640,6 +640,7 @@ "high_contrast_theme": "Thème à contraste élevé", "matrix_green_dark_theme": "Thème Matrix Green Dark", "monero_light_theme": "Thème de lumière Monero", + "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "cake_2fa_preset": "Gâteau 2FA prédéfini", "narrow": "Étroit", "normal": "Normal", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index e3542e9ac..d344bfb15 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -618,6 +618,7 @@ "high_contrast_theme": "Babban Jigon Kwatance", "matrix_green_dark_theme": "Matrix Green Dark Jigo", "monero_light_theme": "Jigon Hasken Monero", + "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", "cake_2fa_preset": "Cake 2FA saiti", "narrow": "kunkuntar", "normal": "Na al'ada", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index ca3e79bd0..e9ee219fe 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -640,6 +640,7 @@ "high_contrast_theme": "उच्च कंट्रास्ट थीम", "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", "monero_light_theme": "मोनेरो लाइट थीम", + "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", "cake_2fa_preset": "केक 2एफए प्रीसेट", "narrow": "सँकरा", "normal": "सामान्य", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e19d32ea1..91176248d 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -640,6 +640,7 @@ "high_contrast_theme": "Tema visokog kontrasta", "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero lagana tema", + "auto_generate_subaddresses": "Automatski generirajte podadrese", "cake_2fa_preset": "Cake 2FA Preset", "narrow": "Usko", "normal": "Normalno", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 3f62f968c..daebfd579 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -622,6 +622,7 @@ "setup_totp_recommended": "Siapkan TOTP (Disarankan)", "disable_buy": "Nonaktifkan tindakan beli", "disable_sell": "Nonaktifkan aksi jual", + "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", "cake_2fa_preset": "Preset Kue 2FA", "narrow": "Sempit", "normal": "Normal", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8ad7502fd..691abd15c 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -634,6 +634,7 @@ "setup_totp_recommended": "Imposta TOTP (consigliato)", "disable_buy": "Disabilita l'azione di acquisto", "disable_sell": "Disabilita l'azione di vendita", + "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", "cake_2fa_preset": "Torta 2FA Preset", "narrow": "Stretto", "normal": "Normale", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3fe586279..254d7bbba 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -686,5 +686,6 @@ "support_title_other_links": "その他のサポートリンク", "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", "select_destination": "バックアップファイルの保存先を選択してください。", - "save_to_downloads": "ダウンロードに保存" + "save_to_downloads": "ダウンロードに保存", + "auto_generate_subaddresses": "Autoはサブアドレスを生成します" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 1b7116e90..63a446fa3 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -686,5 +686,6 @@ "support_title_other_links": "다른 지원 링크", "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", "select_destination": "백업 파일의 대상을 선택하십시오.", - "save_to_downloads": "다운로드에 저장" + "save_to_downloads": "다운로드에 저장", + "auto_generate_subaddresses": "자동 생성 서브 아드 드레스" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c12adb5ac..b131e66d8 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -684,5 +684,6 @@ "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", - "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။" + "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။", + "auto_generate_subaddresses": "အော်တို Generate Subaddresses" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 18b3b5e5b..fcd683fd1 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -634,6 +634,7 @@ "setup_totp_recommended": "TOTP instellen (aanbevolen)", "disable_buy": "Koopactie uitschakelen", "disable_sell": "Verkoopactie uitschakelen", + "auto_generate_subaddresses": "Automatisch subadressen genereren", "cake_2fa_preset": "Taart 2FA Voorinstelling", "narrow": "Smal", "normal": "Normaal", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index e458339ba..17745ccb8 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -634,6 +634,7 @@ "setup_totp_recommended": "Skonfiguruj TOTP (zalecane)", "disable_buy": "Wyłącz akcję kupna", "disable_sell": "Wyłącz akcję sprzedaży", + "auto_generate_subaddresses": "Automatycznie generuj podadresy", "cake_2fa_preset": "Ciasto 2FA Preset", "narrow": "Wąski", "normal": "Normalna", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index aa06cd095..2148e6905 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -633,6 +633,7 @@ "setup_totp_recommended": "Configurar TOTP (recomendado)", "disable_buy": "Desativar ação de compra", "disable_sell": "Desativar ação de venda", + "auto_generate_subaddresses": "Gerar subendereços automaticamente", "cake_2fa_preset": "Predefinição de bolo 2FA", "narrow": "Estreito", "normal": "Normal", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 533ca431d..e229ddee9 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -686,5 +686,6 @@ "support_title_other_links": "Другие ссылки на поддержку", "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", "select_destination": "Пожалуйста, выберите место для файла резервной копии.", - "save_to_downloads": "Сохранить в загрузках" + "save_to_downloads": "Сохранить в загрузках", + "auto_generate_subaddresses": "Авто генерируйте Subaddresses" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f54194617..100929da2 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -684,5 +684,6 @@ "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", - "save_to_downloads": "บันทึกลงดาวน์โหลด" + "save_to_downloads": "บันทึกลงดาวน์โหลด", + "auto_generate_subaddresses": "Auto สร้าง subaddresses" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index fa835912a..e74d1a281 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -632,6 +632,7 @@ "setup_totp_recommended": "TOTP'yi kurun (Önerilir)", "disable_buy": "Satın alma işlemini devre dışı bırak", "disable_sell": "Satış işlemini devre dışı bırak", + "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", "cake_2fa_preset": "Kek 2FA Ön Ayarı", "narrow": "Dar", "normal": "Normal", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 6d9a648fa..313f6aeb0 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -634,6 +634,7 @@ "setup_totp_recommended": "Налаштувати TOTP (рекомендовано)", "disable_buy": "Вимкнути дію покупки", "disable_sell": "Вимкнути дію продажу", + "auto_generate_subaddresses": "Автоматично генерувати підадреси", "cake_2fa_preset": "Торт 2FA Preset", "narrow": "вузькі", "normal": "нормальний", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 39cae33d0..b8e0c0a00 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -678,5 +678,6 @@ "support_title_other_links": "دوسرے سپورٹ لنکس", "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", - "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ" + "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", + "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 75df8de6b..143fd0ccd 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -680,5 +680,6 @@ "matrix_green_dark_theme": "Matrix Green Dark Akori", "monero_light_theme": "Monero Light Akori", "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", - "save_to_downloads": "Fipamọ si Awọn igbasilẹ" + "save_to_downloads": "Fipamọ si Awọn igbasilẹ", + "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 3fa31bb10..7e3ceae31 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -685,5 +685,6 @@ "matrix_green_dark_theme": "矩阵绿暗主题", "monero_light_theme": "门罗币浅色主题", "select_destination": "请选择备份文件的目的地。", - "save_to_downloads": "保存到下载" + "save_to_downloads": "保存到下载", + "auto_generate_subaddresses": "自动生成子辅助" } diff --git a/tool/append_translation.dart b/tool/append_translation.dart index e56ad89d6..5c48aceab 100644 --- a/tool/append_translation.dart +++ b/tool/append_translation.dart @@ -1,15 +1,6 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:translator/translator.dart'; - -const defaultLang = "en"; -const langs = [ - "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", - "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", - "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) -]; -final translator = GoogleTranslator(); +import 'utils/translation/arb_file_utils.dart'; +import 'utils/translation/translation_constants.dart'; +import 'utils/translation/translation_utils.dart'; void main(List<String> args) async { if (args.length != 2) { @@ -23,44 +14,9 @@ void main(List<String> args) async { print('Appending "$name": "$text"'); for (var lang in langs) { - final fileName = getFileName(lang); + final fileName = getArbFileName(lang); final translation = await getTranslation(text, lang); - appendArbFile(fileName, name, translation); + appendStringToArbFile(fileName, name, translation); } } - -void appendArbFile(String fileName, String name, String text) { - final file = File(fileName); - final inputContent = file.readAsStringSync(); - final arbObj = json.decode(inputContent) as Map<String, dynamic>; - - if (arbObj.containsKey(name)) { - print("String $name already exists in $fileName!"); - return; - } - - arbObj.addAll({name: text}); - - final outputContent = json - .encode(arbObj) - .replaceAll('","', '",\n "') - .replaceAll('{"', '{\n "') - .replaceAll('"}', '"\n}') - .replaceAll('":"', '": "'); - - file.writeAsStringSync(outputContent); -} - - -Future<String> getTranslation(String text, String lang) async { - if (lang == defaultLang) return text; - return (await translator.translate(text, from: defaultLang, to: lang)).text; -} - -String getFileName(String lang) { - final shortLang = lang - .split("-") - .first; - return "./res/values/strings_$shortLang.arb"; -} diff --git a/tool/translation_consistence.dart b/tool/translation_consistence.dart new file mode 100644 index 000000000..04f64dfc8 --- /dev/null +++ b/tool/translation_consistence.dart @@ -0,0 +1,37 @@ +import 'dart:io'; + +import 'utils/translation/arb_file_utils.dart'; +import 'utils/translation/translation_constants.dart'; +import 'utils/translation/translation_utils.dart'; + +void main(List<String> args) async { + print('Checking Consistency of all arb-files. Default: $defaultLang'); + + final doFix = args.contains("--fix"); + + if (doFix) + print('Auto fixing enabled!\n'); + else + print('Auto fixing disabled!\nRun with arg "--fix" to enable autofix\n'); + + final fileName = getArbFileName(defaultLang); + final file = File(fileName); + final arbObj = readArbFile(file); + + for (var lang in langs) { + final fileName = getArbFileName(lang); + final missingKeys = getMissingKeysInArbFile(fileName, arbObj.keys); + if (missingKeys.isNotEmpty) { + final missingDefaults = <String, String>{}; + + missingKeys.forEach((key) { + print('Missing in "$lang": "$key"'); + if (doFix) + missingDefaults[key] = arbObj[key] as String; + }); + + if (missingDefaults.isNotEmpty) + await appendTranslations(lang, missingDefaults); + } + } +} diff --git a/tool/utils/translation/arb_file_utils.dart b/tool/utils/translation/arb_file_utils.dart new file mode 100644 index 000000000..693c5b93e --- /dev/null +++ b/tool/utils/translation/arb_file_utils.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'dart:io'; + +void appendStringToArbFile(String fileName, String name, String text) { + final file = File(fileName); + final arbObj = readArbFile(file); + + if (arbObj.containsKey(name)) { + print("String $name already exists in $fileName!"); + return; + } + + arbObj.addAll({name: text}); + + final outputContent = json + .encode(arbObj) + .replaceAll('","', '",\n "') + .replaceAll('{"', '{\n "') + .replaceAll('"}', '"\n}') + .replaceAll('":"', '": "'); + + file.writeAsStringSync(outputContent); +} + +void appendStringsToArbFile(String fileName, Map<String, String> strings) { + final file = File(fileName); + final arbObj = readArbFile(file); + + arbObj.addAll(strings); + + final outputContent = json + .encode(arbObj) + .replaceAll('","', '",\n "') + .replaceAll('{"', '{\n "') + .replaceAll('"}', '"\n}') + .replaceAll('":"', '": "'); + + file.writeAsStringSync(outputContent); +} + +Map<String, dynamic> readArbFile(File file) { + final inputContent = file.readAsStringSync(); + + return json.decode(inputContent) as Map<String, dynamic>; +} + +String getArbFileName(String lang) { + final shortLang = lang + .split("-") + .first; + return "./res/values/strings_$shortLang.arb"; +} + +List<String> getMissingKeysInArbFile(String fileName, Iterable<String> langKeys) { + final file = File(fileName); + final arbObj = readArbFile(file); + final results = <String>[]; + + for (var langKey in langKeys) { + if (!arbObj.containsKey(langKey)) { + results.add(langKey); + } + } + + return results; +} diff --git a/tool/utils/translation/translation_constants.dart b/tool/utils/translation/translation_constants.dart new file mode 100644 index 000000000..6563feb32 --- /dev/null +++ b/tool/utils/translation/translation_constants.dart @@ -0,0 +1,6 @@ +const defaultLang = "en"; +const langs = [ + "ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it", + "ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo", + "zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified) +]; diff --git a/tool/utils/translation/translation_utils.dart b/tool/utils/translation/translation_utils.dart new file mode 100644 index 000000000..a37838b91 --- /dev/null +++ b/tool/utils/translation/translation_utils.dart @@ -0,0 +1,37 @@ +import 'package:translator/translator.dart'; + +import 'arb_file_utils.dart'; +import 'translation_constants.dart'; + +final translator = GoogleTranslator(); + +Future<void> appendTranslation(String lang, String key, String text) async { + final fileName = getArbFileName(lang); + final translation = await getTranslation(text, lang); + + appendStringToArbFile(fileName, key, translation); +} + +Future<void> appendTranslations(String lang, Map<String, String> defaults) async { + final fileName = getArbFileName(lang); + final translations = <String, String>{}; + + for (var key in defaults.keys) { + final value = defaults[key]!; + + if (value.contains("{")) continue; + final translation = await getTranslation(value, lang); + + translations[key] = translation; + } + + print(translations); + + appendStringsToArbFile(fileName, translations); +} + +Future<String> getTranslation(String text, String lang) async { + if (lang == defaultLang) return text; + return (await translator.translate(text, from: defaultLang, to: lang)).text; +} + From 1cc2c645fa1e6fc338c62b96eab830c13012d186 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Wed, 30 Aug 2023 18:11:56 +0300 Subject: [PATCH 12/18] Fix Wallet Loading issues (basic_string & input_stream) (#1059) * Recover from wallet loading exceptions (basic_string & input_stream) Recover from removed cached wallets * Fix restoring as Monero wallets Fix restoring wallets with invalid files * Add coin control missing changes for macos monero files * Add same key for cached dependencies [skip ci] --- .github/workflows/cache_dependencies.yml | 2 +- cw_monero/lib/monero_wallet_service.dart | 21 +- cw_monero/macos/Classes/monero_api.cpp | 203 +++++++++++++++++-- lib/entities/default_settings_migration.dart | 77 ++++++- macos/Podfile.lock | 8 +- 5 files changed, 279 insertions(+), 32 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index d57281447..ef4175641 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -45,7 +45,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }} + key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh', '**/monero_api.cpp') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 90c63fb72..9d1a0b3e4 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -57,7 +57,7 @@ class MoneroWalletService extends WalletService< final Box<WalletInfo> walletInfoSource; final Box<UnspentCoinsInfo> unspentCoinsInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -124,13 +124,20 @@ class MoneroWalletService extends WalletService< } catch (e) { // TODO: Implement Exception for wallet list service. - if ((e.toString().contains('bad_alloc') || + final bool isBadAlloc = e.toString().contains('bad_alloc') || (e is WalletOpeningException && - (e.message == 'std::bad_alloc' || - e.message.contains('bad_alloc')))) || - (e.toString().contains('does not correspond') || - (e is WalletOpeningException && - e.message.contains('does not correspond')))) { + (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc'))); + + final bool doesNotCorrespond = e.toString().contains('does not correspond') || + (e is WalletOpeningException && e.message.contains('does not correspond')); + + final bool isMissingCacheFilesIOS = e.toString().contains('basic_string') || + (e is WalletOpeningException && e.message.contains('basic_string')); + + final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') || + (e is WalletOpeningException && e.message.contains('input_stream')); + + if (isBadAlloc || doesNotCorrespond || isMissingCacheFilesIOS || isMissingCacheFilesAndroid) { await restoreOrResetWalletFiles(name); return openWallet(name, password); } diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index 56548e79e..ac8a64861 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -3,8 +3,10 @@ #include <chrono> #include <functional> #include <iostream> +#include <fstream> #include <unistd.h> #include <mutex> +#include <list> #include "thread" #include "CwWalletListener.h" #if __APPLE__ @@ -137,7 +139,7 @@ extern "C" int8_t direction; int8_t isPending; uint32_t subaddrIndex; - + char *hash; char *paymentId; @@ -152,7 +154,7 @@ extern "C" std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); - datetime = static_cast<int64_t>(transaction->timestamp()); + datetime = static_cast<int64_t>(transaction->timestamp()); direction = transaction->direction(); isPending = static_cast<int8_t>(transaction->isPending()); std::string *hash_str = new std::string(transaction->hash()); @@ -181,6 +183,62 @@ extern "C" } }; + struct CoinsInfoRow + { + uint64_t blockHeight; + char *hash; + uint64_t internalOutputIndex; + uint64_t globalOutputIndex; + bool spent; + bool frozen; + uint64_t spentHeight; + uint64_t amount; + bool rct; + bool keyImageKnown; + uint64_t pkIndex; + uint32_t subaddrIndex; + uint32_t subaddrAccount; + char *address; + char *addressLabel; + char *keyImage; + uint64_t unlockTime; + bool unlocked; + char *pubKey; + bool coinbase; + char *description; + + CoinsInfoRow(Monero::CoinsInfo *coinsInfo) + { + blockHeight = coinsInfo->blockHeight(); + std::string *hash_str = new std::string(coinsInfo->hash()); + hash = strdup(hash_str->c_str()); + internalOutputIndex = coinsInfo->internalOutputIndex(); + globalOutputIndex = coinsInfo->globalOutputIndex(); + spent = coinsInfo->spent(); + frozen = coinsInfo->frozen(); + spentHeight = coinsInfo->spentHeight(); + amount = coinsInfo->amount(); + rct = coinsInfo->rct(); + keyImageKnown = coinsInfo->keyImageKnown(); + pkIndex = coinsInfo->pkIndex(); + subaddrIndex = coinsInfo->subaddrIndex(); + subaddrAccount = coinsInfo->subaddrAccount(); + address = strdup(coinsInfo->address().c_str()) ; + addressLabel = strdup(coinsInfo->addressLabel().c_str()); + keyImage = strdup(coinsInfo->keyImage().c_str()); + unlockTime = coinsInfo->unlockTime(); + unlocked = coinsInfo->unlocked(); + pubKey = strdup(coinsInfo->pubKey().c_str()); + coinbase = coinsInfo->coinbase(); + description = strdup(coinsInfo->description().c_str()); + } + + void setUnlocked(bool unlocked); + + }; + + Monero::Coins *m_coins; + Monero::Wallet *m_wallet; Monero::TransactionHistory *m_transaction_history; MoneroWalletListener *m_listener; @@ -188,6 +246,7 @@ extern "C" Monero::SubaddressAccount *m_account; uint64_t m_last_known_wallet_height; uint64_t m_cached_syncing_blockchain_height = 0; + std::list<Monero::CoinsInfo*> m_coins_info; std::mutex store_lock; bool is_storing = false; @@ -195,7 +254,7 @@ extern "C" { m_wallet = wallet; m_listener = nullptr; - + if (wallet != nullptr) { @@ -223,6 +282,17 @@ extern "C" { m_subaddress = nullptr; } + + m_coins_info = std::list<Monero::CoinsInfo*>(); + + if (wallet != nullptr) + { + m_coins = wallet->coins(); + } + else + { + m_coins = nullptr; + } } Monero::Wallet *get_current_wallet() @@ -405,13 +475,14 @@ extern "C" return is_connected; } - bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error) + bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error) { nice(19); Monero::Wallet *wallet = get_current_wallet(); - + std::string _login = ""; std::string _password = ""; + std::string _socksProxyAddress = ""; if (login != nullptr) { @@ -423,7 +494,12 @@ extern "C" _password = std::string(password); } - bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet); + if (socksProxyAddress != nullptr) + { + _socksProxyAddress = std::string(socksProxyAddress); + } + + bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress); if (!inited) { @@ -480,10 +556,19 @@ extern "C" } bool transaction_create(char *address, char *payment_id, char *amount, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); - + + std::set<std::string> _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } + auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -496,13 +581,13 @@ extern "C" if (amount != nullptr) { uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount)); - transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } else { - transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } - + int status = transaction->status(); if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) @@ -520,7 +605,9 @@ extern "C" } bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); @@ -534,6 +621,13 @@ extern "C" amounts++; } + std::set<std::string> _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } + auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -793,6 +887,91 @@ extern "C" return m_wallet->trustedDaemon(); } + CoinsInfoRow* coin(int index) + { + if (index >= 0 && index < m_coins_info.size()) { + std::list<Monero::CoinsInfo*>::iterator it = m_coins_info.begin(); + std::advance(it, index); + Monero::CoinsInfo* element = *it; + std::cout << "Element at index " << index << ": " << element << std::endl; + return new CoinsInfoRow(element); + } else { + std::cout << "Invalid index." << std::endl; + return nullptr; // Return a default value (nullptr) for invalid index + } + } + + void refresh_coins(uint32_t accountIndex) + { + m_coins_info.clear(); + + m_coins->refresh(); + for (const auto i : m_coins->getAll()) { + if (i->subaddrAccount() == accountIndex && !(i->spent())) { + m_coins_info.push_back(i); + } + } + } + + uint64_t coins_count() + { + return m_coins_info.size(); + } + + CoinsInfoRow** coins_from_account(uint32_t accountIndex) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (coinInfo->subaddrAccount == accountIndex) { + matchingCoins.push_back(coinInfo); + } + } + + CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_txid(const char* txid, size_t* count) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (std::string(coinInfo->hash) == txid) { + matchingCoins.push_back(coinInfo); + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count) + { + std::vector<CoinsInfoRow*> matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinsInfoRow = coin(i); + for (size_t j = 0; j < keyimageCount; j++) { + if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) { + matchingCoins.push_back(coinsInfoRow); + break; + } + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + #ifdef __cplusplus } #endif diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index b4cb23131..a783eec43 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,12 +1,11 @@ -import 'dart:io' show File, Platform; +import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; -import 'package:share_plus/share_plus.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/wallet_type.dart'; @@ -28,7 +27,7 @@ const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; -Future defaultSettingsMigration( +Future<void> defaultSettingsMigration( {required int version, required SharedPreferences sharedPreferences, required FlutterSecureStorage secureStorage, @@ -43,6 +42,8 @@ Future defaultSettingsMigration( // check current nodes for nullability regardless of the version await checkCurrentNodes(nodes, sharedPreferences); + await _validateWalletInfoBoxData(walletInfoSource); + final isNewInstall = sharedPreferences .getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null; @@ -179,6 +180,66 @@ Future defaultSettingsMigration( PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async { + final root = await getApplicationDocumentsDirectory(); + + for (var type in WalletType.values) { + if (type == WalletType.none) { + continue; + } + + String prefix = walletTypeToString(type).toLowerCase(); + Directory walletsDir = Directory('${root.path}/wallets/$prefix/'); + + if (!walletsDir.existsSync()) { + continue; + } + + List<String> walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList(); + + for (var name in walletNames) { + final dir = Directory(await pathForWalletDir(name: name, type: type)); + + final walletFiles = dir.listSync(); + final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name")); + + if (!hasCacheFile) { + continue; + } + + if (type == WalletType.monero || type == WalletType.haven) { + final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys")); + + if (!hasKeysFile) { + continue; + } + } + + final id = prefix + '_' + name; + final exist = walletInfoSource.values.any((el) => el.id == id); + + if (exist) { + continue; + } + + final walletInfo = WalletInfo.external( + id: id, + type: type, + name: name, + isRecovery: true, + restoreHeight: 0, + date: DateTime.now(), + dirPath: dir.path, + path: '${dir.path}/$name', + address: '', + showIntroCakePayCard: false, + ); + + walletInfoSource.add(walletInfo); + } + } +} + Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { if (bitcoin == null) { return; @@ -226,7 +287,7 @@ Future<void> changeMoneroCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async { final node = getMoneroDefaultNode(nodes: nodes); - final nodeId = node?.key as int ?? 0; // 0 - England + final nodeId = node.key as int? ?? 0; // 0 - England await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, nodeId); } @@ -279,7 +340,7 @@ Future<void> changeBitcoinCurrentElectrumServerToDefault( {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async { final server = getBitcoinDefaultElectrumServer(nodes: nodes); - final serverId = server?.key as int ?? 0; + final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId); } @@ -288,7 +349,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault( {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async { final server = getLitecoinDefaultElectrumServer(nodes: nodes); - final serverId = server?.key as int ?? 0; + final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId); } @@ -297,7 +358,7 @@ Future<void> changeHavenCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async { final node = getHavenDefaultNode(nodes: nodes); - final nodeId = node?.key as int ?? 0; + final nodeId = node?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, nodeId); } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 6657ec4dc..664a5231b 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -57,11 +57,11 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`) - - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`) - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) @@ -87,7 +87,7 @@ EXTERNAL SOURCES: package_info: :path: Flutter/ephemeral/.symlinks/plugins/package_info/macos path_provider_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin platform_device_id: :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos platform_device_id_macos: @@ -95,7 +95,7 @@ EXTERNAL SOURCES: share_plus_macos: :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos wakelock_macos: From 6b9c47563e6410772f080bc3f6c875814285b786 Mon Sep 17 00:00:00 2001 From: OmarHatem <omarh.ismail1@gmail.com> Date: Wed, 30 Aug 2023 19:15:07 +0300 Subject: [PATCH 13/18] Allow triggering cache workflow manually Fix haven build script --- .github/workflows/cache_dependencies.yml | 1 + scripts/android/build_haven.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index ef4175641..5373bbc87 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -1,6 +1,7 @@ name: Cache Dependencies on: + workflow_dispatch: push: branches: [ main ] diff --git a/scripts/android/build_haven.sh b/scripts/android/build_haven.sh index f745e942e..16cf05039 100755 --- a/scripts/android/build_haven.sh +++ b/scripts/android/build_haven.sh @@ -5,8 +5,8 @@ HAVEN_VERSION=tags/v3.0.7 HAVEN_SRC_DIR=${WORKDIR}/haven git clone https://github.com/haven-protocol-org/haven-main.git ${HAVEN_SRC_DIR} -git checkout ${HAVEN_VERSION} cd $HAVEN_SRC_DIR +git checkout ${HAVEN_VERSION} git submodule init git submodule update From d51b9bd684d2bb888bc1b77ea970f7f183100b10 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 31 Aug 2023 18:09:10 +0100 Subject: [PATCH 14/18] feat: Replace transfer.sh (#1066) * feat: Replace transfer.sh * Update build_haven.sh * Update pr_test_build.yml * Update pr_test_build.yml * Update pr_test_build.yml * feat: Change apk name in PR workflow * feat: Change apk name in PR workflow * feat: Change apk name in PR workflow * fix: Remove test-apk prefix in app name --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --- .github/workflows/pr_test_build.yml | 12 ++++++--- cw_core/pubspec.lock | 42 ++++++++++++++--------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 80d5d74aa..30bf3058e 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -163,7 +163,11 @@ jobs: - name: Send Test APK continue-on-error: true - run: | - cd /opt/android/cake_wallet - var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") - curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' + uses: adrey/slack-file-upload-action@1.0.5 + with: + token: ${{ secrets.SLACK_APP_TOKEN }} + path: /opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk + channel: ${{ secrets.SLACK_APK_CHANNEL }} + title: '${{github.head_ref}}.apk' + filename: ${{github.head_ref}}.apk + initial_comment: ${{ github.event.head_commit.message }} diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 01e19dda4..e399526fd 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -279,10 +279,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -303,10 +303,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -319,10 +319,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -343,10 +343,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -359,10 +359,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -399,10 +399,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -596,10 +596,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -665,5 +665,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" From 8757390c8f1da5500e750c5592796c0bc2b04c2f Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich <konstantinullrich12@gmail.com> Date: Fri, 1 Sep 2023 13:04:35 +0200 Subject: [PATCH 15/18] CW-481 Fix empty Address (#1072) --- cw_monero/lib/monero_wallet_addresses.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/cw_monero/lib/monero_wallet_addresses.dart b/cw_monero/lib/monero_wallet_addresses.dart index fcc3576f4..a9da3d5d4 100644 --- a/cw_monero/lib/monero_wallet_addresses.dart +++ b/cw_monero/lib/monero_wallet_addresses.dart @@ -41,6 +41,7 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { Future<void> init() async { accountList.update(); account = accountList.accounts.first; + updateSubaddressList(accountIndex: account?.id ?? 0); await updateAddressesInBox(); } From e634562cf468776bea7c5e887f063fc1dfb0ef68 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:59:18 +0100 Subject: [PATCH 16/18] Cw-465-Remove CakePay Button on Mobile/Desktop (#1057) * feat: Remove CakePayButton Mobile * feat: Remove CakePayButton Desktop * feat: Remove CakePay Mobile Button * feat: Remove CakePay Mobile Button * feat: Remove CakePay Mobile Button * fix: Action breaking --- cw_bitcoin/pubspec.lock | 56 +++++++++---------- cw_haven/pubspec.lock | 42 +++++++------- cw_monero/example/pubspec.lock | 42 +++++++------- cw_monero/pubspec.lock | 42 +++++++------- .../desktop_dashboard_actions.dart | 10 ++-- .../dashboard/widgets/market_place_page.dart | 18 +++--- 6 files changed, 105 insertions(+), 105 deletions(-) diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index bfcd9e5a6..843daa771 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -37,19 +37,19 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" bech32: dependency: transitive description: path: "." - ref: "cake-0.2.1" - resolved-ref: cafd1c270641e95017d57d69f55cca9831d4db56 + ref: "cake-0.2.2" + resolved-ref: "05755063b593aa6cca0a4820a318e0ce17de6192" url: "https://github.com/cake-tech/bech32.git" source: git - version: "0.2.1" + version: "0.2.2" bip32: dependency: transitive description: @@ -70,8 +70,8 @@ packages: dependency: "direct main" description: path: "." - ref: cake-update-v2 - resolved-ref: "8f86453761c0c26e368392d0ff2c6f12f3b7397b" + ref: cake-update-v3 + resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.0.2" @@ -159,10 +159,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -191,18 +191,18 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" crypto: dependency: transitive description: @@ -344,10 +344,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -368,10 +368,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -384,10 +384,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -408,10 +408,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -424,10 +424,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -464,10 +464,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -669,10 +669,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -746,5 +746,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index a79d2d3cf..a63aa3237 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -286,10 +286,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -310,10 +310,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -326,10 +326,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -350,10 +350,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -366,10 +366,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -406,10 +406,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -603,10 +603,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -672,5 +672,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index f4c36e69c..1aae6b0c9 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_parser: dependency: transitive description: @@ -173,18 +173,18 @@ packages: dependency: transitive description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" lints: dependency: transitive description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mobx: dependency: transitive description: @@ -229,10 +229,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: transitive description: @@ -362,10 +362,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" typed_data: dependency: transitive description: @@ -399,5 +399,5 @@ packages: source: hosted version: "0.2.0+3" sdks: - dart: ">=2.18.1 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 437184a7d..37e08e7ca 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -286,10 +286,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -310,10 +310,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -326,10 +326,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -350,10 +350,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -366,10 +366,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -406,10 +406,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -603,10 +603,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -672,5 +672,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart index ad2291ba5..5e1f8d16a 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart @@ -73,12 +73,12 @@ class DesktopDashboardActions extends StatelessWidget { ), ], ), - Expanded( - child: MarketPlacePage( - dashboardViewModel: dashboardViewModel, - marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(), - ), + Expanded( + child: MarketPlacePage( + dashboardViewModel: dashboardViewModel, + marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(), ), + ), ], ); } diff --git a/lib/src/screens/dashboard/widgets/market_place_page.dart b/lib/src/screens/dashboard/widgets/market_place_page.dart index 2d6539370..1bdcb61b4 100644 --- a/lib/src/screens/dashboard/widgets/market_place_page.dart +++ b/lib/src/screens/dashboard/widgets/market_place_page.dart @@ -48,15 +48,15 @@ class MarketPlacePage extends StatelessWidget { child: ListView( controller: _scrollController, children: <Widget>[ - SizedBox(height: 20), - DashBoardRoundedCardWidget( - onTap: () => launchUrl( - Uri.parse("https://cakelabs.com/news/cake-pay-mobile-to-shut-down/"), - mode: LaunchMode.externalApplication, - ), - title: S.of(context).cake_pay_title, - subTitle: S.of(context).cake_pay_subtitle, - ), + // SizedBox(height: 20), + // DashBoardRoundedCardWidget( + // onTap: () => launchUrl( + // Uri.parse("https://cakelabs.com/news/cake-pay-mobile-to-shut-down/"), + // mode: LaunchMode.externalApplication, + // ), + // title: S.of(context).cake_pay_title, + // subTitle: S.of(context).cake_pay_subtitle, + // ), SizedBox(height: 20), DashBoardRoundedCardWidget( onTap: () => launchUrl( From 710fe82d7a7ba327b0b146400b0fbdfac0a32d24 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 1 Sep 2023 15:05:45 +0100 Subject: [PATCH 17/18] CW-471-Changing-nodes-bug (#1062) * chore: Cleanup * fix: Node selection not updating * fix: Node selection not updating --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --- .../screens/settings/manage_nodes_page.dart | 58 ++++++++++--------- .../node_list/node_list_view_model.dart | 1 + 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart index 0a67f0502..4b1034f2b 100644 --- a/lib/src/screens/settings/manage_nodes_page.dart +++ b/lib/src/screens/settings/manage_nodes_page.dart @@ -42,36 +42,40 @@ class ManageNodesPage extends BasePage { return nodeListViewModel.nodes.length; }, itemBuilder: (_, index) { - final node = nodeListViewModel.nodes[index]; - final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex; - final nodeListRow = NodeListRow( - title: node.uriRaw, - node: node, - isSelected: isSelected, - onTap: (_) async { - if (isSelected) { - return; - } + return Observer( + builder: (context) { + final node = nodeListViewModel.nodes[index]; + final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex; + final nodeListRow = NodeListRow( + title: node.uriRaw, + node: node, + isSelected: isSelected, + onTap: (_) async { + if (isSelected) { + return; + } - await showPopUp<void>( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).change_current_node_title, - alertContent: nodeListViewModel.getAlertContent(node.uriRaw), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).change, - actionLeftButton: () => Navigator.of(context).pop(), - actionRightButton: () async { - await nodeListViewModel.setAsCurrent(node); - Navigator.of(context).pop(); - }, - ); - }); + await showPopUp<void>( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_current_node_title, + alertContent: nodeListViewModel.getAlertContent(node.uriRaw), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => Navigator.of(context).pop(), + actionRightButton: () async { + await nodeListViewModel.setAsCurrent(node); + Navigator.of(context).pop(); + }, + ); + }, + ); + }, + ); + return nodeListRow; }, ); - - return nodeListRow; }, ), ); diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 1c81c255b..ea612c63c 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -76,6 +76,7 @@ abstract class NodeListViewModelBase with Store { @action Future<void> delete(Node node) async => node.delete(); + @action Future<void> setAsCurrent(Node node) async => settingsStore.nodes[_appStore.wallet!.type] = node; @action From 68a821cc0e293e38dccdc6cc0e015ed86f087489 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Fri, 1 Sep 2023 18:06:18 +0300 Subject: [PATCH 18/18] Fiat api fix (#1070) * Cw 474 linux swapping wallets btc then xmr still shows btc receive qr code (#1068) * feat: improve address page txt field * fix: switching wallets from the desktop dropdown updates dashboard pages * Revert "feat: improve address page txt field" This reverts commit 0a30e6d9e1d13795219b66a6fdf2c1d218479089. * refactor: rename to WalletChangeListener * fix: _init also behaves on wallet change * Fix Fiat conversion API parsing Cherry pick fix for Desktop switching wallets not updating dashboard screens * Minor indentations fix [skip ci] --------- Co-authored-by: Rafael Saes <76502841+saltrafael@users.noreply.github.com> --- cw_monero/ios/Classes/monero_api.cpp | 14 +- lib/core/fiat_conversion_service.dart | 8 +- .../wallet_change_listener_view_model.dart | 30 ++++ lib/di.dart | 5 +- .../exchange/exchange_view_model.dart | 164 ++++++++---------- lib/view_model/send/send_view_model.dart | 133 +++++++------- .../wallet_address_list_view_model.dart | 56 +++--- 7 files changed, 209 insertions(+), 201 deletions(-) create mode 100644 lib/core/wallet_change_listener_view_model.dart diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 66b8605c6..1cb01fac7 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -139,7 +139,7 @@ extern "C" int8_t direction; int8_t isPending; uint32_t subaddrIndex; - + char *hash; char *paymentId; @@ -154,7 +154,7 @@ extern "C" std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); - datetime = static_cast<int64_t>(transaction->timestamp()); + datetime = static_cast<int64_t>(transaction->timestamp()); direction = transaction->direction(); isPending = static_cast<int8_t>(transaction->isPending()); std::string *hash_str = new std::string(transaction->hash()); @@ -234,7 +234,7 @@ extern "C" } void setUnlocked(bool unlocked); - + }; Monero::Coins *m_coins; @@ -254,7 +254,7 @@ extern "C" { m_wallet = wallet; m_listener = nullptr; - + if (wallet != nullptr) { @@ -479,7 +479,7 @@ extern "C" { nice(19); Monero::Wallet *wallet = get_current_wallet(); - + std::string _login = ""; std::string _password = ""; std::string _socksProxyAddress = ""; @@ -568,7 +568,7 @@ extern "C" _preferred_inputs.insert(std::string(*preferred_inputs)); preferred_inputs++; } - + auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -587,7 +587,7 @@ extern "C" { transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } - + int status = transaction->status(); if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) diff --git a/lib/core/fiat_conversion_service.dart b/lib/core/fiat_conversion_service.dart index 9690c430a..479aa3b82 100644 --- a/lib/core/fiat_conversion_service.dart +++ b/lib/core/fiat_conversion_service.dart @@ -21,7 +21,7 @@ Future<double> _fetchPrice(Map<String, dynamic> args) async { 'key': secrets.fiatApiKey, }; - double price = 0.0; + num price = 0.0; try { late final Uri uri; @@ -41,12 +41,12 @@ Future<double> _fetchPrice(Map<String, dynamic> args) async { final results = responseJSON['results'] as Map<String, dynamic>; if (results.isNotEmpty) { - price = results.values.first as double; + price = results.values.first as num; } - return price; + return price.toDouble(); } catch (e) { - return price; + return price.toDouble(); } } diff --git a/lib/core/wallet_change_listener_view_model.dart b/lib/core/wallet_change_listener_view_model.dart new file mode 100644 index 000000000..6735afee5 --- /dev/null +++ b/lib/core/wallet_change_listener_view_model.dart @@ -0,0 +1,30 @@ +import 'package:cw_core/balance.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cake_wallet/store/app_store.dart'; + +part 'wallet_change_listener_view_model.g.dart'; + +class WalletChangeListenerViewModel = WalletChangeListenerViewModelBase + with _$WalletChangeListenerViewModel; + +abstract class WalletChangeListenerViewModelBase with Store { + WalletChangeListenerViewModelBase({ + required AppStore appStore, + }) : _wallet = appStore.wallet! { + reaction((_) => appStore.wallet, (WalletBase? wallet) { + _wallet = wallet!; + onWalletChange(wallet); + }); + } + + void onWalletChange(WalletBase wallet) {} + + @observable + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet; + @computed + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> get wallet => + _wallet; +} diff --git a/lib/di.dart b/lib/di.dart index d32576836..dd3e6c495 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -523,8 +523,7 @@ Future<void> setup({ getIt.registerFactory<SendViewModel>( () => SendViewModel( - getIt.get<AppStore>().wallet!, - getIt.get<AppStore>().settingsStore, + getIt.get<AppStore>(), getIt.get<SendTemplateViewModel>(), getIt.get<FiatConversionStore>(), getIt.get<BalanceViewModel>(), @@ -702,7 +701,7 @@ Future<void> setup({ )); getIt.registerFactory(() => ExchangeViewModel( - getIt.get<AppStore>().wallet!, + getIt.get<AppStore>(), _tradesSource, getIt.get<ExchangeTemplateStore>(), getIt.get<TradesStore>(), diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 162a3d723..4ff3cb390 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; +import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; @@ -13,7 +14,7 @@ import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trocador/trocador_request.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/wallet_type.dart'; @@ -45,16 +46,22 @@ part 'exchange_view_model.g.dart'; class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel; -abstract class ExchangeViewModelBase with Store { +abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with Store { + @override + void onWalletChange(wallet) { + receiveCurrency = wallet.currency; + depositCurrency = wallet.currency; + } + ExchangeViewModelBase( - this.wallet, - this.trades, - this._exchangeTemplateStore, - this.tradesStore, - this._settingsStore, - this.sharedPreferences, - this.contactListViewModel) - : _cryptoNumberFormat = NumberFormat(), + AppStore appStore, + this.trades, + this._exchangeTemplateStore, + this.tradesStore, + this._settingsStore, + this.sharedPreferences, + this.contactListViewModel, + ) : _cryptoNumberFormat = NumberFormat(), isFixedRateMode = false, isReceiveAmountEntered = false, depositAmount = '', @@ -70,10 +77,11 @@ abstract class ExchangeViewModelBase with Store { limits = Limits(min: 0, max: 0), tradeState = ExchangeTradeStateInitial(), limitsState = LimitsInitialState(), - receiveCurrency = wallet.currency, - depositCurrency = wallet.currency, + receiveCurrency = appStore.wallet!.currency, + depositCurrency = appStore.wallet!.currency, providerList = [], - selectedProviders = ObservableList<ExchangeProvider>() { + selectedProviders = ObservableList<ExchangeProvider>(), + super(appStore: appStore) { _useTorOnly = _settingsStore.exchangeStatus == ExchangeApiMode.torOnly; _setProviders(); const excludeDepositCurrencies = [CryptoCurrency.btt, CryptoCurrency.nano]; @@ -86,10 +94,9 @@ abstract class ExchangeViewModelBase with Store { ]; _initialPairBasedOnWallet(); - final Map<String, dynamic> exchangeProvidersSelection = json.decode( - sharedPreferences - .getString(PreferencesKey.exchangeProvidersSelection) ?? - "{}") as Map<String, dynamic>; + final Map<String, dynamic> exchangeProvidersSelection = + json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}") + as Map<String, dynamic>; /// if the provider is not in the user settings (user's first time or newly added provider) /// then use its default value decided by us @@ -102,34 +109,28 @@ abstract class ExchangeViewModelBase with Store { _setAvailableProviders(); _calculateBestRate(); - bestRateSync = - Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate()); + bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate()); isDepositAddressEnabled = !(depositCurrency == wallet.currency); isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); depositAmount = ''; receiveAmount = ''; receiveAddress = ''; - depositAddress = depositCurrency == wallet.currency - ? wallet.walletAddresses.address - : ''; + depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : ''; provider = providersForCurrentPair().first; final initialProvider = provider; provider!.checkIsAvailable().then((bool isAvailable) { if (!isAvailable && provider == initialProvider) { - provider = providerList.firstWhere( - (provider) => provider is ChangeNowExchangeProvider, + provider = providerList.firstWhere((provider) => provider is ChangeNowExchangeProvider, orElse: () => providerList.last); _onPairChange(); } }); receiveCurrencies = CryptoCurrency.all - .where((cryptoCurrency) => - !excludeReceiveCurrencies.contains(cryptoCurrency)) + .where((cryptoCurrency) => !excludeReceiveCurrencies.contains(cryptoCurrency)) .toList(); depositCurrencies = CryptoCurrency.all - .where((cryptoCurrency) => - !excludeDepositCurrencies.contains(cryptoCurrency)) + .where((cryptoCurrency) => !excludeDepositCurrencies.contains(cryptoCurrency)) .toList(); _defineIsReceiveAmountEditable(); loadLimits(); @@ -140,7 +141,6 @@ abstract class ExchangeViewModelBase with Store { }); } bool _useTorOnly; - final WalletBase wallet; final Box<Trade> trades; final ExchangeTemplateStore _exchangeTemplateStore; final TradesStore tradesStore; @@ -165,8 +165,7 @@ abstract class ExchangeViewModelBase with Store { /// initialize with descending comparator /// since we want largest rate first final SplayTreeMap<double, ExchangeProvider> _sortedAvailableProviders = - SplayTreeMap<double, ExchangeProvider>( - (double a, double b) => b.compareTo(a)); + SplayTreeMap<double, ExchangeProvider>((double a, double b) => b.compareTo(a)); final List<ExchangeProvider> _tradeAvailableProviders = []; @@ -222,21 +221,17 @@ abstract class ExchangeViewModelBase with Store { SyncStatus get status => wallet.syncStatus; @computed - ObservableList<ExchangeTemplate> get templates => - _exchangeTemplateStore.templates; + ObservableList<ExchangeTemplate> get templates => _exchangeTemplateStore.templates; @computed - List<WalletContact> get walletContactsToShow => - contactListViewModel.walletContacts - .where((element) => - receiveCurrency == null || element.type == receiveCurrency) - .toList(); + List<WalletContact> get walletContactsToShow => contactListViewModel.walletContacts + .where((element) => receiveCurrency == null || element.type == receiveCurrency) + .toList(); @action bool checkIfWalletIsAnInternalWallet(String address) { - final walletContactList = walletContactsToShow - .where((element) => element.address == address) - .toList(); + final walletContactList = + walletContactsToShow.where((element) => element.address == address).toList(); return walletContactList.isNotEmpty; } @@ -256,7 +251,6 @@ abstract class ExchangeViewModelBase with Store { return false; } - @computed TransactionPriority get transactionPriority { final priority = _settingsStore.priority[wallet.type]; @@ -269,7 +263,8 @@ abstract class ExchangeViewModelBase with Store { } bool get hasAllAmount => - (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) && depositCurrency == wallet.currency; + (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) && + depositCurrency == wallet.currency; bool get isMoneroWallet => wallet.type == WalletType.monero; @@ -277,14 +272,11 @@ abstract class ExchangeViewModelBase with Store { switch (wallet.type) { case WalletType.monero: case WalletType.haven: - return transactionPriority == - monero!.getMoneroTransactionPrioritySlow(); + return transactionPriority == monero!.getMoneroTransactionPrioritySlow(); case WalletType.bitcoin: - return transactionPriority == - bitcoin!.getBitcoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: - return transactionPriority == - bitcoin!.getLitecoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); default: return false; } @@ -390,20 +382,18 @@ abstract class ExchangeViewModelBase with Store { } Future<void> _calculateBestRate() async { - final amount = - double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1; + final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1; final _providers = _tradeAvailableProviders .where((element) => !isFixedRateMode || element.supportsFixedRate) .toList(); - final result = await Future.wait<double>(_providers.map((element) => - element.fetchRate( - from: depositCurrency, - to: receiveCurrency, - amount: amount, - isFixedRateMode: isFixedRateMode, - isReceiveAmount: isFixedRateMode))); + final result = await Future.wait<double>(_providers.map((element) => element.fetchRate( + from: depositCurrency, + to: receiveCurrency, + amount: amount, + isFixedRateMode: isFixedRateMode, + isReceiveAmount: isFixedRateMode))); _sortedAvailableProviders.clear(); @@ -445,14 +435,13 @@ abstract class ExchangeViewModelBase with Store { } try { - final tempLimits = await provider.fetchLimits( - from: from, to: to, isFixedRateMode: isFixedRateMode); + final tempLimits = + await provider.fetchLimits(from: from, to: to, isFixedRateMode: isFixedRateMode); if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) { lowestMin = tempLimits.min; } - if (highestMax != null && - (tempLimits.max ?? double.maxFinite) > highestMax) { + if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) { highestMax = tempLimits.max; } } catch (e) { @@ -568,8 +557,8 @@ abstract class ExchangeViewModelBase with Store { } else { try { tradeState = TradeIsCreating(); - final trade = await provider.createTrade( - request: request!, isFixedRateMode: isFixedRateMode); + final trade = + await provider.createTrade(request: request!, isFixedRateMode: isFixedRateMode); trade.walletId = wallet.id; tradesStore.setTrade(trade); await trades.add(trade); @@ -604,12 +593,8 @@ abstract class ExchangeViewModelBase with Store { isReceiveAmountEntered = false; depositAmount = ''; receiveAmount = ''; - depositAddress = depositCurrency == wallet.currency - ? wallet.walletAddresses.address - : ''; - receiveAddress = receiveCurrency == wallet.currency - ? wallet.walletAddresses.address - : ''; + depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : ''; + receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : ''; isDepositAddressEnabled = !(depositCurrency == wallet.currency); isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); isFixedRateMode = false; @@ -628,8 +613,7 @@ abstract class ExchangeViewModelBase with Store { } final amount = availableBalance - fee; - changeDepositAmount( - amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); + changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); } } @@ -664,9 +648,8 @@ abstract class ExchangeViewModelBase with Store { List<ExchangeProvider> _providersForPair( {required CryptoCurrency from, required CryptoCurrency to}) { final providers = providerList - .where((provider) => provider.pairList - .where((pair) => pair.from == from && pair.to == to) - .isNotEmpty) + .where((provider) => + provider.pairList.where((pair) => pair.from == from && pair.to == to).isNotEmpty) .toList(); return providers; @@ -746,14 +729,12 @@ abstract class ExchangeViewModelBase with Store { _bestRate = 0; _calculateBestRate(); - final Map<String, dynamic> exchangeProvidersSelection = json.decode( - sharedPreferences - .getString(PreferencesKey.exchangeProvidersSelection) ?? - "{}") as Map<String, dynamic>; + final Map<String, dynamic> exchangeProvidersSelection = + json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}") + as Map<String, dynamic>; for (var provider in providerList) { - exchangeProvidersSelection[provider.title] = - selectedProviders.contains(provider); + exchangeProvidersSelection[provider.title] = selectedProviders.contains(provider); } sharedPreferences.setString( @@ -764,15 +745,15 @@ abstract class ExchangeViewModelBase with Store { bool get isAvailableInSelected { final providersForPair = providersForCurrentPair(); - return selectedProviders.any( - (element) => element.isAvailable && providersForPair.contains(element)); + return selectedProviders + .any((element) => element.isAvailable && providersForPair.contains(element)); } void _setAvailableProviders() { _tradeAvailableProviders.clear(); - _tradeAvailableProviders.addAll(selectedProviders - .where((provider) => providersForCurrentPair().contains(provider))); + _tradeAvailableProviders.addAll( + selectedProviders.where((provider) => providersForCurrentPair().contains(provider))); } @action @@ -780,16 +761,13 @@ abstract class ExchangeViewModelBase with Store { switch (wallet.type) { case WalletType.monero: case WalletType.haven: - _settingsStore.priority[wallet.type] = - monero!.getMoneroTransactionPriorityAutomatic(); + _settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic(); break; case WalletType.bitcoin: - _settingsStore.priority[wallet.type] = - bitcoin!.getBitcoinTransactionPriorityMedium(); + _settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium(); break; case WalletType.litecoin: - _settingsStore.priority[wallet.type] = - bitcoin!.getLitecoinTransactionPriorityMedium(); + _settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium(); break; default: break; @@ -798,9 +776,7 @@ abstract class ExchangeViewModelBase with Store { void _setProviders() { if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly) { - providerList = _allProviders - .where((provider) => provider.supportsOnionAddress) - .toList(); + providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList(); } else { providerList = _allProviders; } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 9a04b5ea7..329b3c4ad 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; @@ -15,7 +16,7 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cake_wallet/core/validator.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cw_core/sync_status.dart'; @@ -34,30 +35,38 @@ part 'send_view_model.g.dart'; class SendViewModel = SendViewModelBase with _$SendViewModel; -abstract class SendViewModelBase with Store { - SendViewModelBase( - this._wallet, - this._settingsStore, - this.sendTemplateViewModel, - this._fiatConversationStore, - this.balanceViewModel, - this.contactListViewModel, - this.transactionDescriptionBox) - : state = InitialExecutionState(), - currencies = _wallet.balance.keys.toList(), - selectedCryptoCurrency = _wallet.currency, - hasMultipleTokens = _wallet.type == WalletType.ethereum, - outputs = ObservableList<Output>(), - fiatFromSettings = _settingsStore.fiatCurrency { - final priority = _settingsStore.priority[_wallet.type]; - final priorities = priorityForWalletType(_wallet.type); +abstract class SendViewModelBase extends WalletChangeListenerViewModel with Store { + @override + void onWalletChange(wallet) { + currencies = wallet.balance.keys.toList(); + selectedCryptoCurrency = wallet.currency; + hasMultipleTokens = wallet.type == WalletType.ethereum; + } - if (!priorityForWalletType(_wallet.type).contains(priority)) { - _settingsStore.priority[_wallet.type] = priorities.first; + SendViewModelBase( + AppStore appStore, + this.sendTemplateViewModel, + this._fiatConversationStore, + this.balanceViewModel, + this.contactListViewModel, + this.transactionDescriptionBox, + ) : state = InitialExecutionState(), + currencies = appStore.wallet!.balance.keys.toList(), + selectedCryptoCurrency = appStore.wallet!.currency, + hasMultipleTokens = appStore.wallet!.type == WalletType.ethereum, + outputs = ObservableList<Output>(), + _settingsStore = appStore.settingsStore, + fiatFromSettings = appStore.settingsStore.fiatCurrency, + super(appStore: appStore) { + final priority = _settingsStore.priority[wallet.type]; + final priorities = priorityForWalletType(wallet.type); + + if (!priorityForWalletType(wallet.type).contains(priority)) { + _settingsStore.priority[wallet.type] = priorities.first; } outputs - .add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); + .add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); } @observable @@ -68,7 +77,7 @@ abstract class SendViewModelBase with Store { @action void addOutput() { outputs - .add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); + .add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency)); } @action @@ -107,9 +116,8 @@ abstract class SendViewModelBase with Store { String get pendingTransactionFeeFiatAmount { try { if (pendingTransaction != null) { - final currency = walletType == WalletType.ethereum - ? _wallet.currency - : selectedCryptoCurrency; + final currency = + walletType == WalletType.ethereum ? wallet.currency : selectedCryptoCurrency; final fiat = calculateFiatAmount( price: _fiatConversationStore.prices[currency]!, cryptoAmount: pendingTransaction!.feeFormatted); @@ -125,19 +133,19 @@ abstract class SendViewModelBase with Store { FiatCurrency get fiat => _settingsStore.fiatCurrency; TransactionPriority get transactionPriority { - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Unexpected type ${_wallet.type}'); + throw Exception('Unexpected type ${wallet.type}'); } return priority; } - CryptoCurrency get currency => _wallet.currency; + CryptoCurrency get currency => wallet.currency; Validator<String> get amountValidator => - AmountValidator(currency: walletTypeToCryptoCurrency(_wallet.type)); + AmountValidator(currency: walletTypeToCryptoCurrency(wallet.type)); Validator<String> get allAmountValidator => AllAmountValidator(); @@ -151,7 +159,7 @@ abstract class SendViewModelBase with Store { PendingTransaction? pendingTransaction; @computed - String get balance => _wallet.balance[selectedCryptoCurrency]!.formattedAvailableBalance; + String get balance => wallet.balance[selectedCryptoCurrency]!.formattedAvailableBalance; @computed bool get isFiatDisabled => balanceViewModel.isFiatDisabled; @@ -165,7 +173,7 @@ abstract class SendViewModelBase with Store { isFiatDisabled ? '' : pendingTransactionFeeFiatAmount + ' ' + fiat.title; @computed - bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; + bool get isReadyForSend => wallet.syncStatus is SyncedSyncStatus; @computed List<Template> get templates => sendTemplateViewModel.templates @@ -174,39 +182,40 @@ abstract class SendViewModelBase with Store { @computed bool get hasCoinControl => - _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin || _wallet.type == WalletType.monero; + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.monero; @computed bool get isElectrumWallet => - _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin; + wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin; @observable CryptoCurrency selectedCryptoCurrency; List<CryptoCurrency> currencies; - bool get hasYat => outputs.any((out) => - out.isParsedAddress && - out.parsedAddress.parseFrom == ParseFrom.yatRecord); + bool get hasYat => outputs + .any((out) => out.isParsedAddress && out.parsedAddress.parseFrom == ParseFrom.yatRecord); - WalletType get walletType => _wallet.type; + WalletType get walletType => wallet.type; - String? get walletCurrencyName => - _wallet.currency.fullName?.toLowerCase() ?? _wallet.currency.name; + String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name; bool get hasCurrecyChanger => walletType == WalletType.haven; @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; - final WalletBase _wallet; final SettingsStore _settingsStore; final SendTemplateViewModel sendTemplateViewModel; final BalanceViewModel balanceViewModel; final ContactListViewModel contactListViewModel; final FiatConversionStore _fiatConversationStore; final Box<TransactionDescription> transactionDescriptionBox; - final bool hasMultipleTokens; + + @observable + bool hasMultipleTokens; @computed List<ContactRecord> get contactsToShow => contactListViewModel.contacts @@ -275,7 +284,7 @@ abstract class SendViewModelBase with Store { Future<void> createTransaction() async { try { state = IsExecutingState(); - pendingTransaction = await _wallet.createTransaction(_credentials()); + pendingTransaction = await wallet.createTransaction(_credentials()); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); @@ -322,61 +331,60 @@ abstract class SendViewModelBase with Store { @action void setTransactionPriority(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; + _settingsStore.priority[wallet.type] = priority; Object _credentials() { - switch (_wallet.type) { + switch (wallet.type) { case WalletType.bitcoin: - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Priority is null for wallet type: ${_wallet.type}'); + throw Exception('Priority is null for wallet type: ${wallet.type}'); } return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority); case WalletType.litecoin: - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Priority is null for wallet type: ${_wallet.type}'); + throw Exception('Priority is null for wallet type: ${wallet.type}'); } return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority); case WalletType.monero: - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Priority is null for wallet type: ${_wallet.type}'); + throw Exception('Priority is null for wallet type: ${wallet.type}'); } return monero! .createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority); case WalletType.haven: - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Priority is null for wallet type: ${_wallet.type}'); + throw Exception('Priority is null for wallet type: ${wallet.type}'); } return haven!.createHavenTransactionCreationCredentials( outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title); case WalletType.ethereum: - final priority = _settingsStore.priority[_wallet.type]; + final priority = _settingsStore.priority[wallet.type]; if (priority == null) { - throw Exception('Priority is null for wallet type: ${_wallet.type}'); + throw Exception('Priority is null for wallet type: ${wallet.type}'); } - return ethereum!.createEthereumTransactionCredentials( - outputs, priority: priority, currency: selectedCryptoCurrency); + return ethereum!.createEthereumTransactionCredentials(outputs, + priority: priority, currency: selectedCryptoCurrency); default: - throw Exception('Unexpected wallet type: ${_wallet.type}'); + throw Exception('Unexpected wallet type: ${wallet.type}'); } } String displayFeeRate(dynamic priority) { final _priority = priority as TransactionPriority; - final wallet = _wallet; if (isElectrumWallet) { final rate = bitcoin!.getFeeRate(wallet, _priority); @@ -387,22 +395,21 @@ abstract class SendViewModelBase with Store { } bool _isEqualCurrency(String currency) => - _wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase()); + wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase()); @action void onClose() => _settingsStore.fiatCurrency = fiatFromSettings; @action - void setFiatCurrency(FiatCurrency fiat) => - _settingsStore.fiatCurrency = fiat; + void setFiatCurrency(FiatCurrency fiat) => _settingsStore.fiatCurrency = fiat; @action void setSelectedCryptoCurrency(String cryptoCurrency) { try { - selectedCryptoCurrency = _wallet.balance.keys + selectedCryptoCurrency = wallet.balance.keys .firstWhere((e) => cryptoCurrency.toLowerCase() == e.title.toLowerCase()); } catch (e) { - selectedCryptoCurrency = _wallet.currency; + selectedCryptoCurrency = wallet.currency; } } } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index d692b4ea8..db45ae117 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; @@ -5,16 +6,12 @@ import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cw_core/currency.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/utils/list_item.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/haven/haven.dart'; @@ -110,29 +107,36 @@ class EthereumURI extends PaymentURI { } } -abstract class WalletAddressListViewModelBase with Store { +abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store { WalletAddressListViewModelBase({ required AppStore appStore, required this.yatStore, required this.fiatConversionStore, - }) : _appStore = appStore, - _baseItems = <ListItem>[], - _wallet = appStore.wallet!, + }) : _baseItems = <ListItem>[], selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type), _cryptoNumberFormat = NumberFormat(_cryptoNumberPattern), hasAccounts = appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven, - amount = '' { + amount = '', + super(appStore: appStore) { _init(); } + @override + void onWalletChange(wallet) { + _init(); + + selectedCurrency = walletTypeToCryptoCurrency(wallet.type); + hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven; + } + static const String _cryptoNumberPattern = '0.00000000'; final NumberFormat _cryptoNumberFormat; final FiatConversionStore fiatConversionStore; - List<Currency> get currencies => [walletTypeToCryptoCurrency(_wallet.type), ...FiatCurrency.all]; + List<Currency> get currencies => [walletTypeToCryptoCurrency(wallet.type), ...FiatCurrency.all]; @observable Currency selectedCurrency; @@ -144,31 +148,31 @@ abstract class WalletAddressListViewModelBase with Store { String amount; @computed - WalletType get type => _wallet.type; + WalletType get type => wallet.type; @computed WalletAddressListItem get address => - WalletAddressListItem(address: _wallet.walletAddresses.address, isPrimary: false); + WalletAddressListItem(address: wallet.walletAddresses.address, isPrimary: false); @computed PaymentURI get uri { - if (_wallet.type == WalletType.monero) { + if (wallet.type == WalletType.monero) { return MoneroURI(amount: amount, address: address.address); } - if (_wallet.type == WalletType.haven) { + if (wallet.type == WalletType.haven) { return HavenURI(amount: amount, address: address.address); } - if (_wallet.type == WalletType.bitcoin) { + if (wallet.type == WalletType.bitcoin) { return BitcoinURI(amount: amount, address: address.address); } - if (_wallet.type == WalletType.litecoin) { + if (wallet.type == WalletType.litecoin) { return LitecoinURI(amount: amount, address: address.address); } - if (_wallet.type == WalletType.ethereum) { + if (wallet.type == WalletType.ethereum) { return EthereumURI(amount: amount, address: address.address); } @@ -182,7 +186,6 @@ abstract class WalletAddressListViewModelBase with Store { @computed ObservableList<ListItem> get addressList { - final wallet = _wallet; final addressList = ObservableList<ListItem>(); if (wallet.type == WalletType.monero) { @@ -237,8 +240,6 @@ abstract class WalletAddressListViewModelBase with Store { @computed String get accountLabel { - final wallet = _wallet; - if (wallet.type == WalletType.monero) { return monero!.getCurrentAccount(wallet).label; } @@ -251,29 +252,24 @@ abstract class WalletAddressListViewModelBase with Store { } @computed - bool get hasAddressList => _wallet.type == WalletType.monero || _wallet.type == WalletType.haven; + bool get hasAddressList => wallet.type == WalletType.monero || wallet.type == WalletType.haven; @computed bool get showElectrumAddressDisclaimer => - _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin; - - @observable - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet; + wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin; List<ListItem> _baseItems; - AppStore _appStore; - final YatStore yatStore; @action void setAddress(WalletAddressListItem address) => - _wallet.walletAddresses.address = address.address; + wallet.walletAddresses.address = address.address; void _init() { _baseItems = []; - if (_wallet.type == WalletType.monero || _wallet.type == WalletType.haven) { + if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) { _baseItems.add(WalletAccountListHeader()); } @@ -294,7 +290,7 @@ abstract class WalletAddressListViewModelBase with Store { } void _convertAmountToCrypto() { - final cryptoCurrency = walletTypeToCryptoCurrency(_wallet.type); + final cryptoCurrency = walletTypeToCryptoCurrency(wallet.type); try { final crypto = double.parse(amount.replaceAll(',', '.')) / fiatConversionStore.prices[cryptoCurrency]!;