From a45d09ef5c4997283bb411b2e4ca117cbdc25780 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 4 Feb 2014 12:32:51 +0000 Subject: [PATCH] Show whether identities are anonymous, unknown, or verified. Dev task #52. Known but unverified identities are also supported, but currently unused. These will be used in future for contacts who've been introduced but not verified face to face. --- .../res/drawable-hdpi/contact_connected.png | Bin 1432 -> 1316 bytes .../drawable-hdpi/contact_disconnected.png | Bin 1429 -> 1133 bytes .../res/drawable-hdpi/identity_anonymous.png | Bin 0 -> 975 bytes .../res/drawable-hdpi/identity_unknown.png | Bin 0 -> 1416 bytes .../res/drawable-hdpi/identity_unverified.png | Bin 0 -> 1429 bytes .../res/drawable-hdpi/identity_verified.png | Bin 0 -> 1009 bytes .../res/drawable-mdpi/contact_connected.png | Bin 689 -> 682 bytes .../drawable-mdpi/contact_disconnected.png | Bin 605 -> 484 bytes .../res/drawable-mdpi/identity_anonymous.png | Bin 0 -> 362 bytes .../res/drawable-mdpi/identity_unknown.png | Bin 0 -> 708 bytes .../res/drawable-mdpi/identity_unverified.png | Bin 0 -> 713 bytes .../res/drawable-mdpi/identity_verified.png | Bin 0 -> 531 bytes .../res/drawable-xhdpi/contact_connected.png | Bin 1521 -> 1094 bytes .../drawable-xhdpi/contact_disconnected.png | Bin 1417 -> 1168 bytes .../res/drawable-xhdpi/identity_anonymous.png | Bin 0 -> 853 bytes .../res/drawable-xhdpi/identity_unknown.png | Bin 0 -> 1470 bytes .../drawable-xhdpi/identity_unverified.png | Bin 0 -> 1565 bytes .../res/drawable-xhdpi/identity_verified.png | Bin 0 -> 1139 bytes briar-android/res/values/color.xml | 1 - .../android/contact/ConversationAdapter.java | 14 +-- .../contact/ReadPrivateMessageActivity.java | 18 ++- .../android/groups/GroupActivity.java | 1 + .../android/groups/GroupAdapter.java | 32 +++-- .../android/groups/ReadGroupPostActivity.java | 26 ++--- .../briarproject/android/util/AuthorView.java | 51 ++++++++ .../src/org/briarproject/api/Author.java | 2 + .../briarproject/api/db/MessageHeader.java | 10 +- .../src/org/briarproject/db/JdbcDatabase.java | 28 ++++- .../org/briarproject/db/H2DatabaseTest.java | 109 ++++++++++++------ 29 files changed, 197 insertions(+), 95 deletions(-) create mode 100644 briar-android/res/drawable-hdpi/identity_anonymous.png create mode 100644 briar-android/res/drawable-hdpi/identity_unknown.png create mode 100644 briar-android/res/drawable-hdpi/identity_unverified.png create mode 100644 briar-android/res/drawable-hdpi/identity_verified.png create mode 100644 briar-android/res/drawable-mdpi/identity_anonymous.png create mode 100644 briar-android/res/drawable-mdpi/identity_unknown.png create mode 100644 briar-android/res/drawable-mdpi/identity_unverified.png create mode 100644 briar-android/res/drawable-mdpi/identity_verified.png create mode 100644 briar-android/res/drawable-xhdpi/identity_anonymous.png create mode 100644 briar-android/res/drawable-xhdpi/identity_unknown.png create mode 100644 briar-android/res/drawable-xhdpi/identity_unverified.png create mode 100644 briar-android/res/drawable-xhdpi/identity_verified.png create mode 100644 briar-android/src/org/briarproject/android/util/AuthorView.java diff --git a/briar-android/res/drawable-hdpi/contact_connected.png b/briar-android/res/drawable-hdpi/contact_connected.png index 6c9f76c4522f49d5239cb10ade1d8e5964427f0a..9fa452b33cdc41c6771b7df4bd6d24c60458d851 100644 GIT binary patch delta 1284 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 Hu0mjf=ya~$ diff --git a/briar-android/res/drawable-hdpi/contact_disconnected.png b/briar-android/res/drawable-hdpi/contact_disconnected.png index 4a1053fc7d3f76039fbc93c9fb1dffd1fd5e2af1..9de4968499c5c464a53beb423088bbe7c618b5b4 100644 GIT binary patch delta 1100 zcmV-S1he~<3+)JyFnA+&o=psK17;2dyN(kk%O z_N5r(^$m`5OwwuFJ9F9n2K*Fbe6f*nni~u%N#6orNdmY5d>3Q9wb6-4DJ>L55hZ;J zl#-?;jTc4nM@p$T1j@2J3w#YA>6+~yVvNr^t>2W=a(`Ktzvt6xTGAe1drE1(>jbK* znvwL4?U(r!`98+j-s~xsQgT_AbHE-+pGf+wEX(^Tr3dTze`B4Sb_h6?AD1Lu=w!qF zA3_LiNf&G{*~a#%9J4zFfPIn<+8&m4DTJ`t?G7G7Sd?@L7zPdk`?^NJ_Q{<5LI~kH zJwgcKx__hvNyEU&t`Ml}dIvBAv~AD!L7&aqZrh&8u{$S_8`hD0PCo%|_BwmpH*>5Z z+ehlUZfs@+wgLO|X|)I}^& zWU+Q5>;5rGhx)Jrhis1ltCDWKPcXi>6KA~y8$a&3&5Z)`**DL0(04tKF ztADCG)~n3xx;~aKHY>KTbW@Gq18(Pw`02W?r+Se5l9 zvsG0!x|Mt$>ueqy+m}NKt6ja3rIa2NMX^)T0iXoNilUfHDS4AK-;i_;_%i1+8)ICz z>fKOdDvIJSU{cavNz=gYqA31ODJ^$eHh;i*;Ar-WegS^$*`+?EL|K-%fC<~XCG7&f zD2iewrL@q2t#aP>?wrT3z|S$p4GBhdTCTPPpaTKo@*t+o$HI&S;0q#>YTyUlBZ7uyX&)-~hV*f@6RI1{h#~P2nH?su8Yg SyVsil0000?e1vHa4#5?7z|0;z`f9m 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 Q@c;k-07*qoM6N<$g81b=jQ{`u literal 689 zcmV;i0#5yjP)Px%Ye_^wR9M69mN8G;Kp2MK@33MgBuE8SA|Zk)gJosuiLFw{!cd8S5GlW)106ec zEJJ?*D*u2D`WvF_f-F}GOOU}!p%g=6N6vj6>Va0mI7un3ly|i6{5|*i?tKrKX{JXO zO)^PJSqIPru$DgR0XR}h`40*prQBrjOVadI#6pW$3>XYHxu{J|Ech#dJ}IRR{wRQy za*e@nL?kMGr+=PQ&Jb^war9Mv#kgoh)T#sXS-?hOoLH9s2 z7=+l_ay-*FO#;2m>V&xGTiaaVo7}~JE{VV}-F?^Q0^cxrJ8QVe+HfKg3*Mf$n!EUK z5Z<1*Dk8BUrQ94FfWaGmr+*zaqWW0HZ$U(jsNQ$_*9_hm3qVR)CrwL1J6K6K+@u-? z?O=s8Ev4R(y8}%T3l7&q13Z~orER2eJv2ltI5n=^0BaP}AX!YRQRLW{f-W%F>RNuuEtLs$IJOZf zr4F>Euk4n60zy0%M4AV7%RbSTzRHScagUkp(2(YxEyv3ZaVw0{MBK?5K9}_}2!ijm zTCF#CHTQh^ZE%_4!00000NkvXXu0mjfQcN$2 diff --git a/briar-android/res/drawable-mdpi/contact_disconnected.png b/briar-android/res/drawable-mdpi/contact_disconnected.png index 790357f4e5d8e306028516269cd39a708f7bb017..bef15c40b285d783f8586d6e0af2476ec8c609d7 100644 GIT binary patch delta 446 zcmV;v0YU!V1mpvdFnKTiTd5XFCr2~;K|XS0ydVnO3{HbP<4FG6dB zg~Xah8e6`I8VmUXqXi9?C}a!I5IRgWv6&X`k4MmiSKiIMeLFilZ()NC){Lz*Ng`4P zYCy$4jevowj#nx`M9zQ{U=PRvU-oMU_y*pAdsV&7RDg(7fPV|12#kS8-~|XRBmnk- zBcKdSfooMA{aS#C902FQ9O$X4M#Kxy1PZ{7sy;1?&&AmJCGY{XRP`-Nu=n0O=N^DV zpy8Z*_TJAH#cxOOwQT2YRsD>6t`^(2+}5(#?TCgeTG{7GyW4VlK+(7oSKt(wM4fqr z2n8m_6<>he^M3&7XE1B}KwzA)D^Rlr9cCb4Xk4`<0xC9S!VCn2##Kpk3s#Or0!B7o zgACRPjBAucz`$mEH3I=v;~K;kV6GMd^$Y~mfpC#iF6)6ipk%W>6)d-8T*(HJS?UyM zibx^F;srCM=`wqcx&>WxwT_776D*zwI+oi_?S|g_nKyIp6=(p*&N=VB_c6+T1?-v~ o5C8Xre2XLOCIuZpqjsO4v07*qoM6N<$f@SH)a{vGU delta 568 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 B9KQen delta 1386 zcmV-w1(o`c35g4kFnL@8@K|D0e_fTxlTQuB48V^OZR0(OAqiH@U@xUT{Z-G@3#S; z0qf=UZXf`D1g@CbvxN2bh=dP-Hx&_Gz+b>uW;XWR34ie3Zw0>4Sf7{YM}cq5>_L+V zUI%;x3`W{`3Vdm1H=i2;-g~FcuT$azIBRC#rj%R{0*6)X1RjWldr9l;SYpEa9M}}e z=BLfl5qZ|keo9-osExB~vnUMv zlh&6{=zsl9z#d>)Nof=~-$Dt0UTt;>!yaKup8)TD2XF}J)i}HloN1MIR}_?hGitk2 zSPltW>JhL>VK=Mt1vC4*)vGwQc_E@KcL-Z7>rBx0pcXSl;0|!PPQ)CKB->N<@`U$( z2soDzjCS6D(^TZFZ_LdZF{UTgce{DLbD^FPl=`^*?TWW#vZ8>2>>7K zqSEvFrct{W*+W<@tfWD}sz{hVN}%9Q==;#yxr+O;JRet4K8g&lRcR5h23Q#(U^2nn zJyJnJx#IprOwWfl86jY$u%^BicquFn0e_FByTftZ7q>BG`{9Vka~1c)wRA$A;Th(S zX<=x!iq ztIg8Flo!TS2q0EYXh@U&sQqElV&!eq<6AW#aN~OPM}|yW`(hk1_4jB(0>RI zE;gv)dRA58MYH`PI-wj{6xFhRVF_`K3u|);Ftd5!rsmu-3;Xul8~i-#`Kt4LL?={6 zLOt6qEM;N4DXh((2F+|1xT>9)8DN+9zPrw64J*7FigB^Wu)dEIs?o)AvFioUR zfX3H3C7LxP@6?zxFk%p zgaFz13cD^PtHTKtToUgOv2Z#xuePrXOCn2rG869yGS0rT_o{07*qoM6N<$g6UhE761SM diff --git a/briar-android/res/drawable-xhdpi/identity_anonymous.png b/briar-android/res/drawable-xhdpi/identity_anonymous.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f254fdac6b62ee348a82b48d5e166eeb6cfb11 GIT binary patch literal 853 zcmV-b1FHOqP)Px&4@pEpRA}DqnO|s*Q5?rV=XtltP$ILlB2q?~ZNCf4GOUz@OHywAi72;Rs9oSf zh)7(xpeD(UxFKYX-TdCwZbpexdWLDu_6p-YE<9?@=6$y3wb}DL-#WeTbDnd~=XcKU z{LXXE^FXRpsZvc%iO4h&nU?a$FE64EYlAddn)3XThz4v5ejiNI08Dwl7a{zX0=+cZbDd+pF|Hg~1{@fn ztybWINZkwP%sXRv4}1)E3jIO)q^h3_bTCnTGYq~PXaYKc*Fl7Q1_q|j&VO%v)bTis zR~t6euK)7MD*7^nsws_KgpeJ+Q7b0Oh}fJ)$qs{V)=!m;KTJO=~~903}~V0U9NI-dl7*n`*- zpk)jOv;=jErP%UAI>1%sfAB3V{a0C6RlNSkmmkUjE^k)XY|FL(xz^QHiqzTR`8C^e z?JjRt7p?m-=7(~C@mO@V`T2*Td280y9(8$h)H!pkzM*#4(0f;#pMNkOi;6V>apo6v zfQVE8UB9oJwybItk=tJfyv}Tg?$2g*@8B1&Peg7tZCN$+LDd!1jr#H{*8DKr(6zuk zpdH+Pmp3`%ab8t(!^)MpJO_>E%D`L%>VY0rZH+hpvF3;QC|?6C2R4H_o$b)BQMPM2 z;G~Ew4-O!M!OUrmI0<9T595Fpz&%yH6LR0&1?(1)trX`gQF8erQYs?lQC>ueNNLJX fl`2)L|585z?&-`o`IpIW00000NkvXXu0mjfNEn-4 literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-xhdpi/identity_unknown.png b/briar-android/res/drawable-xhdpi/identity_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b91a85841af0985cc2635ea3ec9e516719520e GIT binary patch literal 1470 zcmV;v1ws0WP)Px)cu7P-RA}DqnQe#_RT#&A&&-|mx~5_;t~=sto0Ti6t0!tnT~iYBB`btV=u028 zFibQkNGRCog@}qu2_+N~6v`qj`;eFvmIP-v3{x{J6dBEz)phT>&b>2FAG{mewz_xs zF6+H<|8Tf>&YUy9bI$)fGv~}eNhOt3QgO-{GsqY-sKoEPoIKkwGn=lJik_dyvjO*K ze|KJ^0VsODlSlZCuXUm+wN5m}7&HDFg#UP;8E7tMexD6!QyyI4W+pChGZWjCMb}{V zJqmo3O^*~S-|3_KL(i*>sgT&Okk~)3Qe})8I)JlpC@{%dd(>Kc6qsDB{5}~V=z>*V zI3um1X%$`Ng);Bt6S}b^DnAsN8UvhUG0VQjWKlt5dL+*)^1L1Ek=H#8$dZQ3>cbC zBY+!FDo!C~K}^*IFG`3Y|J;%Unczf;AYHbkYTBLCZ$d+alfaqmO5s8_wODK0dgx%c zd{st@Xa#UP@N_p-zXR49GwqP7oD|`&V&F>`_)=g_trLy7MdERQB%sYhQ?5tLT~RbI z76?_evjG6AXql)u3O~B;S5cZ_X=F$S$^kv1&YwTUZZojUTD##2onH#f0rmlZWFxc< zXiW}_Gkd;i+MUa+nm&8#z3nYd0=SOL{1~_ym|SRl>825LCrh+uaWXybx(roa2fDXX zMOzab-PZ2?xli3!thHbFFazhRGJVwT=?`{n*>|E}o|sD}k2-P4drE{og~oTg77l{o zcem1S`YiOWpPk554TAE%nxKldz^RoNlV7%oylidb_dV4Kg5Y=GuWW8T?Y`#w{HGd3;2q!he+Yu$LLWOn8hBfTRfWoTuhNJM)xN*$^C)q{OgE|-B088HJrI;L zIOm=Xlbc2e&s%God)xRR2rl@(|0VFI@B2+b5S;I2=c|AQU|AvaC5H>S7nK){6OCEs zg-^siRB=$&r^`0l*gZB_Xt35sd4{kHyb2t**1nr#oo9g2zzc=W?{Obst&Ii?4ZEU5 z%FO}p0=uF_sy_z5gAcp_)c2xVeSZx8K=5h%ndEm&@veV&LawKx-^_Oe)X#{~Bmj z&ML>6m1A^?i%I1fzcrRS`mOu1++DjUwfDdG+G(SWndW!RuU(YdtFhc&4E&r7$Ox6g zLn=F#mr0Zl%e;@*TuOfO?4{(^-Qw&`qNrZBVt7bpMlP4{4~fIrjSUA+bl` z%NkXAsc!nz$2*_f*l_TaIE*a@evbwiV=8Aj(bxz`sB*YW_CMTSzIK1g-TX_FU45j< zKDRyeUVEs${QbjavOl3p1k7-vvBsFZO~_v3K*#Z%g;VN{F`r&)b@nwj+2xIm_Q`a+ zbKV&9$()5#IzK266azn(W$4Vu-1LT9ohZ32>;*UCIrKVxFGlM)xgF zq;ESMyX{*eZ>hERyF3SACU7IL7j(JCk`jmay5noi3UPD@$U2}7I9=%cTt3RzZpwH& z!1I#Ax}Tctfh#Q6QotLoG20tMcR7$w3bom{g!!lzr~&4Kyw!Mh{_Dn=n(PKBot?P_ z&CkVviAiCHwRU@s>*fQ%3S-Oz^v_qSiO_5Q(*FhD7~>gZD)M;|WsLDk{E|v4sicC` Y-%B_^7(+Az6#xJL07*qoM6N<$f)t6=NdN!< literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-xhdpi/identity_unverified.png b/briar-android/res/drawable-xhdpi/identity_unverified.png new file mode 100644 index 0000000000000000000000000000000000000000..85785c09cceadbf4357e8ac8e0f25366ab5c5f19 GIT binary patch literal 1565 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 #FFFFFF #CCCCCC - #AAAAAA #AAAAAA #AAAAAA \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java index d36a862bd..7fe48d298 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java @@ -3,10 +3,12 @@ package org.briarproject.android.contact; import static android.widget.LinearLayout.HORIZONTAL; import static java.text.DateFormat.SHORT; import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; +import static org.briarproject.api.Author.Status.VERIFIED; import java.util.ArrayList; import org.briarproject.R; +import org.briarproject.android.util.AuthorView; import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.db.MessageHeader; @@ -41,14 +43,10 @@ class ConversationAdapter extends ArrayAdapter { layout.setBackgroundColor(res.getColor(R.color.unread_background)); } - TextView name = new TextView(ctx); - // Give me all the unused width - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(pad, pad, pad, pad); - name.setText(header.getAuthor().getName()); - layout.addView(name); + AuthorView authorView = new AuthorView(ctx); + authorView.setLayoutParams(WRAP_WRAP_1); + authorView.init(header.getAuthor().getName(), VERIFIED); + layout.addView(authorView); TextView date = new TextView(ctx); date.setTextSize(14); diff --git a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java index 932e6b49c..06c72712a 100644 --- a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java @@ -10,6 +10,7 @@ import static java.util.logging.Level.WARNING; import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; +import static org.briarproject.api.Author.Status.VERIFIED; import java.io.UnsupportedEncodingException; import java.util.concurrent.Executor; @@ -18,8 +19,9 @@ import java.util.logging.Logger; import javax.inject.Inject; import org.briarproject.R; -import org.briarproject.android.util.HorizontalBorder; +import org.briarproject.android.util.AuthorView; import org.briarproject.android.util.ElasticHorizontalSpace; +import org.briarproject.android.util.HorizontalBorder; import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.AuthorId; import org.briarproject.api.android.DatabaseUiExecutor; @@ -116,16 +118,12 @@ implements OnClickListener { header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); - int pad = LayoutUtils.getPadding(this); + AuthorView author = new AuthorView(this); + author.setLayoutParams(WRAP_WRAP_1); + author.init(authorName, VERIFIED); + header.addView(author); - TextView name = new TextView(this); - // Give me all the unused width - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(pad, pad, pad, pad); - name.setText(authorName); - header.addView(name); + int pad = LayoutUtils.getPadding(this); TextView date = new TextView(this); date.setTextSize(14); diff --git a/briar-android/src/org/briarproject/android/groups/GroupActivity.java b/briar-android/src/org/briarproject/android/groups/GroupActivity.java index 11ff72b1e..629a73b43 100644 --- a/briar-android/src/org/briarproject/android/groups/GroupActivity.java +++ b/briar-android/src/org/briarproject/android/groups/GroupActivity.java @@ -230,6 +230,7 @@ OnClickListener, OnItemClickListener { i.putExtra("briar.AUTHOR_ID", author.getId().getBytes()); i.putExtra("briar.AUTHOR_NAME", author.getName()); } + i.putExtra("briar.AUTHOR_STATUS", item.getAuthorStatus().name()); i.putExtra("briar.CONTENT_TYPE", item.getContentType()); i.putExtra("briar.TIMESTAMP", item.getTimestamp()); startActivityForResult(i, position); diff --git a/briar-android/src/org/briarproject/android/groups/GroupAdapter.java b/briar-android/src/org/briarproject/android/groups/GroupAdapter.java index 4900e2f3e..25195e5d3 100644 --- a/briar-android/src/org/briarproject/android/groups/GroupAdapter.java +++ b/briar-android/src/org/briarproject/android/groups/GroupAdapter.java @@ -7,6 +7,7 @@ import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; import java.util.ArrayList; import org.briarproject.R; +import org.briarproject.android.util.AuthorView; import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.Author; import org.briarproject.api.db.MessageHeader; @@ -32,34 +33,27 @@ class GroupAdapter extends ArrayAdapter { @Override public View getView(int position, View convertView, ViewGroup parent) { - MessageHeader item = getItem(position); + MessageHeader header = getItem(position); Context ctx = getContext(); - Resources res = ctx.getResources(); LinearLayout layout = new LinearLayout(ctx); layout.setOrientation(HORIZONTAL); - if(!item.isRead()) + if(!header.isRead()) { + Resources res = ctx.getResources(); layout.setBackgroundColor(res.getColor(R.color.unread_background)); - - TextView name = new TextView(ctx); - // Give me all the unused width - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(pad, pad, pad, pad); - Author author = item.getAuthor(); - if(author == null) { - name.setTextColor(res.getColor(R.color.anonymous_author)); - name.setText(R.string.anonymous); - } else { - name.setText(author.getName()); } - layout.addView(name); + + AuthorView authorView = new AuthorView(ctx); + authorView.setLayoutParams(WRAP_WRAP_1); + Author author = header.getAuthor(); + if(author == null) authorView.init(null, header.getAuthorStatus()); + else authorView.init(author.getName(), header.getAuthorStatus()); + layout.addView(authorView); TextView date = new TextView(ctx); date.setTextSize(14); - date.setPadding(pad, pad, pad, pad); - long then = item.getTimestamp(), now = System.currentTimeMillis(); + date.setPadding(0, pad, pad, pad); + long then = header.getTimestamp(), now = System.currentTimeMillis(); date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT)); layout.addView(date); diff --git a/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java b/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java index 83e97520d..d4591a8e3 100644 --- a/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java +++ b/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java @@ -18,9 +18,11 @@ import java.util.logging.Logger; import javax.inject.Inject; import org.briarproject.R; -import org.briarproject.android.util.HorizontalBorder; +import org.briarproject.android.util.AuthorView; import org.briarproject.android.util.ElasticHorizontalSpace; +import org.briarproject.android.util.HorizontalBorder; import org.briarproject.android.util.LayoutUtils; +import org.briarproject.api.Author; import org.briarproject.api.android.DatabaseUiExecutor; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; @@ -83,6 +85,9 @@ implements OnClickListener { timestamp = i.getLongExtra("briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); String authorName = i.getStringExtra("briar.AUTHOR_NAME"); + String s = i.getStringExtra("briar.AUTHOR_STATUS"); + if(s == null) throw new IllegalStateException(); + Author.Status authorStatus = Author.Status.valueOf(s); if(state == null) { read = false; @@ -109,21 +114,12 @@ implements OnClickListener { header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); - int pad = LayoutUtils.getPadding(this); + AuthorView author = new AuthorView(this); + author.setLayoutParams(WRAP_WRAP_1); + author.init(authorName, authorStatus); + header.addView(author); - TextView name = new TextView(this); - // Give me all the unused width - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(pad, pad, pad, pad); - if(authorName == null) { - name.setTextColor(res.getColor(R.color.anonymous_author)); - name.setText(R.string.anonymous); - } else { - name.setText(authorName); - } - header.addView(name); + int pad = LayoutUtils.getPadding(this); TextView date = new TextView(this); date.setTextSize(14); diff --git a/briar-android/src/org/briarproject/android/util/AuthorView.java b/briar-android/src/org/briarproject/android/util/AuthorView.java new file mode 100644 index 000000000..fbb2d8e77 --- /dev/null +++ b/briar-android/src/org/briarproject/android/util/AuthorView.java @@ -0,0 +1,51 @@ +package org.briarproject.android.util; + +import org.briarproject.R; +import org.briarproject.api.Author; + +import android.content.Context; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class AuthorView extends LinearLayout { + + public AuthorView(Context ctx) { + super(ctx); + } + + public void init(String name, Author.Status status) { + Context ctx = getContext(); + int pad = LayoutUtils.getPadding(ctx); + setOrientation(VERTICAL); + TextView nameView = new TextView(ctx); + // Give me all the unused width + nameView.setTextSize(18); + nameView.setMaxLines(1); + nameView.setPadding(pad, pad, pad, pad); + if(name == null) nameView.setText(R.string.anonymous); + else nameView.setText(name); + addView(nameView); + LinearLayout statusLayout = new LinearLayout(ctx); + statusLayout.setOrientation(HORIZONTAL); + ImageView statusView = new ImageView(ctx); + statusView.setPadding(pad, 0, pad, pad); + switch(status) { + case ANONYMOUS: + statusView.setImageResource(R.drawable.identity_anonymous); + break; + case UNKNOWN: + statusView.setImageResource(R.drawable.identity_unknown); + break; + case UNVERIFIED: + statusView.setImageResource(R.drawable.identity_unverified); + break; + case VERIFIED: + statusView.setImageResource(R.drawable.identity_verified); + break; + } + statusLayout.addView(statusView); + statusLayout.addView(new ElasticHorizontalSpace(ctx)); + addView(statusLayout); + } +} diff --git a/briar-api/src/org/briarproject/api/Author.java b/briar-api/src/org/briarproject/api/Author.java index 16693137b..0ff392f9f 100644 --- a/briar-api/src/org/briarproject/api/Author.java +++ b/briar-api/src/org/briarproject/api/Author.java @@ -7,6 +7,8 @@ import java.io.UnsupportedEncodingException; /** A pseudonym for a user. */ public class Author { + public enum Status { ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED }; + private final AuthorId id; private final String name; private final byte[] publicKey; diff --git a/briar-api/src/org/briarproject/api/db/MessageHeader.java b/briar-api/src/org/briarproject/api/db/MessageHeader.java index 64831d9fe..4a1b2054b 100644 --- a/briar-api/src/org/briarproject/api/db/MessageHeader.java +++ b/briar-api/src/org/briarproject/api/db/MessageHeader.java @@ -9,16 +9,19 @@ public class MessageHeader { private final MessageId id, parent; private final GroupId groupId; private final Author author; + private final Author.Status authorStatus; private final String contentType; private final long timestamp; private final boolean read; public MessageHeader(MessageId id, MessageId parent, GroupId groupId, - Author author, String contentType, long timestamp, boolean read) { + Author author, Author.Status authorStatus, String contentType, + long timestamp, boolean read) { this.id = id; this.parent = parent; this.groupId = groupId; this.author = author; + this.authorStatus = authorStatus; this.contentType = contentType; this.timestamp = timestamp; this.read = read; @@ -51,6 +54,11 @@ public class MessageHeader { return author; } + /** Returns the status of the message's author. */ + public Author.Status getAuthorStatus() { + return authorStatus; + } + /** Returns the message's content type. */ public String getContentType() { return contentType; diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java index ce5f74aab..004c0787b 100644 --- a/briar-core/src/org/briarproject/db/JdbcDatabase.java +++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java @@ -4,6 +4,9 @@ import static java.sql.Types.BINARY; import static java.sql.Types.VARCHAR; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static org.briarproject.api.Author.Status.ANONYMOUS; +import static org.briarproject.api.Author.Status.UNKNOWN; +import static org.briarproject.api.Author.Status.VERIFIED; import static org.briarproject.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS; import static org.briarproject.api.messaging.MessagingConstants.RETENTION_GRANULARITY; import static org.briarproject.db.ExponentialBackoff.calculateExpiry; @@ -1525,10 +1528,12 @@ abstract class JdbcDatabase implements Database { boolean read = rs.getBoolean(7); if(incoming) { headers.add(new MessageHeader(id, parent, groupId, - remoteAuthor, contentType, timestamp, read)); + remoteAuthor, VERIFIED, contentType, timestamp, + read)); } else { headers.add(new MessageHeader(id, parent, groupId, - localAuthor, contentType, timestamp, read)); + localAuthor, VERIFIED, contentType, timestamp, + read)); } } rs.close(); @@ -1701,9 +1706,14 @@ abstract class JdbcDatabase implements Database { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT messageId, parentId, authorId, authorName," - + " authorKey, contentType, timestamp, read" - + " FROM messages" + String sql = "SELECT messageId, parentId, m.authorId, authorName," + + " authorKey, contentType, timestamp, read," + + " la.authorId IS NOT NULL, c.authorId IS NOT NULL" + + " FROM messages AS m" + + " LEFT OUTER JOIN localAuthors AS la" + + " ON m.authorId = la.authorId" + + " LEFT OUTER JOIN contacts AS c" + + " ON m.authorId = c.authorId" + " WHERE groupId = ?"; ps = txn.prepareStatement(sql); ps.setBytes(1, g.getBytes()); @@ -1726,8 +1736,14 @@ abstract class JdbcDatabase implements Database { String contentType = rs.getString(6); long timestamp = rs.getLong(7); boolean read = rs.getBoolean(8); + boolean isSelf = rs.getBoolean(9); + boolean isContact = rs.getBoolean(10); + Author.Status authorStatus; + if(author == null) authorStatus = ANONYMOUS; + else if(isSelf || isContact) authorStatus = VERIFIED; + else authorStatus = UNKNOWN; headers.add(new MessageHeader(id, parent, g, author, - contentType, timestamp, read)); + authorStatus, contentType, timestamp, read)); } rs.close(); ps.close(); diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java index 1799cfb64..37a4c944f 100644 --- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java +++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java @@ -41,7 +41,6 @@ import org.briarproject.api.messaging.MessageId; import org.briarproject.api.transport.Endpoint; import org.briarproject.api.transport.TemporarySecret; import org.briarproject.system.SystemClock; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -898,42 +897,26 @@ public class H2DatabaseTest extends BriarTestCase { // Mark one of the messages read db.setReadFlag(txn, messageId, true); - // Retrieve the message headers + // Retrieve the message headers (order is undefined) Collection headers = db.getMessageHeaders(txn, groupId); - Iterator it = headers.iterator(); - boolean messageFound = false, message1Found = false; - // First header (order is undefined) - assertTrue(it.hasNext()); - MessageHeader header = it.next(); - if(messageId.equals(header.getId())) { - assertHeadersMatch(message, header); - assertTrue(header.isRead()); - messageFound = true; - } else if(messageId1.equals(header.getId())) { - assertHeadersMatch(message1, header); - assertFalse(header.isRead()); - message1Found = true; - } else { - fail(); + assertEquals(2, headers.size()); + boolean firstFound = false, secondFound = false; + for(MessageHeader header : headers) { + if(messageId.equals(header.getId())) { + assertHeadersMatch(message, header); + assertTrue(header.isRead()); + firstFound = true; + } else if(messageId1.equals(header.getId())) { + assertHeadersMatch(message1, header); + assertFalse(header.isRead()); + secondFound = true; + } else { + fail(); + } } - // Second header - assertTrue(it.hasNext()); - header = it.next(); - if(messageId.equals(header.getId())) { - assertHeadersMatch(message, header); - assertTrue(header.isRead()); - messageFound = true; - } else if(messageId1.equals(header.getId())) { - assertHeadersMatch(message1, header); - assertFalse(header.isRead()); - message1Found = true; - } else { - fail(); - } - // No more headers - assertFalse(it.hasNext()); - assertTrue(messageFound); - assertTrue(message1Found); + // Both the headers should have been retrieved + assertTrue(firstFound); + assertTrue(secondFound); db.commitTransaction(txn); db.close(); @@ -950,6 +933,62 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(m.getTimestamp(), h.getTimestamp()); } + @Test + public void testAuthorStatus() throws Exception { + Database db = open(false); + Connection txn = db.startTransaction(); + + // Add a contact and subscribe to a group + db.addLocalAuthor(txn, localAuthor); + assertEquals(contactId, db.addContact(txn, author, localAuthorId)); + db.addGroup(txn, group); + + // Store a message from the contact - status VERIFIED + db.addMessage(txn, message, false); + AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); + // Store a message from an unknown author - status UNKNOWN + Author author1 = new Author(authorId1, "Bob", + new byte[MAX_PUBLIC_KEY_LENGTH]); + MessageId messageId1 = new MessageId(TestUtils.getRandomId()); + Message message1 = new TestMessage(messageId1, null, group, author1, + contentType, subject, timestamp, raw); + db.addMessage(txn, message1, false); + // Store an anonymous message - status ANONYMOUS + MessageId messageId2 = new MessageId(TestUtils.getRandomId()); + Message message2 = new TestMessage(messageId2, null, group, null, + contentType, subject, timestamp, raw); + db.addMessage(txn, message2, false); + + // Retrieve the message headers (order is undefined) + Collection headers = db.getMessageHeaders(txn, groupId); + assertEquals(3, headers.size()); + boolean firstFound = false, secondFound = false, thirdFound = false; + for(MessageHeader header : headers) { + if(messageId.equals(header.getId())) { + assertHeadersMatch(message, header); + assertEquals(Author.Status.VERIFIED, header.getAuthorStatus()); + firstFound = true; + } else if(messageId1.equals(header.getId())) { + assertHeadersMatch(message1, header); + assertEquals(Author.Status.UNKNOWN, header.getAuthorStatus()); + secondFound = true; + } else if(messageId2.equals(header.getId())) { + assertHeadersMatch(message2, header); + assertEquals(Author.Status.ANONYMOUS, header.getAuthorStatus()); + thirdFound = true; + } else { + fail(); + } + } + // All of the headers should have been retrieved + assertTrue(firstFound); + assertTrue(secondFound); + assertTrue(thirdFound); + + db.commitTransaction(txn); + db.close(); + } + @Test public void testReadFlag() throws Exception { Database db = open(false);