Replaced last connection time with time of last private message.

This commit is contained in:
akwizgran
2014-04-05 18:14:07 +01:00
parent 3d9f5c496f
commit 839f67dd44
11 changed files with 27 additions and 154 deletions

View File

@@ -10,6 +10,7 @@
<color name="unread_background">#FFFFFF</color> <color name="unread_background">#FFFFFF</color>
<color name="horizontal_border">#CCCCCC</color> <color name="horizontal_border">#CCCCCC</color>
<color name="groups_available_background">#FCCF1C</color> <color name="groups_available_background">#FCCF1C</color>
<color name="no_private_messages">#AAAAAA</color>
<color name="no_posts">#AAAAAA</color> <color name="no_posts">#AAAAAA</color>
<color name="settings_title_text">#2D3E50</color> <color name="settings_title_text">#2D3E50</color>
<color name="settings_title_underline">#2D3E50</color> <color name="settings_title_underline">#2D3E50</color>

View File

@@ -23,7 +23,6 @@
<string name="contact_list_title">Contacts</string> <string name="contact_list_title">Contacts</string>
<string name="no_contacts">No contacts</string> <string name="no_contacts">No contacts</string>
<string name="contact_connected">Connected</string> <string name="contact_connected">Connected</string>
<string name="format_last_connected">Last connected &lt;br /&gt; %s</string>
<string name="add_contact_title">Add a Contact</string> <string name="add_contact_title">Add a Contact</string>
<string name="your_nickname">Your nickname: </string> <string name="your_nickname">Your nickname: </string>
<string name="face_to_face">For security reasons you must be face-to-face with the person you want to add as a contact.\n\nThis will prevent anyone from impersonating you or reading your messages in future.</string> <string name="face_to_face">For security reasons you must be face-to-face with the person you want to add as a contact.\n\nThis will prevent anyone from impersonating you or reading your messages in future.</string>

View File

@@ -12,7 +12,6 @@ import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
@@ -127,15 +126,12 @@ ConnectionListener {
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
Map<ContactId, Long> times = db.getLastConnected();
for(Contact c : db.getContacts()) { for(Contact c : db.getContacts()) {
Long lastConnected = times.get(c.getId());
if(lastConnected == null) continue;
try { try {
GroupId inbox = db.getInboxGroupId(c.getId()); GroupId inbox = db.getInboxGroupId(c.getId());
Collection<MessageHeader> headers = Collection<MessageHeader> headers =
db.getInboxMessageHeaders(c.getId()); db.getInboxMessageHeaders(c.getId());
displayContact(c, lastConnected, inbox, headers); displayContact(c, inbox, headers);
} catch(NoSuchContactException e) { } catch(NoSuchContactException e) {
// Continue // Continue
} }
@@ -164,7 +160,7 @@ ConnectionListener {
}); });
} }
private void displayContact(final Contact c, final long lastConnected, private void displayContact(final Contact c,
final GroupId inbox, final Collection<MessageHeader> headers) { final GroupId inbox, final Collection<MessageHeader> headers) {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
@@ -175,8 +171,7 @@ ConnectionListener {
ContactListItem item = findItem(c.getId()); ContactListItem item = findItem(c.getId());
if(item != null) adapter.remove(item); if(item != null) adapter.remove(item);
// Add a new item // Add a new item
adapter.add(new ContactListItem(c, connected, lastConnected, adapter.add(new ContactListItem(c, connected, inbox, headers));
inbox, headers));
adapter.sort(ContactListItemComparator.INSTANCE); adapter.sort(ContactListItemComparator.INSTANCE);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }
@@ -308,12 +303,10 @@ ConnectionListener {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
ContactListItem item = findItem(c); ContactListItem item = findItem(c);
if(item == null) return; if(item != null) {
if(LOG.isLoggable(INFO)) item.setConnected(connected);
LOG.info("Setting connection status " + connected); adapter.notifyDataSetChanged();
item.setConnected(connected); }
item.setLastConnected(System.currentTimeMillis());
adapter.notifyDataSetChanged();
} }
}); });
} }

View File

