From 127ed22c40dc169a0e31848d9d68e9768b92753a Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Tue, 12 Mar 2013 11:26:46 +0000
Subject: [PATCH] Show number of unread messages rather than total number of
 messages.

---
 .../res/drawable-hdpi/content_new_email.png   | Bin 0 -> 1517 bytes
 .../res/drawable-mdpi/content_new_email.png   | Bin 0 -> 1393 bytes
 .../android/AscendingHeaderComparator.java    |  19 +++
 .../android/DescendingHeaderComparator.java   |  19 +++
 .../messages/AscendingHeaderComparator.java   |  19 ---
 .../messages/ConversationActivity.java        |   1 +
 .../messages/ConversationListActivity.java    | 111 +++++++++---------
 .../messages/ConversationListAdapter.java     |  23 ++--
 .../messages/ConversationListItem.java        |  30 ++---
 .../messages/DescendingHeaderComparator.java  |  19 ---
 10 files changed, 121 insertions(+), 120 deletions(-)
 create mode 100644 briar-android/res/drawable-hdpi/content_new_email.png
 create mode 100644 briar-android/res/drawable-mdpi/content_new_email.png
 create mode 100644 briar-android/src/net/sf/briar/android/AscendingHeaderComparator.java
 create mode 100644 briar-android/src/net/sf/briar/android/DescendingHeaderComparator.java
 delete mode 100644 briar-android/src/net/sf/briar/android/messages/AscendingHeaderComparator.java
 delete mode 100644 briar-android/src/net/sf/briar/android/messages/DescendingHeaderComparator.java

