show date separators. fixes #2271
168
art/date_bubble_grey.svg
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="26"
|
||||||
|
height="26"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.1 r"
|
||||||
|
sodipodi:docname="date_bubble_white.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<filter
|
||||||
|
x="-0.25"
|
||||||
|
y="-0.25"
|
||||||
|
width="1.5"
|
||||||
|
height="1.5"
|
||||||
|
inkscape:label="Drop Shadow"
|
||||||
|
id="filter3811"
|
||||||
|
style="color-interpolation-filters:sRGB">
|
||||||
|
<feFlood
|
||||||
|
flood-opacity="0.25"
|
||||||
|
flood-color="rgb(0,0,0)"
|
||||||
|
result="flood"
|
||||||
|
id="feFlood3813" />
|
||||||
|
<feComposite
|
||||||
|
in="flood"
|
||||||
|
in2="SourceGraphic"
|
||||||
|
operator="in"
|
||||||
|
result="composite1"
|
||||||
|
id="feComposite3815" />
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="0.5"
|
||||||
|
result="blur"
|
||||||
|
id="feGaussianBlur3817" />
|
||||||
|
<feOffset
|
||||||
|
dx="0"
|
||||||
|
dy="1"
|
||||||
|
result="offset"
|
||||||
|
id="feOffset3819" />
|
||||||
|
<feComposite
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="offset"
|
||||||
|
operator="over"
|
||||||
|
result="composite2"
|
||||||
|
id="feComposite3821" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="16"
|
||||||
|
inkscape:cx="9.745257"
|
||||||
|
inkscape:cy="9.618802"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1916"
|
||||||
|
inkscape:window-height="1156"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
guidecolor="#000000"
|
||||||
|
guideopacity="0.49803922"
|
||||||
|
fit-margin-top="-2"
|
||||||
|
fit-margin-left="-2"
|
||||||
|
fit-margin-right="-2"
|
||||||
|
fit-margin-bottom="-2">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2985"
|
||||||
|
empspacing="4"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="1"
|
||||||
|
spacingy="1"
|
||||||
|
originx="-9"
|
||||||
|
originy="-1"
|
||||||
|
color="#0000ff"
|
||||||
|
opacity="0.03137255" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="11,26"
|
||||||
|
id="guide3060"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="15,26"
|
||||||
|
id="guide3062"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="26,21"
|
||||||
|
id="guide3064"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="26,5"
|
||||||
|
id="guide3066"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="17,0"
|
||||||
|
id="guide3068"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="9,0"
|
||||||
|
id="guide3070"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="0,18"
|
||||||
|
id="guide3074"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="0,16"
|
||||||
|
id="guide3076"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer"
|
||||||
|
transform="translate(-9,-1)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3805"
|
||||||
|
d="m 8,8 c 2,2 4,6 4,10 L 16,8 Z"
|
||||||
|
style="display:none;fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)"
|
||||||
|
id="rect2987"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
x="12"
|
||||||
|
y="4"
|
||||||
|
ry="2" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
168
art/date_bubble_white.svg
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="26"
|
||||||
|
height="26"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.1 r"
|
||||||
|
sodipodi:docname="date_bubble_white.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<filter
|
||||||
|
x="-0.25"
|
||||||
|
y="-0.25"
|
||||||
|
width="1.5"
|
||||||
|
height="1.5"
|
||||||
|
inkscape:label="Drop Shadow"
|
||||||
|
id="filter3811"
|
||||||
|
style="color-interpolation-filters:sRGB">
|
||||||
|
<feFlood
|
||||||
|
flood-opacity="0.25"
|
||||||
|
flood-color="rgb(0,0,0)"
|
||||||
|
result="flood"
|
||||||
|
id="feFlood3813" />
|
||||||
|
<feComposite
|
||||||
|
in="flood"
|
||||||
|
in2="SourceGraphic"
|
||||||
|
operator="in"
|
||||||
|
result="composite1"
|
||||||
|
id="feComposite3815" />
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="0.5"
|
||||||
|
result="blur"
|
||||||
|
id="feGaussianBlur3817" />
|
||||||
|
<feOffset
|
||||||
|
dx="0"
|
||||||
|
dy="1"
|
||||||
|
result="offset"
|
||||||
|
id="feOffset3819" />
|
||||||
|
<feComposite
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="offset"
|
||||||
|
operator="over"
|
||||||
|
result="composite2"
|
||||||
|
id="feComposite3821" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="16"
|
||||||
|
inkscape:cx="9.745257"
|
||||||
|
inkscape:cy="9.618802"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1916"
|
||||||
|
inkscape:window-height="1156"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
guidecolor="#000000"
|
||||||
|
guideopacity="0.49803922"
|
||||||
|
fit-margin-top="-2"
|
||||||
|
fit-margin-left="-2"
|
||||||
|
fit-margin-right="-2"
|
||||||
|
fit-margin-bottom="-2">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2985"
|
||||||
|
empspacing="4"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="1"
|
||||||
|
spacingy="1"
|
||||||
|
originx="-9"
|
||||||
|
originy="-1"
|
||||||
|
color="#0000ff"
|
||||||
|
opacity="0.03137255" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="11,26"
|
||||||
|
id="guide3060"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="15,26"
|
||||||
|
id="guide3062"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="26,21"
|
||||||
|
id="guide3064"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="26,5"
|
||||||
|
id="guide3066"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="17,0"
|
||||||
|
id="guide3068"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="9,0"
|
||||||
|
id="guide3070"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="0,18"
|
||||||
|
id="guide3074"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="0,16"
|
||||||
|
id="guide3076"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer"
|
||||||
|
transform="translate(-9,-1)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3805"
|
||||||
|
d="m 8,8 c 2,2 4,6 4,10 L 16,8 Z"
|
||||||
|
style="display:none;fill:#fafafa;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#fafafa;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)"
|
||||||
|
id="rect2987"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
x="12"
|
||||||
|
y="4"
|
||||||
|
ry="2" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
|
@ -64,6 +64,8 @@ images = {
|
||||||
'message_bubble_received_white.svg' => ['message_bubble_received_white.9', 0],
|
'message_bubble_received_white.svg' => ['message_bubble_received_white.9', 0],
|
||||||
'message_bubble_sent.svg' => ['message_bubble_sent.9', 0],
|
'message_bubble_sent.svg' => ['message_bubble_sent.9', 0],
|
||||||
'message_bubble_sent_grey.svg' => ['message_bubble_sent_grey.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
|
# Executable paths for Mac OSX
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.net.URL;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||||
import eu.siacs.conversations.http.AesGcmURLStreamHandler;
|
import eu.siacs.conversations.http.AesGcmURLStreamHandler;
|
||||||
|
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.MimeUtils;
|
import eu.siacs.conversations.utils.MimeUtils;
|
||||||
|
@ -203,6 +204,14 @@ public class Message extends AbstractEntity {
|
||||||
return message;
|
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
|
@Override
|
||||||
public ContentValues getContentValues() {
|
public ContentValues getContentValues() {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
|
@ -493,7 +502,8 @@ public class Message extends AbstractEntity {
|
||||||
!this.getBody().startsWith(ME_COMMAND) &&
|
!this.getBody().startsWith(ME_COMMAND) &&
|
||||||
!this.bodyIsHeart() &&
|
!this.bodyIsHeart() &&
|
||||||
!message.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())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
@ -154,14 +155,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final int oldPosition = messagesView.getFirstVisiblePosition();
|
final int oldPosition = messagesView.getFirstVisiblePosition();
|
||||||
final Message message;
|
Message message = null;
|
||||||
if (oldPosition < messageList.size()) {
|
int childPos;
|
||||||
message = messageList.get(oldPosition);
|
for(childPos = 0; childPos + oldPosition < messageList.size(); ++childPos) {
|
||||||
} else {
|
message = messageList.get(oldPosition + childPos);
|
||||||
message = null;
|
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();
|
final int pxOffset = (v == null) ? 0 : v.getTop();
|
||||||
ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
|
ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
|
||||||
try {
|
try {
|
||||||
|
@ -1300,7 +1303,20 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
||||||
this.mSendButton.setImageResource(getSendButtonImageResource(action, status));
|
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() {
|
protected void updateStatusMessages() {
|
||||||
|
updateDateSeparators();
|
||||||
synchronized (this.messageList) {
|
synchronized (this.messageList) {
|
||||||
if (showLoadMoreMessages(conversation)) {
|
if (showLoadMoreMessages(conversation)) {
|
||||||
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
|
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
|
||||||
|
|
|
@ -391,6 +391,7 @@ public abstract class XmppActivity extends Activity {
|
||||||
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey50);
|
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey50);
|
||||||
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey200);
|
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey200);
|
||||||
|
|
||||||
|
this.mTheme = findTheme();
|
||||||
if(isDarkTheme()) {
|
if(isDarkTheme()) {
|
||||||
mPrimaryTextColor = ContextCompat.getColor(this, R.color.white);
|
mPrimaryTextColor = ContextCompat.getColor(this, R.color.white);
|
||||||
mSecondaryTextColor = ContextCompat.getColor(this, R.color.white70);
|
mSecondaryTextColor = ContextCompat.getColor(this, R.color.white70);
|
||||||
|
@ -398,8 +399,6 @@ public abstract class XmppActivity extends Activity {
|
||||||
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey800);
|
mPrimaryBackgroundColor = ContextCompat.getColor(this, R.color.grey800);
|
||||||
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey900);
|
mSecondaryBackgroundColor = ContextCompat.getColor(this, R.color.grey900);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mTheme = findTheme();
|
|
||||||
setTheme(this.mTheme);
|
setTheme(this.mTheme);
|
||||||
|
|
||||||
this.mUsingEnterKey = usingEnterKey();
|
this.mUsingEnterKey = usingEnterKey();
|
||||||
|
@ -411,7 +410,7 @@ public abstract class XmppActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDarkTheme() {
|
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) {
|
public int getThemeResource(int r_attr_name, int r_drawable_def) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.RelativeSizeSpan;
|
import android.text.style.RelativeSizeSpan;
|
||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
|
@ -72,6 +73,10 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
private static final int SENT = 0;
|
private static final int SENT = 0;
|
||||||
private static final int RECEIVED = 1;
|
private static final int RECEIVED = 1;
|
||||||
private static final int STATUS = 2;
|
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
|
private static final Pattern XMPP_PATTERN = Pattern
|
||||||
.compile("xmpp\\:(?:(?:["
|
.compile("xmpp\\:(?:(?:["
|
||||||
+ Patterns.GOOD_IRI_CHAR
|
+ Patterns.GOOD_IRI_CHAR
|
||||||
|
@ -135,12 +140,16 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewTypeCount() {
|
public int getViewTypeCount() {
|
||||||
return 3;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemViewType(Message message) {
|
public int getItemViewType(Message message) {
|
||||||
if (message.getType() == Message.TYPE_STATUS) {
|
if (message.getType() == Message.TYPE_STATUS) {
|
||||||
|
if (DATE_SEPARATOR_BODY.equals(message.getBody())) {
|
||||||
|
return DATE_SEPARATOR;
|
||||||
|
} else {
|
||||||
return STATUS;
|
return STATUS;
|
||||||
|
}
|
||||||
} else if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
} else if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
||||||
return RECEIVED;
|
return RECEIVED;
|
||||||
}
|
}
|
||||||
|
@ -591,6 +600,11 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
viewHolder = new ViewHolder();
|
viewHolder = new ViewHolder();
|
||||||
switch (type) {
|
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:
|
case SENT:
|
||||||
view = activity.getLayoutInflater().inflate(
|
view = activity.getLayoutInflater().inflate(
|
||||||
R.layout.message_sent, parent, false);
|
R.layout.message_sent, parent, false);
|
||||||
|
@ -659,7 +673,18 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
|
|
||||||
boolean darkBackground = type == RECEIVED && (!isInValidSession || mUseGreenBackground) || activity.isDarkTheme();
|
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())) {
|
if ("LOAD_MORE".equals(message.getBody())) {
|
||||||
viewHolder.status_message.setVisibility(View.GONE);
|
viewHolder.status_message.setVisibility(View.GONE);
|
||||||
viewHolder.contact_picture.setVisibility(View.GONE);
|
viewHolder.contact_picture.setVisibility(View.GONE);
|
||||||
|
|
|
@ -100,6 +100,24 @@ public class UIHelper {
|
||||||
return sameDay(date,new Date(System.currentTimeMillis()));
|
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) {
|
private static boolean sameDay(Date a, Date b) {
|
||||||
Calendar cal1 = Calendar.getInstance();
|
Calendar cal1 = Calendar.getInstance();
|
||||||
Calendar cal2 = Calendar.getInstance();
|
Calendar cal2 = Calendar.getInstance();
|
||||||
|
|
BIN
src/main/res/drawable-hdpi/date_bubble_grey.9.png
Normal file
After Width: | Height: | Size: 657 B |
BIN
src/main/res/drawable-hdpi/date_bubble_white.9.png
Normal file
After Width: | Height: | Size: 689 B |
BIN
src/main/res/drawable-mdpi/date_bubble_grey.9.png
Normal file
After Width: | Height: | Size: 514 B |
BIN
src/main/res/drawable-mdpi/date_bubble_white.9.png
Normal file
After Width: | Height: | Size: 525 B |
BIN
src/main/res/drawable-xhdpi/date_bubble_grey.9.png
Normal file
After Width: | Height: | Size: 739 B |
BIN
src/main/res/drawable-xhdpi/date_bubble_white.9.png
Normal file
After Width: | Height: | Size: 769 B |
BIN
src/main/res/drawable-xxhdpi/date_bubble_grey.9.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
src/main/res/drawable-xxhdpi/date_bubble_white.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/main/res/drawable-xxxhdpi/date_bubble_white.9.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
26
src/main/res/layout/message_date_bubble.xml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:paddingTop="5dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/date_bubble_white"
|
||||||
|
android:id="@+id/message_box"
|
||||||
|
android:layout_centerHorizontal="true">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColorLink="@color/black87"
|
||||||
|
android:textColor="?attr/color_text_secondary"
|
||||||
|
android:textSize="?attr/TextSizeBody"
|
||||||
|
android:id="@+id/message_body" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -754,4 +754,6 @@
|
||||||
<string name="application_found_to_open_website">No application found to open website</string>
|
<string name="application_found_to_open_website">No application found to open website</string>
|
||||||
<string name="pref_headsup_notifications">Heads-up Notifications</string>
|
<string name="pref_headsup_notifications">Heads-up Notifications</string>
|
||||||
<string name="pref_headsup_notifications_summary">Show Heads-up Notifications</string>
|
<string name="pref_headsup_notifications_summary">Show Heads-up Notifications</string>
|
||||||
|
<string name="today">Today</string>
|
||||||
|
<string name="yesterday">Yesterday</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|