@@ -12,7 +12,6 @@ import org.briarproject.android.util.LayoutUtils;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.text.Html;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -62,17 +61,19 @@ class ContactListAdapter extends ArrayAdapter<ContactListItem> {
else name.setText(contactName); else name.setText(contactName);
layout.addView(name); layout.addView(name);
TextView connected = new TextView(ctx); if(item.isEmpty()) {
connected.setPadding(0, pad, pad, pad); TextView noMessages = new TextView(ctx);
if(item.isConnected()) { noMessages.setPadding(pad, pad, pad, pad);
connected.setText(R.string.contact_connected); noMessages.setTextColor(res.getColor(R.color.no_private_messages));
noMessages.setText(R.string.no_private_messages);
layout.addView(noMessages);
} else { } else {
String format = res.getString(R.string.format_last_connected); TextView date = new TextView(ctx);
long then = item.getLastConnected(); date.setPadding(pad, pad, pad, pad);
CharSequence ago = DateUtils.getRelativeTimeSpanString(then); long timestamp = item.getTimestamp();
connected.setText(Html.fromHtml(String.format(format, ago))); date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp));
layout.addView(date);
} }
layout.addView(connected);
return layout; return layout;
} }

View File

@@ -11,18 +11,15 @@ class ContactListItem {
private final Contact contact; private final Contact contact;
private final GroupId inbox; private final GroupId inbox;
private boolean connected; private boolean connected, empty;
private long lastConnected;
private boolean empty;
private long timestamp; private long timestamp;
private int unread; private int unread;
ContactListItem(Contact contact, boolean connected, long lastConnected, ContactListItem(Contact contact, boolean connected, GroupId inbox,
GroupId inbox, Collection<MessageHeader> headers) { Collection<MessageHeader> headers) {
this.contact = contact; this.contact = contact;
this.inbox = inbox; this.inbox = inbox;
this.connected = connected; this.connected = connected;
this.lastConnected = lastConnected;
setHeaders(headers); setHeaders(headers);
} }
@@ -46,14 +43,6 @@ class ContactListItem {
return inbox; return inbox;
} }
long getLastConnected() {
return lastConnected;
}
void setLastConnected(long lastConnected) {
this.lastConnected = lastConnected;
}
boolean isConnected() { boolean isConnected() {
return connected; return connected;
} }

View File