diff --git a/briar-android/res/drawable-hdpi/content_new_email.png b/briar-android/res/drawable-hdpi/content_new_email.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1c6bcf2e001d754e21e5d9bad1d4a8de22e369a
GIT binary patch
literal 1517
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y
zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP
zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg
zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN
z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83
zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw
zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg
z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVip)y>4%($UD&$-u?X(ACh=#L&{!#L3yw
z&D7A`#K{n**Cju>G&eP`1g19yq1PCvUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnqfV
zG!Lpb1-Dxaaq86vIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1z&JTRPhJk@8-qXb~
zq~g|_S+UwIffC2l)2{E<7T1`veafOeIU7}6^*$)Z{9;-c`%}!Wq5A3CBdkJi-CCS9
zPq8lQNL_3DPyPHglir&*XBwufJzshMTx;3$pL2`neHNQ)xU9v}MD>Xx>yn1k9iRFm
zbj(`abx&}daAXzSz|+V5Gf8RU4?%}5&1xSsJr;1hv3$qq!nKD>?8KkfO3!oyeAX%|
zwF@nOe~we9iF?uq@0R_$d1@L=3!W`w`{pS0r8)2dkHl4$-;2fS8E+>r-`O$CP4Mai
zzBd<gE_`QK3hSIMaNdt~*+Jn5*6C_Wy;B@+HFktP3Vijou<HA?V8(wk409hata<HH
z=4dX#oXgq~p&G~aD1l?kh2Jx0D^6j3|K*Z}>KbuRp}l4<pH%HQ+#HyHEV_SU*ILG-
z%z{_b9(|os;kA8&W*p}ZLC>2$f9`%hJID2g=u4*l2e;NAdCT=g_~F`GKEA(xdjcBo
zyHp+EyulJ`GN;D#&dP>Bm!<b!EU?}CDEv_#Ytg|B{l%BcZhY77Tj9Q6`Awdi+$-k7
z75oV+N=_b-{?YhKC&c!^^~sV3-m~}av0d;|;Nq=WC+BIDTU~j>v4k^lyHI4*pPp=A
zv->>Lg=Z{pwiUK`Hvf*u$GLOd_VWHMQ;~g=xkdDf<T3ljk9q@mOD->M&dR8$E3gvK
zHQ-S@F#F{FAQgj5qo5rRLIqgfy|nq5_=0g>0k3U-sdfC{6FYei2}Chzt8JFwzi~G6
z)C9&kY+Kp(`8=ynewZfGJ^S^7b564odneq^)O?VT9muCulKwVeE_+3y{KcG<%H*}D
j>P;sw1u5M5sC$6nwb5R!v=e_9g9>0zS3j3^P6<r_4W2bn

literal 0
HcmV?d00001

diff --git a/briar-android/res/drawable-mdpi/content_new_email.png b/briar-android/res/drawable-mdpi/content_new_email.png
new file mode 100644
index 0000000000000000000000000000000000000000..7d96f28d15f5a4a6906724b4a1516b0c1504f6b2
GIT binary patch
literal 1393
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y
zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP
zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg
zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN
z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83
zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw
zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg
z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVip)y>4%($UP+$-u?X(ACh=#L&{!#L3yw
z&D7A`#K{n**Cju>G&eP`1g19yq}R>F)xy!m2&Z09V#qB3+U$~Alv$RV;#QQOs{r=2
zRVHq?nBX)Isy79jTOj^0#i>^x=oo!a)FMSSObD2MKumbT1#;j?KQ#}S-iv?<`%nV2
zDgy)KV^0^ykcwMxrtkJ*b`)vbd~#NWYYxlhj;^(Wo#Fx;Lqy~c9J_bO{lc;18#Zke
zlor+2_g}!$(y?|yuY%AbHMQNZ?LX-Ayv`|`d?roM=7S;E?&p7s&&@QJK3q7*WzIC8
zBRLzn4L<+;qjXI(fjRc8M`L*b&nsTm2F?vEI$akMV;`{2VM%LfT)kkKA#>?3?yJnH
zA9#0}er@rLmrpdBbt-Lhe?<PzOB^pUH_E#_;Hh9<{-8seTg2exvYkxjC6{^xEI(LU
zFz_eHOljJr5GS@gVP>SoV&;wO8Y(ZGm)j`%zALSo_4<QJ=g&5oUSKafykzaE*mI3C
z8U^a@51P)UD6)BIGwC;k8XSwO;tF<~yt-n;q5Z8BGUXMOPKcjg%9V4u|EAC56VJE|
zYg#(KPF4zOjJ7h;3g+CIuI5s_cDuBNM}yZ19`~|I|HFl5wYf<YFJZe<nck8w=6PcN
zo<8=26Xr8CXN&CE##tuuI-K)Wj)r$~*Ih>S`16wc*^ge_bulKnS$dUcU9LT2s?gG%
zH%o8XvL@y*<QTloyAT-nJ$l|hZ8t@QvyD?Hrn%{#o;2A@#g5S{kVD`;YxTUF8+qFf
z?pw|iCc-3hbovBU-^&qf6CXxe>nYsL;43-Q^&oQQtpD=M3%P#?CNRw0+hv@@|4;%{
O2zt8uxvX<aXaWGkvg~RA

literal 0
HcmV?d00001

diff --git a/briar-android/src/net/sf/briar/android/AscendingHeaderComparator.java b/briar-android/src/net/sf/briar/android/AscendingHeaderComparator.java
new file mode 100644
index 0000000000..26ac273e33
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/AscendingHeaderComparator.java
@@ -0,0 +1,19 @@
+package net.sf.briar.android;
+
+import java.util.Comparator;
+
+import net.sf.briar.api.db.MessageHeader;
+
+public class AscendingHeaderComparator implements Comparator<MessageHeader> {
+
+	public static final AscendingHeaderComparator INSTANCE =
+			new AscendingHeaderComparator();
+
+	public int compare(MessageHeader a, MessageHeader b) {
+		// The oldest message comes first
+		long aTime = a.getTimestamp(), bTime = b.getTimestamp();
+		if(aTime < bTime) return -1;
+		if(aTime > bTime) return 1;
+		return 0;
+	}
+}
diff --git a/briar-android/src/net/sf/briar/android/DescendingHeaderComparator.java b/briar-android/src/net/sf/briar/android/DescendingHeaderComparator.java
new file mode 100644
index 0000000000..02506d7a94
--- /dev/null
+++ b/briar-android/src/net/sf/briar/android/DescendingHeaderComparator.java
@@ -0,0 +1,19 @@
+package net.sf.briar.android;
+
+import java.util.Comparator;
+
+import net.sf.briar.api.db.MessageHeader;
+
+public class DescendingHeaderComparator implements Comparator<MessageHeader> {
+
+	public static final DescendingHeaderComparator INSTANCE =
+			new DescendingHeaderComparator();
+
+	public int compare(MessageHeader a, MessageHeader b) {
+		// The newest message comes first
+		long aTime = a.getTimestamp(), bTime = b.getTimestamp();
+		if(aTime > bTime) return -1;
+		if(aTime < bTime) return 1;
+		return 0;
+	}
+}
\ No newline at end of file
diff --git a/briar-android/src/net/sf/briar/android/messages/AscendingHeaderComparator.java b/briar-android/src/net/sf/briar/android/messages/AscendingHeaderComparator.java
deleted file mode 100644
index 651f719bea..0000000000
--- a/briar-android/src/net/sf/briar/android/messages/AscendingHeaderComparator.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.sf.briar.android.messages;
-
-import java.util.Comparator;
-
-import net.sf.briar.api.db.PrivateMessageHeader;
-
-class AscendingHeaderComparator implements Comparator<PrivateMessageHeader> {
-
-	static final AscendingHeaderComparator INSTANCE =
-			new AscendingHeaderComparator();
-
-	public int compare(PrivateMessageHeader a, PrivateMessageHeader b) {
-		// The oldest message comes first
-		long aTime = a.getTimestamp(), bTime = b.getTimestamp();
-		if(aTime < bTime) return -1;
-		if(aTime > bTime) return 1;
-		return 0;
-	}
-}
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
index 247898665e..60d3869012 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java
@@ -13,6 +13,7 @@ import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
 import net.sf.briar.R;
+import net.sf.briar.android.AscendingHeaderComparator;
 import net.sf.briar.android.BriarActivity;
 import net.sf.briar.android.BriarService;
 import net.sf.briar.android.BriarService.BriarServiceConnection;
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
index bd3e6d48e0..5618057483 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
@@ -91,7 +91,11 @@ implements OnClickListener, DatabaseListener {
 				serviceConnection, 0);
 
 		// Add some fake messages to the database in a background thread
-		// FIXME: Remove this
+		insertFakeMessages();
+	}
+
+	// FIXME: Remove this
+	private void insertFakeMessages() {
 		final DatabaseComponent db = this.db;
 		final MessageFactory messageFactory = this.messageFactory;
 		dbExecutor.execute(new Runnable() {
@@ -102,42 +106,39 @@ implements OnClickListener, DatabaseListener {
 					// If there are no messages in the DB, create some fake ones
 					Collection<PrivateMessageHeader> headers =
 							db.getPrivateMessageHeaders();
-					if(headers.isEmpty()) {
-						if(LOG.isLoggable(INFO))
-							LOG.info("Inserting fake contact and messages");
-						// Insert a fake contact
-						ContactId contactId = db.addContact("Carol");
-						// Insert some text messages to and from the contact
-						for(int i = 0; i < 20; i++) {
-							String body;
-							if(i % 3 == 0) {
-								body = "Message " + i + " is short.";
-							} else { 
-								body = "Message " + i + " is long enough to"
-										+ " wrap onto a second line on some"
-										+ " screens.";
-							}
-							Message m = messageFactory.createPrivateMessage(
-									null, "text/plain", body.getBytes("UTF-8"));
-							if(Math.random() < 0.5)
-								db.addLocalPrivateMessage(m, contactId);
-							else db.receiveMessage(contactId, m);
-							db.setReadFlag(m.getId(), i != 3);
+					if(!headers.isEmpty()) return;
+					if(LOG.isLoggable(INFO))
+						LOG.info("Inserting fake private messages");
+					// We'll also need a contact to exchange messages with
+					ContactId contactId = db.addContact("Carol");
+					// Insert some text messages to and from the contact
+					for(int i = 0; i < 20; i++) {
+						String body;
+						if(i % 3 == 0) {
+							body = "Message " + i + " is short.";
+						} else { 
+							body = "Message " + i + " is long enough to"
+									+ " wrap onto a second line on some"
+									+ " screens.";
 						}
-						// Insert a non-text message
 						Message m = messageFactory.createPrivateMessage(null,
-								"image/jpeg", new byte[1000]);
-						db.receiveMessage(contactId, m);
-						db.setStarredFlag(m.getId(), true);
-						// Insert a long text message
-						StringBuilder s = new StringBuilder();
-						for(int i = 0; i < 100; i++)
-							s.append("This is a very tedious message. ");
-						m = messageFactory.createPrivateMessage(m.getId(),
-								"text/plain", s.toString().getBytes("UTF-8"));
-						db.addLocalPrivateMessage(m, contactId);
-						db.setStarredFlag(m.getId(), true);
+								"text/plain", body.getBytes("UTF-8"));
+						if(Math.random() < 0.5)
+							db.addLocalPrivateMessage(m, contactId);
+						else db.receiveMessage(contactId, m);
+						db.setReadFlag(m.getId(), i % 4 == 0);
 					}
+					// Insert a non-text message
+					Message m = messageFactory.createPrivateMessage(null,
+							"image/jpeg", new byte[1000]);
+					db.receiveMessage(contactId, m);
+					// Insert a long text message
+					StringBuilder s = new StringBuilder();
+					for(int i = 0; i < 100; i++)
+						s.append("This is a very tedious message. ");
+					m = messageFactory.createPrivateMessage(m.getId(),
+							"text/plain", s.toString().getBytes("UTF-8"));
+					db.addLocalPrivateMessage(m, contactId);
 				} catch(DbException e) {
 					if(LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
@@ -162,27 +163,6 @@ implements OnClickListener, DatabaseListener {
 		reloadMessageHeaders();
 	}
 
-	@Override
-	public void onDestroy() {
-		super.onDestroy();
-		db.removeListener(this);
-		unbindService(serviceConnection);
-	}
-
-	public void onClick(View view) {
-		startActivity(new Intent(this, WriteMessageActivity.class));
-	}
-
-	public void eventOccurred(DatabaseEvent e) {
-		if(e instanceof MessageAddedEvent) {
-			if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
-			reloadMessageHeaders();
-		} else if(e instanceof MessageExpiredEvent) {
-			if(LOG.isLoggable(INFO)) LOG.info("Message removed, reloading");
-			reloadMessageHeaders();
-		}
-	}
-
 	private void reloadMessageHeaders() {
 		final DatabaseComponent db = this.db;
 		dbExecutor.execute(new Runnable() {
@@ -249,4 +229,25 @@ implements OnClickListener, DatabaseListener {
 		}
 		return list;
 	}
+
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		db.removeListener(this);
+		unbindService(serviceConnection);
+	}
+
+	public void onClick(View view) {
+		startActivity(new Intent(this, WriteMessageActivity.class));
+	}
+
+	public void eventOccurred(DatabaseEvent e) {
+		if(e instanceof MessageAddedEvent) {
+			if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
+			reloadMessageHeaders();
+		} else if(e instanceof MessageExpiredEvent) {
+			if(LOG.isLoggable(INFO)) LOG.info("Message removed, reloading");
+			reloadMessageHeaders();
+		}
+	}
 }
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java b/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java
index f58645f0fd..542a14d52e 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java
@@ -10,6 +10,7 @@ import static java.text.DateFormat.SHORT;
 import java.util.ArrayList;
 
 import net.sf.briar.android.widgets.CommonLayoutParams;
+import net.sf.briar.util.StringUtils;
 import android.content.Context;
 import android.content.Intent;
 import android.text.format.DateUtils;
@@ -45,17 +46,21 @@ implements OnItemClickListener {
 
 		TextView name = new TextView(ctx);
 		name.setTextSize(18);
-		name.setPadding(10, 10, 10, 0);
-		name.setText(item.getName() + " (" + item.getLength() + ")");
+		name.setPadding(10, 10, 10, 10);
+		int unread = item.getUnreadCount();
+		if(unread > 0) name.setText(item.getName() + " (" + unread + ")");
+		else name.setText(item.getName());
 		innerLayout.addView(name);
 
-		TextView subject = new TextView(ctx);
-		subject.setTextSize(14);
-		subject.setMaxLines(2);
-		subject.setPadding(10, 0, 10, 10);
-		if(!item.isRead()) subject.setTypeface(null, BOLD);
-		subject.setText(item.getSubject());
-		innerLayout.addView(subject);
+		if(!StringUtils.isNullOrEmpty(item.getSubject())) {
+			TextView subject = new TextView(ctx);
+			subject.setTextSize(14);
+			subject.setMaxLines(2);
+			subject.setPadding(10, 0, 10, 10);
+			if(unread > 0) subject.setTypeface(null, BOLD);
+			subject.setText(item.getSubject());
+			innerLayout.addView(subject);
+		}
 		layout.addView(innerLayout);
 
 		TextView date = new TextView(ctx);
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java b/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java
index 8ef55dd07b..b168f7a9bc 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java
@@ -3,37 +3,35 @@ package net.sf.briar.android.messages;
 import java.util.Collections;
 import java.util.List;
 
+import net.sf.briar.android.DescendingHeaderComparator;
 import net.sf.briar.api.Contact;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.db.PrivateMessageHeader;
 
 class ConversationListItem {
 
-	private final ContactId contactId;
-	private final String name, subject;
+	private final Contact contact;
+	private final String subject;
 	private final long timestamp;
-	private final int length;
-	private final boolean read;
+	private final int unread;
 
 	ConversationListItem(Contact contact, List<PrivateMessageHeader> headers) {
 		if(headers.isEmpty()) throw new IllegalArgumentException();
-		contactId = contact.getId();
-		name = contact.getName();
+		this.contact = contact;
 		Collections.sort(headers, DescendingHeaderComparator.INSTANCE);
 		subject = headers.get(0).getSubject();
 		timestamp = headers.get(0).getTimestamp();
-		length = headers.size();
-		boolean allRead = true;
-		for(PrivateMessageHeader h : headers) allRead &= h.isRead();
-		read = allRead;
+		int unread = 0;
+		for(PrivateMessageHeader h : headers) if(!h.isRead()) unread++;
+		this.unread = unread;
 	}
 
 	ContactId getContactId() {
-		return contactId;
+		return contact.getId();
 	}
 
 	String getName() {
-		return name;
+		return contact.getName();
 	}
 
 	String getSubject() {
@@ -44,11 +42,7 @@ class ConversationListItem {
 		return timestamp;
 	}
 
-	boolean isRead() {
-		return read;
-	}
-
-	int getLength() {
-		return length;
+	int getUnreadCount() {
+		return unread;
 	}
 }
diff --git a/briar-android/src/net/sf/briar/android/messages/DescendingHeaderComparator.java b/briar-android/src/net/sf/briar/android/messages/DescendingHeaderComparator.java
deleted file mode 100644
index 1a8032f098..0000000000
--- a/briar-android/src/net/sf/briar/android/messages/DescendingHeaderComparator.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.sf.briar.android.messages;
-
-import java.util.Comparator;
-
-import net.sf.briar.api.db.PrivateMessageHeader;
-
-class DescendingHeaderComparator implements Comparator<PrivateMessageHeader> {
-
-	static final DescendingHeaderComparator INSTANCE =
-			new DescendingHeaderComparator();
-
-	public int compare(PrivateMessageHeader a, PrivateMessageHeader b) {
-		// The newest message comes first
-		long aTime = a.getTimestamp(), bTime = b.getTimestamp();
-		if(aTime > bTime) return -1;
-		if(aTime < bTime) return 1;
-		return 0;
-	}
-}
\ No newline at end of file
-- 
GitLab