mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Conversation view for private messages.
This commit is contained in:
@@ -40,6 +40,10 @@
|
||||
android:name=".android.invitation.AddContactActivity"
|
||||
android:label="@string/add_contact_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.messages.ConversationActivity"
|
||||
android:label="@string/messages_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.messages.ConversationListActivity"
|
||||
android:label="@string/messages_title" >
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
<string name="quit_button">Quit</string>
|
||||
<string name="contact_list_title">Contacts</string>
|
||||
<string name="contact_connected">Connected</string>
|
||||
<string name="contact_last_connected">Last connected <br /> %s</string>
|
||||
<string name="contact_last_connected">Last connected <br /> %1$s</string>
|
||||
<string name="add_contact_button">New Contact</string>
|
||||
<string name="search_button">Search</string>
|
||||
<string name="add_contact_title">Add a Contact</string>
|
||||
<string name="same_network">Briar can add contacts via Wi-Fi or Bluetooth. For security reasons, you must be face-to-face to add someone as a contact. To use Wi-Fi you must both be connected to the same network.</string>
|
||||
<string name="wifi_not_available">Wi-Fi is not available on this device</string>
|
||||
@@ -39,7 +40,7 @@
|
||||
<string name="interfering">This could mean that someone is trying to interfere with your connection.</string>
|
||||
<string name="contact_added">Contact added</string>
|
||||
<string name="enter_nickname">Please enter a nickname for this contact:</string>
|
||||
<string name="done_button">Done</string>
|
||||
<string name="messages_title">Messages</string>
|
||||
<string name="compose_button">New Message</string>
|
||||
<string name="done_button">Done</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.sf.briar.android.contact;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
class ContactComparator implements Comparator<ContactListItem> {
|
||||
|
||||
static final ContactComparator INSTANCE = new ContactComparator();
|
||||
|
||||
public int compare(ContactListItem a, ContactListItem b) {
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(a.contact.getName(),
|
||||
b.contact.getName());
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
@@ -52,7 +51,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
|
||||
@Inject @DatabaseExecutor private Executor dbExecutor;
|
||||
@Inject private ConnectionRegistry connectionRegistry;
|
||||
|
||||
private ArrayAdapter<ContactListItem> adapter = null;
|
||||
private ContactListAdapter adapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
@@ -67,6 +66,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
|
||||
// Give me all the width and all the unused height
|
||||
list.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f));
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(adapter);
|
||||
layout.addView(list);
|
||||
|
||||
Button addContactButton = new Button(this);
|
||||
@@ -167,7 +167,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener {
|
||||
boolean conn = connectionRegistry.isConnected(c.getId());
|
||||
adapter.add(new ContactListItem(c, conn));
|
||||
}
|
||||
adapter.sort(ContactListItem.COMPARATOR);
|
||||
adapter.sort(ContactComparator.INSTANCE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,17 +8,21 @@ import java.util.ArrayList;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.Html;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
|
||||
class ContactListAdapter extends ArrayAdapter<ContactListItem> {
|
||||
class ContactListAdapter extends ArrayAdapter<ContactListItem>
|
||||
implements OnItemClickListener {
|
||||
|
||||
ContactListAdapter(Context ctx) {
|
||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
||||
@@ -47,13 +51,13 @@ class ContactListAdapter extends ArrayAdapter<ContactListItem> {
|
||||
layout.addView(name);
|
||||
|
||||
TextView connected = new TextView(ctx);
|
||||
connected.setTextSize(12);
|
||||
connected.setTextSize(14);
|
||||
connected.setPadding(5, 0, 5, 0);
|
||||
if(item.isConnected()) {
|
||||
connected.setText(R.string.contact_connected);
|
||||
} else {
|
||||
String format = ctx.getResources().getString(
|
||||
R.string.contact_last_connected);
|
||||
Resources res = ctx.getResources();
|
||||
String format = res.getString(R.string.contact_last_connected);
|
||||
long then = item.getLastConnected();
|
||||
CharSequence ago = DateUtils.getRelativeTimeSpanString(then);
|
||||
connected.setText(Html.fromHtml(String.format(format, ago)));
|
||||
@@ -62,4 +66,9 @@ class ContactListAdapter extends ArrayAdapter<ContactListItem> {
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
// FIXME: Hook this up to an activity
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
package net.sf.briar.android.contact;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import net.sf.briar.api.Contact;
|
||||
import net.sf.briar.api.ContactId;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ContactListItem {
|
||||
|
||||
static Comparator<ContactListItem> COMPARATOR = new ItemComparator();
|
||||
|
||||
private final Contact contact;
|
||||
final Contact contact;
|
||||
private boolean connected;
|
||||
|
||||
ContactListItem(Contact contact, boolean connected) {
|
||||
@@ -37,12 +33,4 @@ class ContactListItem {
|
||||
void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
private static class ItemComparator implements Comparator<ContactListItem> {
|
||||
|
||||
public int compare(ContactListItem a, ContactListItem b) {
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(a.contact.getName(),
|
||||
b.contact.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package net.sf.briar.android.messages;
|
||||
|
||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.DatabaseExecutor;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.PrivateMessageHeader;
|
||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.MessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class ConversationActivity extends BriarActivity
|
||||
implements OnClickListener, DatabaseListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ConversationActivity.class.getName());
|
||||
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
@Inject private DatabaseComponent db;
|
||||
@Inject @DatabaseExecutor private Executor dbExecutor;
|
||||
|
||||
private ContactId contactId = null;
|
||||
private ConversationAdapter adapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(null);
|
||||
|
||||
Intent i = getIntent();
|
||||
int id = i.getIntExtra("net.sf.briar.CONTACT_ID", -1);
|
||||
if(id == -1) throw new IllegalStateException();
|
||||
contactId = new ContactId(id);
|
||||
String contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME");
|
||||
if(contactName == null) throw new IllegalStateException();
|
||||
setTitle(contactName);
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
|
||||
layout.setOrientation(VERTICAL);
|
||||
layout.setGravity(CENTER_HORIZONTAL);
|
||||
|
||||
adapter = new ConversationAdapter(this);
|
||||
ListView list = new ListView(this);
|
||||
// Give me all the width and all the unused height
|
||||
list.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f));
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(adapter);
|
||||
layout.addView(list);
|
||||
|
||||
Button composeButton = new Button(this);
|
||||
composeButton.setBackgroundResource(0);
|
||||
composeButton.setLayoutParams(new LayoutParams(MATCH_PARENT,
|
||||
WRAP_CONTENT));
|
||||
composeButton.setCompoundDrawablesWithIntrinsicBounds(0,
|
||||
R.drawable.content_new_email, 0, 0);
|
||||
composeButton.setText(R.string.compose_button);
|
||||
composeButton.setOnClickListener(this);
|
||||
layout.addView(composeButton);
|
||||
|
||||
setContentView(layout);
|
||||
|
||||
// Listen for messages being added or removed
|
||||
db.addListener(this);
|
||||
// Bind to the service so we can wait for the DB to be opened
|
||||
bindService(new Intent(BriarService.class.getName()),
|
||||
serviceConnection, 0);
|
||||
// Load the message headers from the DB
|
||||
reloadMessageHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
db.removeListener(this);
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
// FIXME: Hook this button up to an activity
|
||||
}
|
||||
|
||||
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() {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Wait for the service to be bound and started
|
||||
serviceConnection.waitForStartup();
|
||||
// Load the message headers from the database
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
db.getPrivateMessageHeaders();
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Loaded " + headers.size() + " headers");
|
||||
// Update the conversation
|
||||
updateConversation(headers);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConversation(
|
||||
final Collection<PrivateMessageHeader> headers) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
adapter.clear();
|
||||
for(PrivateMessageHeader h : headers)
|
||||
if(h.getContactId().equals(contactId)) adapter.add(h);
|
||||
adapter.sort(AscendingHeaderComparator.INSTANCE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package net.sf.briar.android.messages;
|
||||
|
||||
import static android.graphics.Typeface.BOLD;
|
||||
import static android.view.Gravity.CENTER;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static java.text.DateFormat.SHORT;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.api.db.PrivateMessageHeader;
|
||||
import android.content.Context;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
|
||||
class ConversationAdapter extends ArrayAdapter<PrivateMessageHeader>
|
||||
implements OnItemClickListener {
|
||||
|
||||
ConversationAdapter(Context ctx) {
|
||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
||||
new ArrayList<PrivateMessageHeader>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
PrivateMessageHeader item = getItem(position);
|
||||
Context ctx = getContext();
|
||||
LinearLayout layout = new LinearLayout(ctx);
|
||||
layout.setOrientation(HORIZONTAL);
|
||||
layout.setGravity(CENTER);
|
||||
|
||||
ImageView star = new ImageView(ctx);
|
||||
star.setPadding(5, 5, 5, 5);
|
||||
if(item.getStarred())
|
||||
star.setImageResource(R.drawable.rating_important);
|
||||
else star.setImageResource(R.drawable.rating_not_important);
|
||||
layout.addView(star);
|
||||
|
||||
TextView subject = new TextView(ctx);
|
||||
// Give me all the unused width
|
||||
subject.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT,
|
||||
1));
|
||||
subject.setTextSize(14);
|
||||
if(!item.getRead()) subject.setTypeface(null, BOLD);
|
||||
subject.setText(item.getSubject());
|
||||
layout.addView(subject);
|
||||
|
||||
TextView date = new TextView(ctx);
|
||||
date.setTextSize(14);
|
||||
date.setPadding(5, 0, 10, 0);
|
||||
long then = item.getTimestamp(), now = System.currentTimeMillis();
|
||||
date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
|
||||
layout.addView(date);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
// FIXME
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.sf.briar.android.messages;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
class ConversationComparator implements Comparator<ConversationListItem> {
|
||||
|
||||
static final ConversationComparator INSTANCE = new ConversationComparator();
|
||||
|
||||
public int compare(ConversationListItem a, ConversationListItem b) {
|
||||
// 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;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
@@ -58,7 +57,7 @@ implements OnClickListener, DatabaseListener {
|
||||
@Inject @DatabaseExecutor private Executor dbExecutor;
|
||||
@Inject private MessageFactory messageFactory;
|
||||
|
||||
private ArrayAdapter<ConversationListItem> adapter = null;
|
||||
private ConversationListAdapter adapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
@@ -73,6 +72,7 @@ implements OnClickListener, DatabaseListener {
|
||||
// Give me all the width and all the unused height
|
||||
list.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f));
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(adapter);
|
||||
layout.addView(list);
|
||||
|
||||
Button composeButton = new Button(this);
|
||||
@@ -110,16 +110,23 @@ implements OnClickListener, DatabaseListener {
|
||||
LOG.info("Inserting fake contact and messages");
|
||||
// Insert a fake contact
|
||||
ContactId contactId = db.addContact("Carol");
|
||||
// Insert some messages to the contact
|
||||
// Insert some fake messages to and from the contact
|
||||
Message m = messageFactory.createPrivateMessage(null,
|
||||
"First message's subject",
|
||||
"First message's subject is quite long to test"
|
||||
+ " line wrapping and stuff like that",
|
||||
"First message's body".getBytes("UTF-8"));
|
||||
db.addLocalPrivateMessage(m, contactId);
|
||||
db.setReadFlag(m.getId(), true);
|
||||
db.setStarredFlag(m.getId(), true);
|
||||
Thread.sleep(2000);
|
||||
Thread.sleep(1000);
|
||||
m = messageFactory.createPrivateMessage(m.getId(),
|
||||
"Second message's subject",
|
||||
"Second message's subject is short",
|
||||
"Second message's body".getBytes("UTF-8"));
|
||||
db.receiveMessage(contactId, m);
|
||||
Thread.sleep(1000);
|
||||
m = messageFactory.createPrivateMessage(m.getId(),
|
||||
"Third message's subject is also short",
|
||||
"Third message's body".getBytes("UTF-8"));
|
||||
db.addLocalPrivateMessage(m, contactId);
|
||||
db.setReadFlag(m.getId(), true);
|
||||
}
|
||||
@@ -198,7 +205,7 @@ implements OnClickListener, DatabaseListener {
|
||||
adapter.clear();
|
||||
for(ConversationListItem i : sortHeaders(contacts, headers))
|
||||
adapter.add(i);
|
||||
adapter.sort(ConversationListItem.COMPARATOR);
|
||||
adapter.sort(ConversationComparator.INSTANCE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,16 +12,20 @@ import java.util.ArrayList;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
|
||||
class ConversationListAdapter extends ArrayAdapter<ConversationListItem> {
|
||||
class ConversationListAdapter extends ArrayAdapter<ConversationListItem>
|
||||
implements OnItemClickListener {
|
||||
|
||||
ConversationListAdapter(Context ctx) {
|
||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
||||
@@ -72,4 +76,13 @@ class ConversationListAdapter extends ArrayAdapter<ConversationListItem> {
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
ConversationListItem item = getItem(position);
|
||||
Intent i = new Intent(getContext(), ConversationActivity.class);
|
||||
i.putExtra("net.sf.briar.CONTACT_ID", item.getContactId().getInt());
|
||||
i.putExtra("net.sf.briar.CONTACT_NAME", item.getName());
|
||||
getContext().startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,51 @@
|
||||
package net.sf.briar.android.messages;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.briar.api.Contact;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.db.PrivateMessageHeader;
|
||||
|
||||
class ConversationListItem {
|
||||
|
||||
static final Comparator<ConversationListItem> COMPARATOR =
|
||||
new ItemComparator();
|
||||
|
||||
private static final Comparator<PrivateMessageHeader> HEADER_COMPARATOR =
|
||||
new HeaderComparator();
|
||||
|
||||
private final Contact contact;
|
||||
private final List<PrivateMessageHeader> headers;
|
||||
private final ContactId contactId;
|
||||
private final String name, subject;
|
||||
private final long timestamp;
|
||||
private final int length;
|
||||
private final boolean read, starred;
|
||||
|
||||
ConversationListItem(Contact contact, List<PrivateMessageHeader> headers) {
|
||||
if(headers.isEmpty()) throw new IllegalArgumentException();
|
||||
Collections.sort(headers, HEADER_COMPARATOR);
|
||||
boolean read = false, starred = false;
|
||||
contactId = contact.getId();
|
||||
name = contact.getName();
|
||||
Collections.sort(headers, DescendingHeaderComparator.INSTANCE);
|
||||
subject = headers.get(0).getSubject();
|
||||
timestamp = headers.get(0).getTimestamp();
|
||||
length = headers.size();
|
||||
boolean allRead = false, anyStarred = false;
|
||||
for(PrivateMessageHeader h : headers) {
|
||||
read &= h.getRead();
|
||||
starred |= h.getStarred();
|
||||
allRead &= h.getRead();
|
||||
anyStarred |= h.getStarred();
|
||||
}
|
||||
this.contact = contact;
|
||||
this.headers = headers;
|
||||
this.read = read;
|
||||
this.starred = starred;
|
||||
read = allRead;
|
||||
starred = anyStarred;
|
||||
}
|
||||
|
||||
ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return contact.getName();
|
||||
return name;
|
||||
}
|
||||
|
||||
String getSubject() {
|
||||
return headers.get(0).getSubject();
|
||||
return subject;
|
||||
}
|
||||
|
||||
long getTimestamp() {
|
||||
return headers.get(0).getTimestamp();
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
boolean getRead() {
|
||||
@@ -54,28 +57,6 @@ class ConversationListItem {
|
||||
}
|
||||
|
||||
int getLength() {
|
||||
return headers.size();
|
||||
}
|
||||
|
||||
private static class HeaderComparator
|
||||
implements Comparator<PrivateMessageHeader> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ItemComparator
|
||||
implements Comparator<ConversationListItem> {
|
||||
|
||||
public int compare(ConversationListItem a, ConversationListItem b) {
|
||||
// The item with the newest message comes first
|
||||
return HEADER_COMPARATOR.compare(a.headers.get(0),
|
||||
b.headers.get(0));
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user