diff --git a/art/date_bubble_grey.svg b/art/date_bubble_grey.svg
new file mode 100644
index 000000000..38db49f9b
--- /dev/null
+++ b/art/date_bubble_grey.svg
@@ -0,0 +1,168 @@
+
+
+
+
diff --git a/art/date_bubble_white.svg b/art/date_bubble_white.svg
new file mode 100644
index 000000000..452ae9272
--- /dev/null
+++ b/art/date_bubble_white.svg
@@ -0,0 +1,168 @@
+
+
+
+
diff --git a/art/render.rb b/art/render.rb
index 01ab3903d..e20b951c7 100755
--- a/art/render.rb
+++ b/art/render.rb
@@ -64,6 +64,8 @@ images = {
'message_bubble_received_white.svg' => ['message_bubble_received_white.9', 0],
'message_bubble_sent.svg' => ['message_bubble_sent.9', 0],
'message_bubble_sent_grey.svg' => ['message_bubble_sent_grey.9', 0],
+ 'date_bubble_white.svg' => ['date_bubble_white.9', 0],
+ 'date_bubble_grey.svg' => ['date_bubble_grey.9', 0],
}
# Executable paths for Mac OSX
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java
index f360122de..77b54d328 100644
--- a/src/main/java/eu/siacs/conversations/entities/Message.java
+++ b/src/main/java/eu/siacs/conversations/entities/Message.java
@@ -10,6 +10,7 @@ import java.net.URL;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
import eu.siacs.conversations.http.AesGcmURLStreamHandler;
+import eu.siacs.conversations.ui.adapter.MessageAdapter;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.MimeUtils;
@@ -203,6 +204,14 @@ public class Message extends AbstractEntity {
return message;
}
+ public static Message createDateSeparator(Message message) {
+ final Message separator = new Message(message.getConversation());
+ separator.setType(Message.TYPE_STATUS);
+ separator.setBody(MessageAdapter.DATE_SEPARATOR_BODY);
+ separator.setTime(message.getTimeSent());
+ return separator;
+ }
+
@Override
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
@@ -493,7 +502,8 @@ public class Message extends AbstractEntity {
!this.getBody().startsWith(ME_COMMAND) &&
!this.bodyIsHeart() &&
!message.bodyIsHeart() &&
- ((this.axolotlFingerprint == null && message.axolotlFingerprint == null) || this.axolotlFingerprint.equals(message.getFingerprint()))
+ ((this.axolotlFingerprint == null && message.axolotlFingerprint == null) || this.axolotlFingerprint.equals(message.getFingerprint())) &&
+ UIHelper.sameDay(message.getTimeSent(),this.getTimeSent())
);
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 841519305..afdabcfe8 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -46,6 +46,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.ListIterator;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -154,14 +155,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void run() {
final int oldPosition = messagesView.getFirstVisiblePosition();
- final Message message;
- if (oldPosition < messageList.size()) {
- message = messageList.get(oldPosition);
- } else {
- message = null;
+ Message message = null;
+ int childPos;
+ for(childPos = 0; childPos + oldPosition < messageList.size(); ++childPos) {
+ message = messageList.get(oldPosition + childPos);
+ if (message.getType() != Message.TYPE_STATUS) {
+ break;
+ }
}
- String uuid = message != null ? message.getUuid() : null;
- View v = messagesView.getChildAt(0);
+ final String uuid = message != null ? message.getUuid() : null;
+ View v = messagesView.getChildAt(childPos);
final int pxOffset = (v == null) ? 0 : v.getTop();
ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
try {
@@ -1300,7 +1303,20 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
this.mSendButton.setImageResource(getSendButtonImageResource(action, status));
}
+ protected void updateDateSeparators() {
+ synchronized (this.messageList) {
+ for(int i = 0; i < this.messageList.size(); ++i) {
+ final Message current = this.messageList.get(i);
+ if (i == 0 || !UIHelper.sameDay(this.messageList.get(i-1).getTimeSent(),current.getTimeSent())) {
+ this.messageList.add(i,Message.createDateSeparator(current));
+ i++;
+ }
+ }
+ }
+ }
+
protected void updateStatusMessages() {
+ updateDateSeparators();
synchronized (this.messageList) {
if (showLoadMoreMessages(conversation)) {
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index 9c2e9bae2..a4b7c5caf 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -391,6 +391,7 @@ public abstract class XmppActivity extends Activity {
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey50);
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey200);
+ this.mTheme = findTheme();
if(isDarkTheme()) {
mPrimaryTextColor = ContextCompat.getColor(this, R.color.white);
mSecondaryTextColor = ContextCompat.getColor(this, R.color.white70);
@@ -398,8 +399,6 @@ public abstract class XmppActivity extends Activity {
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey800);
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey900);
}
-
- this.mTheme = findTheme();
setTheme(this.mTheme);
this.mUsingEnterKey = usingEnterKey();
@@ -411,7 +410,7 @@ public abstract class XmppActivity extends Activity {
}
public boolean isDarkTheme() {
- return getPreferences().getString("theme", getResources().getString(R.string.theme)).equals("dark");
+ return this.mTheme == R.style.ConversationsTheme_Dark || this.mTheme == R.style.ConversationsTheme_Dark_LargerText;
}
public int getThemeResource(int r_attr_name, int r_drawable_def) {
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index 1a203e9e9..adaa31174 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -16,6 +16,7 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
@@ -72,6 +73,10 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie
private static final int SENT = 0;
private static final int RECEIVED = 1;
private static final int STATUS = 2;
+ private static final int DATE_SEPARATOR = 3;
+
+ public static final String DATE_SEPARATOR_BODY = "DATE_SEPARATOR";
+
private static final Pattern XMPP_PATTERN = Pattern
.compile("xmpp\\:(?:(?:["
+ Patterns.GOOD_IRI_CHAR
@@ -135,12 +140,16 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie
@Override
public int getViewTypeCount() {
- return 3;
+ return 4;
}
public int getItemViewType(Message message) {
if (message.getType() == Message.TYPE_STATUS) {
- return STATUS;
+ if (DATE_SEPARATOR_BODY.equals(message.getBody())) {
+ return DATE_SEPARATOR;
+ } else {
+ return STATUS;
+ }
} else if (message.getStatus() <= Message.STATUS_RECEIVED) {
return RECEIVED;
}
@@ -591,6 +600,11 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie
if (view == null) {
viewHolder = new ViewHolder();
switch (type) {
+ case DATE_SEPARATOR:
+ view = activity.getLayoutInflater().inflate(R.layout.message_date_bubble, parent, false);
+ viewHolder.status_message = (TextView) view.findViewById(R.id.message_body);
+ viewHolder.message_box = (LinearLayout) view.findViewById(R.id.message_box);
+ break;
case SENT:
view = activity.getLayoutInflater().inflate(
R.layout.message_sent, parent, false);
@@ -659,7 +673,18 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie
boolean darkBackground = type == RECEIVED && (!isInValidSession || mUseGreenBackground) || activity.isDarkTheme();
- if (type == STATUS) {
+ if (type == DATE_SEPARATOR) {
+ if (UIHelper.today(message.getTimeSent())) {
+ viewHolder.status_message.setText(R.string.today);
+ } else if (UIHelper.yesterday(message.getTimeSent())) {
+ viewHolder.status_message.setText(R.string.yesterday);
+ } else {
+ viewHolder.status_message.setText(DateUtils.formatDateTime(activity,message.getTimeSent(),DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR));
+ }
+ viewHolder.message_box.setBackgroundResource(activity.isDarkTheme() ? R.drawable.date_bubble_grey : R.drawable.date_bubble_white);
+ viewHolder.status_message.setTextColor(activity.getSecondaryTextColor());
+ return view;
+ } else if (type == STATUS) {
if ("LOAD_MORE".equals(message.getBody())) {
viewHolder.status_message.setVisibility(View.GONE);
viewHolder.contact_picture.setVisibility(View.GONE);
diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
index 658fdc1e5..af0f5b6c6 100644
--- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
@@ -100,6 +100,24 @@ public class UIHelper {
return sameDay(date,new Date(System.currentTimeMillis()));
}
+ public static boolean today(long date) {
+ return sameDay(date,System.currentTimeMillis());
+ }
+
+ public static boolean yesterday(long date) {
+ Calendar cal1 = Calendar.getInstance();
+ Calendar cal2 = Calendar.getInstance();
+ cal1.add(Calendar.DAY_OF_YEAR,-1);
+ cal2.setTime(new Date(date));
+ return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
+ && cal1.get(Calendar.DAY_OF_YEAR) == cal2
+ .get(Calendar.DAY_OF_YEAR);
+ }
+
+ public static boolean sameDay(long a, long b) {
+ return sameDay(new Date(a),new Date(b));
+ }
+
private static boolean sameDay(Date a, Date b) {
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
diff --git a/src/main/res/drawable-hdpi/date_bubble_grey.9.png b/src/main/res/drawable-hdpi/date_bubble_grey.9.png
new file mode 100644
index 000000000..d12d22f4e
Binary files /dev/null and b/src/main/res/drawable-hdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-hdpi/date_bubble_white.9.png b/src/main/res/drawable-hdpi/date_bubble_white.9.png
new file mode 100644
index 000000000..df74d811a
Binary files /dev/null and b/src/main/res/drawable-hdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-mdpi/date_bubble_grey.9.png b/src/main/res/drawable-mdpi/date_bubble_grey.9.png
new file mode 100644
index 000000000..864f6910f
Binary files /dev/null and b/src/main/res/drawable-mdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-mdpi/date_bubble_white.9.png b/src/main/res/drawable-mdpi/date_bubble_white.9.png
new file mode 100644
index 000000000..cdfa31095
Binary files /dev/null and b/src/main/res/drawable-mdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xhdpi/date_bubble_grey.9.png
new file mode 100644
index 000000000..c83fd6130
Binary files /dev/null and b/src/main/res/drawable-xhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xhdpi/date_bubble_white.9.png b/src/main/res/drawable-xhdpi/date_bubble_white.9.png
new file mode 100644
index 000000000..ba59e1c55
Binary files /dev/null and b/src/main/res/drawable-xhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png
new file mode 100644
index 000000000..4b4dc4d56
Binary files /dev/null and b/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/date_bubble_white.9.png b/src/main/res/drawable-xxhdpi/date_bubble_white.9.png
new file mode 100644
index 000000000..80885df75
Binary files /dev/null and b/src/main/res/drawable-xxhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png
new file mode 100644
index 000000000..d3db7bf27
Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png b/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png
new file mode 100644
index 000000000..37c12f385
Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/layout/message_date_bubble.xml b/src/main/res/layout/message_date_bubble.xml
new file mode 100644
index 000000000..2d3cae7f0
--- /dev/null
+++ b/src/main/res/layout/message_date_bubble.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index a372a297f..53a8c036e 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -754,4 +754,6 @@
No application found to open website
Heads-up Notifications
Show Heads-up Notifications
+ Today
+ Yesterday