make unread status and notifications presistent across restarts

This commit is contained in:
Daniel Gultsch 2015-10-14 21:18:34 +02:00
parent 0587ba2ad2
commit 5f9476448f
6 changed files with 74 additions and 34 deletions

View file

@ -111,6 +111,16 @@ public class Conversation extends AbstractEntity implements Blockable {
} }
} }
public void findUnreadMessages(OnMessageFound onMessageFound) {
synchronized (this.messages) {
for(Message message : this.messages) {
if (!message.isRead()) {
onMessageFound.onMessageFound(message);
}
}
}
}
public void findMessagesWithFiles(final OnMessageFound onMessageFound) { public void findMessagesWithFiles(final OnMessageFound onMessageFound) {
synchronized (this.messages) { synchronized (this.messages) {
for (final Message message : this.messages) { for (final Message message : this.messages) {
@ -266,9 +276,8 @@ public class Conversation extends AbstractEntity implements Blockable {
} }
} }
public interface OnMessageFound { public interface OnMessageFound {
public void onMessageFound(final Message message); void onMessageFound(final Message message);
} }
public Conversation(final String name, final Account account, final Jid contactJid, public Conversation(final String name, final Account account, final Jid contactJid,
@ -301,13 +310,18 @@ public class Conversation extends AbstractEntity implements Blockable {
return (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead(); return (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead();
} }
public void markRead() { public List<Message> markRead() {
for (int i = this.messages.size() - 1; i >= 0; --i) { final List<Message> unread = new ArrayList<>();
if (messages.get(i).isRead()) { synchronized (this.messages) {
break; for (int i = this.messages.size() - 1; i >= 0; --i) {
if (this.messages.get(i).isRead()) {
break;
}
this.messages.get(i).markRead();
unread.add(this.messages.get(i));
} }
this.messages.get(i).markRead();
} }
return unread;
} }
public Message getLatestMarkableMessage() { public Message getLatestMarkableMessage() {

View file

@ -56,6 +56,7 @@ public class Message extends AbstractEntity {
public static final String SERVER_MSG_ID = "serverMsgId"; public static final String SERVER_MSG_ID = "serverMsgId";
public static final String RELATIVE_FILE_PATH = "relativeFilePath"; public static final String RELATIVE_FILE_PATH = "relativeFilePath";
public static final String FINGERPRINT = "axolotl_fingerprint"; public static final String FINGERPRINT = "axolotl_fingerprint";
public static final String READ = "read";
public static final String ME_COMMAND = "/me "; public static final String ME_COMMAND = "/me ";
@ -87,11 +88,8 @@ public class Message extends AbstractEntity {
public Message(Conversation conversation, String body, int encryption) { public Message(Conversation conversation, String body, int encryption) {
this(conversation, body, encryption, STATUS_UNSEND); this(conversation, body, encryption, STATUS_UNSEND);
} }
public Message(Conversation conversation, String body, int encryption, int status) {
this(conversation, body, encryption, status, false);
}
public Message(Conversation conversation, String body, int encryption, int status, boolean carbon) { public Message(Conversation conversation, String body, int encryption, int status) {
this(java.util.UUID.randomUUID().toString(), this(java.util.UUID.randomUUID().toString(),
conversation.getUuid(), conversation.getUuid(),
conversation.getJid() == null ? null : conversation.getJid().toBareJid(), conversation.getJid() == null ? null : conversation.getJid().toBareJid(),
@ -105,7 +103,8 @@ public class Message extends AbstractEntity {
null, null,
null, null,
null, null,
null); null,
true);
this.conversation = conversation; this.conversation = conversation;
} }
@ -113,7 +112,7 @@ public class Message extends AbstractEntity {
final Jid trueCounterpart, final String body, final long timeSent, final Jid trueCounterpart, final String body, final long timeSent,
final int encryption, final int status, final int type, final boolean carbon, final int encryption, final int status, final int type, final boolean carbon,
final String remoteMsgId, final String relativeFilePath, final String remoteMsgId, final String relativeFilePath,
final String serverMsgId, final String fingerprint) { final String serverMsgId, final String fingerprint, final boolean read) {
this.uuid = uuid; this.uuid = uuid;
this.conversationUuid = conversationUUid; this.conversationUuid = conversationUUid;
this.counterpart = counterpart; this.counterpart = counterpart;
@ -128,6 +127,7 @@ public class Message extends AbstractEntity {
this.relativeFilePath = relativeFilePath; this.relativeFilePath = relativeFilePath;
this.serverMsgId = serverMsgId; this.serverMsgId = serverMsgId;
this.axolotlFingerprint = fingerprint; this.axolotlFingerprint = fingerprint;
this.read = read;
} }
public static Message fromCursor(Cursor cursor) { public static Message fromCursor(Cursor cursor) {
@ -166,7 +166,8 @@ public class Message extends AbstractEntity {
cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)), cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)),
cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)), cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)),
cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)), cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)),
cursor.getString(cursor.getColumnIndex(FINGERPRINT))); cursor.getString(cursor.getColumnIndex(FINGERPRINT)),
cursor.getInt(cursor.getColumnIndex(READ)) > 0);
} }
public static Message createStatusMessage(Conversation conversation, String body) { public static Message createStatusMessage(Conversation conversation, String body) {
@ -202,6 +203,7 @@ public class Message extends AbstractEntity {
values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(RELATIVE_FILE_PATH, relativeFilePath);
values.put(SERVER_MSG_ID, serverMsgId); values.put(SERVER_MSG_ID, serverMsgId);
values.put(FINGERPRINT, axolotlFingerprint); values.put(FINGERPRINT, axolotlFingerprint);
values.put(READ,read);
return values; return values;
} }

View file

@ -43,7 +43,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null; private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history"; private static final String DATABASE_NAME = "history";
private static final int DATABASE_VERSION = 17; private static final int DATABASE_VERSION = 18;
private static String CREATE_CONTATCS_STATEMENT = "create table " private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@ -143,6 +143,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ Message.SERVER_MSG_ID + " TEXT, " + Message.SERVER_MSG_ID + " TEXT, "
+ Message.FINGERPRINT + " TEXT, " + Message.FINGERPRINT + " TEXT, "
+ Message.CARBON + " INTEGER, " + Message.CARBON + " INTEGER, "
+ Message.READ + " NUMBER DEFAULT 1, "
+ Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY(" + Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY("
+ Message.CONVERSATION + ") REFERENCES " + Message.CONVERSATION + ") REFERENCES "
+ Conversation.TABLENAME + "(" + Conversation.UUID + Conversation.TABLENAME + "(" + Conversation.UUID
@ -320,6 +321,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
} }
} }
} }
if (oldVersion < 18 && newVersion >= 18) {
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "+ Message.READ+ " NUMBER DEFAULT 1");
}
} }
public static synchronized DatabaseBackend getInstance(Context context) { public static synchronized DatabaseBackend getInstance(Context context) {

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.services; package eu.siacs.conversations.services;
import android.annotation.SuppressLint;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -10,7 +9,6 @@ import android.content.SharedPreferences;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.BigPictureStyle; import android.support.v4.app.NotificationCompat.BigPictureStyle;
@ -115,31 +113,45 @@ public class NotificationService {
return mXmppConnectionService.getPreferences().getBoolean("always_notify_in_conference", false); return mXmppConnectionService.getPreferences().getBoolean("always_notify_in_conference", false);
} }
public void pushFromBacklog(final Message message) {
if (notify(message)) {
pushToStack(message);
}
}
public void finishBacklog() {
synchronized (notifications) {
mXmppConnectionService.updateUnreadCountBadge();
updateNotification(false);
}
}
private void pushToStack(final Message message) {
final String conversationUuid = message.getConversationUuid();
if (notifications.containsKey(conversationUuid)) {
notifications.get(conversationUuid).add(message);
} else {
final ArrayList<Message> mList = new ArrayList<>();
mList.add(message);
notifications.put(conversationUuid, mList);
}
}
public void push(final Message message) { public void push(final Message message) {
mXmppConnectionService.updateUnreadCountBadge(); mXmppConnectionService.updateUnreadCountBadge();
if (!notify(message)) { if (!notify(message)) {
return; return;
} }
final boolean isScreenOn = mXmppConnectionService.isInteractive(); final boolean isScreenOn = mXmppConnectionService.isInteractive();
if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) {
return; return;
} }
synchronized (notifications) { synchronized (notifications) {
final String conversationUuid = message.getConversationUuid(); pushToStack(message);
if (notifications.containsKey(conversationUuid)) {
notifications.get(conversationUuid).add(message);
} else {
final ArrayList<Message> mList = new ArrayList<>();
mList.add(message);
notifications.put(conversationUuid, mList);
}
final Account account = message.getConversation().getAccount(); final Account account = message.getConversation().getAccount();
final boolean doNotify = (!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) final boolean doNotify = (!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn)
&& !account.inGracePeriod() && !account.inGracePeriod()
&& !this.inMiniGracePeriod(account); && !this.inMiniGracePeriod(account);
updateNotification(doNotify); updateNotification(doNotify);
if (doNotify) { if (doNotify) {
notifyPebble(message); notifyPebble(message);

View file

@ -1072,7 +1072,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
for (Conversation conversation : conversations) { for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
checkDeletedFiles(conversation); checkDeletedFiles(conversation);
conversation.findUnreadMessages(new Conversation.OnMessageFound() {
@Override
public void onMessageFound(Message message) {
mNotificationService.pushFromBacklog(message);
}
});
} }
mNotificationService.finishBacklog();
mRestoredFromDatabase = true; mRestoredFromDatabase = true;
Log.d(Config.LOGTAG,"restored all messages"); Log.d(Config.LOGTAG,"restored all messages");
updateConversationUi(); updateConversationUi();
@ -1330,7 +1337,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} }
public void updateKeyInAccount(final Account account, final String alias) { public void updateKeyInAccount(final Account account, final String alias) {
Log.d(Config.LOGTAG,"update key in account "+alias); Log.d(Config.LOGTAG, "update key in account " + alias);
try { try {
X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias); X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias);
Pair<Jid, String> info = CryptoHelper.extractJidAndName(chain[0]); Pair<Jid, String> info = CryptoHelper.extractJidAndName(chain[0]);
@ -2566,7 +2573,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void markRead(final Conversation conversation) { public void markRead(final Conversation conversation) {
mNotificationService.clear(conversation); mNotificationService.clear(conversation);
conversation.markRead(); for(Message message : conversation.markRead()) {
databaseBackend.updateMessage(message);
}
updateUnreadCountBadge(); updateUnreadCountBadge();
} }

View file

@ -216,8 +216,7 @@ public class ConversationActivity extends XmppActivity
return null; return null;
} }
listAdapter.remove(swipedConversation); listAdapter.remove(swipedConversation);
swipedConversation.markRead(); xmppConnectionService.markRead(swipedConversation);
xmppConnectionService.getNotificationService().clear(swipedConversation);
final boolean formerlySelected = (getSelectedConversation() == swipedConversation); final boolean formerlySelected = (getSelectedConversation() == swipedConversation);
if (position == 0 && listAdapter.getCount() == 0) { if (position == 0 && listAdapter.getCount() == 0) {