diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f4d116fe..f2c4fed4 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -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) { synchronized (this.messages) { for (final Message message : this.messages) { @@ -266,9 +276,8 @@ public class Conversation extends AbstractEntity implements Blockable { } } - 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, @@ -301,13 +310,18 @@ public class Conversation extends AbstractEntity implements Blockable { return (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead(); } - public void markRead() { - for (int i = this.messages.size() - 1; i >= 0; --i) { - if (messages.get(i).isRead()) { - break; + public List markRead() { + final List unread = new ArrayList<>(); + synchronized (this.messages) { + 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() { diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index bfb26446..36cc0842 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -56,6 +56,7 @@ public class Message extends AbstractEntity { public static final String SERVER_MSG_ID = "serverMsgId"; public static final String RELATIVE_FILE_PATH = "relativeFilePath"; public static final String FINGERPRINT = "axolotl_fingerprint"; + public static final String READ = "read"; public static final String ME_COMMAND = "/me "; @@ -87,11 +88,8 @@ public class Message extends AbstractEntity { public Message(Conversation conversation, String body, int encryption) { 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(), conversation.getUuid(), conversation.getJid() == null ? null : conversation.getJid().toBareJid(), @@ -105,7 +103,8 @@ public class Message extends AbstractEntity { null, null, null, - null); + null, + true); this.conversation = conversation; } @@ -113,7 +112,7 @@ public class Message extends AbstractEntity { final Jid trueCounterpart, final String body, final long timeSent, final int encryption, final int status, final int type, final boolean carbon, 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.conversationUuid = conversationUUid; this.counterpart = counterpart; @@ -128,6 +127,7 @@ public class Message extends AbstractEntity { this.relativeFilePath = relativeFilePath; this.serverMsgId = serverMsgId; this.axolotlFingerprint = fingerprint; + this.read = read; } 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(RELATIVE_FILE_PATH)), 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) { @@ -202,6 +203,7 @@ public class Message extends AbstractEntity { values.put(RELATIVE_FILE_PATH, relativeFilePath); values.put(SERVER_MSG_ID, serverMsgId); values.put(FINGERPRINT, axolotlFingerprint); + values.put(READ,read); return values; } diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index be827929..07071323 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -43,7 +43,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private static DatabaseBackend instance = null; 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 " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -143,6 +143,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + Message.SERVER_MSG_ID + " TEXT, " + Message.FINGERPRINT + " TEXT, " + Message.CARBON + " INTEGER, " + + Message.READ + " NUMBER DEFAULT 1, " + Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY(" + Message.CONVERSATION + ") REFERENCES " + 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) { diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 3ed155a8..e9095020 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.services; -import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -10,7 +9,6 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; -import android.os.PowerManager; import android.os.SystemClock; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat.BigPictureStyle; @@ -115,31 +113,45 @@ public class NotificationService { 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 mList = new ArrayList<>(); + mList.add(message); + notifications.put(conversationUuid, mList); + } + } + public void push(final Message message) { mXmppConnectionService.updateUnreadCountBadge(); if (!notify(message)) { return; } - final boolean isScreenOn = mXmppConnectionService.isInteractive(); - if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { return; } - synchronized (notifications) { - final String conversationUuid = message.getConversationUuid(); - if (notifications.containsKey(conversationUuid)) { - notifications.get(conversationUuid).add(message); - } else { - final ArrayList mList = new ArrayList<>(); - mList.add(message); - notifications.put(conversationUuid, mList); - } + pushToStack(message); final Account account = message.getConversation().getAccount(); final boolean doNotify = (!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) - && !account.inGracePeriod() - && !this.inMiniGracePeriod(account); + && !account.inGracePeriod() + && !this.inMiniGracePeriod(account); updateNotification(doNotify); if (doNotify) { notifyPebble(message); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 7a39bd06..cfd3ba6e 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1072,7 +1072,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa for (Conversation conversation : conversations) { conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); checkDeletedFiles(conversation); + conversation.findUnreadMessages(new Conversation.OnMessageFound() { + @Override + public void onMessageFound(Message message) { + mNotificationService.pushFromBacklog(message); + } + }); } + mNotificationService.finishBacklog(); mRestoredFromDatabase = true; Log.d(Config.LOGTAG,"restored all messages"); updateConversationUi(); @@ -1330,7 +1337,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } 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 { X509Certificate[] chain = KeyChain.getCertificateChain(XmppConnectionService.this, alias); Pair info = CryptoHelper.extractJidAndName(chain[0]); @@ -2566,7 +2573,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void markRead(final Conversation conversation) { mNotificationService.clear(conversation); - conversation.markRead(); + for(Message message : conversation.markRead()) { + databaseBackend.updateMessage(message); + } updateUnreadCountBadge(); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 48045a64..5831df56 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -216,8 +216,7 @@ public class ConversationActivity extends XmppActivity return null; } listAdapter.remove(swipedConversation); - swipedConversation.markRead(); - xmppConnectionService.getNotificationService().clear(swipedConversation); + xmppConnectionService.markRead(swipedConversation); final boolean formerlySelected = (getSelectedConversation() == swipedConversation); if (position == 0 && listAdapter.getCount() == 0) {