diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml
index 986454bcf..7dfd4ee1f 100644
--- a/briar-android/res/values/color.xml
+++ b/briar-android/res/values/color.xml
@@ -4,6 +4,7 @@
#FFFFFF
#FFFFFF
#CCCCCC
- #AAAAAA
- #000000
+ #999999
+ #999999
+ #999999
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index dbbb46c06..d3580ced8 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -40,6 +40,7 @@
Contact added
Done
Messages
+ (No messages)
From: %1$s
To: %1$s
New Message
@@ -47,6 +48,7 @@
To:
(Anonymous)
Groups
+ (No posts)
New Group
Choose a name for your group:
New Post
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java
index 048f62256..121fd5039 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java
@@ -17,7 +17,6 @@ import net.sf.briar.android.widgets.HorizontalSpace;
import net.sf.briar.api.Author;
import net.sf.briar.api.db.GroupMessageHeader;
import net.sf.briar.api.messaging.Rating;
-import net.sf.briar.util.StringUtils;
import android.content.Context;
import android.content.res.Resources;
import android.text.format.DateUtils;
@@ -77,22 +76,20 @@ class GroupAdapter extends ArrayAdapter {
name.setTextColor(res.getColor(R.color.anonymous_author));
name.setText(R.string.anonymous);
} else {
- name.setTextColor(res.getColor(R.color.pseudonymous_author));
name.setText(author.getName());
}
authorLayout.addView(name);
innerLayout.addView(authorLayout);
if(item.getContentType().equals("text/plain")) {
- if(!StringUtils.isNullOrEmpty(item.getSubject())) {
- 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);
- }
+ TextView subject = new TextView(ctx);
+ subject.setTextSize(14);
+ subject.setMaxLines(2);
+ subject.setPadding(10, 0, 10, 10);
+ if(!item.isRead()) subject.setTypeface(null, BOLD);
+ String s = item.getSubject();
+ subject.setText(s == null ? "" : s);
+ innerLayout.addView(subject);
} else {
LinearLayout attachmentLayout = new LinearLayout(ctx);
attachmentLayout.setOrientation(HORIZONTAL);
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
index 5ca3267d5..ccbfa93dc 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
@@ -10,10 +10,10 @@ import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -62,7 +62,6 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
@Inject private volatile DatabaseComponent db;
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
private volatile boolean restricted = false;
- private volatile boolean noGroups = true;
@Override
public void onCreate(Bundle state) {
@@ -126,23 +125,39 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
}
private void loadHeaders() {
+ clearHeaders();
dbUiExecutor.execute(new Runnable() {
public void run() {
try {
serviceConnection.waitForStartup();
long now = System.currentTimeMillis();
- if(restricted) noGroups = db.getLocalGroups().isEmpty();
- for(Group g : db.getSubscriptions()) {
- // Filter out restricted/unrestricted groups
- if(g.isRestricted() != restricted) continue;
- if(!restricted) noGroups = false;
- try {
- Collection headers =
- db.getMessageHeaders(g.getId());
- displayHeaders(g, headers);
- } catch(NoSuchSubscriptionException e) {
- if(LOG.isLoggable(INFO))
- LOG.info("Subscription removed");
+ Collection subs = db.getSubscriptions();
+ if(restricted) {
+ Set local = new HashSet();
+ for(Group g : db.getLocalGroups()) local.add(g.getId());
+ for(Group g : subs) {
+ if(!g.isRestricted()) continue;
+ boolean postable = local.contains(g.getId());
+ try {
+ Collection headers =
+ db.getMessageHeaders(g.getId());
+ displayHeaders(g, postable, headers);
+ } catch(NoSuchSubscriptionException e) {
+ if(LOG.isLoggable(INFO))
+ LOG.info("Subscription removed");
+ }
+ }
+ } else {
+ for(Group g : subs) {
+ if(g.isRestricted()) continue;
+ try {
+ Collection headers =
+ db.getMessageHeaders(g.getId());
+ displayHeaders(g, true, headers);
+ } catch(NoSuchSubscriptionException e) {
+ if(LOG.isLoggable(INFO))
+ LOG.info("Subscription removed");
+ }
}
}
long duration = System.currentTimeMillis() - now;
@@ -160,20 +175,24 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
});
}
- private void displayHeaders(final Group g,
+ private void clearHeaders() {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ adapter.clear();
+ }
+ });
+ }
+
+ private void displayHeaders(final Group g, final boolean postable,
final Collection headers) {
runOnUiThread(new Runnable() {
public void run() {
// Remove the old item, if any
GroupListItem item = findGroup(g.getId());
if(item != null) adapter.remove(item);
- // Add a new item if there are any headers to display
- if(!headers.isEmpty()) {
- List headerList =
- new ArrayList(headers);
- adapter.add(new GroupListItem(g, headerList));
- adapter.sort(GroupComparator.INSTANCE);
- }
+ // Add a new item
+ adapter.add(new GroupListItem(g, postable, headers));
+ adapter.sort(GroupComparator.INSTANCE);
adapter.notifyDataSetChanged();
selectFirstUnread();
}
@@ -219,7 +238,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
startActivity(new Intent(this, CreateBlogActivity.class));
else startActivity(new Intent(this, CreateGroupActivity.class));
} else if(view == composeButton) {
- if(noGroups) {
+ if(countPostableGroups() == 0) {
NoGroupsDialog dialog = new NoGroupsDialog();
dialog.setListener(this);
dialog.setRestricted(restricted);
@@ -232,6 +251,13 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
}
}
+ private int countPostableGroups() {
+ int postable = 0, count = adapter.getCount();
+ for(int i = 0; i < count; i++)
+ if(adapter.getItem(i).isPostable()) postable++;
+ return postable;
+ }
+
public void eventOccurred(DatabaseEvent e) {
if(e instanceof GroupMessageAddedEvent) {
Group g = ((GroupMessageAddedEvent) e).getGroup();
@@ -258,12 +284,15 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
try {
serviceConnection.waitForStartup();
long now = System.currentTimeMillis();
+ boolean postable;
+ if(restricted) postable = db.getLocalGroups().contains(g);
+ else postable = true;
Collection headers =
db.getMessageHeaders(g.getId());
long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO))
LOG.info("Partial load took " + duration + " ms");
- displayHeaders(g, headers);
+ displayHeaders(g, postable, headers);
} catch(NoSuchSubscriptionException e) {
if(LOG.isLoggable(INFO)) LOG.info("Subscription removed");
removeGroup(g.getId());
@@ -306,8 +335,13 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
private static final GroupComparator INSTANCE = new GroupComparator();
public int compare(GroupListItem a, GroupListItem b) {
- return String.CASE_INSENSITIVE_ORDER.compare(a.getGroupName(),
- b.getGroupName());
+ // The item with the newest message comes first
+ long aTime = a.getTimestamp(), bTime = b.getTimestamp();
+ if(aTime > bTime) return -1;
+ if(aTime < bTime) return 1;
+ // Break ties by group name
+ String aName = a.getGroupName(), bName = b.getGroupName();
+ return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
}
}
}
\ No newline at end of file
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
index 87b36a1e6..0fd73a29a 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java
@@ -10,7 +10,6 @@ import java.util.ArrayList;
import net.sf.briar.R;
import net.sf.briar.android.widgets.HorizontalSpace;
-import net.sf.briar.util.StringUtils;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -36,12 +35,12 @@ implements OnItemClickListener {
public View getView(int position, View convertView, ViewGroup parent) {
GroupListItem item = getItem(position);
Context ctx = getContext();
+ Resources res = ctx.getResources();
+
LinearLayout layout = new LinearLayout(ctx);
layout.setOrientation(HORIZONTAL);
- if(item.getUnreadCount() > 0) {
- Resources res = ctx.getResources();
+ if(item.getUnreadCount() > 0)
layout.setBackgroundColor(res.getColor(R.color.unread_background));
- }
LinearLayout innerLayout = new LinearLayout(ctx);
// Give me all the unused width
@@ -57,34 +56,43 @@ implements OnItemClickListener {
else name.setText(item.getGroupName());
innerLayout.addView(name);
- if(item.getContentType().equals("text/plain")) {
- if(!StringUtils.isNullOrEmpty(item.getSubject())) {
+ if(item.isEmpty()) {
+ TextView noPosts = new TextView(ctx);
+ noPosts.setTextSize(14);
+ noPosts.setPadding(10, 0, 10, 10);
+ noPosts.setTextColor(res.getColor(R.color.no_posts));
+ noPosts.setText(R.string.no_posts);
+ innerLayout.addView(noPosts);
+ layout.addView(innerLayout);
+ } else {
+ if(item.getContentType().equals("text/plain")) {
TextView subject = new TextView(ctx);
subject.setTextSize(14);
subject.setMaxLines(2);
subject.setPadding(10, 0, 10, 10);
if(item.getUnreadCount() > 0) subject.setTypeface(null, BOLD);
- subject.setText(item.getSubject());
+ String s = item.getSubject();
+ subject.setText(s == null ? "" : s);
innerLayout.addView(subject);
+ } else {
+ LinearLayout attachmentLayout = new LinearLayout(ctx);
+ attachmentLayout.setOrientation(HORIZONTAL);
+ ImageView attachment = new ImageView(ctx);
+ attachment.setPadding(10, 0, 10, 10);
+ attachment.setImageResource(R.drawable.content_attachment);
+ attachmentLayout.addView(attachment);
+ attachmentLayout.addView(new HorizontalSpace(ctx));
+ innerLayout.addView(attachmentLayout);
}
- } else {
- LinearLayout attachmentLayout = new LinearLayout(ctx);
- attachmentLayout.setOrientation(HORIZONTAL);
- ImageView attachment = new ImageView(ctx);
- attachment.setPadding(10, 0, 10, 10);
- attachment.setImageResource(R.drawable.content_attachment);
- attachmentLayout.addView(attachment);
- attachmentLayout.addView(new HorizontalSpace(ctx));
- innerLayout.addView(attachmentLayout);
- }
- layout.addView(innerLayout);
+ layout.addView(innerLayout);
- TextView date = new TextView(ctx);
- date.setTextSize(14);
- date.setPadding(0, 10, 10, 10);
- long then = item.getTimestamp(), now = System.currentTimeMillis();
- date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
- layout.addView(date);
+ TextView date = new TextView(ctx);
+ date.setTextSize(14);
+ date.setPadding(0, 10, 10, 10);
+ long then = item.getTimestamp(), now = System.currentTimeMillis();
+ date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
+ layout.addView(date);
+ }
return layout;
}
@@ -93,6 +101,7 @@ implements OnItemClickListener {
long id) {
GroupListItem item = getItem(position);
Intent i = new Intent(getContext(), GroupActivity.class);
+ i.putExtra("net.sf.briar.RESTRICTED", item.isRestricted());
i.putExtra("net.sf.briar.GROUP_ID", item.getGroupId().getBytes());
i.putExtra("net.sf.briar.GROUP_NAME", item.getGroupName());
getContext().startActivity(i);
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListItem.java b/briar-android/src/net/sf/briar/android/groups/GroupListItem.java
index 6302b5153..abc61370d 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListItem.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListItem.java
@@ -1,5 +1,7 @@
package net.sf.briar.android.groups;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -12,24 +14,37 @@ import net.sf.briar.api.messaging.GroupId;
class GroupListItem {
private final Group group;
+ private final boolean postable, empty;
private final String authorName, contentType, subject;
private final long timestamp;
private final int unread;
- GroupListItem(Group group, List headers) {
- if(headers.isEmpty()) throw new IllegalArgumentException();
+ GroupListItem(Group group, boolean postable,
+ Collection headers) {
this.group = group;
- Collections.sort(headers, DescendingHeaderComparator.INSTANCE);
- GroupMessageHeader newest = headers.get(0);
- Author a = newest.getAuthor();
- if(a == null) authorName = null;
- else authorName = a.getName();
- contentType = newest.getContentType();
- subject = newest.getSubject();
- timestamp = newest.getTimestamp();
- int unread = 0;
- for(GroupMessageHeader h : headers) if(!h.isRead()) unread++;
- this.unread = unread;
+ this.postable = postable;
+ empty = headers.isEmpty();
+ if(empty) {
+ authorName = null;
+ contentType = null;
+ subject = null;
+ timestamp = 0;
+ unread = 0;
+ } else {
+ List list =
+ new ArrayList(headers);
+ Collections.sort(list, DescendingHeaderComparator.INSTANCE);
+ GroupMessageHeader newest = list.get(0);
+ Author a = newest.getAuthor();
+ if(a == null) authorName = null;
+ else authorName = a.getName();
+ contentType = newest.getContentType();
+ subject = newest.getSubject();
+ timestamp = newest.getTimestamp();
+ int unread = 0;
+ for(GroupMessageHeader h : list) if(!h.isRead()) unread++;
+ this.unread = unread;
+ }
}
GroupId getGroupId() {
@@ -40,6 +55,18 @@ class GroupListItem {
return group.getName();
}
+ boolean isRestricted() {
+ return group.isRestricted();
+ }
+
+ boolean isPostable() {
+ return postable;
+ }
+
+ boolean isEmpty() {
+ return empty;
+ }
+
String getAuthorName() {
return authorName;
}
diff --git a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java
index 14b138061..cce96dde7 100644
--- a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java
@@ -150,7 +150,6 @@ implements OnClickListener {
author.setTextColor(res.getColor(R.color.anonymous_author));
author.setText(R.string.anonymous);
} else {
- author.setTextColor(res.getColor(R.color.pseudonymous_author));
author.setText(authorName);
}
header.addView(author);
diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java
index 92e98c143..7094b77ed 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java
@@ -11,7 +11,6 @@ import java.util.ArrayList;
import net.sf.briar.R;
import net.sf.briar.android.widgets.HorizontalSpace;
import net.sf.briar.api.db.PrivateMessageHeader;
-import net.sf.briar.util.StringUtils;
import android.content.Context;
import android.content.res.Resources;
import android.text.format.DateUtils;
@@ -65,15 +64,14 @@ class ConversationAdapter extends ArrayAdapter {
innerLayout.addView(name);
if(item.getContentType().equals("text/plain")) {
- if(!StringUtils.isNullOrEmpty(item.getSubject())) {
- 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);
- }
+ TextView subject = new TextView(ctx);
+ subject.setTextSize(14);
+ subject.setMaxLines(2);
+ subject.setPadding(10, 0, 10, 10);
+ if(!item.isRead()) subject.setTypeface(null, BOLD);
+ String s = item.getSubject();
+ subject.setText(s == null ? "" : s);
+ innerLayout.addView(subject);
} else {
LinearLayout attachmentLayout = new LinearLayout(ctx);
attachmentLayout.setOrientation(HORIZONTAL);
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 0e8f50293..746552eee 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java
@@ -7,10 +7,8 @@ import static java.util.logging.Level.WARNING;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
-import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -57,7 +55,6 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
// Fields that are accessed from background threads must be volatile
@Inject private volatile DatabaseComponent db;
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
- private volatile boolean noContacts = true;
@Override
public void onCreate(Bundle state) {
@@ -101,18 +98,12 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
dbUiExecutor.execute(new Runnable() {
public void run() {
try {
- // Wait for the service to be bound and started
serviceConnection.waitForStartup();
- // Load the contact list from the database
long now = System.currentTimeMillis();
- Collection contacts = db.getContacts();
- noContacts = contacts.isEmpty();
- for(Contact c : contacts) {
+ for(Contact c : db.getContacts()) {
try {
- // Load the headers from the database
Collection headers =
db.getPrivateMessageHeaders(c.getId());
- // Display the headers in the UI
displayHeaders(c, headers);
} catch(NoSuchContactException e) {
if(LOG.isLoggable(INFO))
@@ -141,13 +132,9 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
// Remove the old item, if any
ConversationListItem item = findConversation(c.getId());
if(item != null) adapter.remove(item);
- // Add a new item if there are any headers to display
- if(!headers.isEmpty()) {
- List headerList =
- new ArrayList(headers);
- adapter.add(new ConversationListItem(c, headerList));
- adapter.sort(ConversationComparator.INSTANCE);
- }
+ // Add a new item
+ adapter.add(new ConversationListItem(c, headers));
+ adapter.sort(ConversationComparator.INSTANCE);
adapter.notifyDataSetChanged();
selectFirstUnread();
}
@@ -188,7 +175,7 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
}
public void onClick(View view) {
- if(noContacts) {
+ if(adapter.isEmpty()) {
NoContactsDialog dialog = new NoContactsDialog();
dialog.setListener(this);
dialog.show(getSupportFragmentManager(), "NoContactsDialog");
@@ -270,7 +257,9 @@ implements OnClickListener, DatabaseListener, NoContactsDialog.Listener {
long aTime = a.getTimestamp(), bTime = b.getTimestamp();
if(aTime > bTime) return -1;
if(aTime < bTime) return 1;
- return 0;
+ // Break ties by contact name
+ String aName = a.getContactName(), bName = b.getContactName();
+ return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
}
}
}
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 442c4a293..80431fa55 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java
@@ -10,7 +10,6 @@ import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1;
import java.util.ArrayList;
import net.sf.briar.R;
-import net.sf.briar.util.StringUtils;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -35,12 +34,12 @@ implements OnItemClickListener {
public View getView(int position, View convertView, ViewGroup parent) {
ConversationListItem item = getItem(position);
Context ctx = getContext();
+ Resources res = ctx.getResources();
+
LinearLayout layout = new LinearLayout(ctx);
layout.setOrientation(HORIZONTAL);
- if(item.getUnreadCount() > 0) {
- Resources res = ctx.getResources();
+ if(item.getUnreadCount() > 0)
layout.setBackgroundColor(res.getColor(R.color.unread_background));
- }
LinearLayout innerLayout = new LinearLayout(ctx);
// Give me all the unused width
@@ -58,23 +57,32 @@ implements OnItemClickListener {
else name.setText(contactName);
innerLayout.addView(name);
- if(!StringUtils.isNullOrEmpty(item.getSubject())) {
+ if(item.isEmpty()) {
+ TextView noMessages = new TextView(ctx);
+ noMessages.setTextSize(14);
+ noMessages.setPadding(10, 0, 10, 10);
+ noMessages.setTextColor(res.getColor(R.color.no_messages));
+ noMessages.setText(R.string.no_messages);
+ innerLayout.addView(noMessages);
+ layout.addView(innerLayout);
+ } else {
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());
+ String s = item.getSubject();
+ subject.setText(s == null ? "" : s);
innerLayout.addView(subject);
- }
- layout.addView(innerLayout);
+ layout.addView(innerLayout);
- TextView date = new TextView(ctx);
- date.setTextSize(14);
- date.setPadding(0, 10, 10, 10);
- long then = item.getTimestamp(), now = System.currentTimeMillis();
- date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
- layout.addView(date);
+ TextView date = new TextView(ctx);
+ date.setTextSize(14);
+ date.setPadding(0, 10, 10, 10);
+ long then = item.getTimestamp(), now = System.currentTimeMillis();
+ date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
+ layout.addView(date);
+ }
return layout;
}
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 f7ffc36f8..52a3dcb87 100644
--- a/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java
+++ b/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java
@@ -1,5 +1,7 @@
package net.sf.briar.android.messages;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -12,19 +14,29 @@ import net.sf.briar.api.db.PrivateMessageHeader;
class ConversationListItem {
private final Contact contact;
+ private final boolean empty;
private final String subject;
private final long timestamp;
private final int unread;
- ConversationListItem(Contact contact, List headers) {
- if(headers.isEmpty()) throw new IllegalArgumentException();
+ ConversationListItem(Contact contact,
+ Collection headers) {
this.contact = contact;
- Collections.sort(headers, DescendingHeaderComparator.INSTANCE);
- subject = headers.get(0).getSubject();
- timestamp = headers.get(0).getTimestamp();
- int unread = 0;
- for(PrivateMessageHeader h : headers) if(!h.isRead()) unread++;
- this.unread = unread;
+ empty = headers.isEmpty();
+ if(empty) {
+ subject = null;
+ timestamp = 0;
+ unread = 0;
+ } else {
+ List list =
+ new ArrayList(headers);
+ Collections.sort(list, DescendingHeaderComparator.INSTANCE);
+ subject = list.get(0).getSubject();
+ timestamp = list.get(0).getTimestamp();
+ int unread = 0;
+ for(PrivateMessageHeader h : list) if(!h.isRead()) unread++;
+ this.unread = unread;
+ }
}
ContactId getContactId() {
@@ -39,6 +51,10 @@ class ConversationListItem {
return contact.getLocalAuthorId();
}
+ boolean isEmpty() {
+ return empty;
+ }
+
String getSubject() {
return subject;
}