diff --git a/res/drawable-v21/conversation_list_item_read_background_dark.xml b/res/drawable-v21/conversation_list_item_background.xml
similarity index 82%
rename from res/drawable-v21/conversation_list_item_read_background_dark.xml
rename to res/drawable-v21/conversation_list_item_background.xml
index 19f004e729..642879178e 100644
--- a/res/drawable-v21/conversation_list_item_read_background_dark.xml
+++ b/res/drawable-v21/conversation_list_item_background.xml
@@ -5,7 +5,6 @@
-
-
diff --git a/res/drawable-v21/conversation_list_item_read_background.xml b/res/drawable-v21/conversation_list_item_background_dark.xml
similarity index 81%
rename from res/drawable-v21/conversation_list_item_read_background.xml
rename to res/drawable-v21/conversation_list_item_background_dark.xml
index 169f87c14b..642879178e 100644
--- a/res/drawable-v21/conversation_list_item_read_background.xml
+++ b/res/drawable-v21/conversation_list_item_background_dark.xml
@@ -5,7 +5,6 @@
-
-
diff --git a/res/drawable-v21/conversation_list_item_unread_background.xml b/res/drawable-v21/conversation_list_item_unread_background.xml
deleted file mode 100644
index 06c7a5f786..0000000000
--- a/res/drawable-v21/conversation_list_item_unread_background.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- -
-
-
-
-
-
-
diff --git a/res/drawable-v21/conversation_list_item_unread_background_dark.xml b/res/drawable-v21/conversation_list_item_unread_background_dark.xml
deleted file mode 100644
index 0b33205dee..0000000000
--- a/res/drawable-v21/conversation_list_item_unread_background_dark.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- -
-
-
-
-
-
-
diff --git a/res/drawable/conversation_list_item_read_background_dark.xml b/res/drawable/conversation_list_item_background.xml
similarity index 83%
rename from res/drawable/conversation_list_item_read_background_dark.xml
rename to res/drawable/conversation_list_item_background.xml
index 237d729853..92908acc6a 100644
--- a/res/drawable/conversation_list_item_read_background_dark.xml
+++ b/res/drawable/conversation_list_item_background.xml
@@ -3,5 +3,4 @@
-
diff --git a/res/drawable/conversation_list_item_read_background.xml b/res/drawable/conversation_list_item_background_dark.xml
similarity index 82%
rename from res/drawable/conversation_list_item_read_background.xml
rename to res/drawable/conversation_list_item_background_dark.xml
index 8ad9fae358..92908acc6a 100644
--- a/res/drawable/conversation_list_item_read_background.xml
+++ b/res/drawable/conversation_list_item_background_dark.xml
@@ -3,5 +3,4 @@
-
diff --git a/res/drawable/conversation_list_item_unread_background.xml b/res/drawable/conversation_list_item_unread_background.xml
deleted file mode 100644
index 2f11d8cc99..0000000000
--- a/res/drawable/conversation_list_item_unread_background.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/res/drawable/conversation_list_item_unread_background_dark.xml b/res/drawable/conversation_list_item_unread_background_dark.xml
deleted file mode 100644
index bf0b92d290..0000000000
--- a/res/drawable/conversation_list_item_unread_background_dark.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml
index be65a5ce12..dc9dc014e6 100644
--- a/res/layout/conversation_activity.xml
+++ b/res/layout/conversation_activity.xml
@@ -1,12 +1,12 @@
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/layout_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ android:layout_height="match_parent">
diff --git a/res/layout/conversation_list_item_view.xml b/res/layout/conversation_list_item_view.xml
index 6e74c90326..b475f7af6d 100644
--- a/res/layout/conversation_list_item_view.xml
+++ b/res/layout/conversation_list_item_view.xml
@@ -3,6 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
+ android:background="?attr/conversation_list_item_background"
android:layout_width="match_parent"
android:focusable="true"
android:nextFocusRight="@+id/fab"
@@ -144,5 +145,13 @@
android:layout_alignWithParentIfMissing="true"
app:iconColor="?attr/conversation_list_item_subject_color"/>
+
+
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 689384eb8f..2d8cb341b2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -2,10 +2,7 @@
-
-
-
-
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6ce9a15bdd..601fb1cfc1 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -27,14 +27,6 @@
#32000000
- @color/gray5
- #ffffffff
- #ff000000
- #ff333333
-
-
-
-
#ff33b5e5
#ff111111
diff --git a/res/values/themes.xml b/res/values/themes.xml
index dfc50988c7..45ad3fe0dc 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -110,15 +110,12 @@
- @color/textsecure_primary_dark
- @color/signal_primary
- @color/signal_primary
- - @color/gray5
+ - @color/white
- @style/AppCompatAlertDialogStyleLight
- @style/AppCompatDialogStyleLight
- @color/white
- - @drawable/list_selected_holo_light
- - @drawable/conversation_list_item_unread_background
- - @drawable/conversation_list_item_read_background
- - #66333333
+ - @drawable/conversation_list_item_background
- #FF333333
- #FF444444
- #ff999999
@@ -129,7 +126,7 @@
- #99000000
- - #eeeeee
+ - @color/gray5
- #22000000
- #ff111111
- @drawable/ic_send_sms_insecure
@@ -240,10 +237,7 @@
- @color/black
- @style/AppCompatAlertDialogStyleDark
- @style/AppCompatDialogStyleDark
- - @drawable/list_selected_holo_dark
- - @drawable/conversation_list_item_unread_background_dark
- - @drawable/conversation_list_item_read_background_dark
- - #66dddddd
+ - @drawable/conversation_list_item_background_dark
- #ffdddddd
- #ffdddddd
- #ffdddddd
@@ -277,7 +271,7 @@
- @color/textsecure_primary_dark
- @drawable/divet_lower_right_light
- - #22ffffff
+ - @color/black
- #22ffffff
- #ffeeeeee
- @drawable/ic_send_sms_insecure_dark
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index b711fc5e7a..b1b2be7c2a 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -265,6 +265,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY);
setContentView(R.layout.conversation_activity);
+ TypedArray typedArray = obtainStyledAttributes(new int[] {R.attr.conversation_background});
+ int color = typedArray.getColor(0, Color.WHITE);
+ typedArray.recycle();
+
+ getWindow().getDecorView().setBackgroundColor(color);
+
fragment = initFragment(R.id.fragment_content, new ConversationFragment(),
masterSecret, dynamicLanguage.getCurrentLocale());
diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java
index 14e439acd8..38561718ba 100644
--- a/src/org/thoughtcrime/securesms/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationItem.java
@@ -240,9 +240,7 @@ public class ConversationItem extends LinearLayout
}
private void initializeAttributes() {
- final int[] attributes = new int[] {R.attr.conversation_item_bubble_background,
- R.attr.conversation_list_item_background_selected,
- R.attr.conversation_item_background};
+ final int[] attributes = new int[] {R.attr.conversation_item_bubble_background};
final TypedArray attrs = context.obtainStyledAttributes(attributes);
defaultBubbleColor = attrs.getColor(0, Color.WHITE);
diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java
index b2dff8044e..e7cbaf6e80 100644
--- a/src/org/thoughtcrime/securesms/ConversationListActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java
@@ -1,5 +1,5 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
+/*
+ * Copyright (C) 2014-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,7 +31,6 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
@@ -117,9 +116,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
}
private void initializeSearchListener() {
- searchAction.setOnClickListener(v -> {
- searchToolbar.display(searchAction.getX() + (searchAction.getWidth() / 2), searchAction.getY() + (searchAction.getHeight() / 2));
- });
+ searchAction.setOnClickListener(v -> searchToolbar.display(searchAction.getX() + (searchAction.getWidth() / 2),
+ searchAction.getY() + (searchAction.getHeight() / 2)));
searchToolbar.setListener(new SearchToolbar.SearchListener() {
@Override
@@ -235,12 +233,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
super.onChange(selfChange);
Log.w(TAG, "Detected android contact data changed, refreshing cache");
Recipient.clearCache(ConversationListActivity.this);
- ConversationListActivity.this.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- fragment.getListAdapter().notifyDataSetChanged();
- }
- });
+ ConversationListActivity.this.runOnUiThread(() -> fragment.getListAdapter().notifyDataSetChanged());
}
};
diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java
index fccbecb68d..e4675600e9 100644
--- a/src/org/thoughtcrime/securesms/ConversationListFragment.java
+++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java
@@ -130,7 +130,7 @@ public class ConversationListFragment extends Fragment
TypedArray typedArray = getContext().obtainStyledAttributes(new int[]{R.attr.conversation_list_item_divider});
Drawable itemDrawable = typedArray.getDrawable(0);
DividerItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL);
- itemDecoration.setDrawable(itemDrawable);
+ if (itemDrawable != null) itemDecoration.setDrawable(itemDrawable);
list.addItemDecoration(itemDecoration);
typedArray.recycle();
@@ -472,8 +472,8 @@ public class ConversationListFragment extends Fragment
@SuppressLint("StaticFieldLeak")
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
- final long threadId = ((ConversationListItem)viewHolder.itemView).getThreadId();
- final boolean read = ((ConversationListItem)viewHolder.itemView).getRead();
+ final long threadId = ((ConversationListItem)viewHolder.itemView).getThreadId();
+ final int unreadCount = ((ConversationListItem)viewHolder.itemView).getUnreadCount();
if (archive) {
new SnackbarAsyncTask(getView(),
@@ -503,7 +503,7 @@ public class ConversationListFragment extends Fragment
protected void executeAction(@Nullable Long parameter) {
DatabaseFactory.getThreadDatabase(getActivity()).archiveConversation(threadId);
- if (!read) {
+ if (unreadCount > 0) {
List messageIds = DatabaseFactory.getThreadDatabase(getActivity()).setRead(threadId, false);
MessageNotifier.updateNotification(getActivity(), masterSecret);
MarkReadReceiver.process(getActivity(), messageIds);
@@ -514,8 +514,8 @@ public class ConversationListFragment extends Fragment
protected void reverseAction(@Nullable Long parameter) {
DatabaseFactory.getThreadDatabase(getActivity()).unarchiveConversation(threadId);
- if (!read) {
- DatabaseFactory.getThreadDatabase(getActivity()).setUnread(threadId);
+ if (unreadCount > 0) {
+ DatabaseFactory.getThreadDatabase(getActivity()).incrementUnread(threadId, unreadCount);
MessageNotifier.updateNotification(getActivity(), masterSecret);
}
}
@@ -560,7 +560,7 @@ public class ConversationListFragment extends Fragment
}
}
}
-
+
}
diff --git a/src/org/thoughtcrime/securesms/ConversationListItem.java b/src/org/thoughtcrime/securesms/ConversationListItem.java
index 8cf9ea0c6d..cd1e28e901 100644
--- a/src/org/thoughtcrime/securesms/ConversationListItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationListItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Whisper Systems
+ * Copyright (C) 2014-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,17 +19,20 @@ package org.thoughtcrime.securesms;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.RippleDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
-import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
+import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.amulyakhare.textdrawable.TextDrawable;
+
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
@@ -41,7 +44,6 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.DateUtils;
-import org.thoughtcrime.securesms.util.ResUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -50,17 +52,11 @@ import java.util.Set;
import static org.thoughtcrime.securesms.util.SpanUtil.color;
-/**
- * A view that displays the element in a list of multiple conversation threads.
- * Used by SecureSMS's ListActivity via a ConversationListAdapter.
- *
- * @author Moxie Marlinspike
- */
-
public class ConversationListItem extends RelativeLayout
implements RecipientModifiedListener,
BindableConversationListItem, Unbindable
{
+ @SuppressWarnings("unused")
private final static String TAG = ConversationListItem.class.getSimpleName();
private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif", Typeface.BOLD);
@@ -76,15 +72,13 @@ public class ConversationListItem extends RelativeLayout
private TextView archivedView;
private DeliveryStatusView deliveryStatusIndicator;
private AlertView alertView;
+ private ImageView unreadIndicator;
private long lastSeen;
- private boolean read;
+ private int unreadCount;
private AvatarImageView contactPhotoImage;
private ThumbnailView thumbnailView;
- private final @DrawableRes int readBackground;
- private final @DrawableRes int unreadBackround;
-
private int distributionType;
public ConversationListItem(Context context) {
@@ -93,8 +87,6 @@ public class ConversationListItem extends RelativeLayout
public ConversationListItem(Context context, AttributeSet attrs) {
super(context, attrs);
- readBackground = ResUtil.getDrawableRes(context, R.attr.conversation_list_item_background_read);
- unreadBackround = ResUtil.getDrawableRes(context, R.attr.conversation_list_item_background_unread);
}
@Override
@@ -107,7 +99,8 @@ public class ConversationListItem extends RelativeLayout
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
this.thumbnailView = findViewById(R.id.thumbnail);
- this.archivedView = ViewUtil.findById(this, R.id.archived);
+ this.archivedView = findViewById(R.id.archived);
+ this.unreadIndicator = findViewById(R.id.unread_indicator);
thumbnailView.setClickable(false);
ViewUtil.setTextViewGravityStart(this.fromView, getContext());
@@ -123,20 +116,20 @@ public class ConversationListItem extends RelativeLayout
this.recipient = thread.getRecipient();
this.threadId = thread.getThreadId();
this.glideRequests = glideRequests;
- this.read = thread.isRead();
+ this.unreadCount = thread.getUnreadCount();
this.distributionType = thread.getDistributionType();
this.lastSeen = thread.getLastSeen();
this.recipient.addListener(this);
- this.fromView.setText(recipient, read);
+ this.fromView.setText(recipient, unreadCount == 0);
this.subjectView.setText(thread.getDisplayBody());
- this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
+// this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
if (thread.getDate() > 0) {
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
- dateView.setText(read ? date : color(getResources().getColor(R.color.textsecure_primary), date));
- dateView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
+ dateView.setText(unreadCount == 0 ? date : color(getResources().getColor(R.color.textsecure_primary_dark), date));
+ dateView.setTypeface(unreadCount == 0 ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
}
if (thread.isArchived()) {
@@ -148,8 +141,8 @@ public class ConversationListItem extends RelativeLayout
setStatusIcons(thread);
setThumbnailSnippet(masterSecret, thread);
setBatchState(batchMode);
- setBackground(thread);
setRippleColor(recipient);
+ setUnreadIndicator(thread);
this.contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
@@ -170,8 +163,8 @@ public class ConversationListItem extends RelativeLayout
return threadId;
}
- public boolean getRead() {
- return read;
+ public int getUnreadCount() {
+ return unreadCount;
}
public int getDistributionType() {
@@ -226,12 +219,6 @@ public class ConversationListItem extends RelativeLayout
}
}
- private void setBackground(ThreadRecord thread) {
- if (thread.isRead()) setBackgroundResource(readBackground);
- else setBackgroundResource(unreadBackround);
- }
-
- @TargetApi(VERSION_CODES.LOLLIPOP)
private void setRippleColor(Recipient recipient) {
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
((RippleDrawable)(getBackground()).mutate())
@@ -239,10 +226,27 @@ public class ConversationListItem extends RelativeLayout
}
}
+ private void setUnreadIndicator(ThreadRecord thread) {
+ if (thread.isOutgoing() || thread.getUnreadCount() == 0) {
+ unreadIndicator.setVisibility(View.GONE);
+ return;
+ }
+
+ unreadIndicator.setImageDrawable(TextDrawable.builder()
+ .beginConfig()
+ .width(ViewUtil.dpToPx(getContext(), 24))
+ .height(ViewUtil.dpToPx(getContext(), 24))
+ .textColor(Color.WHITE)
+ .bold()
+ .endConfig()
+ .buildRound(String.valueOf(thread.getUnreadCount()), getResources().getColor(R.color.textsecure_primary_dark)));
+ unreadIndicator.setVisibility(View.VISIBLE);
+ }
+
@Override
public void onModified(final Recipient recipient) {
Util.runOnMain(() -> {
- fromView.setText(recipient, read);
+ fromView.setText(recipient, unreadCount == 0);
contactPhotoImage.setAvatar(glideRequests, recipient, true);
setRippleColor(recipient);
});
diff --git a/src/org/thoughtcrime/securesms/ShareListItem.java b/src/org/thoughtcrime/securesms/ShareListItem.java
index 97b577ffae..b5e9f46dee 100644
--- a/src/org/thoughtcrime/securesms/ShareListItem.java
+++ b/src/org/thoughtcrime/securesms/ShareListItem.java
@@ -85,7 +85,7 @@ public class ShareListItem extends RelativeLayout
}
private void setBackground() {
- int[] attributes = new int[]{R.attr.conversation_list_item_background_read};
+ int[] attributes = new int[]{R.attr.conversation_list_item_background};
TypedArray drawables = context.obtainStyledAttributes(attributes);
setBackgroundDrawable(drawables.getDrawable(0));
diff --git a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
index bb95a72733..01512adac6 100644
--- a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
+++ b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
@@ -109,7 +109,8 @@ public class DatabaseFactory {
private static final int UNSEEN_NUMBER_OFFER = 43;
private static final int READ_RECEIPTS = 44;
private static final int GROUP_RECEIPT_TRACKING = 45;
- private static final int DATABASE_VERSION = 45;
+ private static final int UNREAD_COUNT_VERSION = 46;
+ private static final int DATABASE_VERSION = 46;
private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object();
@@ -1346,6 +1347,33 @@ public class DatabaseFactory {
db.execSQL("CREATE INDEX IF NOT EXISTS group_receipt_mms_id_index ON group_receipts (mms_id)");
}
+ if (oldVersion < UNREAD_COUNT_VERSION) {
+ db.execSQL("ALTER TABLE thread ADD COLUMN unread_count INTEGER DEFAULT 0");
+
+ try (Cursor cursor = db.query("thread", new String[] {"_id"}, "read = 0", null, null, null, null)) {
+ while (cursor != null && cursor.moveToNext()) {
+ long threadId = cursor.getLong(0);
+ int unreadCount = 0;
+
+ try (Cursor smsCursor = db.rawQuery("SELECT COUNT(*) FROM sms WHERE thread_id = ? AND read = '0'", new String[] {String.valueOf(threadId)})) {
+ if (smsCursor != null && smsCursor.moveToFirst()) {
+ unreadCount += smsCursor.getInt(0);
+ }
+ }
+
+ try (Cursor mmsCursor = db.rawQuery("SELECT COUNT(*) FROM mms WHERE thread_id = ? AND read = '0'", new String[] {String.valueOf(threadId)})) {
+ if (mmsCursor != null && mmsCursor.moveToFirst()) {
+ unreadCount += mmsCursor.getInt(0);
+ }
+ }
+
+ db.execSQL("UPDATE thread SET unread_count = ? WHERE _id = ?",
+ new String[] {String.valueOf(unreadCount),
+ String.valueOf(threadId)});
+ }
+ }
+ }
+
db.setTransactionSuccessful();
db.endTransaction();
}
diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
index 4a5ef4d68c..0ae9b62e33 100644
--- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
@@ -677,7 +677,7 @@ public class MmsDatabase extends MessagingDatabase {
long messageId = insertMediaMessage(masterSecret, retrieved.getBody(), retrieved.getAttachments(), contentValues, null);
if (!Types.isExpirationTimerUpdate(mailbox)) {
- DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
+ DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
}
@@ -775,7 +775,7 @@ public class MmsDatabase extends MessagingDatabase {
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
if (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context)) {
- DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
+ DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
}
jobManager.add(new TrimThreadJob(context, threadId));
diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
index f8ba35c1bb..154ee2e6ee 100644
--- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
@@ -1,5 +1,6 @@
-/**
+/*
* Copyright (C) 2011 Whisper Systems
+ * Copyright (C) 2013 - 2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -486,7 +487,7 @@ public class SmsDatabase extends MessagingDatabase {
jobManager.add(new TrimThreadJob(context, threadId));
if (unread) {
- DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
+ DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
}
return new Pair<>(messageId, threadId);
@@ -561,7 +562,7 @@ public class SmsDatabase extends MessagingDatabase {
long messageId = db.insert(TABLE_NAME, null, values);
if (unread) {
- DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
+ DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
}
if (!message.isIdentityUpdate() && !message.isIdentityVerified() && !message.isIdentityDefault()) {
diff --git a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
index 9d72d5d3c5..abf15b3969 100644
--- a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
@@ -1,5 +1,6 @@
-/**
+/*
* Copyright (C) 2011 Whisper Systems
+ * Copyright (C) 2013-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -65,6 +66,7 @@ public class ThreadDatabase extends Database {
public static final String SNIPPET = "snippet";
private static final String SNIPPET_CHARSET = "snippet_cs";
public static final String READ = "read";
+ public static final String UNREAD_COUNT = "unread_count";
public static final String TYPE = "type";
private static final String ERROR = "error";
public static final String SNIPPET_TYPE = "snippet_type";
@@ -86,15 +88,15 @@ public class ThreadDatabase extends Database {
ARCHIVED + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT 0, " +
DELIVERY_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + EXPIRES_IN + " INTEGER DEFAULT 0, " +
LAST_SEEN + " INTEGER DEFAULT 0, " + HAS_SENT + " INTEGER DEFAULT 0, " +
- READ_RECEIPT_COUNT + " INTEGER DEFAULT 0);";
+ READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + UNREAD_COUNT + " INTEGER DEFAULT 0);";
- public static final String[] CREATE_INDEXS = {
+ static final String[] CREATE_INDEXS = {
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + ADDRESS + ");",
"CREATE INDEX IF NOT EXISTS archived_count_index ON " + TABLE_NAME + " (" + ARCHIVED + ", " + MESSAGE_COUNT + ");",
};
private static final String[] THREAD_PROJECTION = {
- ID, DATE, MESSAGE_COUNT, ADDRESS, SNIPPET, SNIPPET_CHARSET, READ, TYPE, ERROR, SNIPPET_TYPE,
+ ID, DATE, MESSAGE_COUNT, ADDRESS, SNIPPET, SNIPPET_CHARSET, READ, UNREAD_COUNT, TYPE, ERROR, SNIPPET_TYPE,
SNIPPET_URI, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT
};
@@ -248,6 +250,7 @@ public class ThreadDatabase extends Database {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(1);
contentValues.put(READ, 1);
+ contentValues.put(UNREAD_COUNT, 0);
db.update(TABLE_NAME, contentValues, null, null);
@@ -265,6 +268,7 @@ public class ThreadDatabase extends Database {
public List setRead(long threadId, boolean lastSeen) {
ContentValues contentValues = new ContentValues(1);
contentValues.put(READ, 1);
+ contentValues.put(UNREAD_COUNT, 0);
if (lastSeen) {
contentValues.put(LAST_SEEN, System.currentTimeMillis());
@@ -284,13 +288,22 @@ public class ThreadDatabase extends Database {
}};
}
- public void setUnread(long threadId) {
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(READ, 0);
+// public void setUnread(long threadId, int unreadCount) {
+// ContentValues contentValues = new ContentValues(1);
+// contentValues.put(READ, 0);
+// contentValues.put(UNREAD_COUNT, unreadCount);
+//
+// SQLiteDatabase db = databaseHelper.getWritableDatabase();
+// db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId + ""});
+// notifyConversationListListeners();
+// }
+ public void incrementUnread(long threadId, int amount) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
- db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId + ""});
- notifyConversationListListeners();
+ db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = 0, " +
+ UNREAD_COUNT + " = " + UNREAD_COUNT + " + ? WHERE " + ID + " = ?",
+ new String[] {String.valueOf(amount),
+ String.valueOf(threadId)});
}
public void setDistributionType(long threadId, int distributionType) {
@@ -530,11 +543,12 @@ public class ThreadDatabase extends Database {
notifyConversationListeners(threadId);
}
- public void updateReadState(long threadId) {
+ void updateReadState(long threadId) {
int unreadCount = DatabaseFactory.getMmsSmsDatabase(context).getUnreadCount(threadId);
ContentValues contentValues = new ContentValues();
contentValues.put(READ, unreadCount == 0);
+ contentValues.put(UNREAD_COUNT, unreadCount);
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues,ID_WHERE,
new String[] {String.valueOf(threadId)});
@@ -595,8 +609,8 @@ public class ThreadDatabase extends Database {
" ORDER BY " + TABLE_NAME + "." + DATE + " DESC";
}
- public static interface ProgressListener {
- public void onProgress(int complete, int total);
+ public interface ProgressListener {
+ void onProgress(int complete, int total);
}
public Reader readerFor(Cursor cursor, MasterCipher masterCipher) {
@@ -648,7 +662,7 @@ public class ThreadDatabase extends Database {
DisplayRecord.Body body = getPlaintextBody(cursor);
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
- long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ));
+ int unreadCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.UNREAD_COUNT));
long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE));
boolean archived = cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0;
int status = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS));
@@ -662,9 +676,9 @@ public class ThreadDatabase extends Database {
readReceiptCount = 0;
}
- return new ThreadRecord(context, body, snippetUri, recipient, date, count, read == 1,
- threadId, deliveryReceiptCount, status, type, distributionType, archived,
- expiresIn, lastSeen, readReceiptCount);
+ return new ThreadRecord(context, body, snippetUri, recipient, date, count,
+ unreadCount, threadId, deliveryReceiptCount, status, type,
+ distributionType, archived, expiresIn, lastSeen, readReceiptCount);
}
private DisplayRecord.Body getPlaintextBody(Cursor cursor) {
diff --git a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
index 8ea53a899a..33f83faa6f 100644
--- a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
@@ -1,5 +1,6 @@
-/**
+/*
* Copyright (C) 2012 Moxie Marlinspike
+ * Copyright (C) 2013-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,14 +43,14 @@ public class ThreadRecord extends DisplayRecord {
private @NonNull final Context context;
private @Nullable final Uri snippetUri;
private final long count;
- private final boolean read;
+ private final int unreadCount;
private final int distributionType;
private final boolean archived;
private final long expiresIn;
private final long lastSeen;
public ThreadRecord(@NonNull Context context, @NonNull Body body, @Nullable Uri snippetUri,
- @NonNull Recipient recipient, long date, long count, boolean read,
+ @NonNull Recipient recipient, long date, long count, int unreadCount,
long threadId, int deliveryReceiptCount, int status, long snippetType,
int distributionType, boolean archived, long expiresIn, long lastSeen,
int readReceiptCount)
@@ -58,7 +59,7 @@ public class ThreadRecord extends DisplayRecord {
this.context = context.getApplicationContext();
this.snippetUri = snippetUri;
this.count = count;
- this.read = read;
+ this.unreadCount = unreadCount;
this.distributionType = distributionType;
this.archived = archived;
this.expiresIn = expiresIn;
@@ -134,8 +135,8 @@ public class ThreadRecord extends DisplayRecord {
return count;
}
- public boolean isRead() {
- return read;
+ public int getUnreadCount() {
+ return unreadCount;
}
public long getDate() {