mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Display conversations and groups even if they're empty.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
<color name="content_background">#FFFFFF</color>
|
||||
<color name="unread_background">#FFFFFF</color>
|
||||
<color name="horizontal_border">#CCCCCC</color>
|
||||
<color name="anonymous_author">#AAAAAA</color>
|
||||
<color name="pseudonymous_author">#000000</color>
|
||||
<color name="anonymous_author">#999999</color>
|
||||
<color name="no_posts">#999999</color>
|
||||
<color name="no_messages">#999999</color>
|
||||
</resources>
|
||||
@@ -40,6 +40,7 @@
|
||||
<string name="contact_added">Contact added</string>
|
||||
<string name="done_button">Done</string>
|
||||
<string name="messages_title">Messages</string>
|
||||
<string name="no_messages">(No messages)</string>
|
||||
<string name="format_from">From: %1$s</string>
|
||||
<string name="format_to">To: %1$s</string>
|
||||
<string name="compose_message_title">New Message</string>
|
||||
@@ -47,6 +48,7 @@
|
||||
<string name="to">To:</string>
|
||||
<string name="anonymous">(Anonymous)</string>
|
||||
<string name="groups_title">Groups</string>
|
||||
<string name="no_posts">(No posts)</string>
|
||||
<string name="create_group_title">New Group</string>
|
||||
<string name="choose_group_name">Choose a name for your group:</string>
|
||||
<string name="compose_group_title">New Post</string>
|
||||
|
||||
@@ -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<GroupMessageHeader> {
|
||||
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);
|
||||
|
||||
@@ -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<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
displayHeaders(g, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Subscription removed");
|
||||
Collection<Group> subs = db.getSubscriptions();
|
||||
if(restricted) {
|
||||
Set<GroupId> local = new HashSet<GroupId>();
|
||||
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<GroupMessageHeader> 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<GroupMessageHeader> 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<GroupMessageHeader> 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<GroupMessageHeader> headerList =
|
||||
new ArrayList<GroupMessageHeader>(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<GroupMessageHeader> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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<GroupMessageHeader> headers) {
|
||||
if(headers.isEmpty()) throw new IllegalArgumentException();
|
||||
GroupListItem(Group group, boolean postable,
|
||||
Collection<GroupMessageHeader> 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<GroupMessageHeader> list =
|
||||
new ArrayList<GroupMessageHeader>(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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<PrivateMessageHeader> {
|
||||
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);
|
||||
|
||||
@@ -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<Contact> contacts = db.getContacts();
|
||||
noContacts = contacts.isEmpty();
|
||||
for(Contact c : contacts) {
|
||||
for(Contact c : db.getContacts()) {
|
||||
try {
|
||||
// Load the headers from the database
|
||||
Collection<PrivateMessageHeader> 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<PrivateMessageHeader> headerList =
|
||||
new ArrayList<PrivateMessageHeader>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<PrivateMessageHeader> headers) {
|
||||
if(headers.isEmpty()) throw new IllegalArgumentException();
|
||||
ConversationListItem(Contact contact,
|
||||
Collection<PrivateMessageHeader> 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<PrivateMessageHeader> list =
|
||||
new ArrayList<PrivateMessageHeader>(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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user