From 4bcd20468730b646c769f7a2ac4428ddc9f8d5e4 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 22 Dec 2015 18:22:51 -0200 Subject: [PATCH] Use a RecyclerView for the Contact List --- briar-android/build.gradle | 1 + .../res/drawable-hdpi/contact_connected.png | Bin 1316 -> 0 bytes .../drawable-hdpi/contact_disconnected.png | Bin 1133 -> 0 bytes .../res/drawable-hdpi/social_add_person.png | Bin 1784 -> 0 bytes .../res/drawable-mdpi/contact_connected.png | Bin 1025 -> 0 bytes .../drawable-mdpi/contact_disconnected.png | Bin 484 -> 0 bytes .../res/drawable-mdpi/social_add_person.png | Bin 1496 -> 0 bytes .../res/drawable-xhdpi/contact_connected.png | Bin 1094 -> 0 bytes .../drawable-xhdpi/contact_disconnected.png | Bin 1168 -> 0 bytes .../res/drawable-xhdpi/social_add_person.png | Bin 2103 -> 0 bytes .../res/drawable/contact_connected.xml | 26 ++ .../res/drawable/contact_disconnected.xml | 5 + .../res/drawable/social_add_person.xml | 5 + .../res/drawable/social_remove_person.xml | 5 + .../res/layout/activity_contact_list.xml | 33 +++ .../res/layout/list_item_contact.xml | 51 ++++ briar-android/res/layout/transports_list.xml | 5 +- briar-android/res/menu/contact_actions.xml | 12 + .../res/menu/contact_list_actions.xml | 12 + briar-android/res/values/strings.xml | 2 + briar-android/res/values/styles.xml | 9 + .../android/contact/ContactListActivity.java | 249 ++++++------------ .../android/contact/ContactListAdapter.java | 230 ++++++++++++---- .../android/contact/ConversationActivity.java | 90 +++++++ 24 files changed, 505 insertions(+), 230 deletions(-) delete mode 100644 briar-android/res/drawable-hdpi/contact_connected.png delete mode 100644 briar-android/res/drawable-hdpi/contact_disconnected.png delete mode 100644 briar-android/res/drawable-hdpi/social_add_person.png delete mode 100644 briar-android/res/drawable-mdpi/contact_connected.png delete mode 100644 briar-android/res/drawable-mdpi/contact_disconnected.png delete mode 100644 briar-android/res/drawable-mdpi/social_add_person.png delete mode 100644 briar-android/res/drawable-xhdpi/contact_connected.png delete mode 100644 briar-android/res/drawable-xhdpi/contact_disconnected.png delete mode 100644 briar-android/res/drawable-xhdpi/social_add_person.png create mode 100644 briar-android/res/drawable/contact_connected.xml create mode 100644 briar-android/res/drawable/contact_disconnected.xml create mode 100644 briar-android/res/drawable/social_add_person.xml create mode 100644 briar-android/res/drawable/social_remove_person.xml create mode 100644 briar-android/res/layout/activity_contact_list.xml create mode 100644 briar-android/res/layout/list_item_contact.xml create mode 100644 briar-android/res/menu/contact_actions.xml create mode 100644 briar-android/res/menu/contact_list_actions.xml diff --git a/briar-android/build.gradle b/briar-android/build.gradle index 3e6d17c84..f06ca62b1 100644 --- a/briar-android/build.gradle +++ b/briar-android/build.gradle @@ -7,6 +7,7 @@ dependencies { compile project(':briar-core') compile fileTree(dir: 'libs', include: '*.jar') compile "com.android.support:appcompat-v7:23.1.1" + compile 'com.android.support:recyclerview-v7:23.1.1' } android { diff --git a/briar-android/res/drawable-hdpi/contact_connected.png b/briar-android/res/drawable-hdpi/contact_connected.png deleted file mode 100644 index 9fa452b33cdc41c6771b7df4bd6d24c60458d851..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1316 zcmV+<1>5?GP)Px(-bqA3RA}DqnNMg`R}{v-@4lJI%p^0(jJ28svQcZgh~hk?i&9!^5u~d^7D}Md z+Jy_DZUZh0Ze6%=p+XCxE(CWK#D8rmSmZs?bfK8iHV_7Cok?b#Ofoa?eqH1R6s`I9 zMlH;@oHzI0^SkHVch5Nw=%}NPI_hWxV$>75uIorjlI#J{9sXPc@I=yr@B6_U3s5K& zvH(U%ZU@i@AR9iaNSY-%1z^(iyviE`P$(4QBzH>MPhywEge(Z41;B=XGXP>V5UGZQ zdnB((df@wh^R)rEuDeUpL6SSIMSQ+&D)FSM?;Wn~&b)26gb)A_t3BpFKb_6o2GEzz z*(|9hfCnTmd!Bdil>)e~Ya|^a`3WG@D<;Sf1?AC`<>L}-@ucmhLHy}4vS>Byrb?rp zi{rUdrD-RZ%322?BwZzW!Sg)Zc7Q^mkOc5KiTADLLL#N+*y+-j@h+u;7Dc{%P6={i zVsnx8iDUWmjXLATC@J9=0N?q(ztA>-LZLvCUjh1XuIQ9L`)2N=p*@X3<0!xOy%21` z()69g%%u~(H+%boJis3%o%MZRtDVJJ%aQ{F17m>p%@v*5FV2@n`-hv`NTj5dcm8=# zP{t^o8w|D#f4n$!YogmrX6!ov(#2wNGID@Ip)f-7u(fP_I$rspf4I3#A^>8o#sdh) zER9cPZD#9mEB*VgU4I(GZ36=Xe-w+wzgIJlS>>Tk05}K;iIkc{dm4jMboYk@4DD$Q zCQ@nwf~14tn$Z9N*iLe|UNOPg>CzG7C@)db0Z_(Ke(ZGVNWEeL0K)*bM+PA2fVD{E zhl1I7my+uZo0Y;T-lb%ID43O)0B|4@0M~W9NsP>wO=a|C`FPM`gu(Nyf)+J;vV45L zY$||8T-WX15I}fg?FNttS}0k|CsFSFi#%a1p9C$G03;;sc3szO!~-b+J8VF+?`U;z zB4sn}PLC5Qo7s1?y4MCY0Cq@9ts6j6Cd?|E-J7(T2C=s1_Xe@XOE)d{ za+fjaVB%yII@x+hBmAZ z!1sL%;4XlM6GPq@^+-_r;vF(ZJx&aH01c9NLmSqA6Z^hj12~z^+3dyf+$krfwq0aS zOuRUrJC)AaEWk<6^J-Bgb5}?;O4CkXbCC;686yT7WZVy1Fwp>bp4T9G86X;U#;5NjW*A{0k-+qw z#7v{kcv$3L_B^i>kX&nupx!=Ossh6MDI;wlmu|y z_x-6Vj|0sa5lDo+*ohU6gtku?rh+e5Sn)V2b3M)n0$W`EW=kB|Z0n13=^-I6CU6qmDY- akp2bu44pSGze%?M0000~8k} diff --git a/briar-android/res/drawable-hdpi/contact_disconnected.png b/briar-android/res/drawable-hdpi/contact_disconnected.png deleted file mode 100644 index 9de4968499c5c464a53beb423088bbe7c618b5b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1133 zcmV-z1d{uSP)Px(CrLy>RA}Dqna^ufR~*GZXGW8#F$p!Hya!68ih_;8d(cH))S?J(Tw4U8;Qv%; zS8WkoyAdRc&~{bsZB42uO3m(qLGVY6COUJv@Cvr3m`r9y7jstgW|;f^o_oLde$PD* z1{h#~0S4Fv)a?Q5x^CJYku(bI$X`DLmTbR>F}6Nh0##Lw0W*^J0TaMj{^^PBN0ROV z^C5&M9}R)3s-m3Uott(DIF%olBwgra!~GvZ2yIChY%kfy_Ng4R zI|P7zk`CG)mUJnEu-NSm9zs}@bO{&+4g&kSM!@#Tocuxv;W|A+2;sV<1xdre$*vHn z>v{(;1GH_=_CcS`+HTvP$+0^pkQ>&Kd`>?BZuUBR+c$HpA=^jlx^8S{1-1eE^J%pR zEcIapma+_K0{d-m>zF|9k`t0zk{$xDdam!KS6NH7BuxN2J0>7$yQFcTW&814+NPIi z0gr9BfN@FNH?sn7lOf9o`mhhy{M^YNSk5!wv^{RS*@yg_S$;ROG+*8ffv3QuJlHN^ zOCJbq$+4O__S4M}cn;jP-I6qw^?a|(XH?RZq?YZwIfu>&WU+Q5>;5rGhx)Jrhis1l ztCDWKPcXi>6KA~y8$a&3&5Z)`**DL0(04tKFtExKItIX@VK9(;wE4Ht6 zQ;psOZs&{m>AJ3`dXW5-?bA8N?QFqxhd>BnRnq0$4@QBrRaG^*m3$uSY#tlimqQ4v zUA>W|lpYjCu~X6kpajN>qL@o5d6P5WkaQ0CGUqcJV_diD-B4pHisCO|Qqo>Y)4=Yc zDE>|>=TpkcesYl9ct4M~kma21#Xt^#*L2p`VeU4zV+?V0Q-Oi22dy$;-y z^l{niYwVAvq!HWiyx;)3{(@tG0R|XgfKA~a{i+eJYP;8)00000NkvXXu0mjf7%mje diff --git a/briar-android/res/drawable-hdpi/social_add_person.png b/briar-android/res/drawable-hdpi/social_add_person.png deleted file mode 100644 index 38b91cc7ce29dac49f4f048c4e7738bde2e41bf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1784 zcmaJ?c~BEq98QrK1eK$V4IsJ(JV27{<^Ylq&ICy%luJRBmK+NNNOrSXAYj#aaCo#@ z#SR{Lj0ei02(1@LMUh4;M{AYCDpW-*RY6B3)T7-XVE-uHncer^Z@%yQoo{wyWW=Ir z*3Q->5^0(wOcYJ5p!v0$Onl=kh6{+r2^YuXF-S6=EyG|^kP?x@fJ7}zfumuWGDmwA z_9KxdxvOI1@px%CUxBC@GBbvuSEB@*MDh#JqcTN0j018wMWqqa25Ntx0V<`C7RQx> zQZxikRfXkZa7=DQtRgpE!Bf%#`~g2bpAb;PxD3#%Gc-EBUPv3!@fLT!{M>26CjfnJp3Tkv*R-+p&6HzdxUWPIu253%c3@DZUKUA$AN9*ut_(Qz^ zDXfdlL1AVztV1#}1<|-jH$9bUpv1irC87-4s_|Tz18-I1t?jEuUm4! zWku<>d^_Ol5>idjzLw>c&RfZ>g7#KQ`z1TOY;C2l*5SIPVn)i}DGm{Ht0*r-9)ZEV zq~hMH{`<@Fh6)SwqNZ%ykl4I)NDj}-MI0?SRdWpk+Y{rjM#g$3Imchpzfx4&#Kc<_ zSr=0h`op_&G0E`s@MJ1kcC_{KjU9#qdyWL|k84ePBlq}~zVO&e^t_SmvV`7aV}w3w z{3dAArdr1~iT%J5n*~+SpGR)|ax4)a7A7XSQZ0}}zQ$SAaHwra21)hL&o7-nms8>t4GE zU)^|67{;noKI*p0Z(!eLS0osUF0M)_=jM!~^fwvk9KZdI)h{XZId+GaJbJ^ZUtZnfTH3IyquXayeZodfQ@wrk%ksh6 zq32cQPcOzg47mYU(qgvcrB~N%j<>7O={k|=__BPH$VhX4c;;CWXZ@#go^&9e>i=ra zn#R`aPuzQWQR>jIS`WSmUR|+%P6Fn8A@gZIel{ROaH!^x>y`w=cQXp8{45uk@j~E8 z&GE>pv9~mO`e*sh%$&8)S0XVv| A7ytkO diff --git a/briar-android/res/drawable-mdpi/contact_connected.png b/briar-android/res/drawable-mdpi/contact_connected.png deleted file mode 100644 index d91970da5b783896c4d9054cbd9e37538fe20d2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmV+c1pfPpP)H@rHO9+)AU7ayfHq@wV)tx_}1AE)4 zQWmyIQHLt5VL(L{^?NZL5;Yy#3fUMH5-8xc1S*{R4Tu}aRATr5QZUq z-%pd6i45+THb-;$DCM|_0Kj&jU)1zTV#w|~8V^NK4T9jL7kg;{-}ey&0X)x}QHr0w ztT{uI3oU;1$??b8k?1BJxBwtl%%8iu@%>6>?fH6AZWN+d*2?`b46D6w#0Dr9i>Op8 zC>H(c)-gZNPZ_tobWqL?+nc6M0E7tS^+yN_v@1B;SAVQ7=T;j(>vl3DUsfu?)_D*E zGEkgppWw6k#p4gB%gs3|Xo3W#PpAMw2t>rfY^|n#*jULtO{DDCVHj4=+C!aF`!p%{ z@>3?+-JF^v1(5#S>>`k)qMj}{=kik~sTA+|zMqZ_pcJQH)|^y%>EJdMG}+y?_w1X_ zQ){T8%S#8hU(}owi0Rk>k-^=`g_g<=+Yy57)%zk6fe>VN*p7U#&{7idZY%)L^C!$J zj?6C}-!g3ilym>QZzd=(ZDM}$_*SQh5zq4{E(B02l|YK0D@56Aqb3jGCHoZtA+C*@ ze6A2>N%)@U4F<5*YLeql0v#&q?xDM!1Q04}CxH&hagur%9i+K$pgmwiRE19)K3VUG~ZpZ2abmYPF^`t%8S9=1HxYtl1 zazeQ&NcG4z&A+o<0-26R%;JXCw%eR2KUXOD*(ZpMBURD!Kyv50!T9)BG7Jb~{Q zXGn=Px$o=HSOR9M69mOoDdK@i1%iV0LEBxkdb&|*R3bT&d^)GtD7gN4MJMjBhbh#Cv| z0;2^DmMCNk&k#CHG_jc$?vF>%gje3pynQ=6J8xlw4c3gUG)W>-25LaXK8=8Zs*YDG zKt#@f6JQU>0bllO2lxiwfqPZG%~XJhRDcVh2#kS8-~|XRBmnk-BcKdSfooMA{aS#C z902FQ9O$X4M#Kxy1PZ{7sy;1?&&AmJCGY{XRP`-Nu=n0O=N^DVpy8Z*_TJAH#cxOO zwQT2YRsD>6t`^(2+}5(#?TCgeTG{7GyW4VlK+(7oSKt(wM4fqr2n8m_6<>he^8n~) zFl+iiV4SflP_qUdW*}f_T(u+uDmG-o3w!CG>J(^-NFl}I1v91TGJB4? z1zmHsj)>$FES?8CmfKD3hTi*`bM6&r0LRWb@4fdi%6l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi(%+%Pz#K_gu$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19yq1O$kUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnrq& zG!Lpb1-DyVaO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zo)^j5$H2hk<>}%W zQgQ3a^xfXdfg;C@11G)t#S$2P&&{U4l3*4r$lk;iwzGo$aKRTIb)Reg2}esL-!-I`9lF0D@Mr9- z%L+gE#O|0a3Q09Sopzc3*g-~%E5ypy*i z-z?~NcHb&sc>(mdKI;Vst0IBOL)c^nh diff --git a/briar-android/res/drawable-xhdpi/contact_connected.png b/briar-android/res/drawable-xhdpi/contact_connected.png deleted file mode 100644 index 4341f01a1a16797592c31e81c119d260cff7f9c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1094 zcmV-M1iAZ(P)Px(07*naRCwC$nmuS;Wf;eQ_v_@li3v4Ut)bPpv`cs>=#;woK?lLXK?(__;O3-L zrsANJvxEdnhYqCPBj01N}K=pJAbcnUlLiom9GuJ+OxU}inQ zY2Xxa66gbZfo}cFbKn`U4XgkUfFDa4^RebKvnlSJum3KqUV7!<4@oh=iGx-8(?Prz{kL(>Uv3! zx`6fJw<=FR__Fxn;A^#W`~AMSnqBz$+rgVV8`)7{2-wx5KyAZa;8*9|R_Y8evp0Y* zfU~O8IlX^ndVX!@An%-;8o8o2qpob}2L1r9Ip_XOjR9u%E^rBWRbRaecsM=3_DvM; zpPL%_4mhEV2!O}HtaI+Kwi{q(s25(dAZpA_WPyJqpV){?*-TI{y6YFjG?yS z2j|>k+YB(X*H!rAYPgu5U%M1%&oVbPGOIuHz^Y96@1XC?9mb%zZHmo#7YQV4>ni^0UI9{7biveN@ z*AV)|8jAtF4O7#!sVcVKxC|HodX9hrJz|Z0F7Q&Q6$6SIcV{#aNt?nIs2#CJZom^Q zLZsb*XJU=TfNlLIUtG;Dq^0Cy$%}0}E(12%+q5VHnV)8cZluKkv1G)yBGwlhM70oS z3s_QrTd(Y9PNc;Eu~gI(EQvMR3~fkj|L-OW&n>i>|KHh@L3M&AuO=gPo>R$_Lw zZr@gkAzUtB5M!+C0l%rC0eCY7Uq58n7F+BKBFpUU)fMywzHj5#4`Ua^v>dwus$aL% z&{TlY`}czDNf%x*N5!xO+-jxnA8IJ1iDkZvpO0-)Nk zW0OSc&#KD{#Be)_xj=IkYynr<+o;SnfF)7*aOnFOxO$lFa=$qm1zbmOk2jdmxd$W~ zOz7MrGEGKw<{_zljOff`a{Cz3nFl4COi1NXSuZayFE1}IFRxD3|8PgMT?Y<&b^rhX M07*qoM6N<$f=^ryhX4Qo diff --git a/briar-android/res/drawable-xhdpi/contact_disconnected.png b/briar-android/res/drawable-xhdpi/contact_disconnected.png deleted file mode 100644 index d0499ddf1ffb6335c4b4f48d42ffed128d863a62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1168 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 SCLS>V%0;1(g44X@ynh4GY&7Bk diff --git a/briar-android/res/drawable/contact_connected.xml b/briar-android/res/drawable/contact_connected.xml new file mode 100644 index 000000000..95e7a0bc0 --- /dev/null +++ b/briar-android/res/drawable/contact_connected.xml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/briar-android/res/drawable/contact_disconnected.xml b/briar-android/res/drawable/contact_disconnected.xml new file mode 100644 index 000000000..d8ee38c1e --- /dev/null +++ b/briar-android/res/drawable/contact_disconnected.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/social_add_person.xml b/briar-android/res/drawable/social_add_person.xml new file mode 100644 index 000000000..982183dea --- /dev/null +++ b/briar-android/res/drawable/social_add_person.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/social_remove_person.xml b/briar-android/res/drawable/social_remove_person.xml new file mode 100644 index 000000000..4adacc148 --- /dev/null +++ b/briar-android/res/drawable/social_remove_person.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/layout/activity_contact_list.xml b/briar-android/res/layout/activity_contact_list.xml new file mode 100644 index 000000000..acde6fdc9 --- /dev/null +++ b/briar-android/res/layout/activity_contact_list.xml @@ -0,0 +1,33 @@ + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/layout/list_item_contact.xml b/briar-android/res/layout/list_item_contact.xml new file mode 100644 index 000000000..69ec0383e --- /dev/null +++ b/briar-android/res/layout/list_item_contact.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/layout/transports_list.xml b/briar-android/res/layout/transports_list.xml index c1ec632f6..c359d7c1d 100644 --- a/briar-android/res/layout/transports_list.xml +++ b/briar-android/res/layout/transports_list.xml @@ -5,10 +5,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - + + + + + + \ No newline at end of file diff --git a/briar-android/res/menu/contact_list_actions.xml b/briar-android/res/menu/contact_list_actions.xml new file mode 100644 index 000000000..718200a65 --- /dev/null +++ b/briar-android/res/menu/contact_list_actions.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index fe43fd7c2..0a7c7b1f0 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -126,4 +126,6 @@ Lost password Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ? + Confirm Contact Deletion + Are you sure that you want to remove this contact and all messages exchanged with this contact? diff --git a/briar-android/res/values/styles.xml b/briar-android/res/values/styles.xml index f40b8b541..0e0c2c0b9 100644 --- a/briar-android/res/values/styles.xml +++ b/briar-android/res/values/styles.xml @@ -33,4 +33,13 @@ @dimen/text_size_small @android:color/primary_text_light + + + + \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java index fff550fc4..1edbd2d2a 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java @@ -1,28 +1,20 @@ package org.briarproject.android.contact; import android.content.Intent; -import android.content.res.Resources; +import android.graphics.PorterDuff; import android.os.Bundle; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; import android.view.View.OnCreateContextMenuListener; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.ListView; +import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import org.briarproject.R; import org.briarproject.android.BriarActivity; import org.briarproject.android.invitation.AddContactActivity; -import org.briarproject.android.util.HorizontalBorder; -import org.briarproject.android.util.ListLoadingProgressBar; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; @@ -36,43 +28,34 @@ import org.briarproject.api.event.Event; import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventListener; import org.briarproject.api.event.MessageAddedEvent; -import org.briarproject.api.identity.AuthorId; import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.sync.GroupId; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.logging.Logger; import javax.inject.Inject; -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.Menu.NONE; import static android.view.View.GONE; import static android.view.View.VISIBLE; -import static android.widget.LinearLayout.VERTICAL; -import static android.widget.Toast.LENGTH_SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; public class ContactListActivity extends BriarActivity -implements OnClickListener, OnItemClickListener, OnCreateContextMenuListener, -EventListener { + implements OnCreateContextMenuListener, EventListener { - private static final int MENU_ITEM_DELETE = 1; private static final Logger LOG = Logger.getLogger(ContactListActivity.class.getName()); @Inject private ConnectionRegistry connectionRegistry; private TextView empty = null; private ContactListAdapter adapter = null; - private ListView list = null; - private ListLoadingProgressBar loading = null; + private RecyclerView list = null; + private ProgressBar loading = null; // Fields that are accessed from background threads must be volatile @Inject private volatile ContactManager contactManager; @@ -82,47 +65,28 @@ EventListener { @Override public void onCreate(Bundle state) { super.onCreate(state); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_MATCH); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - empty = new TextView(this); - empty.setLayoutParams(MATCH_WRAP_1); - empty.setGravity(CENTER); - empty.setTextSize(18); - empty.setText(R.string.no_contacts); - empty.setVisibility(GONE); - layout.addView(empty); + setContentView(R.layout.activity_contact_list); adapter = new ContactListAdapter(this); - list = new ListView(this); - list.setLayoutParams(MATCH_WRAP_1); + list = (RecyclerView) findViewById(R.id.contactList); + list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); - list.setOnItemClickListener(this); list.setOnCreateContextMenuListener(this); list.setVisibility(GONE); - layout.addView(list); + + // Show a notice when there are no contacts + empty = (TextView) findViewById(R.id.emptyView); // Show a progress bar while the list is loading - loading = new ListLoadingProgressBar(this); - layout.addView(loading); + loading = (ProgressBar) findViewById(R.id.progressBar); + loading.setVisibility(VISIBLE); + } - layout.addView(new HorizontalBorder(this)); - - LinearLayout footer = new LinearLayout(this); - footer.setLayoutParams(MATCH_WRAP); - footer.setGravity(CENTER); - Resources res = getResources(); - footer.setBackgroundColor(res.getColor(R.color.button_bar_background)); - ImageButton addContactButton = new ImageButton(this); - addContactButton.setBackgroundResource(0); - addContactButton.setImageResource(R.drawable.social_add_person); - addContactButton.setOnClickListener(this); - footer.addView(addContactButton); - layout.addView(footer); - - setContentView(layout); + @Override + public void onPause() { + super.onPause(); + eventBus.removeListener(this); } @Override @@ -132,12 +96,47 @@ EventListener { loadContacts(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu items for use in the action bar + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.contact_list_actions, menu); + + // adapt icon color to dark action bar + menu.findItem(R.id.action_social_add_person).getIcon().setColorFilter( + getResources().getColor(R.color.action_bar_text), + PorterDuff.Mode.SRC_IN); + + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + // Handle presses on the action bar items + switch (item.getItemId()) { + case R.id.action_social_add_person: + startActivity(new Intent(this, AddContactActivity.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void loadContacts() { - clearContacts(); + runOnUiThread(new Runnable() { + public void run() { + empty.setVisibility(GONE); + list.setVisibility(GONE); + loading.setVisibility(VISIBLE); + } + }); runOnDbThread(new Runnable() { public void run() { try { long now = System.currentTimeMillis(); + List contacts = + new ArrayList(); for (Contact c : contactManager.getContacts()) { try { ContactId id = c.getId(); @@ -145,15 +144,20 @@ EventListener { messagingManager.getConversationId(id); Collection headers = messagingManager.getMessageHeaders(id); - displayContact(c, conversation, headers); + + boolean connected = + connectionRegistry.isConnected(c.getId()); + contacts.add(new ContactListItem(c, connected, + conversation, + headers)); } catch (NoSuchContactException e) { // Continue } } + displayContacts(contacts); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Full load took " + duration + " ms"); - hideProgressBar(); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -162,110 +166,19 @@ EventListener { }); } - private void clearContacts() { + private void displayContacts(final List contacts) { runOnUiThread(new Runnable() { public void run() { - empty.setVisibility(GONE); - list.setVisibility(GONE); - loading.setVisibility(VISIBLE); - adapter.clear(); - adapter.notifyDataSetChanged(); - } - }); - } - - private void displayContact(final Contact c, final GroupId conversation, - final Collection headers) { - runOnUiThread(new Runnable() { - public void run() { - list.setVisibility(VISIBLE); - loading.setVisibility(GONE); - boolean connected = connectionRegistry.isConnected(c.getId()); - // Remove the old item, if any - ContactListItem item = findItem(c.getId()); - if (item != null) adapter.remove(item); - // Add a new item - adapter.add(new ContactListItem(c, connected, conversation, - headers)); - adapter.sort(ContactListItemComparator.INSTANCE); - adapter.notifyDataSetChanged(); - } - }); - } - - private void hideProgressBar() { - runOnUiThread(new Runnable() { - public void run() { - if (adapter.isEmpty()) empty.setVisibility(VISIBLE); - else list.setVisibility(VISIBLE); - loading.setVisibility(GONE); - } - }); - } - - private ContactListItem findItem(ContactId c) { - int count = adapter.getCount(); - for (int i = 0; i < count; i++) { - ContactListItem item = adapter.getItem(i); - if (item.getContact().getId().equals(c)) return item; - } - return null; // Not found - } - - @Override - public void onPause() { - super.onPause(); - eventBus.removeListener(this); - } - - public void onClick(View view) { - startActivity(new Intent(this, AddContactActivity.class)); - } - - public void onItemClick(AdapterView parent, View view, int position, - long id) { - ContactListItem item = adapter.getItem(position); - ContactId contactId = item.getContact().getId(); - String contactName = item.getContact().getAuthor().getName(); - GroupId groupId = item.getConversationId(); - AuthorId localAuthorId = item.getContact().getLocalAuthorId(); - Intent i = new Intent(this, ConversationActivity.class); - i.putExtra("briar.CONTACT_ID", contactId.getInt()); - i.putExtra("briar.CONTACT_NAME", contactName); - i.putExtra("briar.GROUP_ID", groupId.getBytes()); - i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes()); - startActivity(i); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View view, - ContextMenu.ContextMenuInfo info) { - String delete = getString(R.string.delete_contact); - menu.add(NONE, MENU_ITEM_DELETE, NONE, delete); - } - - @Override - public boolean onContextItemSelected(MenuItem menuItem) { - if (menuItem.getItemId() == MENU_ITEM_DELETE) { - ContextMenuInfo info = menuItem.getMenuInfo(); - int position = ((AdapterContextMenuInfo) info).position; - ContactListItem item = adapter.getItem(position); - removeContact(item.getContact().getId()); - String deleted = getString(R.string.contact_deleted_toast); - Toast.makeText(this, deleted, LENGTH_SHORT).show(); - } - return true; - } - - private void removeContact(final ContactId c) { - runOnDbThread(new Runnable() { - public void run() { - try { - contactManager.removeContact(c); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); + if(contacts.size() > 0) { + list.setVisibility(VISIBLE); + empty.setVisibility(GONE); + } else { + list.setVisibility(GONE); + empty.setVisibility(VISIBLE); } + loading.setVisibility(GONE); + + adapter.addAll(contacts); } }); } @@ -314,7 +227,7 @@ EventListener { final Collection headers) { runOnUiThread(new Runnable() { public void run() { - ContactListItem item = findItem(c); + ContactListItem item = adapter.findItem(c); if (item != null) { item.setHeaders(headers); adapter.notifyDataSetChanged(); @@ -326,10 +239,10 @@ EventListener { private void removeItem(final ContactId c) { runOnUiThread(new Runnable() { public void run() { - ContactListItem item = findItem(c); + ContactListItem item = adapter.findItem(c); if (item != null) { adapter.remove(item); - adapter.notifyDataSetChanged(); + if (adapter.isEmpty()) { empty.setVisibility(VISIBLE); list.setVisibility(GONE); @@ -342,7 +255,7 @@ EventListener { private void setConnected(final ContactId c, final boolean connected) { runOnUiThread(new Runnable() { public void run() { - ContactListItem item = findItem(c); + ContactListItem item = adapter.findItem(c); if (item != null) { item.setConnected(connected); adapter.notifyDataSetChanged(); diff --git a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java index 1acb52435..7e511ea9a 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java @@ -1,80 +1,194 @@ package org.briarproject.android.contact; -import static android.text.TextUtils.TruncateAt.END; -import static android.view.Gravity.CENTER_VERTICAL; -import static android.widget.LinearLayout.HORIZONTAL; -import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; - -import java.util.ArrayList; - -import org.briarproject.R; -import org.briarproject.android.util.LayoutUtils; - import android.content.Context; +import android.content.Intent; import android.content.res.Resources; +import android.support.v7.util.SortedList; +import android.support.v7.widget.RecyclerView; import android.text.format.DateUtils; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; -class ContactListAdapter extends ArrayAdapter { +import org.briarproject.R; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.identity.AuthorId; +import org.briarproject.api.sync.GroupId; - private final int pad; +import java.util.List; - ContactListAdapter(Context ctx) { - super(ctx, android.R.layout.simple_expandable_list_item_1, - new ArrayList()); - pad = LayoutUtils.getPadding(ctx); +public class ContactListAdapter + extends RecyclerView.Adapter { + + private SortedList contacts = + new SortedList(ContactListItem.class, + new SortedList.Callback() { + @Override + public void onInserted(int position, int count) { + notifyItemRangeInserted(position, count); + } + + @Override + public void onChanged(int position, int count) { + notifyItemRangeChanged(position, count); + } + + @Override + public void onMoved(int fromPosition, int toPosition) { + notifyItemMoved(fromPosition, toPosition); + } + + @Override + public void onRemoved(int position, int count) { + notifyItemRangeRemoved(position, count); + } + + @Override + public int compare(ContactListItem c1, + ContactListItem c2) { + return (int) (c1.getTimestamp() - + c2.getTimestamp()); + } + + @Override + public boolean areItemsTheSame(ContactListItem c1, + ContactListItem c2) { + return c1.getContact().getId().equals(c2.getContact().getId()); + } + + @Override + public boolean areContentsTheSame(ContactListItem c1, + ContactListItem c2) { + return c1.equals(c2); + } + }); + private Context ctx; + + public ContactListAdapter(Context context) { + ctx = context; } @Override - public View getView(int position, View convertView, ViewGroup parent) { - ContactListItem item = getItem(position); - Context ctx = getContext(); + public ContactHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View v = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.list_item_contact, viewGroup, false); + + return new ContactHolder(v); + } + + @Override + public void onBindViewHolder(final ContactHolder ui, final int position) { + final ContactListItem item = getItem(position); Resources res = ctx.getResources(); - LinearLayout layout = new LinearLayout(ctx); - layout.setOrientation(HORIZONTAL); - layout.setGravity(CENTER_VERTICAL); int unread = item.getUnreadCount(); - if (unread > 0) - layout.setBackgroundColor(res.getColor(R.color.unread_background)); - - ImageView bulb = new ImageView(ctx); - bulb.setPadding(pad, pad, pad, pad); - if (item.isConnected()) - bulb.setImageResource(R.drawable.contact_connected); - else bulb.setImageResource(R.drawable.contact_disconnected); - layout.addView(bulb); - - TextView name = new TextView(ctx); - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setSingleLine(); - name.setEllipsize(END); - name.setPadding(0, pad, pad, pad); - String contactName = item.getContact().getAuthor().getName(); - if (unread > 0) name.setText(contactName + " (" + unread + ")"); - else name.setText(contactName); - layout.addView(name); - - if (item.isEmpty()) { - TextView noMessages = new TextView(ctx); - noMessages.setPadding(pad, pad, pad, pad); - noMessages.setTextColor(res.getColor(R.color.no_private_messages)); - noMessages.setText(R.string.no_private_messages); - layout.addView(noMessages); - } else { - TextView date = new TextView(ctx); - date.setPadding(pad, pad, pad, pad); - long timestamp = item.getTimestamp(); - date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp)); - layout.addView(date); + if (unread > 0) { + ui.layout.setBackgroundColor( + res.getColor(R.color.unread_background)); } - return layout; + if (item.isConnected()) { + ui.bulb.setImageResource(R.drawable.contact_connected); + } else { + ui.bulb.setImageResource(R.drawable.contact_disconnected); + } + + String contactName = item.getContact().getAuthor().getName(); + if (unread > 0) { + ui.name.setText(contactName + " (" + unread + ")"); + } else { + ui.name.setText(contactName); + } + + if (item.isEmpty()) { + ui.date.setText(R.string.no_private_messages); + } else { + long timestamp = item.getTimestamp(); + ui.date.setText( + DateUtils.getRelativeTimeSpanString(ctx, timestamp)); + } + + ui.layout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ContactId contactId = item.getContact().getId(); + String contactName = item.getContact().getAuthor().getName(); + GroupId groupId = item.getConversationId(); + AuthorId localAuthorId = item.getContact().getLocalAuthorId(); + + Intent i = new Intent(ctx, ConversationActivity.class); + i.putExtra("briar.CONTACT_ID", contactId.getInt()); + i.putExtra("briar.CONTACT_NAME", contactName); + i.putExtra("briar.GROUP_ID", groupId.getBytes()); + i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes()); + + ctx.startActivity(i); + } + }); + } + + @Override + public int getItemCount() { + return contacts == null ? 0 : contacts.size(); + } + + public boolean isEmpty() { + return contacts == null || contacts.size() == 0; + } + + public ContactListItem getItem(int position) { + if (position == -1 || contacts.size() <= position) { + return null; // Not found + } + return contacts.get(position); + } + + public ContactListItem findItem(ContactId c) { + int count = getItemCount(); + for (int i = 0; i < count; i++) { + ContactListItem item = getItem(i); + if (item.getContact().getId().equals(c)) return item; + } + return null; // Not found + } + + public void addAll(final List contacts) { + this.contacts.addAll(contacts); + } + + public void add(final ContactListItem contact) { + this.contacts.add(contact); + } + + public void remove(final ContactListItem contact) { + this.contacts.remove(contact); + } + + public void clear() { + contacts.beginBatchedUpdates(); + + while(contacts.size() != 0) { + contacts.removeItemAt(0); + } + + contacts.endBatchedUpdates(); + } + + public static class ContactHolder extends RecyclerView.ViewHolder { + public ViewGroup layout; + public ImageView bulb; + public TextView name; + public TextView date; + + public ContactHolder(View v) { + super(v); + + layout = (ViewGroup) v; + bulb = (ImageView) v.findViewById(R.id.bulbView); + name = (TextView) v.findViewById(R.id.nameView); + date = (TextView) v.findViewById(R.id.dateView); + } } } diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index ff90470fe..98dcd179f 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -1,10 +1,16 @@ package org.briarproject.android.contact; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; +import android.graphics.PorterDuff; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v7.app.ActionBar; +import android.support.v7.app.AlertDialog; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -15,6 +21,7 @@ import android.widget.ImageButton; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; import org.briarproject.R; import org.briarproject.android.BriarActivity; @@ -66,6 +73,7 @@ import javax.inject.Inject; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static android.widget.Toast.LENGTH_SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.contact.ReadPrivateMessageActivity.RESULT_PREV_NEXT; @@ -161,6 +169,33 @@ implements EventListener, OnClickListener, OnItemClickListener { loadHeaders(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu items for use in the action bar + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.contact_actions, menu); + + // adapt icon color to dark action bar + menu.findItem(R.id.action_social_remove_person).getIcon().setColorFilter( + getResources().getColor(R.color.action_bar_text), + PorterDuff.Mode.SRC_IN); + + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + // Handle presses on the action bar items + switch (item.getItemId()) { + case R.id.action_social_remove_person: + askToRemoveContact(); + + return true; + default: + return super.onOptionsItemSelected(item); + } + } + private void loadContactAndGroup() { runOnDbThread(new Runnable() { public void run() { @@ -478,4 +513,59 @@ implements EventListener, OnClickListener, OnItemClickListener { i.putExtra("briar.POSITION", position); startActivityForResult(i, REQUEST_READ); } + + private void askToRemoveContact() { + runOnUiThread(new Runnable() { + @Override + public void run() { + DialogInterface.OnClickListener okListener = + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + removeContact(); + } + }; + + AlertDialog.Builder builder = + new AlertDialog.Builder(ConversationActivity.this); + builder.setTitle( + getString(R.string.dialog_title_delete_contact)); + builder.setMessage( + getString(R.string.dialog_message_delete_contact)); + builder.setPositiveButton(android.R.string.ok, okListener); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + } + }); + } + + private void removeContact() { + runOnDbThread(new Runnable() { + public void run() { + try { + contactManager.removeContact(contactId); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } finally { + finishAfterContactRemoved(); + } + } + }); + } + + private void finishAfterContactRemoved() { + runOnUiThread(new Runnable() { + @Override + public void run() { + String deleted = getString(R.string.contact_deleted_toast); + Toast.makeText(ConversationActivity.this, deleted, LENGTH_SHORT) + .show(); + + finish(); + } + }); + } + }