@@ -198,12 +198,6 @@ public interface DatabaseComponent {
Collection<MessageHeader> getInboxMessageHeaders(ContactId c) Collection<MessageHeader> getInboxMessageHeaders(ContactId c)
throws DbException; throws DbException;
/**
* Returns the time at which a connection to each contact was last opened
* or closed.
*/
Map<ContactId, Long> getLastConnected() throws DbException;
/** Returns the local pseudonym with the given ID. */ /** Returns the local pseudonym with the given ID. */
LocalAuthor getLocalAuthor(AuthorId a) throws DbException; LocalAuthor getLocalAuthor(AuthorId a) throws DbException;

View File

@@ -326,14 +326,6 @@ interface Database<T> {
Collection<MessageHeader> getInboxMessageHeaders(T txn, ContactId c) Collection<MessageHeader> getInboxMessageHeaders(T txn, ContactId c)
throws DbException; throws DbException;
/**
* Returns the time at which a connection to each contact was last opened
* or closed.
* <p>
* Locking: window read.
*/
Map<ContactId, Long> getLastConnected(T txn) throws DbException;
/** /**
* Returns the local pseudonym with the given ID. * Returns the local pseudonym with the given ID.
* <p> * <p>
@@ -732,13 +724,6 @@ interface Database<T> {
*/ */
public void setInboxGroup(T txn, ContactId c, Group g) throws DbException; public void setInboxGroup(T txn, ContactId c, Group g) throws DbException;
/**
* Sets the time at which a connection to the given contact was last made.
* <p>
* Locking: window write.
*/
void setLastConnected(T txn, ContactId c, long now) throws DbException;
/** /**
* Marks a message as read or unread. * Marks a message as read or unread.
* <p> * <p>

View File

@@ -77,7 +77,6 @@ import org.briarproject.api.messaging.SubscriptionAck;
import org.briarproject.api.messaging.SubscriptionUpdate; import org.briarproject.api.messaging.SubscriptionUpdate;
import org.briarproject.api.messaging.TransportAck; import org.briarproject.api.messaging.TransportAck;
import org.briarproject.api.messaging.TransportUpdate; import org.briarproject.api.messaging.TransportUpdate;
import org.briarproject.api.system.Clock;
import org.briarproject.api.transport.Endpoint; import org.briarproject.api.transport.Endpoint;
import org.briarproject.api.transport.TemporarySecret; import org.briarproject.api.transport.TemporarySecret;
@@ -119,7 +118,6 @@ DatabaseCleaner.Callback {
private final Database<T> db; private final Database<T> db;
private final DatabaseCleaner cleaner; private final DatabaseCleaner cleaner;
private final ShutdownManager shutdown; private final ShutdownManager shutdown;
private final Clock clock;
private final Collection<EventListener> listeners = private final Collection<EventListener> listeners =
new CopyOnWriteArrayList<EventListener>(); new CopyOnWriteArrayList<EventListener>();
@@ -130,11 +128,10 @@ DatabaseCleaner.Callback {
@Inject @Inject
DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner, DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner,
ShutdownManager shutdown, Clock clock) { ShutdownManager shutdown) {
this.db = db; this.db = db;
this.cleaner = cleaner; this.cleaner = cleaner;
this.shutdown = shutdown; this.shutdown = shutdown;
this.clock = clock;
} }
public boolean open() throws DbException, IOException { public boolean open() throws DbException, IOException {
@@ -965,23 +962,6 @@ DatabaseCleaner.Callback {
} }
} }
public Map<ContactId, Long> getLastConnected() throws DbException {
windowLock.readLock().lock();
try {
T txn = db.startTransaction();
try {
Map<ContactId, Long> times = db.getLastConnected(txn);
db.commitTransaction(txn);
return times;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
windowLock.readLock().unlock();
}
}
public LocalAuthor getLocalAuthor(AuthorId a) throws DbException { public LocalAuthor getLocalAuthor(AuthorId a) throws DbException {
identityLock.readLock().lock(); identityLock.readLock().lock();
try { try {
@@ -1244,10 +1224,6 @@ DatabaseCleaner.Callback {
throw new NoSuchTransportException(); throw new NoSuchTransportException();
long counter = db.incrementConnectionCounter(txn, c, t, long counter = db.incrementConnectionCounter(txn, c, t,
period); period);
if(counter != -1) {
long now = clock.currentTimeMillis();
db.setLastConnected(txn, c, now);
}
db.commitTransaction(txn); db.commitTransaction(txn);
return counter; return counter;
} catch(DbException e) { } catch(DbException e) {
@@ -1802,7 +1778,6 @@ DatabaseCleaner.Callback {
throw new NoSuchTransportException(); throw new NoSuchTransportException();
db.setConnectionWindow(txn, c, t, period, centre, db.setConnectionWindow(txn, c, t, period, centre,
bitmap); bitmap);
db.setLastConnected(txn, c, clock.currentTimeMillis());
db.commitTransaction(txn); db.commitTransaction(txn);
} catch(DbException e) { } catch(DbException e) {
db.abortTransaction(txn); db.abortTransaction(txn);

View File

@@ -17,7 +17,6 @@ import org.briarproject.api.db.DatabaseConfig;
import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.FileUtils; import org.briarproject.api.system.FileUtils;
import org.briarproject.system.SystemClock; import org.briarproject.system.SystemClock;
@@ -54,9 +53,8 @@ public class DatabaseModule extends AbstractModule {
@Provides @Singleton @Provides @Singleton
DatabaseComponent getDatabaseComponent(Database<Connection> db, DatabaseComponent getDatabaseComponent(Database<Connection> db,
DatabaseCleaner cleaner, ShutdownManager shutdown, Clock clock) { DatabaseCleaner cleaner, ShutdownManager shutdown) {
return new DatabaseComponentImpl<Connection>(db, cleaner, shutdown, return new DatabaseComponentImpl<Connection>(db, cleaner, shutdown);
clock);
} }
@Provides @Singleton @DatabaseExecutor @Provides @Singleton @DatabaseExecutor

View File

@@ -62,7 +62,7 @@ import org.briarproject.api.transport.TemporarySecret;
*/ */
abstract class JdbcDatabase implements Database<Connection> { abstract class JdbcDatabase implements Database<Connection> {
private static final int SCHEMA_VERSION = 5; private static final int SCHEMA_VERSION = 6;
private static final int MIN_SCHEMA_VERSION = 5; private static final int MIN_SCHEMA_VERSION = 5;
private static final String CREATE_SETTINGS = private static final String CREATE_SETTINGS =
@@ -326,16 +326,6 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " REFERENCES transports (transportId)" + " REFERENCES transports (transportId)"
+ " ON DELETE CASCADE)"; + " ON DELETE CASCADE)";
// Locking: window
private static final String CREATE_CONNECTION_TIMES =
"CREATE TABLE connectionTimes"
+ " (contactId INT NOT NULL,"
+ " lastConnected BIGINT NOT NULL,"
+ " PRIMARY KEY (contactId),"
+ " FOREIGN KEY (contactId)"
+ " REFERENCES contacts (contactId)"
+ " ON DELETE CASCADE)";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(JdbcDatabase.class.getName()); Logger.getLogger(JdbcDatabase.class.getName());
@@ -445,7 +435,6 @@ abstract class JdbcDatabase implements Database<Connection> {
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_VERSIONS)); s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_VERSIONS));
s.executeUpdate(insertTypeNames(CREATE_ENDPOINTS)); s.executeUpdate(insertTypeNames(CREATE_ENDPOINTS));
s.executeUpdate(insertTypeNames(CREATE_SECRETS)); s.executeUpdate(insertTypeNames(CREATE_SECRETS));
s.executeUpdate(insertTypeNames(CREATE_CONNECTION_TIMES));
s.close(); s.close();
} catch(SQLException e) { } catch(SQLException e) {
tryToClose(s); tryToClose(s);
@@ -633,15 +622,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
ps.close(); ps.close();
} }
// Create a connection time row
sql = "INSERT INTO connectionTimes (contactId, lastConnected)"
+ " VALUES (?, ?)";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setLong(2, clock.currentTimeMillis());
affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException();
ps.close();
// Create a retention version row // Create a retention version row
sql = "INSERT INTO retentionVersions (contactId, retention," sql = "INSERT INTO retentionVersions (contactId, retention,"
+ " localVersion, localAcked, remoteVersion, remoteAcked," + " localVersion, localAcked, remoteVersion, remoteAcked,"
@@ -1525,27 +1505,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public Map<ContactId, Long> getLastConnected(Connection txn)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId, lastConnected FROM connectionTimes";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
Map<ContactId, Long> times = new HashMap<ContactId, Long>();
while(rs.next())
times.put(new ContactId(rs.getInt(1)), rs.getLong(2));
rs.close();
ps.close();
return Collections.unmodifiableMap(times);
} catch(SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
public LocalAuthor getLocalAuthor(Connection txn, AuthorId a) public LocalAuthor getLocalAuthor(Connection txn, AuthorId a)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -3087,24 +3046,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void setLastConnected(Connection txn, ContactId c, long now)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE connectionTimes SET lastConnected = ?"
+ " WHERE contactId = ?";
ps = txn.prepareStatement(sql);
ps.setLong(1, now);
ps.setInt(2, c.getInt());
int affected = ps.executeUpdate();
if(affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch(SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
public void setReadFlag(Connection txn, MessageId m, boolean read) public void setReadFlag(Connection txn, MessageId m, boolean read)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;

View File

@@ -9,8 +9,6 @@ import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.lifecycle.ShutdownManager; import org.briarproject.api.lifecycle.ShutdownManager;
import org.briarproject.db.DatabaseCleaner.Callback; import org.briarproject.db.DatabaseCleaner.Callback;
import org.briarproject.system.SystemClock;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
@@ -75,7 +73,6 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
private <T> DatabaseComponentImpl<T> createDatabaseComponentImpl( private <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
ShutdownManager shutdown) { ShutdownManager shutdown) {
return new DatabaseComponentImpl<T>(database, cleaner, shutdown, return new DatabaseComponentImpl<T>(database, cleaner, shutdown);
new SystemClock());
} }
} }