From 9f405ee18d9407198a6752040ccb9342f3d7be87 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Tue, 21 Jun 2016 17:15:46 +0300 Subject: [PATCH 01/22] applied new design --- .../main/res/drawable-hdpi/icon_ok_blue.png | Bin 0 -> 647 bytes .../res/drawable-hdpi/icon_ok_disabled.png | Bin 0 -> 604 bytes .../src/main/res/drawable-hdpi/scan_blue.png | Bin 0 -> 358 bytes .../main/res/drawable-mdpi/icon_ok_blue.png | Bin 0 -> 501 bytes .../res/drawable-mdpi/icon_ok_disabled.png | Bin 0 -> 436 bytes .../src/main/res/drawable-mdpi/scan_blue.png | Bin 0 -> 227 bytes .../main/res/drawable-xhdpi/icon_ok_blue.png | Bin 0 -> 930 bytes .../res/drawable-xhdpi/icon_ok_disabled.png | Bin 0 -> 836 bytes .../src/main/res/drawable-xhdpi/scan_blue.png | Bin 0 -> 361 bytes .../main/res/drawable-xxhdpi/icon_ok_blue.png | Bin 0 -> 1464 bytes .../res/drawable-xxhdpi/icon_ok_disabled.png | Bin 0 -> 1263 bytes .../main/res/drawable-xxhdpi/scan_blue.png | Bin 0 -> 578 bytes .../res/drawable-xxxhdpi/icon_ok_blue.png | Bin 0 -> 2050 bytes .../res/drawable-xxxhdpi/icon_ok_disabled.png | Bin 0 -> 1718 bytes .../main/res/drawable-xxxhdpi/scan_blue.png | Bin 0 -> 787 bytes src/status_im/components/styles.cljs | 10 ++-- src/status_im/contacts/styles.cljs | 14 +++++- src/status_im/contacts/views/new_contact.cljs | 43 ++++++++---------- src/status_im/qr_scanner/styles.cljs | 22 +++++++++ ...port-qr-button.cljs => import-button.cljs} | 0 .../qr_scanner/views/scan-button.cljs | 23 ++++++++++ src/status_im/translations/en.cljs | 7 ++- 22 files changed, 87 insertions(+), 32 deletions(-) create mode 100644 android/app/src/main/res/drawable-hdpi/icon_ok_blue.png create mode 100644 android/app/src/main/res/drawable-hdpi/icon_ok_disabled.png create mode 100644 android/app/src/main/res/drawable-hdpi/scan_blue.png create mode 100644 android/app/src/main/res/drawable-mdpi/icon_ok_blue.png create mode 100644 android/app/src/main/res/drawable-mdpi/icon_ok_disabled.png create mode 100644 android/app/src/main/res/drawable-mdpi/scan_blue.png create mode 100644 android/app/src/main/res/drawable-xhdpi/icon_ok_blue.png create mode 100644 android/app/src/main/res/drawable-xhdpi/icon_ok_disabled.png create mode 100644 android/app/src/main/res/drawable-xhdpi/scan_blue.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/icon_ok_blue.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/icon_ok_disabled.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/scan_blue.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/icon_ok_blue.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/icon_ok_disabled.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/scan_blue.png rename src/status_im/qr_scanner/views/{import-qr-button.cljs => import-button.cljs} (100%) create mode 100644 src/status_im/qr_scanner/views/scan-button.cljs diff --git a/android/app/src/main/res/drawable-hdpi/icon_ok_blue.png b/android/app/src/main/res/drawable-hdpi/icon_ok_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..66e62ce1a3afdf162c35e4950145ce0f5c3601cb GIT binary patch literal 647 zcmV;20(kw2P)Px%K}keGR7efAluK{ZKoG}wwjgn$=2V+AMSO)GIU*sH3lUPPs#WEfG)Q1qh^x6F zgp!I!i)~7HKY}3Q#E~O>2H;#fTu81!Jj@tx+&rK(#B=a$W_SO;%Pdr(QTf_O~=a}lNO?bvPu52=lR^9*u=&=VM2Y8?pqWZ{Uh^d}IngJu(FK6b)~ zF^Uou`<;EEU;}dy6=Kz1>yd+r@RZdAIT+6@%( zq7tLGE+CM#9}w>yfN|iGAKe}3GJr3X@iCrD45U{#=PLUJ@!k;_cbgqV_o-ydiTJ<= zw(4cQIthqnMlLlA@uAb-c)puMO>}3&GS(&qjfHWLn?jp6s2Si*vIyW-%`z_VI5+b= hJV+(YF7JPmegOhJ??J0h8Y}<+002ovPDHLkV1n#;5{Uo+ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-hdpi/icon_ok_disabled.png b/android/app/src/main/res/drawable-hdpi/icon_ok_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..dc6068da44c3f22be04cc096d17b83ffde376769 GIT binary patch literal 604 zcmV-i0;BzjP)Px%7D+@wR7efAl;2MiK@i7xcCV#xMnS|M(J1BDUq<9gReZ6r#wBgi7ofT8RfB(+ zpe+w3Mn#|vJ}Gy%W9OPVTR39dT=!*fXJ@{je0S$oh$#=fvonW?Ko~hqR;AH+EM<1B z>biLXM#O0Vb-n&XqPox83c~hOoYm^@hCsao?D*&B$Em{zvM zr#NAfnc6vbV?K`qAS(kWuZ#AlK}W1T@tqMU`hNs0#9{_cN`*oqh;pKCq(bew4>aOP z-Ps52=P~>T0%`p$y}TYoFrdQiU2jE7ysZ>={ciUowJB{TjVOPwxg^2d;e7&?pFRDY zbab3Uv)tbOFiRj>gdyC_-db2CL0VrP6t6WegUm=E(uzc@p7+RHn1?K$)J+7cI?gg0 zInQ}kRvwpZyY)XuoFCm$xls558TiUU#Bi?aykBOAeNb;b05Uiph_r`}i(UW>MEqlt z;M*;`6@g6^d8w9L*-byOd(42hv-1o4zL2Hw_XEHO{q;2f0000Px$AW1|)R7ef&R?P~+Fbq!0@D&8F>brRKE#`5czJeDOyw0ca=)>rB;48>jO*#U# ztoxyJAZ(X!Ns}*4Xq#Yi%?=2#)fy(?`4I6DX|+1W)2C~)PhayKi@Vl(;jW2{2yf7E zQcZ!_fr)Y`*5Yg<>+1rQ{*(y9PSs^3q$V>^H<4|ONYCrGuIiuTV3KB97BBIP67Bc1 z`BlHv^=xCX`uen79kz^eYz13xvbCA;GDiF|@Wmvoyhp8BJ%+#L_kH)q(~m*V;eFzGA+kZG{>Er0-DSM=0=%_KNqQt!-mvnegFUf07*qoM6N<$ Ef+0erWdHyG literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/icon_ok_blue.png b/android/app/src/main/res/drawable-mdpi/icon_ok_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..8b6c5482cf652f6bbc2bb0534c9e8b6213d38972 GIT binary patch literal 501 zcmVPx$uSrBfR45gtlS?lHQ546|xieE0Qtwtjf_Np^8){`GHg<%d3!6S9UYl;PKv=LC z6+&3}3`oC$h(|oaQl?d}HcE+^;|^)lHf^HJ=H7em`Tz1i=iCAK$2X=tmU#R@mw~{) za(o+4rIC;L9s#v5WRrgajqf~{y~kenh@hE!xiK-5oHxk57AXfU#+^VDB3?s*Bro<= z-m-j3o7jw2kRChufxwj{h^+=BuO4}oXr&G>`yA59g_i(Q+mf?NO&Ixh6HHw}RIACj>y2qqghutDVN> zq(5ZS-Y7sswS2^PGIOmR^<3C#2|hF&B&Zy&!5-400000NkvXXu0mjfqu|`R literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/icon_ok_disabled.png b/android/app/src/main/res/drawable-mdpi/icon_ok_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..62a6bdebf489b75fca2b9bd16694e787b96b88ed GIT binary patch literal 436 zcmV;l0ZaagP)Px$Zb?KzR45gt(#=Z4Ko9`n-N{dBDrhArQc)0*9?a|X6$(NFo&+z>q2Q&|i$4^6 zg1kiEp}B}4N(D=>P!Mg6-DJ%ax2DCv*1hcR%;aNsH;nybAU5@C{h~kwpVz@=QwQI7 zm|zQ#(eCDg8jXe#gyAkB47ArJh+6ur9TC#$4;_#!rx4e5Lv0p_kZyu78RvlU!J-!X zgpl#)qbVf%Kz7zwTcuLzO*I0vkW&5#P9tIpA%lCKXI`~Cj&Abyq3b?UFg*~_gnZs% z5x3|#gkY)@RSUO4U^C#B5Uhx`nynHvBYFw4GD4W9_r=rK2-U(trSf2KoG(Dten1hbs2nJbE>iJlfy8i6sQIp9N9hPt5cyRBNZ3 e^yCwXUpDW5F{8BQvMRX%0000@7ndHw(Y|Gg3y7?hbGU;9_$DWCH2(9HAO|D^wT->bux)O^J#(U>JxaSs0##&l&v zhc;ueGd17jRm>D)xmGKwe2tiC@Yg3I^`wAI4co>Br#U?H4{QxsC7*YJBf+3)69=7y7Dl>#vvRpdt5+uZ~<+fem2>VP% ZhH0@Djz@0`O#?cV!PC{xWt~$(69A+!QpNxP literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/icon_ok_blue.png b/android/app/src/main/res/drawable-xhdpi/icon_ok_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..df4ddc7541de4b4aa9539237759ec3775028fe74 GIT binary patch literal 930 zcmV;T16}-yP)|00001b5ch_0Itp) z=>Px&TuDShR7efQm(6PvQ4ql2yi_f{)C!uU=&=`19=sGqsftn*QEOZJVXd~=pok=! z7CcD~dJs#tA|ksnja6Dys9L`&DE!-9vkR{hArTKW(g=F0*Y21CkVC-{QmiCb|{fa?dvbqjUlcjD#Asm~vWRlU0y4DEK`T403#+>t3#<2A5mfDiI_hVrIY3Hm0BttmxkACoW+tEmyngNSP(ux~ZM_l*R6 zvzA_tr~1%jNwT#c3IfSetL{-GKh>YLi|tUjpadMEvhMCL$hK!q{2-5g-yv*dE!AHP zhW=UidSQfr*A58Af`uaFM}!=b&LFd}|YAaSFk1C076 zUk}x!X)$*S>Hctl)6@^#hiGXMYp07*qoM6N<$ Ef+umOV*mgE literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/icon_ok_disabled.png b/android/app/src/main/res/drawable-xhdpi/icon_ok_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..07c323e77e1e9d0dfd6a2dc9e04990b0f2dfe7d8 GIT binary patch literal 836 zcmV-K1H1f*P)|00001b5ch_0Itp) z=>Px%{z*hZR7efQm+4OvK@`AuW@p_tDqa=zqfrq7js8!XrWV#hzypX`6QE$5(h?TZ zsNsA68{<#vO|Yaa-qT{A zY`}(8NY6Yv&P>tahoOr@y?(5OI6Uq?e6Z+-duHU>d~pG z6TcB#U^qh;y_J!X`g*V@x)c<5T^V9daB3c>n?j0MNiE%W7)jmb%n#q%l=qw#cThUjv?s* zS$*ePC^#Vub;8S&%kEKvU^uG{2Evz*?9R>Tdj%;UocTDV%1^9b%47;*r`?vJ=c-i( zVD$c-SH_N8xn*~IVs8~hDnD|t03%6R$19g-XJPx$BS}O-R9Fe^SW6DVAP^nUOK8;lc#*m_@f=Ouwioe08a;)@p(#kQ=?n>|i(ymR z`MlxLOn9hM``AChv|wNZoT1>h09Do1>N4kU^LEBG24Fkq=WRn?om7mC#=`p;pJ{qx zeb~hWc{Q7vY23VDaj`lzqXM|vEu-RkAKV7YFSe^=b4O<1<9t{n=J!U7pUhC{Ql%h@ zVPQxZq8Om;8p7rk&Z)>;_7D^2+ILiZ;dJ0!b+|mg#&>ndQy35igaOBZ@~Q*B*d|4( z2^W~_8RIWQ)zN`z5NMYRjFTtEAE}Nc*}_5N_yl^;;>!VzB25?)hA0Lo```UTAKIQ; zfjxtBI(qW`&;XpyP^tSNUr>1JC+R8dFj5^%tYY^=!>{lH7PD=4)A#3T00000NkvXX Hu0mjfg4v<> literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_ok_blue.png b/android/app/src/main/res/drawable-xxhdpi/icon_ok_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8661249d229565a03af452b324bb9009e22575 GIT binary patch literal 1464 zcmV;p1xNacP)Px)a!Eu%RA>d=m}^WNRTO~lS@y-l&d{c2R{dd2B;kjDjDKttOA9F>)Jh|(Ev*$> zSmP^DjgKED^TT&Qs-~I+YsK1NDIx(&oBF^A?wxywvH!u-*2Xie7!IposkLjHw1&O`tvwjzF0=1T8mu;W zrjc>J6M^nH#q{^oUhXvDmMmCZ@XRX+QEPxO#y5t4orZ&H#nP$OHEFML&L6V#7#JLs z@|4Z97M-1Oy2ua)2Cu$jKkUMDLwpa?9jBQ^=u%sJam z&e}czKViQ(qTL`sH z=nJs#yq=t*=eI38Z)cNs5sN}K>u+NkZnblmWa#usmXTfDxI?-S$3~=Dd^sIvzY1wB z5zZ<_vjebiJ=s~sFI36{A{&yY&8|pLeIadMTqp+LNUqGHL{J2l7AFsaIv&#BWt?py zr|cd8_}a}p#n0|o9=6k4Whq}{bRx&Y>wa8QeyelSZ8+g!o^>w<<_1OmQo1WnLbW2) zozoE38XT9i-6iUl<%3pDymrbWMi)c6L(z3ZFUC!LGnc%`Bg9oznaCpLz#Em5Tb}C9zjxN|_pfe?>O)k;7zq9K-au$+jcFDSV5o z&37GJJAqK$%e~=I{R14oL|}q%7d~OR%KAn>42f*!D|e`V80EllhY~!T=T8jrkDqE8 zTp_R!iU}$-rgg@HLaL9F4Mh$`cg0;bzIxn=o)&qCj@>Xk{LfKJS&@xZUf0Gm5vmK1 zN$adSqmAp}sO<9Hp3F!YV^3}OjWt(2gA+YxD6A!C?8Z?TIr8|P{wu6HYn!0hfZmNz z#a5ls#`HTPxqTbdDi}6o$t6wZsqWtzo8j(fYCKV&6giP&_D%)S=4_ zMSjf!BVj|0@-Rkb57q4+TytwfV|oYesD}Qrcl2zGR1ZdbwIQ>X2-Pj+DjP3nq>MRd zrJ|vTUeTM*ws02NV#sXDPC3t4!TS5X;m~*wMbpM6CIaY^Wu=04VWCYD6+$qYBYFWG z&|5J=6{0yY3I|c|L;Wox8YfU!6>Nma!KqnToNCXEiQ8x}S*bmTMT?!|;6 zKW*2T89*(BaY^?1X?r%y=TgTbS-YI4+_l(Haz(@n@!7tyHB8R8n3lMUGA>Nf|7OgZu{rZVPx(sYygZRA>d=ncYqsM-<0rX4l4Q1S!UifhMJGNJDWMGO@K`+nDKKYt!Byv!GQ>2tKX)lqP^O!!&X0ICD{MEroff~o6A6N>M#%G*4phfn|(=v5J*ettZEjbIiBV;fx>ChudPg!1Wh+Hkf9RxyB@ znLim600vSq+x;?`Z#W~DoGLi;Zc52Mfm7@d>ZvCbb8$Zj1!Ofp;j=M1Arp zt0@yoAsdSN#*{j?Bd7ajphS@D@U6{)=zDA^fUHvtZiU$EY;kc>BRzcyvi<(%!oottXY8??&k70*t11Rit7{tx zi?HP+jOLRTx4P>LXIA9ptMxHTPYy>p7f|t0%fh{N^UI15 z-fEXpa!T73f6Znu@0;i=Sy`7dz8CL~Joh`Fsp9~O%+4hc;-9K*M`gSicQ`tP>ib|I-U1yC0|`UV3L{H zr(YV}xZ*aUeY9y}!?dB+1(e|qrD>sxG4b8XX+VMfHOu|fk-^w|&!r-EEoSN!-cvJn&qxNZc z*%J(I25=8&=RHpiUPkFU5>Vxue^*}p+tt?46`hlVTS8pG^6ac{CJ$;(jgOy6OsV$x zDkcZmt6(N`!)wKpeIb>(46htC%zdHqz0-!2%NRO0v!^?KBkF)ifA%hVvYI zS1!N_1j>yrJ%mf}LlNt>E>ML7Ucy0oODXN57s*#&1kW4JVZ|K6XSh60<8rI>_( zZ+ipc4+j#bepv^5UQnP;3Px${7FPXRA>e5TCq~YFbtJ)IY#JM`eAIavNBN?xE@SwtgLk7!`hC8kwr)$DY?X{ z&x)@$MV@R&lAoXAT-9e>ywl0YcJl}XR|Iqp+J?A7faTd_`mngbuaGbe1_HPQqFIP< z+ZF-Wfbb?5O4$?<&D#d5J_BN4bB-tOcOfxiVW<*AKNt$hR0s&KttOtvXCDxbSB!f7 z_61M)O!ibnU!ULc(3ps@4E6EZ$J>~EJP@Dd;QAKrK0lpI@5Q$|{N0DjG2Xnc_{{g) z%k_*ua{0F*{P8lD83(qp%o5^-V;S>Ol$n8LEVG1o;aJAJ6lG>$8OtmoUN{BtkJp}+ zYp!RM$%G3l&lOV6cOkmwx;D9tU07wVlrp0#=j$p~Y9lTqf=iE78~y9}Q}Jf&8Ux0F zF<=ZB1IBb%707*qoM6N<$f{<7Vb^rhX literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_ok_blue.png b/android/app/src/main/res/drawable-xxxhdpi/icon_ok_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..f8a9b938b49673e6796132c029f3351176c0717e GIT binary patch literal 2050 zcmV+d2>thoP)Px+yh%hsRA>e5ntNaL=GAO6Nml7=pCCoTE#Q+jIG8*Ia6B;v86838_3aa- zFpV5CCFXF_k`60^ZEm}{R&JBAIp`VB$!kcsr$q}KjIhKZT&jdaL1knFIcr-dNfM^> zoXPTNQ2R~cV2ny?Y?iHR`izU9XB+(2iXv{&3J0L9P6mep%cuyd@ClPe5}hGWQi}$; zj7AQ@WR=^N_m*6){GBm?9QA?gNLZw=@@te%Cfs8z!W?;}+h%$vL8lO8#1LEO2~0s@ zu?2k71c%4?2`z9atF)g7IcnRk7f}?>MCwqV7eo$+@roL&`Mo~vWXiOTAXs=#MPj4{ zR^bz5KB@kMoD+e3@)*E*U)3OqFl{3U)>b!!Bhj2QK8bI=VhV?F=ux-L@bn`n`CfGT~h)58*`aLkGBC?x;~amCek(+;IZ z>wQ`Qa@PB2h!NBT`#C0-gD^YpL6|FcSuC>)M^ z*i~xY&9Y_b(;`VbJi=@VktSGpGU0&3=K#?|kdQxRIj==O{u#|rD9uN+ct-YB8?noAEIywzf5m9w7;r=9KN=Bu+(i1h0g4+YUmi7ieq}%!s)}! zM2Z|F1YOCh4~9TDhxw&0yJ^SIJ8Z2dsqzbfuq{X2c!qG zN}>H*MS>1$fdh}7B^-C(K*FJ2>jmWS3CrMBx&y*G?rfSGfoz@_BD>^AvQ)0;<*4=F zCJ}T17M{!@4d+!|1`aQATg@~_4d@jGIG8@N*x zB~5T3a!&II;8=6N)Y4DAYM?DD8ux zJBn2Wg@X~dsM?M@GzTY=TWaigkqkh{uG4+M+*14 zN-f{2TMUjgZiva7gw5@>u*RvA%aZ+uoa8L?2`?wpQ#t7KwZehp%uZw=g%=wR?RQc@ zkQm7rtHlP%@oj3zyd>#)hqv_wH9LnlP>2&|=xUabaS-a@F)DPGxDqV$$JxP$U5H{GqSL!a-eV>46 zr;3ZQI1QOsz&<8jz_KqwHkEmWr>UXS8z_=A!U6Mk12Po2?KwZN8yP%{q)A%Y1-irt zb_hG^Y+9*HxQF4%5%dP+oKnz5zZOlfkqMv^C$NDptSK@5C=(BfpPB*D-qOWtFf7nl zbiQ7_r*L?VFW77~{iIi&de*}nV)DkSp2Q)31YQa-n(o{5jQU2h+Y^fM^HlR&21R8%{XUoRm9^aez0V{OZ+~ zUs8T{kRRwbAlgs5sox#yYJo_arM2G>If9WR`5UcyziNHvV%nvYgOnY8b>-;xksMbD zlz&s|)b0U}-)Jz*PZv1UhYO0J7zFy6Kjfst5J^*FvV;=jRt^~!)Yx*4Cg_H+;DRD3 z<``NS4<`^;a~X2XyoUo8yxC`E)f)iK|iE~Zv_uS;{N}mCXD{ZoMC~h zH23$IT{@MzL{Q9O*J{%rMuV{cmL&ly1Nz5|grA?TaL)S>b5Fk#_L648hTC>zPx*a7jc#RA>e5n_EvCM-<0rXLoIEE`eOz^palH6k;AL^`%n21do-Xw4y-jgjFda ziPEVQ1rUjIW_D*m=*{6vK=Eze1&zsMQlDS3j(q&?f%_dD9k$oxT@8p362J{D5rma6(v`)d zhYn49Az?4E-BKoGB7j>CZomPfP1Za!JJ(7Wb1`uhb`6{ffb%qhY%A=xnKk41)ix)j zUFTwi!_j8v+9_foH=I``Rn-^Fg}G_&f^=6YXhH%GV6ttq1=Y8-GR73`6}Q^XB@&6? zo!PmFpK@FT>hQdxC~Q{%0yvA5wj+e=ToCdUR3&)t;`g18ptVoRsAA5TK1u){M*&t2Gc-!RgkKsl#GwpA-2@6 zFearO6^HIzjD9zli$To+0yx^j5)a5In9E>q9l$w%=G&Zbpl?mN*!T-LR2mNTg#&F(vCt~g_&P^UIiZk#yRWP3F+lJ;YC=H(XBh|h( zHcdk_=Zvl=qFgAgY6Zn&6ItaH1t%Jnh6C`bHU^PoGK|;ENIBsEpsI8+fPQ4+Uu+LTj4L&@YGv#ufXXw{66>(>iP+j+rKJdj7FpXiMrR7x@NJnr#t`F z75yKXn=@)1{5dxI=~k2k>#SnnSUUsCPco?I$)-Ey|OT+Df+v%TGaQik*HI6C`++6Lple&DS0=Hv14qLiasI}ZnJ$O{O9 z?@vb0T?ocrV{?^FX1)hOK3Ch|*jURFT9$Gvq+m<8)>HlcJF6UFM_v~b9UusAOzZZ3 zQRkNiHFUo}8l4q=0FIfqTV-Y|fU_^4qbBM=SVLwoy^`wd`+7wTrV`VlT+C?zyo%NTm}<8f zt#{VTkk>RfcQwXc;qAq8Oai-effF0Wg1Q+4&Y0`8t zoZ=TtLwVD|;WW^LRizwZLrDO^#RxgE9!3^d5?6}z$im6oG>nclXLYsYO9luGHVk8p zhV&E!;w*rdaEz*i12$|sNM}KK{=j!UD_ZEYCYHGc&^*m=inT=Ge|%%f%@!1Jm;e9( M07*qoM6N<$f_^M8SpWb4 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxxhdpi/scan_blue.png b/android/app/src/main/res/drawable-xxxhdpi/scan_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..2365f04fc5c3ebe27c74237049bc68e1058b2fe7 GIT binary patch literal 787 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!jKx9jP7LeL$-HD>U^?sR;uuoF z_;$|5B4I;;wsOeDs2oV+DJ#!|8yfjB?F3Og79dY{ALPBep1+ zKlVBI%W{6nw}b0v_PmY0oAv$kuPKq4ONDN~+&^Je+-+?`dbi`0|KLY&eUJG<_meQWu#xKfMh+y3OJvHLEUTEFU3@uJO- z_f2TqW?u2+O55WDwLRXS^Y_L}Uy760{&9ZQ{FAcp%q(AC*uC}jgm1qh7XC0^esyhO zT!~qt$K}5duUFel{d~{LN<%{E!lCpwzHM8}=DzsSYX2d+RaEa9yU6lN(Mo&X&A)5Y z4Zhzm{gI=gC9m?AJFxN8EU(&c-ws`~yI=A9*~`E$@9*cH`2S1Lq-Yxp%RUDtB?SkD z4oOEA77hkO<&FjhMujvMK>-DZBRvXCOe_sE1YH~&7zB))6c)r>(o|>ea#ue0QzEr6 zRC&7kHpkEVcQbv^hUdJ%l{AOzx~_6{V!|r_o}sr_DRKES~uta&Zyqjd$Z*B*VX)v z_Duff8@}wD^3VCJuUbrrU;T5RWyr00K5yMW*{|z9I%yH_*^&cReY|E@_RsllpYnPw z*Y%{UKW7eM$1pUqb%Q6;ph_G1}H^uj7AlYSPBJ@>dvScmkvfQl7K#JbTc* z&wR^|s<{oDIbF|v*}1O#@p7eP-io>jx25;UEnXXzymjH=uKW}^%a1vWmW4ev=iDlz+cdeY2$;$lJYD@<);T3K0RSC2WcmOA literal 0 HcmV?d00001 diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs index a1176d46bf..0498011c07 100644 --- a/src/status_im/components/styles.cljs +++ b/src/status_im/components/styles.cljs @@ -63,6 +63,10 @@ {:width 23 :height 22}) +(def icon-scan + {:width 18 + :height 18}) + (def icon-plus {:width 18 :height 18}) @@ -92,10 +96,8 @@ (def button-input-container {:flex 1 - :flexDirection :row - :height 50}) + :flexDirection :row}) (def button-input {:flex 1 - :flexDirection :column - :height 50}) \ No newline at end of file + :flexDirection :column}) \ No newline at end of file diff --git a/src/status_im/contacts/styles.cljs b/src/status_im/contacts/styles.cljs index 4b64148fc9..410adf7ed2 100644 --- a/src/status_im/contacts/styles.cljs +++ b/src/status_im/contacts/styles.cljs @@ -71,7 +71,8 @@ (def contact-form-container {:flex 1 - :color :white}) + :color :white + :backgroundColor :white}) (def gradient-background {:position :absolute @@ -82,4 +83,13 @@ (def form-container {:marginLeft 16 - :margin-top 50}) \ No newline at end of file + :margin-top 16}) + +(def address-explication-container + {:flex 1 + :paddingLeft 16 + :paddingRight 16}) + +(def address-explication + {:textAlign :center + :color "#838c93de"}) \ No newline at end of file diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 469ed6b914..9c09c3a806 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -19,8 +19,8 @@ toolbar-title-text button-input-container button-input - white-form-text-input]] - [status-im.qr-scanner.views.import-button :refer [import-button]] + form-text-input]] + [status-im.qr-scanner.views.scan-button :refer [scan-button]] [status-im.i18n :refer [label]] [status-im.contacts.styles :as st])) @@ -28,51 +28,46 @@ (def toolbar-title [view toolbar-title-container - [text {:style (merge toolbar-title-text {:color color-white})} - (label :t/new-contact)]]) + [text {:style toolbar-title-text} + (label :t/add-new-contact)]]) (defview contact-name-input [name] [] [text-input - {:underlineColorAndroid color-white - :placeholderTextColor color-white - :style white-form-text-input + {:underlineColorAndroid "#0000001f" + :placeholderTextColor "#838c93de" + :style form-text-input :autoFocus true - :placeholder (label :t/contact-name) + :placeholder (label :t/name) :onChangeText #(dispatch [:set-in [:new-contact :name] %])} name]) (defview contact-whisper-id-input [whisper-identity] [view button-input-container [text-input - {:underlineColorAndroid color-white - :placeholderTextColor color-white - :style (merge white-form-text-input button-input) + {:underlineColorAndroid "#0000001f" + :placeholderTextColor "#838c93de" + :style (merge form-text-input button-input) :autoFocus true - :placeholder (label :t/whisper-identity) + :placeholder (label :t/address) :onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])} whisper-identity] - [import-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]]) + [scan-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]]) (defview new-contact [] [{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]] [drawer-view [view st/contact-form-container - [linear-gradient {:colors ["rgba(182, 116, 241, 1)" "rgba(107, 147, 231, 1)" "rgba(43, 171, 238, 1)"] - :start [0, 0] - :end [0.5, 1] - :locations [0, 0.8 ,1] - :style st/gradient-background}] - - [toolbar {:background-color :transparent - :nav-action {:image {:source {:uri :icon_back_white} + [toolbar {:background-color :white + :nav-action {:image {:source {:uri :icon_back} :style icon-back} :handler #(dispatch [:navigate-back])} :custom-content toolbar-title - :action {:image {:source {:uri :icon_add} + :action {:image {:source {:uri :icon_ok_blue} :style icon-search} :handler #(dispatch [:add-new-contact new-contact])}}] [view st/form-container - [contact-whisper-id-input whisper-identity] [contact-name-input name] - ]]]) + [contact-whisper-id-input whisper-identity]] + [view st/address-explication-container + [text {:style st/address-explication} (label :t/address-explication)]]]]) diff --git a/src/status_im/qr_scanner/styles.cljs b/src/status_im/qr_scanner/styles.cljs index 05198031b1..65838b9ec6 100644 --- a/src/status_im/qr_scanner/styles.cljs +++ b/src/status_im/qr_scanner/styles.cljs @@ -74,3 +74,25 @@ :flexDirection :column :color color-white :margin-left 8}) + + +(def scan-button + {:position :absolute + :top 5 + :right 16 + :flex 1 + :height 50 + :alignItems :center}) + +(def scan-button-content + {:flex 1 + :flexDirection :row + :height 50 + :alignItems :center + :alignSelf :center}) + +(def scan-text + {:flex 1 + :flexDirection :column + :color "#7099e6" + :margin-left 8}) \ No newline at end of file diff --git a/src/status_im/qr_scanner/views/import-qr-button.cljs b/src/status_im/qr_scanner/views/import-button.cljs similarity index 100% rename from src/status_im/qr_scanner/views/import-qr-button.cljs rename to src/status_im/qr_scanner/views/import-button.cljs diff --git a/src/status_im/qr_scanner/views/scan-button.cljs b/src/status_im/qr_scanner/views/scan-button.cljs new file mode 100644 index 0000000000..9ed1fd39e5 --- /dev/null +++ b/src/status_im/qr_scanner/views/scan-button.cljs @@ -0,0 +1,23 @@ +(ns status-im.qr-scanner.views.scan-button + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [status-im.components.react :refer [view + text + image + touchable-highlight]] + [status-im.components.toolbar :refer [toolbar]] + [status-im.components.drawer.view :refer [drawer-view open-drawer]] + [status-im.components.styles :refer [icon-scan]] + [status-im.i18n :refer [label]] + [status-im.qr-scanner.styles :as st])) + + +(defview scan-button [handler] + [] + [view st/scan-button + [touchable-highlight + {:on-press handler} + [view st/scan-button-content + [image {:source {:uri :scan_blue} + :style icon-scan}] + [text {:style st/scan-text} (label :t/scan-qr)]]]]) \ No newline at end of file diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 8ec3ba3fb7..3206eeca42 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -115,9 +115,12 @@ :You "You" ;new-contact + :add-new-contact "Add new contact" :import-qr "Import" - :contact-name "Contact Name" + :scan-qr "Scan QR" + :name "Name" :whisper-identity "Whisper Identity" + :address-explication "Maybe here should be some text explaining what an address is and where to look for it" ;login :recover-from-passphrase "Recover from passphrase" @@ -127,6 +130,6 @@ :login "Login" ;users - :add-account "Add account" + :add-account "Add account" }) \ No newline at end of file From b5ea433420517a88bb8aba43d1eab928baf0070d Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Tue, 21 Jun 2016 17:39:05 +0300 Subject: [PATCH 02/22] added disabled state for create contact button --- src/status_im/contacts/views/new_contact.cljs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 9c09c3a806..94b25f115f 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -1,6 +1,7 @@ (ns status-im.contacts.views.new-contact (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [clojure.string :as str] [status-im.components.react :refer [view text text-input @@ -31,6 +32,9 @@ [text {:style toolbar-title-text} (label :t/add-new-contact)]]) +(defn valid-form? [name address] + (and (not (str/blank? name)) (not (str/blank? address)))) + (defview contact-name-input [name] [] [text-input @@ -63,7 +67,9 @@ :style icon-back} :handler #(dispatch [:navigate-back])} :custom-content toolbar-title - :action {:image {:source {:uri :icon_ok_blue} + :action {:image {:source {:uri (if (valid-form? name whisper-identity) + :icon_ok_blue + :icon_ok_disabled)} :style icon-search} :handler #(dispatch [:add-new-contact new-contact])}}] [view st/form-container From 42d8ea47dff1a9494522c764af8eb837512aacf1 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Wed, 22 Jun 2016 11:18:46 +0300 Subject: [PATCH 03/22] try using clojure spec for validation --- project.clj | 4 ++-- src/status_im/contacts/validations.cljs | 10 ++++++++++ src/status_im/contacts/views/new_contact.cljs | 7 +++---- 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 src/status_im/contacts/validations.cljs diff --git a/project.clj b/project.clj index 4007f3100d..15d97363cc 100644 --- a/project.clj +++ b/project.clj @@ -3,8 +3,8 @@ :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.7.0"] - [org.clojure/clojurescript "1.7.170"] + :dependencies [[org.clojure/clojure "1.9.0-alpha7"] + [org.clojure/clojurescript "1.9.76"] [reagent "0.5.1" :exclusions [cljsjs/react]] [re-frame "0.6.0"] [prismatic/schema "1.0.4"] diff --git a/src/status_im/contacts/validations.cljs b/src/status_im/contacts/validations.cljs new file mode 100644 index 0000000000..6fb1819054 --- /dev/null +++ b/src/status_im/contacts/validations.cljs @@ -0,0 +1,10 @@ +(ns status-im.contacts.validations + (:require [cljs.spec :as s])) + +(s/def ::not-empty-string (s/and string? not-empty)) + +(s/def ::name ::not-empty-string) +(s/def ::whisper-identity ::not-empty-string) + +(s/def ::contact (s/keys :req-un [::name ::whisper-identity] + :opt-un [::phone ::photo-path ::address])) \ No newline at end of file diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 94b25f115f..7e797f1f04 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -23,6 +23,8 @@ form-text-input]] [status-im.qr-scanner.views.scan-button :refer [scan-button]] [status-im.i18n :refer [label]] + [cljs.spec :as s] + [status-im.contacts.validations :as v] [status-im.contacts.styles :as st])) @@ -32,9 +34,6 @@ [text {:style toolbar-title-text} (label :t/add-new-contact)]]) -(defn valid-form? [name address] - (and (not (str/blank? name)) (not (str/blank? address)))) - (defview contact-name-input [name] [] [text-input @@ -67,7 +66,7 @@ :style icon-back} :handler #(dispatch [:navigate-back])} :custom-content toolbar-title - :action {:image {:source {:uri (if (valid-form? name whisper-identity) + :action {:image {:source {:uri (if (s/valid? ::v/contact new-contact) :icon_ok_blue :icon_ok_disabled)} :style icon-search} From bb4641fc939f74645e111daee6c4df262ed085d4 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 22 Jun 2016 16:29:25 +0300 Subject: [PATCH 04/22] check uniqueness --- src/status_im/contacts/validations.cljs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/status_im/contacts/validations.cljs b/src/status_im/contacts/validations.cljs index 6fb1819054..ac48954757 100644 --- a/src/status_im/contacts/validations.cljs +++ b/src/status_im/contacts/validations.cljs @@ -1,10 +1,15 @@ (ns status-im.contacts.validations - (:require [cljs.spec :as s])) + (:require [cljs.spec :as s] + [status-im.persistence.realm :as realm])) (s/def ::not-empty-string (s/and string? not-empty)) +(defn unique-identity? [identity] + (println identity) + (not (realm/exists? :contacts :whisper-identity identity))) -(s/def ::name ::not-empty-string) +(s/def ::unique-identity unique-identity?) +(s/def ::name (s/and ::not-empty-string ::unique-identity)) (s/def ::whisper-identity ::not-empty-string) (s/def ::contact (s/keys :req-un [::name ::whisper-identity] - :opt-un [::phone ::photo-path ::address])) \ No newline at end of file + :opt-un [::phone ::photo-path ::address])) From 4181541ae268cb5c427209ac51a90c3b16584088 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 22 Jun 2016 16:32:05 +0300 Subject: [PATCH 05/22] check uniqueness --- src/status_im/contacts/validations.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/status_im/contacts/validations.cljs b/src/status_im/contacts/validations.cljs index ac48954757..9747fe9fb3 100644 --- a/src/status_im/contacts/validations.cljs +++ b/src/status_im/contacts/validations.cljs @@ -8,8 +8,8 @@ (not (realm/exists? :contacts :whisper-identity identity))) (s/def ::unique-identity unique-identity?) -(s/def ::name (s/and ::not-empty-string ::unique-identity)) -(s/def ::whisper-identity ::not-empty-string) +(s/def ::name ::not-empty-string) +(s/def ::whisper-identity (s/and ::not-empty-string ::unique-identity)) (s/def ::contact (s/keys :req-un [::name ::whisper-identity] :opt-un [::phone ::photo-path ::address])) From fa2e2c2f28f95160b252f0e78e9de55dc7462fa7 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 22 Jun 2016 16:38:50 +0300 Subject: [PATCH 06/22] check identity length --- src/status_im/contacts/validations.cljs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/status_im/contacts/validations.cljs b/src/status_im/contacts/validations.cljs index 9747fe9fb3..ca3feee759 100644 --- a/src/status_im/contacts/validations.cljs +++ b/src/status_im/contacts/validations.cljs @@ -2,14 +2,20 @@ (:require [cljs.spec :as s] [status-im.persistence.realm :as realm])) -(s/def ::not-empty-string (s/and string? not-empty)) (defn unique-identity? [identity] (println identity) (not (realm/exists? :contacts :whisper-identity identity))) +(defn valid-length? [identity] + (= 64 (count identity))) + +(s/def ::identity-length valid-length?) (s/def ::unique-identity unique-identity?) +(s/def ::not-empty-string (s/and string? not-empty)) (s/def ::name ::not-empty-string) -(s/def ::whisper-identity (s/and ::not-empty-string ::unique-identity)) +(s/def ::whisper-identity (s/and ::not-empty-string + ::unique-identity + ::identity-length)) (s/def ::contact (s/keys :req-un [::name ::whisper-identity] :opt-un [::phone ::photo-path ::address])) From abaab3b26bbbee5251ea0cfb974464cfb0e0704f Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Mon, 27 Jun 2016 18:35:25 +0300 Subject: [PATCH 07/22] added Geth react-native module --- android/app/build.gradle | 2 +- android/app/src/main/AndroidManifest.xml | 2 +- .../main/java/com/statusim/GethService.java | 140 ----------- .../main/java/com/statusim/MainActivity.java | 81 +------ .../com/statusim/geth/module/GethModule.java | 209 ++++++++++++++++ .../com/statusim/geth/module/GethPackage.java | 33 +++ .../geth/service/ConnectorHandler.java | 12 + .../statusim/geth/service/GethConnector.java | 107 +++++++++ .../statusim/geth/service/GethMessages.java | 56 +++++ .../statusim/geth/service/GethService.java | 227 ++++++++++++++++++ .../geth/service/ServiceConnector.java | 149 ++++++++++++ src/status_im/components/react.cljs | 3 + 12 files changed, 801 insertions(+), 220 deletions(-) delete mode 100644 android/app/src/main/java/com/statusim/GethService.java create mode 100644 android/app/src/main/java/com/statusim/geth/module/GethModule.java create mode 100644 android/app/src/main/java/com/statusim/geth/module/GethPackage.java create mode 100644 android/app/src/main/java/com/statusim/geth/service/ConnectorHandler.java create mode 100644 android/app/src/main/java/com/statusim/geth/service/GethConnector.java create mode 100644 android/app/src/main/java/com/statusim/geth/service/GethMessages.java create mode 100644 android/app/src/main/java/com/statusim/geth/service/GethService.java create mode 100644 android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java diff --git a/android/app/build.gradle b/android/app/build.gradle index 7202b12494..301a07656c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -133,7 +133,7 @@ dependencies { compile project(':react-native-camera') compile project(':react-native-orientation') // compile(name:'geth', ext:'aar') - compile(group: 'status-im', name: 'android-geth', version: '1.4.0-201604110816-a97a114', ext: 'aar') + compile(group: 'status-im', name: 'status-go', version: '0.1.0-test-callback', ext: 'aar') compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"]) } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 42b5ee2517..a7b7a31725 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -23,7 +23,7 @@ diff --git a/android/app/src/main/java/com/statusim/GethService.java b/android/app/src/main/java/com/statusim/GethService.java deleted file mode 100644 index 84ec5daaa2..0000000000 --- a/android/app/src/main/java/com/statusim/GethService.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.statusim; - -import android.app.Service; -import android.content.Intent; -import android.os.Handler; -import android.os.AsyncTask; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.support.annotation.Nullable; -import android.util.Log; -import android.os.Environment; - -import java.lang.ref.WeakReference; - -import com.github.ethereum.go_ethereum.cmd.Geth; - -import java.io.File; - -public class GethService extends Service { - - private static final String TAG = "GethService"; - - private static boolean isGethStarted = false; - private static boolean isGethInitialized = false; - private final Handler handler = new Handler(); - - static class IncomingHandler extends Handler { - - private final WeakReference service; - - IncomingHandler(GethService service) { - - this.service = new WeakReference(service); - } - - @Override - public void handleMessage(Message message) { - - GethService service = this.service.get(); - if (service != null) { - if (!service.handleMessage(message)) { - super.handleMessage(message); - } - } - } - } - - final Messenger serviceMessenger = new Messenger(new IncomingHandler(this)); - - protected class StartTask extends AsyncTask { - - public StartTask() { - } - - protected Void doInBackground(Void... args) { - startGeth(); - return null; - } - - protected void onPostExecute(Void results) { - onGethStarted(); - } - } - - protected void onGethStarted() { - Log.d(TAG, "Geth Service started"); - isGethStarted = true; - } - - protected void startGeth() { - Log.d(TAG, "Starting background Geth Service"); - - File extStore = Environment.getExternalStorageDirectory(); - - final String dataFolder = extStore.exists() ? - extStore.getAbsolutePath() : - getApplicationInfo().dataDir; - - final Runnable addPeer = new Runnable() { - public void run() { - Log.w("Geth", "adding peer"); - Geth.run("--exec admin.addPeer(\"enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:55555\") attach http://localhost:8545"); - } - }; - - new Thread(new Runnable() { - public void run() { - Geth.run("--shh --ipcdisable --nodiscover --rpc --rpcapi db,eth,net,web3,shh,admin --fast --datadir=" + dataFolder); - } - }).start(); - - handler.postDelayed(addPeer, 5000); - } - - public void signalEvent(String jsonEvent) { - - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return serviceMessenger.getBinder(); - } - - @Override - public void onCreate() { - super.onCreate(); - System.loadLibrary("gethraw"); - System.loadLibrary("geth"); - - if (!isGethInitialized) { - isGethInitialized = true; - new StartTask().execute(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - //TODO: stop geth - isGethStarted = false; - isGethInitialized = false; - Log.d(TAG, "Geth Service stopped !"); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - return Service.START_STICKY; - } - - protected boolean handleMessage(Message message) { - return false; - } - - public static boolean isRunning() { - return isGethInitialized; - } -} diff --git a/android/app/src/main/java/com/statusim/MainActivity.java b/android/app/src/main/java/com/statusim/MainActivity.java index ee5ff65fd1..f5c2afe69d 100644 --- a/android/app/src/main/java/com/statusim/MainActivity.java +++ b/android/app/src/main/java/com/statusim/MainActivity.java @@ -1,98 +1,36 @@ package com.statusim; import com.facebook.react.ReactActivity; +import com.statusim.geth.module.GethPackage; import io.realm.react.RealmReactPackage; import com.oblador.vectoricons.VectorIconsPackage; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.rt2zz.reactnativecontacts.ReactNativeContacts; import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnCancelListener; -import android.content.ComponentName; -import android.content.ServiceConnection; import android.content.Intent; -import android.content.Context; import com.bitgo.randombytes.RandomBytesPackage; import com.BV.LinearGradient.LinearGradientPackage; import com.centaurwarchief.smslistener.SmsListener; import com.github.yamill.orientation.OrientationPackage; - -import android.util.Log; - import java.util.Arrays; import java.util.List; import java.util.Properties; -import java.io.File; import com.lwansbrough.RCTCamera.*; import com.i18n.reactnativei18n.ReactNativeI18n; -import io.realm.react.RealmReactPackage; -import android.content.Intent; import android.content.res.Configuration; public class MainActivity extends ReactActivity { private static final String TAG = "MainActivity"; - /** - * Incoming message handler. Calls to its binder are sequential! - */ - protected final IncomingHandler handler = new IncomingHandler(); - - /** Flag indicating if the service is bound. */ - protected boolean isBound; - - /** Sends messages to the service. */ - protected Messenger serviceMessenger = null; - - /** Receives messages from the service. */ - protected Messenger clientMessenger = new Messenger(handler); - - class IncomingHandler extends Handler { - - @Override - public void handleMessage(Message message) { - boolean isClaimed = false; - Log.d(TAG, "!!!!!!!!!!!!!! Received Service Message !!!!!!!!!!!!!!"); - super.handleMessage(message); - } - } - - protected ServiceConnection serviceConnection = new ServiceConnection() { - - public void onServiceConnected(ComponentName className, IBinder service) { - // This is called when the connection with the service has been - // established, giving us the object we can use to - // interact with the service. We are communicating with the - // service using a Messenger, so here we get a client-side - // representation of that from the raw IBinder object. - serviceMessenger = new Messenger(service); - isBound = true; - onConnected(); - } - - public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - serviceMessenger = null; - isBound = false; - Log.d(TAG, "!!!!!!!!!!!!!! Geth Service Disconnected !!!!!!!!!!!!!!"); - } - }; - - protected void onConnected() { - Log.d(TAG, "!!!!!!!!!!!!!! Geth Service Connected !!!!!!!!!!!!!!"); - } - protected void startStatus() { // Required because of crazy APN settings redirecting localhost (found in GB) Properties properties = System.getProperties(); @@ -129,25 +67,11 @@ public class MainActivity extends ReactActivity { }).create(); dialog.show(); } - Intent intent = new Intent(this, GethService.class); - if (!GethService.isRunning()) { - startService(intent); - } - if (serviceConnection != null && GethService.isRunning()) { - bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); - } - } @Override protected void onDestroy() { super.onDestroy(); - try { - unbindService(serviceConnection); - } - catch (Throwable t) { - Log.e(TAG, "Failed to unbind from the geth service", t); - } } /** @@ -184,7 +108,8 @@ public class MainActivity extends ReactActivity { new LinearGradientPackage(), new RCTCameraPackage(), new SmsListener(this), - new OrientationPackage(this) + new OrientationPackage(this), + new GethPackage() ); } diff --git a/android/app/src/main/java/com/statusim/geth/module/GethModule.java b/android/app/src/main/java/com/statusim/geth/module/GethModule.java new file mode 100644 index 0000000000..a4bb3e12d0 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/module/GethModule.java @@ -0,0 +1,209 @@ +package com.statusim.geth.module; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Message; +import com.facebook.react.bridge.*; +import com.statusim.geth.service.ConnectorHandler; +import com.statusim.geth.service.GethConnector; +import com.statusim.geth.service.GethMessages; +import com.statusim.geth.service.GethService; + +import java.util.HashMap; +import java.util.UUID; + +public class GethModule extends ReactContextBaseJavaModule implements LifecycleEventListener, ConnectorHandler { + + protected GethConnector geth = null; + protected String handlerIdentifier = createIdentifier(); + + protected HashMap startNodeCallbacks = new HashMap<>(); + protected HashMap createAccountCallbacks = new HashMap<>(); + protected HashMap addAccountCallbacks = new HashMap<>(); + protected HashMap unlockAccountCallbacks = new HashMap<>(); + + + public GethModule(ReactApplicationContext reactContext) { + super(reactContext); + reactContext.addLifecycleEventListener(this); + } + + @Override + public String getName() { + return "Geth"; + } + + @Override + public void onHostResume() { // Actvity `onResume` + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + return; + } + if (geth == null) { + geth = new GethConnector(currentActivity, GethService.class); + geth.registerHandler(this); + } + geth.bindService(); + } + + @Override + public void onHostPause() { // Actvity `onPause` + + if (geth != null) { + geth.unbindService(); + } + } + + @Override + public void onHostDestroy() { // Actvity `onDestroy` + + if (geth != null) { + geth.stopNode(null); + } + } + + @Override + public String getID() { + + return handlerIdentifier; + } + + @Override + public void onConnectorConnected() { + } + + @Override + public void onConnectorDisconnected() { + } + + @Override + public boolean handleMessage(Message message) { + + boolean isClaimed = true; + Bundle data = message.getData(); + String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER); + Callback callback = null; + switch (message.what) { + case GethMessages.MSG_NODE_STARTED: + callback = startNodeCallbacks.remove(callbackIdentifier); + if (callback != null) { + callback.invoke(null); + } + break; + case GethMessages.MSG_NODE_STOPPED: + break; + case GethMessages.MSG_ACCOUNT_CREATED: + callback = createAccountCallbacks.remove(callbackIdentifier); + if (callback != null) { + callback.invoke(null, "{ \"address\": \"" + data.getString("address") + "\"}"); + } + break; + case GethMessages.MSG_ACCOUNT_ADDED: + callback = addAccountCallbacks.remove(callbackIdentifier); + if (callback != null) { + callback.invoke(null, "{ \"address\": \"" + data.getString("address") + "\"}"); + } + break; + case GethMessages.MSG_ACCOUNT_UNLOCKED: + callback = unlockAccountCallbacks.remove(callbackIdentifier); + if (callback != null) { + callback.invoke(null, "{ \"result\": \"" + data.getString("result") + "\"}"); + } + break; + default: + isClaimed = false; + } + + return isClaimed; + } + + @ReactMethod + public void startNode(Callback callback) { + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + callback.invoke("Activity doesn't exist"); + return; + } + + if (geth == null) { + callback.invoke("Geth connector is null"); + return; + } + + String callbackIdentifier = createIdentifier(); + startNodeCallbacks.put(callbackIdentifier, callback); + + geth.startNode(callbackIdentifier); + } + + @ReactMethod + public void unlockAccount(String address, String password, Callback callback) { + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + callback.invoke("Activity doesn't exist"); + return; + } + + if (geth == null) { + callback.invoke("Geth connector is null"); + return; + } + + String callbackIdentifier = createIdentifier(); + unlockAccountCallbacks.put(callbackIdentifier, callback); + + geth.unlockAccount(callbackIdentifier, address, password); + } + + @ReactMethod + public void createAccount(Callback callback) { + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + callback.invoke("Activity doesn't exist"); + return; + } + + if (geth == null) { + callback.invoke("Geth connector is null"); + return; + } + + String callbackIdentifier = createIdentifier(); + createAccountCallbacks.put(callbackIdentifier, callback); + + geth.createAccount(callbackIdentifier); + } + + @ReactMethod + public void addAccount(String privateKey, Callback callback) { + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + callback.invoke("Activity doesn't exist"); + return; + } + + if (geth == null) { + callback.invoke("Geth connector is null"); + return; + } + + String callbackIdentifier = createIdentifier(); + addAccountCallbacks.put(callbackIdentifier, callback); + geth.addAccount(callbackIdentifier, privateKey); + } + + protected String createIdentifier() { + return UUID.randomUUID().toString(); + } + +} \ No newline at end of file diff --git a/android/app/src/main/java/com/statusim/geth/module/GethPackage.java b/android/app/src/main/java/com/statusim/geth/module/GethPackage.java new file mode 100644 index 0000000000..d7dc02df6f --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/module/GethPackage.java @@ -0,0 +1,33 @@ +package com.statusim.geth.module; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class GethPackage implements ReactPackage { + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new GethModule(reactContext)); + + return modules; + } + + @Override + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/statusim/geth/service/ConnectorHandler.java b/android/app/src/main/java/com/statusim/geth/service/ConnectorHandler.java new file mode 100644 index 0000000000..0df2737a97 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/service/ConnectorHandler.java @@ -0,0 +1,12 @@ +package com.statusim.geth.service; + + +import android.os.Message; + +public interface ConnectorHandler { + + boolean handleMessage(Message message); + void onConnectorConnected(); + void onConnectorDisconnected(); + String getID(); +} \ No newline at end of file diff --git a/android/app/src/main/java/com/statusim/geth/service/GethConnector.java b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java new file mode 100644 index 0000000000..73a1fd74d4 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java @@ -0,0 +1,107 @@ +package com.statusim.geth.service; + + +import android.content.Context; +import android.os.Bundle; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; + +public class GethConnector extends ServiceConnector { + + private static final String TAG = "GethConnector"; + + public static final String CALLBACK_IDENTIFIER = "callbackIdentifier"; + + public GethConnector(Context context, Class serviceClass) { + + super(context, serviceClass); + } + + public void startNode(String callbackIdentifier) { + + if (checkBound()) { + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_START_NODE, null); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(startNode) to service: ", e); + } + } + } + + public void stopNode(String callbackIdentifier) { + + if (checkBound()) { + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_STOP_NODE, null); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(stopNode) to service: ", e); + } + } + } + + public void unlockAccount(String callbackIdentifier, String address, String password) { + + if (checkBound()) { + Bundle data = new Bundle(); + data.putString("address", address); + data.putString("password", password); + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_UNLOCK_ACCOUNT, data); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(unlockAccount) to service: ", e); + } + } + } + + public void createAccount(String callbackIdentifier) { + + if (checkBound()) { + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_CREATE_ACCOUNT, null); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(createAccount) to service: ", e); + } + } + } + + public void addAccount(String callbackIdentifier, String privateKey) { + + if (checkBound()) { + Bundle data = new Bundle(); + data.putString("privateKey", privateKey); + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_ADD_ACCOUNT, data); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(addAccount) to service: ", e); + } + } + } + + + protected boolean checkBound() { + + if (!isBound) { + Log.d(TAG, "GethConnector not bound!"); + return false; + } + return true; + } + + protected Message createMessage(String callbackIdentifier, int idMessage, Bundle data) { + + Message msg = Message.obtain(null, idMessage, 0, 0); + msg.replyTo = clientMessenger; + if (data == null) { + data = new Bundle(); + } + data.putString(CALLBACK_IDENTIFIER, callbackIdentifier); + msg.setData(data); + return msg; + } +} diff --git a/android/app/src/main/java/com/statusim/geth/service/GethMessages.java b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java new file mode 100644 index 0000000000..080725bca2 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java @@ -0,0 +1,56 @@ +package com.statusim.geth.service; + + +public class GethMessages { + + /** + * Start the node + */ + public static final int MSG_START_NODE = 1; + + /** + * Node started event + */ + public static final int MSG_NODE_STARTED = 2; + + /** + * Stop the node + */ + public static final int MSG_STOP_NODE = 3; + + /** + * Node stopped event + */ + public static final int MSG_NODE_STOPPED = 4; + + /** + * Unlock an account + */ + public static final int MSG_UNLOCK_ACCOUNT = 5; + + /** + * Account unlocked event + */ + public static final int MSG_ACCOUNT_UNLOCKED = 6; + + /** + * Create an account + */ + public static final int MSG_CREATE_ACCOUNT = 7; + + /** + * Account created event + */ + public static final int MSG_ACCOUNT_CREATED = 8; + + /** + * Add an account + */ + public static final int MSG_ADD_ACCOUNT = 9; + + /** + * Account added event + */ + public static final int MSG_ACCOUNT_ADDED = 10; + +} diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java new file mode 100644 index 0000000000..638c4c3657 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -0,0 +1,227 @@ +package com.statusim.geth.service; + +import android.app.Service; +import android.content.Intent; +import android.os.*; +import android.support.annotation.Nullable; +import android.util.Log; + +import java.lang.ref.WeakReference; + +import com.github.ethereum.go_ethereum.Statusgo; + +import java.io.File; + +public class GethService extends Service { + + private static final String TAG = "GethService"; + + private static boolean isGethStarted = false; + private static boolean isGethInitialized = false; + private final Handler handler = new Handler(); + + static class IncomingHandler extends Handler { + + private final WeakReference service; + + IncomingHandler(GethService service) { + + this.service = new WeakReference(service); + } + + @Override + public void handleMessage(Message message) { + + GethService service = this.service.get(); + if (service != null) { + if (!service.handleMessage(message)) { + super.handleMessage(message); + } + } + } + } + + final Messenger serviceMessenger = new Messenger(new IncomingHandler(this)); + + + public static void signalEvent(String jsonEvent) { + System.out.println("\n\n\nIT WOOOOOORKS1111!!!!!!\n\n\n"); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return serviceMessenger.getBinder(); + } + + @Override + public void onCreate() { + super.onCreate(); + System.loadLibrary("statusgoraw"); + System.loadLibrary("statusgo"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + //TODO: stop geth + stopNode(null); + isGethStarted = false; + isGethInitialized = false; + Log.d(TAG, "Geth Service stopped !"); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return Service.START_STICKY; + } + + protected boolean handleMessage(Message message) { + switch (message.what) { + + case GethMessages.MSG_START_NODE: + startNode(message); + break; + + case GethMessages.MSG_STOP_NODE: + stopNode(message); + break; + + case GethMessages.MSG_CREATE_ACCOUNT: + createAccount(message); + break; + + case GethMessages.MSG_ADD_ACCOUNT: + addAccount(message); + break; + + case GethMessages.MSG_UNLOCK_ACCOUNT: + unlockAccount(message); + break; + + default: + return false; + } + + return true; + } + + protected void startNode(Message message) { + if (!isGethInitialized) { + isGethInitialized = true; + new StartTask(message).execute(); + } + } + + protected class StartTask extends AsyncTask { + + protected Message message; + + public StartTask(Message message) { + this.message = message; + } + + protected Void doInBackground(Void... args) { + startGeth(); + return null; + } + + protected void onPostExecute(Void results) { + onGethStarted(message); + } + } + + protected void onGethStarted(Message message) { + Log.d(TAG, "Geth Service started"); + isGethStarted = true; + + sendReply(message, GethMessages.MSG_NODE_STARTED, null); + } + + protected void startGeth() { + Log.d(TAG, "Starting background Geth Service"); + + File extStore = Environment.getExternalStorageDirectory(); + + final String dataFolder = extStore.exists() ? + extStore.getAbsolutePath() : + getApplicationInfo().dataDir; + + new Thread(new Runnable() { + public void run() { + + Statusgo.doStartNode(dataFolder); + } + }).start(); + } + + protected void stopNode(Message message) { + // TODO: stop node + + sendReply(message, GethMessages.MSG_NODE_STOPPED, null); + } + + protected void createAccount(Message message) { + Bundle data = message.getData(); + String password = data.getString("password"); + // TODO: remove second argument + String address = Statusgo.doCreateAccount(password, ""); + Log.d(TAG, "Created account: " + address); + + Bundle replyData = new Bundle(); + replyData.putString("address", address); + sendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData); + } + + protected void addAccount(Message message) { + Bundle data = message.getData(); + String privateKey = data.getString("privateKey"); + String password = data.getString("password"); + // TODO: add account + //String address = Statusgo.doAddAccount(privateKey, password); + String address = "added account address"; + Log.d(TAG, "Added account: " + address); + + Bundle replyData = new Bundle(); + replyData.putString("address", address); + sendReply(message, GethMessages.MSG_ACCOUNT_ADDED, replyData); + } + + protected void unlockAccount(Message message) { + Bundle data = message.getData(); + String address = data.getString("address"); + String password = data.getString("password"); + // TODO: remove third argument + String result = Statusgo.doUnlockAccount(address, password, 0); + Log.d(TAG, "Unlocked account: " + result); + + Bundle replyData = new Bundle(); + replyData.putString("result", result); + sendReply(message, GethMessages.MSG_ACCOUNT_UNLOCKED, replyData); + } + + public static boolean isRunning() { + return isGethInitialized; + } + + protected void sendReply(Message message, int replyIdMessage, Bundle replyData) { + + if (message == null) { + return; + } + Message replyMessage = Message.obtain(null, replyIdMessage, 0, 0, message.obj); + if (replyData == null) { + replyData = new Bundle(); + } + Bundle data = message.getData(); + String callbackIdentifier = data.getString("callbackIdentifier"); + replyData.putString("callbackIdentifier", callbackIdentifier); + replyMessage.setData(replyData); + + try { + message.replyTo.send(replyMessage); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message id: " + replyIdMessage, e); + } + } +} diff --git a/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java b/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java new file mode 100644 index 0000000000..1c70e92992 --- /dev/null +++ b/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java @@ -0,0 +1,149 @@ +package com.statusim.geth.service; + + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.*; + +import java.util.ArrayList; + +public class ServiceConnector { + + private static final String TAG = "ServiceConnector"; + + /** + * Incoming message handler. Calls to its binder are sequential! + */ + protected final IncomingHandler handler; + + /** + * Handler thread to avoid running on the main UI thread + */ + protected final HandlerThread handlerThread; + + /** Context of the activity from which this connector was launched */ + protected Context context; + + /** The class of the service we want to connect to */ + protected Class serviceClass; + + /** Flag indicating if the service is bound. */ + protected boolean isBound; + + /** Sends messages to the service. */ + protected Messenger serviceMessenger = null; + + /** Receives messages from the service. */ + protected Messenger clientMessenger = null; + + protected ArrayList handlers = new ArrayList<>(); + + /** Handles incoming messages from service. */ + class IncomingHandler extends Handler { + + public IncomingHandler(HandlerThread thread) { + + super(thread.getLooper()); + } + + @Override + public void handleMessage(Message message) { + + boolean isClaimed = false; + if (message.obj != null) { + String identifier = ((Bundle) message.obj).getString("identifier"); + if (identifier != null) { + + for (ConnectorHandler handler : handlers) { + if (identifier.equals(handler.getID())) { + isClaimed = handler.handleMessage(message); + } + } + } + } + if (!isClaimed) { + super.handleMessage(message); + } + } + } + + /** + * Class for interacting with the main interface of the service. + */ + protected ServiceConnection serviceConnection = new ServiceConnection() { + + public void onServiceConnected(ComponentName className, IBinder service) { + + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + serviceMessenger = new Messenger(service); + isBound = true; + for (ConnectorHandler handler: handlers) { + handler.onConnectorConnected(); + } + } + + public void onServiceDisconnected(ComponentName className) { + + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + serviceMessenger = null; + isBound = false; + for (ConnectorHandler handler: handlers) { + handler.onConnectorDisconnected(); + } + } + }; + + public ServiceConnector(Context context, Class serviceClass) { + + this.context = context; + this.serviceClass = serviceClass; + handlerThread = new HandlerThread("HandlerThread"); + handlerThread.start(); + handler = new IncomingHandler(handlerThread); + clientMessenger = new Messenger(handler); + } + + /** Bind to the service */ + public boolean bindService() { + + if (serviceConnection != null) { + Intent intent = new Intent(context, serviceClass); + context.getApplicationContext().startService(intent); + return context.getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + } else { + return false; + } + } + + /** Unbind from the service */ + public void unbindService() { + + if (isBound && serviceConnection != null) { + context.getApplicationContext().unbindService(serviceConnection); + isBound = false; +/* + Intent intent = new Intent(context, serviceClass); + context.getApplicationContext().stopService(intent); +*/ + } + } + + public void registerHandler(ConnectorHandler handler) { + + if (!handlers.contains(handler)) { + handlers.add(handler); + } + } + + public void removeHandler(ConnectorHandler handler) { + + handlers.remove(handler); + } +} diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index f931ce4e00..f180f463c2 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -4,6 +4,7 @@ [status-im.utils.utils :as u])) (def react (u/require "react-native")) +(def native-modules (.-NativeModules react)) (defn get-react-property [name] (aget react name)) @@ -78,3 +79,5 @@ (def dismiss-keyboard! (u/require "dismissKeyboard")) (def device-event-emitter (.-DeviceEventEmitter react)) (def orientation (u/require "react-native-orientation")) + +(def geth (.-Geth native-modules)) From e947bb0ea17394caa1facee04d43712882409845 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Wed, 29 Jun 2016 23:06:50 +0300 Subject: [PATCH 08/22] fix validation visual feedback and disabled grey tick --- src/status_im/components/animation.cljs | 3 + .../components/text_field/styles.cljs | 40 ++++ src/status_im/components/text_field/view.cljs | 189 ++++++++++++++++++ src/status_im/contacts/styles.cljs | 1 + src/status_im/contacts/views/new_contact.cljs | 71 +++---- src/status_im/qr_scanner/styles.cljs | 2 +- 6 files changed, 270 insertions(+), 36 deletions(-) create mode 100644 src/status_im/components/text_field/styles.cljs create mode 100644 src/status_im/components/text_field/view.cljs diff --git a/src/status_im/components/animation.cljs b/src/status_im/components/animation.cljs index a945d44f4c..20701b0d83 100644 --- a/src/status_im/components/animation.cljs +++ b/src/status_im/components/animation.cljs @@ -14,6 +14,9 @@ (defn anim-sequence [animations] (.sequence animated (clj->js animations))) +(defn parallel [animations] + (.parallel animated (clj->js animations))) + (defn anim-delay [duration] (.delay animated duration)) diff --git a/src/status_im/components/text_field/styles.cljs b/src/status_im/components/text_field/styles.cljs new file mode 100644 index 0000000000..582454b4d6 --- /dev/null +++ b/src/status_im/components/text_field/styles.cljs @@ -0,0 +1,40 @@ +(ns status-im.components.text-field.styles) + + +(def text-field-container + {:position :relative + :height 72 + :paddingTop 30 + :paddingBottom 7}) + +(def text-input + {:fontSize 16 + :height 34 + :lineHeight 34 + :paddingBottom 5 + :textAlignVertical :top}) + +(defn label [top font-size color] + {:position :absolute + :top top + :left 0 + :color color + :fontSize font-size + :backgroundColor :transparent}) + +(def label-float + {}) + +(defn underline-container [backgroundColor] + {:backgroundColor backgroundColor + :height 1 + :alignItems :center}) + +(defn underline [backgroundColor width] + {:backgroundColor backgroundColor + :height 1 + :width width}) + +(defn error-text [color] + {:color color + :fontSize 12}) diff --git a/src/status_im/components/text_field/view.cljs b/src/status_im/components/text_field/view.cljs new file mode 100644 index 0000000000..f3757ac1bc --- /dev/null +++ b/src/status_im/components/text_field/view.cljs @@ -0,0 +1,189 @@ +(ns status-im.components.text-field.view + (:require [clojure.string :as s] + [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [reagent.core :as r] + [status-im.components.react :refer [react + view + text + animated-text + animated-view + text-input + touchable-opacity]] + [status-im.components.text-field.styles :as st] + [status-im.i18n :refer [label]] + [status-im.components.animation :as anim] + [status-im.utils.logging :as log])) + + +(def config {:label-top 16 + :label-bottom 37 + :label-font-large 16 + :label-font-small 12 + :label-animation-duration 200}) + +(def default-props {:wrapperStyle {} + :inputStyle {} + :lineStyle {} + :labelColor "#838c93" + :lineColor "#0000001f" + :focusLineColor "#0000001f" + :errorColor "#d50000" + :onFocus #() + :onBlur #() + :onChangeText #() + :onChange #()}) + +(defn field-animation [{:keys [top to-top font-size to-font-size + line-width to-line-width]}] + (let [duration (:label-animation-duration config) + animation (anim/parallel [(anim/timing top {:toValue to-top + :duration duration}) + (anim/timing font-size {:toValue to-font-size + :duration duration}) + (anim/timing line-width {:toValue to-line-width + :duration duration})])] + (anim/start animation (fn [arg] + (when (.-finished arg) + (log/debug "Field animation finished")))))) + +; Invoked once before the component is mounted. The return value will be used +; as the initial value of this.state. +(defn get-initial-state [component] + {:has-focus false + :float-label? false + :label-top 0 + :label-font-size 0 + :line-width (anim/create-value 0) + :max-line-width 100}) + +; Invoked once, both on the client and server, immediately before the initial +; rendering occurs. If you call setState within this method, render() will see +; the updated state and will be executed only once despite the state change. +(defn component-will-mount [component] + (let [{:keys [value] :as props} (r/props component) + data {:label-top (anim/create-value (if (s/blank? value) + (:label-bottom config) + (:label-top config))) + :label-font-size (anim/create-value (if (s/blank? value) + (:label-font-large config) + (:label-font-small config))) + :float-label? (if (s/blank? value) false true)}] + (log/debug "component-will-mount") + (r/set-state component data))) + +; Invoked once, only on the client (not on the server), immediately after the +; initial rendering occurs. At this point in the lifecycle, you can access any +; refs to your children (e.g., to access the underlying DOM representation). +; The componentDidMount() method of child components is invoked before that of +; parent components. +(defn component-did-mount [component] + (let [props (r/props component)] + (log/debug "component-did-mount:"))) + +; Invoked when a component is receiving new props. This method is not called for +; the initial render. Use this as an opportunity to react to a prop transition +; before render() is called by updating the state using this.setState(). +; The old props can be accessed via this.props. Calling this.setState() within +; this function will not trigger an additional render. +(defn component-will-receive-props [component new-props] + (log/debug "component-will-receive-props: new-props=" new-props)) + +; Invoked before rendering when new props or state are being received. This method +; is not called for the initial render or when forceUpdate is used. Use this as +; an opportunity to return false when you're certain that the transition to the +; new props and state will not require a component update. +; If shouldComponentUpdate returns false, then render() will be completely skipped +; until the next state change. In addition, componentWillUpdate and +; componentDidUpdate will not be called. +(defn should-component-update [component next-props next-state] + (log/debug "should-component-update: " next-props next-state) + true) + +; Invoked immediately before rendering when new props or state are being received. +; This method is not called for the initial render. Use this as an opportunity +; to perform preparation before an update occurs. +(defn component-will-update [component next-props next-state] + (log/debug "component-will-update: " next-props next-state)) + +; Invoked immediately after the component's updates are flushed to the DOM. +; This method is not called for the initial render. Use this as an opportunity +; to operate on the DOM when the component has been updated. +(defn component-did-update [component prev-props prev-state] + (log/debug "component-did-update: " prev-props prev-state)) + +(defn on-focus [{:keys [component animation onFocus]}] + (do + (log/debug "input focused") + (r/set-state component {:has-focus true + :float-label? true}) + (field-animation animation) + (when onFocus (onFocus)))) + +(defn on-blur [{:keys [component value animation onBlur]}] + (do + (log/debug "Input blurred") + (r/set-state component {:has-focus false + :float-label? (if (s/blank? value) false true)}) + (when (s/blank? value) + (field-animation animation)) + (when onBlur (onBlur)))) + +(defn get-width [event] + (.-width (.-layout (.-nativeEvent event)))) + +(defn reagent-render [data children] + (let [component (r/current-component) + {:keys [has-focus + float-label? + label-top + label-font-size + line-width + max-line-width] :as state} (r/state component) + {:keys [wrapperStyle inputStyle lineColor focusLineColor + labelColor errorColor error label value onFocus onBlur + onChangeText onChange] :as props} (merge default-props (r/props component)) + lineColor (if error errorColor lineColor) + focusLineColor (if error errorColor focusLineColor) + labelColor (if (and error (not float-label?)) errorColor labelColor) + label (if error (str label " *") label)] + (log/debug "reagent-render: " data state) + [view (merge st/text-field-container wrapperStyle) + [animated-text {:style (st/label label-top label-font-size labelColor)} label] + [text-input {:style (merge st/text-input inputStyle) + :placeholder "" + :onFocus #(on-focus {:component component + :animation {:top label-top + :to-top (:label-top config) + :font-size label-font-size + :to-font-size (:label-font-small config) + :line-width line-width + :to-line-width max-line-width} + :onFocus onFocus}) + :onBlur #(on-blur {:component component + :value value + :animation {:top label-top + :to-top (:label-bottom config) + :font-size label-font-size + :to-font-size (:label-font-large config) + :line-width line-width + :to-line-width 0} + :onBlur onBlur}) + :onChangeText #(onChangeText %) + :onChange #(onChange %)} value] + [view {:style (st/underline-container lineColor) + :onLayout #(r/set-state component {:max-line-width (get-width %)})} + [animated-view {:style (st/underline focusLineColor line-width)}]] + [text {:style (st/error-text errorColor)} error]])) + +(defn text-field [data children] + (let [component-data {:get-initial-state get-initial-state + :component-will-mount component-will-mount + :component-did-mount component-did-mount + :component-will-receive-props component-will-receive-props + :should-component-update should-component-update + :component-will-update component-will-update + :component-did-update component-did-update + :display-name "text-field" + :reagent-render reagent-render}] + (log/debug "Creating text-field component: " data) + (r/create-class component-data))) \ No newline at end of file diff --git a/src/status_im/contacts/styles.cljs b/src/status_im/contacts/styles.cljs index 7e9ed688c6..64cb693300 100644 --- a/src/status_im/contacts/styles.cljs +++ b/src/status_im/contacts/styles.cljs @@ -173,6 +173,7 @@ (def address-explication-container {:flex 1 + :margin-top 30 :paddingLeft 16 :paddingRight 16}) diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index ee0ae60929..c0cd517fb5 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -8,6 +8,7 @@ image linear-gradient touchable-highlight]] + [status-im.components.text-field.view :refer [text-field]] [status-im.utils.identicon :refer [identicon]] [status-im.components.toolbar :refer [toolbar]] [status-im.components.styles :refer [color-purple @@ -28,7 +29,6 @@ [status-im.contacts.styles :as st])) - (def toolbar-title [view toolbar-title-container [text {:style toolbar-title-text} @@ -36,42 +36,43 @@ (defview contact-name-input [name] [] - [text-input - {:underlineColorAndroid "#0000001f" - :placeholderTextColor "#838c93de" - :style form-text-input - :autoFocus true - :placeholder (label :t/name) - :onChangeText #(dispatch [:set-in [:new-contact :name] %])} - name]) + [text-field + {:error (if (str/blank? name) "" nil) + :value name + :label (label :t/name) + :onChangeText #(dispatch [:set-in [:new-contact :name] %])}]) (defview contact-whisper-id-input [whisper-identity] - [view button-input-container - [text-input - {:underlineColorAndroid "#0000001f" - :placeholderTextColor "#838c93de" - :style (merge form-text-input button-input) - :autoFocus true - :placeholder (label :t/address) - :onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])} - whisper-identity] - [scan-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]]) + [] + (let [error (if (str/blank? whisper-identity) "" nil) + error (if (s/valid? ::v/whisper-identity whisper-identity) + error + "Please enter a valid address or scan a QR code")] + [view button-input-container + [text-field + {:error error + :value whisper-identity + :wrapperStyle (merge button-input) + :label (label :t/address) + :onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])}] + [scan-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]])) (defview new-contact [] [{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]] - [view st/contact-form-container - [toolbar {:background-color :white - :nav-action {:image {:source {:uri :icon_back} - :style icon-back} - :handler #(dispatch [:navigate-back])} - :custom-content toolbar-title - :action {:image {:source {:uri (if (s/valid? ::v/contact new-contact) - :icon_ok_blue - :icon_ok_disabled)} - :style icon-search} - :handler #(dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)])}}] - [view st/form-container - [contact-whisper-id-input whisper-identity] - [contact-name-input name]] - [view st/address-explication-container - [text {:style st/address-explication} (label :t/address-explication)]]]) + (let [valid-contact? (s/valid? ::v/contact new-contact)] + [view st/contact-form-container + [toolbar {:background-color :white + :nav-action {:image {:source {:uri :icon_back} + :style icon-back} + :handler #(dispatch [:navigate-back])} + :custom-content toolbar-title + :action {:image {:source {:uri (if valid-contact? + :icon_ok_blue + :icon_ok_disabled)} + :style icon-search} + :handler #(when valid-contact? dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)])}}] + [view st/form-container + [contact-name-input name] + [contact-whisper-id-input whisper-identity]] + [view st/address-explication-container + [text {:style st/address-explication} (label :t/address-explication)]]])) diff --git a/src/status_im/qr_scanner/styles.cljs b/src/status_im/qr_scanner/styles.cljs index 65838b9ec6..057bf186c8 100644 --- a/src/status_im/qr_scanner/styles.cljs +++ b/src/status_im/qr_scanner/styles.cljs @@ -78,7 +78,7 @@ (def scan-button {:position :absolute - :top 5 + :bottom 0 :right 16 :flex 1 :height 50 From 31a8824d34e46a5eec2abfb61f1c6c44ee34b89b Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Wed, 29 Jun 2016 23:14:06 +0300 Subject: [PATCH 09/22] fix typo --- src/status_im/contacts/views/new_contact.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index c0cd517fb5..20a05ee059 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -70,7 +70,7 @@ :icon_ok_blue :icon_ok_disabled)} :style icon-search} - :handler #(when valid-contact? dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)])}}] + :handler #(when valid-contact? (dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)]))}}] [view st/form-container [contact-name-input name] [contact-whisper-id-input whisper-identity]] From ec9cfe8f8c32d73f04a3cb37a788b8f156f6b212 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 13:37:36 +0300 Subject: [PATCH 10/22] changed add account flow to use new binding system --- android/app/build.gradle | 4 +- android/app/src/main/AndroidManifest.xml | 3 +- .../com/statusim/geth/module/GethModule.java | 24 +++-- .../statusim/geth/service/GethConnector.java | 11 ++- .../statusim/geth/service/GethMessages.java | 4 +- .../statusim/geth/service/GethService.java | 88 ++++++++++++------- .../geth/service/ServiceConnector.java | 14 +-- src/status_im/android/core.cljs | 4 +- src/status_im/chat/handlers.cljs | 8 ++ src/status_im/handlers.cljs | 6 ++ src/status_im/protocol/handlers.cljs | 4 +- 11 files changed, 113 insertions(+), 57 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 301a07656c..c60d4eb2d1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -132,8 +132,8 @@ dependencies { compile project(':ReactNativeAndroidSmsListener') compile project(':react-native-camera') compile project(':react-native-orientation') -// compile(name:'geth', ext:'aar') - compile(group: 'status-im', name: 'status-go', version: '0.1.0-test-callback', ext: 'aar') + compile(name:'statusgo-android-16', ext:'aar') + //compile(group: 'status-im', name: 'status-go', version: '0.1.0-test-callback', ext: 'aar') compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"]) } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a7b7a31725..05008651d2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -25,8 +25,7 @@ + android:exported="true"/> diff --git a/android/app/src/main/java/com/statusim/geth/module/GethModule.java b/android/app/src/main/java/com/statusim/geth/module/GethModule.java index a4bb3e12d0..058ab03667 100644 --- a/android/app/src/main/java/com/statusim/geth/module/GethModule.java +++ b/android/app/src/main/java/com/statusim/geth/module/GethModule.java @@ -8,12 +8,15 @@ import com.statusim.geth.service.ConnectorHandler; import com.statusim.geth.service.GethConnector; import com.statusim.geth.service.GethMessages; import com.statusim.geth.service.GethService; +import android.util.Log; import java.util.HashMap; import java.util.UUID; public class GethModule extends ReactContextBaseJavaModule implements LifecycleEventListener, ConnectorHandler { + private static final String TAG = "GethModule"; + protected GethConnector geth = null; protected String handlerIdentifier = createIdentifier(); @@ -81,15 +84,20 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE @Override public boolean handleMessage(Message message) { + Log.d(TAG, "Received message: " + message.toString()); boolean isClaimed = true; Bundle data = message.getData(); String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER); + Log.d(TAG, "callback identifier: " + callbackIdentifier); Callback callback = null; switch (message.what) { case GethMessages.MSG_NODE_STARTED: + Log.d(TAG, "handle startNodeCallbacks size: " + startNodeCallbacks.size()); callback = startNodeCallbacks.remove(callbackIdentifier); if (callback != null) { - callback.invoke(null); + callback.invoke(true); + } else { + Log.d(TAG, "Could not find callback: " + callbackIdentifier); } break; case GethMessages.MSG_NODE_STOPPED: @@ -97,7 +105,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE case GethMessages.MSG_ACCOUNT_CREATED: callback = createAccountCallbacks.remove(callbackIdentifier); if (callback != null) { - callback.invoke(null, "{ \"address\": \"" + data.getString("address") + "\"}"); + callback.invoke(data.getString("data")); } break; case GethMessages.MSG_ACCOUNT_ADDED: @@ -106,7 +114,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE callback.invoke(null, "{ \"address\": \"" + data.getString("address") + "\"}"); } break; - case GethMessages.MSG_ACCOUNT_UNLOCKED: + case GethMessages.MSG_LOGGED_IN: callback = unlockAccountCallbacks.remove(callbackIdentifier); if (callback != null) { callback.invoke(null, "{ \"result\": \"" + data.getString("result") + "\"}"); @@ -135,13 +143,15 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE } String callbackIdentifier = createIdentifier(); + Log.d(TAG, "Created callback identifier: " + callbackIdentifier); startNodeCallbacks.put(callbackIdentifier, callback); + Log.d(TAG, "startNodeCallbacks size: " + startNodeCallbacks.size()); geth.startNode(callbackIdentifier); } @ReactMethod - public void unlockAccount(String address, String password, Callback callback) { + public void login(String address, String password, Callback callback) { Activity currentActivity = getCurrentActivity(); @@ -158,11 +168,11 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE String callbackIdentifier = createIdentifier(); unlockAccountCallbacks.put(callbackIdentifier, callback); - geth.unlockAccount(callbackIdentifier, address, password); + geth.login(callbackIdentifier, address, password); } @ReactMethod - public void createAccount(Callback callback) { + public void createAccount(String password, Callback callback) { Activity currentActivity = getCurrentActivity(); @@ -179,7 +189,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE String callbackIdentifier = createIdentifier(); createAccountCallbacks.put(callbackIdentifier, callback); - geth.createAccount(callbackIdentifier); + geth.createAccount(callbackIdentifier, password); } @ReactMethod diff --git a/android/app/src/main/java/com/statusim/geth/service/GethConnector.java b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java index 73a1fd74d4..7083dff2d5 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethConnector.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java @@ -42,13 +42,13 @@ public class GethConnector extends ServiceConnector { } } - public void unlockAccount(String callbackIdentifier, String address, String password) { + public void login(String callbackIdentifier, String address, String password) { if (checkBound()) { Bundle data = new Bundle(); data.putString("address", address); data.putString("password", password); - Message msg = createMessage(callbackIdentifier, GethMessages.MSG_UNLOCK_ACCOUNT, data); + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_LOGIN, data); try { serviceMessenger.send(msg); } catch (RemoteException e) { @@ -57,10 +57,12 @@ public class GethConnector extends ServiceConnector { } } - public void createAccount(String callbackIdentifier) { + public void createAccount(String callbackIdentifier, String password) { if (checkBound()) { - Message msg = createMessage(callbackIdentifier, GethMessages.MSG_CREATE_ACCOUNT, null); + Bundle data = new Bundle(); + data.putString("password", password); + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_CREATE_ACCOUNT, data); try { serviceMessenger.send(msg); } catch (RemoteException e) { @@ -95,6 +97,7 @@ public class GethConnector extends ServiceConnector { protected Message createMessage(String callbackIdentifier, int idMessage, Bundle data) { + Log.d(TAG, "Client messenger: " + clientMessenger.toString()); Message msg = Message.obtain(null, idMessage, 0, 0); msg.replyTo = clientMessenger; if (data == null) { diff --git a/android/app/src/main/java/com/statusim/geth/service/GethMessages.java b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java index 080725bca2..f6c3e24737 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethMessages.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java @@ -26,12 +26,12 @@ public class GethMessages { /** * Unlock an account */ - public static final int MSG_UNLOCK_ACCOUNT = 5; + public static final int MSG_LOGIN = 5; /** * Account unlocked event */ - public static final int MSG_ACCOUNT_UNLOCKED = 6; + public static final int MSG_LOGGED_IN = 6; /** * Create an account diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java index 638c4c3657..8a62fcc55f 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethService.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -20,6 +20,8 @@ public class GethService extends Service { private static boolean isGethInitialized = false; private final Handler handler = new Handler(); + private static String dataFolder; + static class IncomingHandler extends Handler { private final WeakReference service; @@ -80,6 +82,7 @@ public class GethService extends Service { switch (message.what) { case GethMessages.MSG_START_NODE: + Log.d(TAG, "Received start node message." + message.toString()); startNode(message); break; @@ -95,8 +98,8 @@ public class GethService extends Service { addAccount(message); break; - case GethMessages.MSG_UNLOCK_ACCOUNT: - unlockAccount(message); + case GethMessages.MSG_LOGIN: + login(message); break; default: @@ -109,16 +112,22 @@ public class GethService extends Service { protected void startNode(Message message) { if (!isGethInitialized) { isGethInitialized = true; - new StartTask(message).execute(); + Log.d(TAG, "Client messenger1: " + message.replyTo.toString()); + Bundle data = message.getData(); + String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER); + Log.d(TAG, "Callback identifier: " + callbackIdentifier); + new StartTask(message.replyTo, callbackIdentifier).execute(); } } protected class StartTask extends AsyncTask { - protected Message message; + protected String callbackIdentifier; + protected Messenger messenger; - public StartTask(Message message) { - this.message = message; + public StartTask(Messenger messenger, String callbackIdentifier) { + this.messenger = messenger; + this.callbackIdentifier = callbackIdentifier; } protected Void doInBackground(Void... args) { @@ -127,30 +136,41 @@ public class GethService extends Service { } protected void onPostExecute(Void results) { - onGethStarted(message); + onGethStarted(messenger, callbackIdentifier); } } - protected void onGethStarted(Message message) { + protected void onGethStarted(Messenger messenger, String callbackIdentifier) { Log.d(TAG, "Geth Service started"); isGethStarted = true; - - sendReply(message, GethMessages.MSG_NODE_STARTED, null); + Message replyMessage = Message.obtain(null, GethMessages.MSG_NODE_STARTED, 0, 0, null); + Bundle replyData = new Bundle(); + Log.d(TAG, "Callback identifier: " + callbackIdentifier); + replyData.putString(GethConnector.CALLBACK_IDENTIFIER, callbackIdentifier); + replyMessage.setData(replyData); + sendReply(messenger, replyMessage); } protected void startGeth() { - Log.d(TAG, "Starting background Geth Service"); + File extStore = Environment.getExternalStorageDirectory(); - final String dataFolder = extStore.exists() ? - extStore.getAbsolutePath() : - getApplicationInfo().dataDir; + dataFolder = extStore.exists() ? + extStore.getAbsolutePath() + "/ethereum" : + getApplicationInfo().dataDir + "/ethereum"; + Log.d(TAG, "Starting background Geth Service in folder: " + dataFolder); + try { + final File newFile = new File(dataFolder); + newFile.mkdir(); + } catch (Exception e) { + Log.e(TAG, "error making folder: " + dataFolder, e); + } new Thread(new Runnable() { public void run() { - Statusgo.doStartNode(dataFolder); + Statusgo.StartNode(dataFolder); } }).start(); } @@ -158,19 +178,20 @@ public class GethService extends Service { protected void stopNode(Message message) { // TODO: stop node - sendReply(message, GethMessages.MSG_NODE_STOPPED, null); + createAndSendReply(message, GethMessages.MSG_NODE_STOPPED, null); } protected void createAccount(Message message) { Bundle data = message.getData(); String password = data.getString("password"); // TODO: remove second argument - String address = Statusgo.doCreateAccount(password, ""); - Log.d(TAG, "Created account: " + address); + Log.d(TAG, "Creating account: " + password + " - " + dataFolder); + String jsonData = Statusgo.CreateAccount(password, dataFolder); + Log.d(TAG, "Created account: " + jsonData); Bundle replyData = new Bundle(); - replyData.putString("address", address); - sendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData); + replyData.putString("data", jsonData); + createAndSendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData); } protected void addAccount(Message message) { @@ -184,27 +205,27 @@ public class GethService extends Service { Bundle replyData = new Bundle(); replyData.putString("address", address); - sendReply(message, GethMessages.MSG_ACCOUNT_ADDED, replyData); + createAndSendReply(message, GethMessages.MSG_ACCOUNT_ADDED, replyData); } - protected void unlockAccount(Message message) { + protected void login(Message message) { Bundle data = message.getData(); String address = data.getString("address"); String password = data.getString("password"); // TODO: remove third argument - String result = Statusgo.doUnlockAccount(address, password, 0); + String result = Statusgo.Login(address, password); Log.d(TAG, "Unlocked account: " + result); Bundle replyData = new Bundle(); replyData.putString("result", result); - sendReply(message, GethMessages.MSG_ACCOUNT_UNLOCKED, replyData); + createAndSendReply(message, GethMessages.MSG_LOGGED_IN, replyData); } public static boolean isRunning() { return isGethInitialized; } - protected void sendReply(Message message, int replyIdMessage, Bundle replyData) { + protected void createAndSendReply(Message message, int replyIdMessage, Bundle replyData) { if (message == null) { return; @@ -214,14 +235,21 @@ public class GethService extends Service { replyData = new Bundle(); } Bundle data = message.getData(); - String callbackIdentifier = data.getString("callbackIdentifier"); - replyData.putString("callbackIdentifier", callbackIdentifier); + String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER); + Log.d(TAG, "Callback identifier: " + callbackIdentifier); + replyData.putString(GethConnector.CALLBACK_IDENTIFIER, callbackIdentifier); replyMessage.setData(replyData); + sendReply(message.replyTo, replyMessage); + } + + protected void sendReply(Messenger messenger, Message message) { try { - message.replyTo.send(replyMessage); - } catch (RemoteException e) { - Log.e(TAG, "Exception sending message id: " + replyIdMessage, e); + messenger.send(message); + + } catch (Exception e) { + + Log.e(TAG, "Exception sending message id: " + message.what, e); } } } diff --git a/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java b/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java index 1c70e92992..f20e1fcf66 100644 --- a/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java +++ b/android/app/src/main/java/com/statusim/geth/service/ServiceConnector.java @@ -52,17 +52,17 @@ public class ServiceConnector { public void handleMessage(Message message) { boolean isClaimed = false; - if (message.obj != null) { - String identifier = ((Bundle) message.obj).getString("identifier"); - if (identifier != null) { + //if (message.obj != null) { + // String identifier = ((Bundle) message.obj).getString("identifier"); + //if (identifier != null) { for (ConnectorHandler handler : handlers) { - if (identifier.equals(handler.getID())) { + // if (identifier.equals(handler.getID())) { isClaimed = handler.handleMessage(message); - } + // } } - } - } + // } + //} if (!isClaimed) { super.handleMessage(message); } diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index 38b60a5b77..db4c13c2e0 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -78,8 +78,10 @@ (defn init [] (dispatch-sync [:initialize-db]) (dispatch [:initialize-crypt]) + (dispatch [:initialize-geth]) (dispatch [:initialize-chats]) - (dispatch [:initialize-protocol]) + ;protocol must be initialized after user enters password and we create account + ;(dispatch [:initialize-protocol]) (dispatch [:load-user-phone-number]) (dispatch [:load-contacts]) ;; load commands from remote server (todo: uncomment) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index ef8ae2d24f..1f05a181bd 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -19,6 +19,9 @@ [status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.datetime :as time] + [status-im.components.react :refer [geth]] + [status-im.utils.logging :as log] + [status-im.utils.types :refer [json->clj]] [status-im.chat.handlers.animation :refer [update-response-height get-response-height]])) @@ -259,6 +262,11 @@ (register-handler :save-password (fn [db [_ password]] + (.createAccount geth password (fn [result] + (let [data (json->clj result) + public-key (:pubkey data)] + (log/debug "Created account: " result) + (when (not (str/blank? public-key)) (dispatch [:initialize-protocol public-key]))))) (sign-up-service/save-password password) (assoc db :password-saved true))) diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index ebf835a9c3..fdfc7f64ff 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -10,6 +10,7 @@ [status-im.utils.logging :as log] [status-im.utils.crypt :refer [gen-random-bytes]] [status-im.utils.handlers :as u] + [status-im.components.react :refer [geth]] status-im.chat.handlers status-im.group-settings.handlers status-im.navigation.handlers @@ -74,6 +75,11 @@ (.toBits (.. js/ecc -sjcl -codec -hex)) (.addEntropy (.. js/ecc -sjcl -random))) (dispatch [:crypt-initialized])))))))) +(register-handler :initialize-geth + (u/side-effect! + (fn [_ _] + (log/debug "Starting node") + (.startNode geth (fn [result] (log/debug "Started Node: " result)))))) (register-handler :crypt-initialized (u/side-effect! diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index a9b94e5541..14690d6f47 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -17,8 +17,8 @@ (register-handler :initialize-protocol (u/side-effect! - (fn [db [_]] - (init-protocol (make-handler db))))) + (fn [db [_ public-key]] + (init-protocol public-key (make-handler db))))) (register-handler :protocol-initialized (fn [db [_ identity]] From 8a75e1eea79515522395d27bcd51f7e992720d37 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 13:51:06 +0300 Subject: [PATCH 11/22] updated status-lib dependency --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 4007f3100d..a407735efa 100644 --- a/project.clj +++ b/project.clj @@ -10,7 +10,7 @@ [prismatic/schema "1.0.4"] ^{:voom {:repo "git@github.com:status-im/status-lib.git" :branch "master"}} - [status-im/protocol "0.1.1-20160525_083359-g53ab2c2"] + [status-im/protocol "0.1.1-20160630_104454-gd663db0"] [natal-shell "0.1.6"] [com.andrewmcveigh/cljs-time "0.4.0"]] :plugins [[lein-cljsbuild "1.1.1"] From c878fba6f13f458d4918ea02cab19e03f9d0b3fe Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 18:06:05 +0300 Subject: [PATCH 12/22] created new accounts realm object and fixed new create account flow --- .../statusim/geth/service/GethService.java | 2 +- src/status_im/accounts/handlers.cljs | 32 +++++++++++++++++++ src/status_im/chat/handlers.cljs | 6 +--- src/status_im/db.cljs | 1 + src/status_im/handlers.cljs | 7 ++-- src/status_im/models/accounts.cljs | 22 +++++++++++++ src/status_im/persistence/realm.cljs | 4 +++ 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/status_im/accounts/handlers.cljs create mode 100644 src/status_im/models/accounts.cljs diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java index 8a62fcc55f..c0af872fe6 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethService.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -186,7 +186,7 @@ public class GethService extends Service { String password = data.getString("password"); // TODO: remove second argument Log.d(TAG, "Creating account: " + password + " - " + dataFolder); - String jsonData = Statusgo.CreateAccount(password, dataFolder); + String jsonData = Statusgo.CreateAccount(password, dataFolder + "/keystore"); Log.d(TAG, "Created account: " + jsonData); Bundle replyData = new Bundle(); diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs new file mode 100644 index 0000000000..e70b48e1d9 --- /dev/null +++ b/src/status_im/accounts/handlers.cljs @@ -0,0 +1,32 @@ +(ns status-im.accounts.handlers + (:require [status-im.models.accounts :as accounts] + [re-frame.core :refer [register-handler after dispatch debug]] + [status-im.utils.logging :as log] + [status-im.components.react :refer [geth]] + [status-im.utils.types :refer [json->clj]] + [clojure.string :as str])) + + +(defn save-account [_ [_ account]] + (accounts/save-accounts [account])) + +(register-handler :add-account + (-> (fn [db [_ {:keys [address] :as account}]] + (update db :accounts assoc address account)) + ((after save-account)))) + +(defn account-created [result] + (let [data (json->clj result) + public-key (:pubkey data) + address (:address data)] + (log/debug "Created account: " result) + (when (not (str/blank? public-key)) + (do + (dispatch [:initialize-protocol public-key]) + (dispatch [:add-account {:address address + :public-key public-key}]))))) + +(register-handler :create-account + (-> (fn [db [_ password]] + (.createAccount geth password (fn [result] (account-created result))) + db))) \ No newline at end of file diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 1f05a181bd..803e09095e 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -262,11 +262,7 @@ (register-handler :save-password (fn [db [_ password]] - (.createAccount geth password (fn [result] - (let [data (json->clj result) - public-key (:pubkey data)] - (log/debug "Created account: " result) - (when (not (str/blank? public-key)) (dispatch [:initialize-protocol public-key]))))) + (dispatch [:create-account password]) (sign-up-service/save-password password) (assoc db :password-saved true))) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 7c07c77636..963e27f342 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -11,6 +11,7 @@ ;; initial state of app-db (def app-db {:identity-password "replace-me-with-user-entered-password" :identity "me" + :accounts {} :contacts [] :contacts-ids #{} :selected-contacts #{} diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index fdfc7f64ff..f98862ff93 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -19,6 +19,7 @@ status-im.new-group.handlers status-im.participants.handlers status-im.qr-scanner.handlers + status-im.accounts.handlers status-im.protocol.handlers)) ;; -- Middleware ------------------------------------------------------------ @@ -77,9 +78,9 @@ (dispatch [:crypt-initialized])))))))) (register-handler :initialize-geth (u/side-effect! - (fn [_ _] - (log/debug "Starting node") - (.startNode geth (fn [result] (log/debug "Started Node: " result)))))) + (fn [_ _] + (log/debug "Starting node") + (.startNode geth (fn [result] (log/debug "Started Node: " result)))))) (register-handler :crypt-initialized (u/side-effect! diff --git a/src/status_im/models/accounts.cljs b/src/status_im/models/accounts.cljs new file mode 100644 index 0000000000..a9f333c3c7 --- /dev/null +++ b/src/status_im/models/accounts.cljs @@ -0,0 +1,22 @@ +(ns status-im.models.accounts + (:require [status-im.persistence.realm :as r])) + +(defn get-accounts [] + (-> (r/get-all :accounts) + r/collection->map)) + +(defn create-account [{:keys [address public-key] :as account}] + (->> account + (r/create :accounts))) + +(defn save-accounts [accounts] + (r/write #(mapv create-account accounts))) + + +;;;;;;;;;;;;;;;;;;;;---------------------------------------------- + +(defn accounts-list [] + (r/get-all :accounts)) + +(defn account-by-address [address] + (r/single-cljs (r/get-by-field :accounts :address address))) diff --git a/src/status_im/persistence/realm.cljs b/src/status_im/persistence/realm.cljs index 5d304828fe..941cd0f1b0 100644 --- a/src/status_im/persistence/realm.cljs +++ b/src/status_im/persistence/realm.cljs @@ -15,6 +15,10 @@ :optional true} :photo-path {:type "string" :optinal true}}} + {:name :accounts + :primaryKey :address + :properties {:address "string" + :public-key "string"}} {:name :kv-store :primaryKey :key :properties {:key "string" From 763aac2141bd13dd108563f353d0e2f4310c740f Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 19:05:28 +0300 Subject: [PATCH 13/22] fix signup process --- project.clj | 2 +- src/status_im/accounts/handlers.cljs | 9 +++++---- src/status_im/handlers/server.cljs | 19 +++++++++++-------- src/status_im/models/protocol.cljs | 12 +++++------- src/status_im/profile/screen.cljs | 2 +- src/status_im/protocol/handlers.cljs | 4 ++-- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/project.clj b/project.clj index a407735efa..1f1b0c77d2 100644 --- a/project.clj +++ b/project.clj @@ -10,7 +10,7 @@ [prismatic/schema "1.0.4"] ^{:voom {:repo "git@github.com:status-im/status-lib.git" :branch "master"}} - [status-im/protocol "0.1.1-20160630_104454-gd663db0"] + [status-im/protocol "0.1.1-20160630_153846-gbf92f5f"] [natal-shell "0.1.6"] [com.andrewmcveigh/cljs-time "0.4.0"]] :plugins [[lein-cljsbuild "1.1.1"] diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs index e70b48e1d9..8ea9cf3e60 100644 --- a/src/status_im/accounts/handlers.cljs +++ b/src/status_im/accounts/handlers.cljs @@ -18,13 +18,14 @@ (defn account-created [result] (let [data (json->clj result) public-key (:pubkey data) - address (:address data)] + address (:address data) + account {:public-key public-key + :address address}] (log/debug "Created account: " result) (when (not (str/blank? public-key)) (do - (dispatch [:initialize-protocol public-key]) - (dispatch [:add-account {:address address - :public-key public-key}]))))) + (dispatch [:initialize-protocol account]) + (dispatch [:add-account account]))))) (register-handler :create-account (-> (fn [db [_ password]] diff --git a/src/status_im/handlers/server.cljs b/src/status_im/handlers/server.cljs index 5d9674c1d7..565f6f90c0 100644 --- a/src/status_im/handlers/server.cljs +++ b/src/status_im/handlers/server.cljs @@ -1,17 +1,20 @@ (ns status-im.handlers.server (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] - [status-im.utils.utils :refer [log on-error http-post]] + [status-im.utils.utils :refer [on-error http-post]] [status-im.utils.logging :as log])) (defn sign-up [db phone-number handler] - ;(user-data/save-phone-number phone-number) - (http-post "sign-up" {:phone-number phone-number - :whisper-identity (get-in db [:user-identity :public])} - (fn [body] - (log body) - (handler))) - db) + (let [{:keys [public-key address] :as account} (get-in db [:user-identity])] + ;(user-data/save-phone-number phone-number) + (log/debug "signing up with public-key" public-key "and phone " phone-number) + (http-post "sign-up" {:phone-number phone-number + :whisper-identity public-key + :address address} + (fn [body] + (log/debug body) + (handler))) + db)) (defn sign-up-confirm [confirmation-code handler] diff --git a/src/status_im/models/protocol.cljs b/src/status_im/models/protocol.cljs index abe2ad110f..441d433688 100644 --- a/src/status_im/models/protocol.cljs +++ b/src/status_im/models/protocol.cljs @@ -12,13 +12,11 @@ (assoc-in db db/protocol-initialized-path initialized?)) (defn update-identity [db identity] - (let [password (:identity-password db) - encrypted (password-encrypt password (to-edn-string identity))] - (s/put kv/kv-store :identity encrypted) + (let [identity-string (to-edn-string identity)] + (s/put kv/kv-store :identity identity-string) (assoc db :user-identity identity))) (defn stored-identity [db] - (let [encrypted (s/get kv/kv-store :identity) - password (:identity-password db)] - (when encrypted - (read-string (password-decrypt password encrypted))))) + (let [identity (s/get kv/kv-store :identity)] + (when identity + (read-string identity)))) diff --git a/src/status_im/profile/screen.cljs b/src/status_im/profile/screen.cljs index ffff2d2e47..09f2fc3d07 100644 --- a/src/status_im/profile/screen.cljs +++ b/src/status_im/profile/screen.cljs @@ -67,7 +67,7 @@ phone-number [:get :phone-number] email [:get :email] status [:get :status] - identity [:get-in [:user-identity :public]]] + identity [:get-in [:user-identity :public-key]]] [scroll-view {:style st/profile} [touchable-highlight {:style st/back-btn-touchable :on-press #(dispatch [:navigate-back])} diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index 14690d6f47..a5010bb56c 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -17,8 +17,8 @@ (register-handler :initialize-protocol (u/side-effect! - (fn [db [_ public-key]] - (init-protocol public-key (make-handler db))))) + (fn [db [_ account]] + (init-protocol account (make-handler db))))) (register-handler :protocol-initialized (fn [db [_ identity]] From 06e0332f4fc36d269e6a9b688db3129d3c7529c3 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 19:14:03 +0300 Subject: [PATCH 14/22] missed conflict --- src/status_im/handlers.cljs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index f9280d8a0f..cd3ce76f44 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -7,12 +7,8 @@ [status-im.protocol.state.storage :as storage] [status-im.utils.logging :as log] [status-im.utils.crypt :refer [gen-random-bytes]] -<<<<<<< HEAD - [status-im.utils.handlers :as u] [status-im.components.react :refer [geth]] -======= [status-im.utils.handlers :refer [register-handler] :as u] ->>>>>>> origin/develop status-im.chat.handlers status-im.chat.handlers.animation status-im.group-settings.handlers From df229035e72723fff5266a0a5cec5128ca424c85 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 20:28:51 +0300 Subject: [PATCH 15/22] login to account after creating it to enable it in whisper --- .../java/com/statusim/geth/service/GethService.java | 2 +- src/status_im/accounts/handlers.cljs | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java index c0af872fe6..295cacd2c1 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethService.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -8,7 +8,7 @@ import android.util.Log; import java.lang.ref.WeakReference; -import com.github.ethereum.go_ethereum.Statusgo; +import com.github.status_im.status_go.Statusgo; import java.io.File; diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs index 8ea9cf3e60..cb64243e8f 100644 --- a/src/status_im/accounts/handlers.cljs +++ b/src/status_im/accounts/handlers.cljs @@ -15,7 +15,7 @@ (update db :accounts assoc address account)) ((after save-account)))) -(defn account-created [result] +(defn account-created [result password] (let [data (json->clj result) public-key (:pubkey data) address (:address data) @@ -24,10 +24,16 @@ (log/debug "Created account: " result) (when (not (str/blank? public-key)) (do + (dispatch [:login-account address password]) (dispatch [:initialize-protocol account]) (dispatch [:add-account account]))))) (register-handler :create-account (-> (fn [db [_ password]] - (.createAccount geth password (fn [result] (account-created result))) - db))) \ No newline at end of file + (.createAccount geth password (fn [result] (account-created result password))) + db))) + +(register-handler :login-account + (-> (fn [db [_ address password]] + (.login geth address password (fn [result] (log/debug "Logged in account: " address result))) + db))) \ No newline at end of file From 6fc1e0b46a0d08dad0bfc2dad5fb415d31b53181 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Thu, 30 Jun 2016 20:56:57 +0300 Subject: [PATCH 16/22] fix missed dapp params --- src/status_im/chat/handlers.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index db08695e00..97df9c4281 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -475,7 +475,9 @@ :group-chat false :is-active true :timestamp (.getTime (js/Date.)) - :contacts [{:identity contcat-id}]}] + :contacts [{:identity contcat-id}] + :dapp-url nil + :dapp-hash nil}] (assoc db :new-chat chat))) (defn add-chat [{:keys [new-chat] :as db} [_ chat-id]] From 7f1ac63cdf584b9d69eb28d97eade7c61082c0b8 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 23:03:43 +0300 Subject: [PATCH 17/22] autologin to account when its already created --- src/status_im/accounts/handlers.cljs | 12 +++++++++--- src/status_im/handlers.cljs | 22 +++++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs index cb64243e8f..cfb6d32d9b 100644 --- a/src/status_im/accounts/handlers.cljs +++ b/src/status_im/accounts/handlers.cljs @@ -4,6 +4,8 @@ [status-im.utils.logging :as log] [status-im.components.react :refer [geth]] [status-im.utils.types :refer [json->clj]] + [status-im.persistence.simple-kv-store :as kv] + [status-im.protocol.state.storage :as storage] [clojure.string :as str])) @@ -15,6 +17,9 @@ (update db :accounts assoc address account)) ((after save-account)))) +(defn save-password [password] + (storage/put kv/kv-store :password password)) + (defn account-created [result password] (let [data (json->clj result) public-key (:pubkey data) @@ -24,6 +29,7 @@ (log/debug "Created account: " result) (when (not (str/blank? public-key)) (do + (save-password password) (dispatch [:login-account address password]) (dispatch [:initialize-protocol account]) (dispatch [:add-account account]))))) @@ -34,6 +40,6 @@ db))) (register-handler :login-account - (-> (fn [db [_ address password]] - (.login geth address password (fn [result] (log/debug "Logged in account: " address result))) - db))) \ No newline at end of file + (-> (fn [db [_ address password]] + (.login geth address password (fn [result] (log/debug "Logged in account: " address result))) + db))) \ No newline at end of file diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index cd3ce76f44..ee070f1ceb 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -9,6 +9,7 @@ [status-im.utils.crypt :refer [gen-random-bytes]] [status-im.components.react :refer [geth]] [status-im.utils.handlers :refer [register-handler] :as u] + [status-im.models.protocol :as protocol] status-im.chat.handlers status-im.chat.handlers.animation status-im.group-settings.handlers @@ -57,7 +58,9 @@ (register-handler :initialize-db (fn [_ _] (assoc app-db - :signed-up (storage/get kv/kv-store :signed-up)))) + :signed-up (storage/get kv/kv-store :signed-up) + :user-identity (protocol/stored-identity nil) + :password (storage/get kv/kv-store :password)))) (register-handler :initialize-crypt (u/side-effect! @@ -74,11 +77,20 @@ (.toBits (.. js/ecc -sjcl -codec -hex)) (.addEntropy (.. js/ecc -sjcl -random))) (dispatch [:crypt-initialized])))))))) + +(defn node-started [db result] + (let [identity (:user-identity db) + password (:password db)] + (log/debug "Started Node: " result) + (when identity (do + (dispatch [:login-account (:address identity) password]) + (dispatch [:initialize-protocol identity]))))) + (register-handler :initialize-geth - (u/side-effect! - (fn [_ _] - (log/debug "Starting node") - (.startNode geth (fn [result] (log/debug "Started Node: " result)))))) + (u/side-effect! + (fn [db _] + (log/debug "Starting node") + (.startNode geth (fn [result] (node-started db result)))))) (register-handler :crypt-initialized (u/side-effect! From 42faf66c1d8b10c631054c2e432304a2929215e8 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 30 Jun 2016 23:09:33 +0300 Subject: [PATCH 18/22] changed error color --- src/status_im/contacts/views/new_contact.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 20a05ee059..2dbe6abc82 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -38,6 +38,7 @@ [] [text-field {:error (if (str/blank? name) "" nil) + :errorColor "#7099e6" :value name :label (label :t/name) :onChangeText #(dispatch [:set-in [:new-contact :name] %])}]) @@ -51,6 +52,7 @@ [view button-input-container [text-field {:error error + :errorColor "#7099e6" :value whisper-identity :wrapperStyle (merge button-input) :label (label :t/address) From 0c77625155f5d619960756c418aaeaeb3c422ee2 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Sat, 2 Jul 2016 10:56:10 +0300 Subject: [PATCH 19/22] upgrade statusgo --- android/app/build.gradle | 2 +- .../src/main/java/com/statusim/geth/service/GethService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 4fe1f11ca2..913abe3bc0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,7 +134,7 @@ dependencies { compile project(':react-native-status') compile project(':react-native-orientation') //compile(name:'statusgo-android-16', ext:'aar') - compile(group: 'status-im', name: 'status-go', version: '0.1.0-201606301634-5d7b29', ext: 'aar') + compile(group: 'status-im', name: 'status-go', version: '0.1.0-201607011545-da53ec', ext: 'aar') compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"]) } diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java index 295cacd2c1..9900b3ef8e 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethService.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -186,7 +186,7 @@ public class GethService extends Service { String password = data.getString("password"); // TODO: remove second argument Log.d(TAG, "Creating account: " + password + " - " + dataFolder); - String jsonData = Statusgo.CreateAccount(password, dataFolder + "/keystore"); + String jsonData = Statusgo.CreateAccount(password); Log.d(TAG, "Created account: " + jsonData); Bundle replyData = new Bundle(); From 32a7821da9ac8c6040fc3227f6cf7eaeebfd2dc2 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Sat, 2 Jul 2016 12:05:42 +0300 Subject: [PATCH 20/22] improvement of suggestions animation --- src/status_im/chat/views/response.cljs | 8 +++++--- src/status_im/chat/views/suggestions.cljs | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index eaad55d093..a0d8e876bc 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -14,7 +14,8 @@ [status-im.chat.styles.response :as st] [status-im.chat.styles.dragdown :as ddst] [status-im.components.animation :as anim] - [status-im.chat.suggestions-responder :as resp])) + [status-im.chat.suggestions-responder :as resp] + [status-im.chat.constants :as c])) (defn drag-icon [] [view st/drag-container @@ -58,7 +59,8 @@ (defn container-animation-logic [{:keys [to-value val]}] (let [to-value @to-value] - (anim/start (anim/spring val {:toValue to-value})))) + (when-not (= to-value (.-_value val)) + (anim/start (anim/spring val {:toValue to-value}))))) (defn container [response-height & children] (let [;; todo to-response-height, cur-response-height must be specific @@ -89,7 +91,7 @@ (when (seq suggestions) suggestions)) (defn response-view [] - (let [response-height (anim/create-value 0)] + (let [response-height (anim/create-value c/input-height)] [container response-height [request-info response-height] [response-suggestions-view] diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index ca2bd8d0fe..909641d829 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -98,7 +98,8 @@ (defn container-animation-logic [{:keys [to-value val]}] (when-let [to-value @to-value] - (anim/start (anim/spring val {:toValue to-value})))) + (when-not (= to-value (.-_value val)) + (anim/start (anim/spring val {:toValue to-value}))))) (defn container [h & elements] (let [;; todo to-response-height, cur-response-height must be specific From 5749f76be55cfd998caf67dc0857755c17438398 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Sat, 2 Jul 2016 15:03:31 +0300 Subject: [PATCH 21/22] fix staged response name --- src/status_im/chat/views/staged_command.cljs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/status_im/chat/views/staged_command.cljs b/src/status_im/chat/views/staged_command.cljs index 424367c56e..4930192bce 100644 --- a/src/status_im/chat/views/staged_command.cljs +++ b/src/status_im/chat/views/staged_command.cljs @@ -11,12 +11,15 @@ (dispatch [:unstage-command staged-command])) (defn simple-command-staged-view [staged-command] - (let [command (:command staged-command)] + (let [{:keys [type name] :as command} (:command staged-command)] [view st/staged-command-container [view st/staged-command-background [view st/staged-command-info-container [view (st/staged-command-text-container command) - [text {:style st/staged-command-text} (str "!" (:name command))]] + [text {:style st/staged-command-text} + (if (= :command type) + (str "!" name) + name)]] [touchable-highlight {:style st/staged-command-cancel :onPress #(cancel-command-input staged-command)} [image {:source res/icon-close-gray From 7413352563d9faf3893f245f5a86bb42813682b0 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Tue, 5 Jul 2016 16:25:33 +0300 Subject: [PATCH 22/22] fix identity-length --- src/status_im/contacts/validations.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/status_im/contacts/validations.cljs b/src/status_im/contacts/validations.cljs index ca3feee759..1e4d517682 100644 --- a/src/status_im/contacts/validations.cljs +++ b/src/status_im/contacts/validations.cljs @@ -7,7 +7,7 @@ (not (realm/exists? :contacts :whisper-identity identity))) (defn valid-length? [identity] - (= 64 (count identity))) + (= 132 (count identity))) (s/def ::identity-length valid-length?) (s/def ::unique-identity unique-identity?)