show real reply text instead of fallback
This commit is contained in:
parent
869f92169d
commit
366e5aa389
|
@ -780,6 +780,45 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
return unread;
|
return unread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Message getMessageWithAnyMatchingId(String uuid) {
|
||||||
|
if (uuid == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (this.messages) {
|
||||||
|
for (int i = 0; i < messages.size(); ++i) {
|
||||||
|
if (uuid.equals(messages.get(i).getServerMsgId())) {
|
||||||
|
return messages.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid.equals(messages.get(i).getRemoteMsgId())) {
|
||||||
|
return messages.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid.equals(messages.get(i).getUuid())) {
|
||||||
|
return messages.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < historyPartMessages.size(); ++i) {
|
||||||
|
if (uuid.equals(historyPartMessages.get(i).getServerMsgId())) {
|
||||||
|
return historyPartMessages.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid.equals(historyPartMessages.get(i).getRemoteMsgId())) {
|
||||||
|
return historyPartMessages.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid.equals(historyPartMessages.get(i).getUuid())) {
|
||||||
|
return historyPartMessages.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Message getLatestMessage() {
|
public Message getLatestMessage() {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
if (this.messages.size() == 0) {
|
if (this.messages.size() == 0) {
|
||||||
|
@ -1190,12 +1229,14 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
if (!message.isPrivateMessage()) {
|
if (!message.isPrivateMessage()) {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
this.messages.add(message);
|
this.messages.add(message);
|
||||||
|
actualizeReplyMessages(this.messages, List.of(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (message.isPrivateMessage() && Objects.equals(res1, res2)) {
|
if (message.isPrivateMessage() && Objects.equals(res1, res2)) {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
this.messages.add(message);
|
this.messages.add(message);
|
||||||
|
actualizeReplyMessages(this.messages, List.of(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1217,19 +1258,24 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
if (!message.isPrivateMessage()) {
|
if (!message.isPrivateMessage()) {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
properListToAdd.add(Math.min(offset, properListToAdd.size()), message);
|
properListToAdd.add(Math.min(offset, properListToAdd.size()), message);
|
||||||
|
actualizeReplyMessages(properListToAdd, List.of(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (message.isPrivateMessage() && Objects.equals(res1, res2)) {
|
if (message.isPrivateMessage() && Objects.equals(res1, res2)) {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
properListToAdd.add(Math.min(offset, properListToAdd.size()), message);
|
properListToAdd.add(Math.min(offset, properListToAdd.size()), message);
|
||||||
|
actualizeReplyMessages(properListToAdd, List.of(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!historyPartMessages.isEmpty() && hasDuplicateMessage(historyPartMessages.get(historyPartMessages.size() - 1))) {
|
synchronized (this.messages) {
|
||||||
messages.addAll(0, historyPartMessages);
|
if (!historyPartMessages.isEmpty() && hasDuplicateMessage(historyPartMessages.get(historyPartMessages.size() - 1))) {
|
||||||
jumpToLatest();
|
messages.addAll(0, historyPartMessages);
|
||||||
|
actualizeReplyMessages(messages, List.of(message));
|
||||||
|
jumpToLatest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,10 +1325,43 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
} else {
|
} else {
|
||||||
properListToAdd.addAll(index, newM);
|
properListToAdd.addAll(index, newM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actualizeReplyMessages(properListToAdd, messages);
|
||||||
}
|
}
|
||||||
account.getPgpDecryptionService().decrypt(newM);
|
account.getPgpDecryptionService().decrypt(newM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void actualizeReplyMessages(List<Message> mainList, List<Message> messages) {
|
||||||
|
for (Message m : mainList) {
|
||||||
|
if (m.isReplyRestoredFromDb()) {
|
||||||
|
Element reply = m.getReply();
|
||||||
|
|
||||||
|
if (reply == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String replyId = reply.getAttribute("id");
|
||||||
|
|
||||||
|
for (Message rep : messages) {
|
||||||
|
if (replyId.equals(rep.getServerMsgId())) {
|
||||||
|
m.setReplyMessage(rep, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyId.equals(rep.getRemoteMsgId())) {
|
||||||
|
m.setReplyMessage(rep, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyId.equals(rep.getUuid())) {
|
||||||
|
m.setReplyMessage(rep, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void expireOldMessages(long timestamp) {
|
public void expireOldMessages(long timestamp) {
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
for (ListIterator<Message> iterator = this.messages.listIterator(); iterator.hasNext(); ) {
|
for (ListIterator<Message> iterator = this.messages.listIterator(); iterator.hasNext(); ) {
|
||||||
|
|
|
@ -4,7 +4,11 @@ import android.content.ContentValues;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.ByteSource;
|
import com.google.common.io.ByteSource;
|
||||||
|
@ -122,6 +126,8 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
protected Transferable transferable = null;
|
protected Transferable transferable = null;
|
||||||
private Message mNextMessage = null;
|
private Message mNextMessage = null;
|
||||||
private Message mPreviousMessage = null;
|
private Message mPreviousMessage = null;
|
||||||
|
private Message replyMessage = null;
|
||||||
|
private boolean replyRestoredFromDb = false;
|
||||||
private String axolotlFingerprint = null;
|
private String axolotlFingerprint = null;
|
||||||
private String errorMessage = null;
|
private String errorMessage = null;
|
||||||
private Set<ReadByMarker> readByMarkers = new CopyOnWriteArraySet<>();
|
private Set<ReadByMarker> readByMarkers = new CopyOnWriteArraySet<>();
|
||||||
|
@ -411,6 +417,25 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Message getReplyMessage() {
|
||||||
|
if (replyMessage != null && replyMessage.deleted) {
|
||||||
|
replyMessage = null;
|
||||||
|
replyRestoredFromDb = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replyMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReplyRestoredFromDb() {
|
||||||
|
return replyRestoredFromDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReplyMessage(Message replyMessage, boolean restoredFromDb) {
|
||||||
|
this.replyMessage = replyMessage;
|
||||||
|
this.replyRestoredFromDb = restoredFromDb;
|
||||||
|
}
|
||||||
|
|
||||||
public String getConversationUuid() {
|
public String getConversationUuid() {
|
||||||
return conversationUuid;
|
return conversationUuid;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +840,42 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpannableStringBuilder getBodyForDisplaying() {
|
public SpannableStringBuilder getBodyForDisplaying() {
|
||||||
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(this.body).trim());
|
if (replyMessage != null) {
|
||||||
|
try {
|
||||||
|
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(">" + removeReplyFallback(replyMessage) + "\n" + removeReplyFallback(this)).trim());
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(this.body).trim());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(this.body).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpannableStringBuilder getBodyForReplyPreview() {
|
||||||
|
try {
|
||||||
|
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(">" + removeReplyFallback(this)).trim());
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
return new SpannableStringBuilder(MessageUtils.filterLtrRtl(this.body).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder removeReplyFallback(Message message) {
|
||||||
|
StringBuilder sb = new StringBuilder(message.body);
|
||||||
|
|
||||||
|
List<Element> replyFallback = message.getFallbacks("urn:xmpp:reply:0");
|
||||||
|
if (replyFallback.size() == 0) {
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element bodyFallback = replyFallback.get(0).findChild("body");
|
||||||
|
int startCodePoint = Integer.parseInt(bodyFallback.getAttribute("start"));
|
||||||
|
int endCodePoint = Integer.parseInt(bodyFallback.getAttribute("end"));
|
||||||
|
|
||||||
|
if (startCodePoint < 0) return sb;
|
||||||
|
if (endCodePoint > sb.length()) return sb;
|
||||||
|
|
||||||
|
sb.replace(message.body.offsetByCodePoints(0, startCodePoint), message.body.offsetByCodePoints(0, endCodePoint), "");
|
||||||
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMeCommand() {
|
public boolean hasMeCommand() {
|
||||||
|
|
|
@ -758,6 +758,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mXmppConnectionService.restoreReplyForMessage(conversation, message);
|
||||||
if (query != null && query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
|
if (query != null && query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
|
||||||
conversation.prepend(query.getActualInThisQuery(), message);
|
conversation.prepend(query.getActualInThisQuery(), message);
|
||||||
} else {
|
} else {
|
||||||
|
@ -946,6 +947,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
message.setServerMsgId(serverMsgId);
|
message.setServerMsgId(serverMsgId);
|
||||||
message.setTime(timestamp);
|
message.setTime(timestamp);
|
||||||
message.setBody(new RtpSessionStatus(false, 0).toString());
|
message.setBody(new RtpSessionStatus(false, 0).toString());
|
||||||
|
mXmppConnectionService.restoreReplyForMessage(conversation, message);
|
||||||
c.add(message);
|
c.add(message);
|
||||||
mXmppConnectionService.databaseBackend.createMessage(message);
|
mXmppConnectionService.databaseBackend.createMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -988,6 +990,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
message.setServerMsgId(serverMsgId);
|
message.setServerMsgId(serverMsgId);
|
||||||
message.setTime(timestamp);
|
message.setTime(timestamp);
|
||||||
message.setBody(new RtpSessionStatus(true, 0).toString());
|
message.setBody(new RtpSessionStatus(true, 0).toString());
|
||||||
|
mXmppConnectionService.restoreReplyForMessage(conversation, message);
|
||||||
if (query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
|
if (query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
|
||||||
c.prepend(query.getActualInThisQuery(), message);
|
c.prepend(query.getActualInThisQuery(), message);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
@ -840,6 +841,45 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<Message> getMessagesByIds(Conversation conversation, Set<String> ids) {
|
||||||
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
List<String> parameters = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String id : ids) {
|
||||||
|
parameters.add("?");
|
||||||
|
}
|
||||||
|
|
||||||
|
String parametersString = TextUtils.join(",", parameters);
|
||||||
|
|
||||||
|
String[] selectionArgs = new String[ids.size() * 3 + 1];
|
||||||
|
selectionArgs[0] = conversation.getUuid();
|
||||||
|
int ind = 1;
|
||||||
|
|
||||||
|
for (int i=0;i<3;i++) {
|
||||||
|
for (String id : ids) {
|
||||||
|
selectionArgs[ind] = id;
|
||||||
|
ind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION
|
||||||
|
+ "=? and (" + Message.SERVER_MSG_ID + " in (" + parametersString + ") or " + Message.REMOTE_MSG_ID + " in (" + parametersString + ") or " + Message.UUID + " in (" + parametersString + "))", selectionArgs, null, null, Message.TIME_SENT
|
||||||
|
+ " DESC", String.valueOf(ids.size()));
|
||||||
|
CursorUtils.upgradeCursorWindowSize(cursor);
|
||||||
|
ArrayList<Message> list = new ArrayList<>();
|
||||||
|
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
try {
|
||||||
|
Message m = Message.fromCursor(cursor, conversation);
|
||||||
|
list.add(m);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(Config.LOGTAG, "unable to restore message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public ArrayList<Message> getMessages(Conversation conversation, int limit, long timestamp, boolean isForward) {
|
public ArrayList<Message> getMessages(Conversation conversation, int limit, long timestamp, boolean isForward) {
|
||||||
ArrayList<Message> list = new ArrayList<>();
|
ArrayList<Message> list = new ArrayList<>();
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
|
|
@ -1821,6 +1821,7 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (addToConversation) {
|
if (addToConversation) {
|
||||||
|
restoreReplyForMessage(conversation, message);
|
||||||
conversation.add(message);
|
conversation.add(message);
|
||||||
}
|
}
|
||||||
if (saveInDb) {
|
if (saveInDb) {
|
||||||
|
@ -2182,7 +2183,9 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreMessages(Conversation conversation) {
|
private void restoreMessages(Conversation conversation) {
|
||||||
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE), false);
|
List<Message> messages = databaseBackend.getMessages(conversation, Config.PAGE_SIZE);
|
||||||
|
restoreRepliesForMessages(conversation, messages);
|
||||||
|
conversation.addAll(0, messages, false);
|
||||||
conversation.findUnsentTextMessages(message -> markMessage(message, Message.STATUS_WAITING));
|
conversation.findUnsentTextMessages(message -> markMessage(message, Message.STATUS_WAITING));
|
||||||
conversation.findUnreadMessagesAndCalls(mNotificationService::pushFromBacklog);
|
conversation.findUnreadMessagesAndCalls(mNotificationService::pushFromBacklog);
|
||||||
}
|
}
|
||||||
|
@ -2310,6 +2313,7 @@ public class XmppConnectionService extends Service {
|
||||||
public void jumpToMessage(final Conversation conversation, final String uuid, JumpToMessageListener listener) {
|
public void jumpToMessage(final Conversation conversation, final String uuid, JumpToMessageListener listener) {
|
||||||
final Runnable runnable = () -> {
|
final Runnable runnable = () -> {
|
||||||
List<Message> messages = databaseBackend.getMessagesNearUuid(conversation, 30, uuid);
|
List<Message> messages = databaseBackend.getMessagesNearUuid(conversation, 30, uuid);
|
||||||
|
restoreRepliesForMessages(conversation, messages);
|
||||||
if (messages != null && !messages.isEmpty()) {
|
if (messages != null && !messages.isEmpty()) {
|
||||||
conversation.jumpToHistoryPart(messages);
|
conversation.jumpToHistoryPart(messages);
|
||||||
listener.onSuccess();
|
listener.onSuccess();
|
||||||
|
@ -2321,6 +2325,88 @@ public class XmppConnectionService extends Service {
|
||||||
mDatabaseReaderExecutor.execute(runnable);
|
mDatabaseReaderExecutor.execute(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void restoreReplyForMessage(final Conversation conversation, Message message) {
|
||||||
|
restoreRepliesForMessages(conversation, List.of(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restoreRepliesForMessages(final Conversation conversation, List<Message> messages) {
|
||||||
|
Map<String, ArrayList<Message>> notFoundReplies = null;
|
||||||
|
|
||||||
|
for (Message m : messages) {
|
||||||
|
Element reply = m.getReply();
|
||||||
|
|
||||||
|
if (reply == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String replyId = reply.getAttribute("id");
|
||||||
|
|
||||||
|
|
||||||
|
Message replyMessage = null;
|
||||||
|
|
||||||
|
for (Message rep : messages) {
|
||||||
|
if (replyId.equals(rep.getServerMsgId())) {
|
||||||
|
replyMessage = rep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyId.equals(rep.getRemoteMsgId())) {
|
||||||
|
replyMessage = rep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyId.equals(rep.getUuid())) {
|
||||||
|
replyMessage = rep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyMessage == null) {
|
||||||
|
replyMessage = conversation.getMessageWithAnyMatchingId(replyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyMessage != null) {
|
||||||
|
m.setReplyMessage(replyMessage, false);
|
||||||
|
} else {
|
||||||
|
if (notFoundReplies == null) {
|
||||||
|
notFoundReplies = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Message> list = notFoundReplies.computeIfAbsent(replyId, id -> new ArrayList<>());
|
||||||
|
list.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notFoundReplies != null) {
|
||||||
|
List<Message> restored = databaseBackend.getMessagesByIds(conversation, notFoundReplies.keySet());
|
||||||
|
|
||||||
|
for (String id : notFoundReplies.keySet()) {
|
||||||
|
for (Message m : restored) {
|
||||||
|
if (id.equals(m.getServerMsgId())) {
|
||||||
|
for (Message rm : notFoundReplies.get(id)) {
|
||||||
|
rm.setReplyMessage(m, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id.equals(m.getRemoteMsgId())) {
|
||||||
|
for (Message rm : notFoundReplies.get(id)) {
|
||||||
|
rm.setReplyMessage(m, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id.equals(m.getUuid())) {
|
||||||
|
for (Message rm : notFoundReplies.get(id)) {
|
||||||
|
rm.setReplyMessage(m, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void loadMoreMessages(final Conversation conversation, final long timestamp, boolean isForward, final OnMoreMessagesLoaded callback) {
|
public void loadMoreMessages(final Conversation conversation, final long timestamp, boolean isForward, final OnMoreMessagesLoaded callback) {
|
||||||
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) {
|
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) {
|
||||||
return;
|
return;
|
||||||
|
@ -2339,11 +2425,14 @@ public class XmppConnectionService extends Service {
|
||||||
List<Message> messages = databaseBackend.getMessages(conversation, Config.PAGE_SIZE, timestamp, isForward);
|
List<Message> messages = databaseBackend.getMessages(conversation, Config.PAGE_SIZE, timestamp, isForward);
|
||||||
|
|
||||||
if (messages.size() > 0) {
|
if (messages.size() > 0) {
|
||||||
|
restoreRepliesForMessages(conversation, messages);
|
||||||
|
|
||||||
if (isForward) {
|
if (isForward) {
|
||||||
conversation.addAll(-1, messages, true);
|
conversation.addAll(-1, messages, true);
|
||||||
} else {
|
} else {
|
||||||
conversation.addAll(0, messages, true);
|
conversation.addAll(0, messages, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.onMoreMessagesLoaded(messages.size(), conversation);
|
callback.onMoreMessagesLoaded(messages.size(), conversation);
|
||||||
} else if (!isForward &&
|
} else if (!isForward &&
|
||||||
conversation.hasMessagesLeftOnServer()
|
conversation.hasMessagesLeftOnServer()
|
||||||
|
@ -2517,7 +2606,9 @@ public class XmppConnectionService extends Service {
|
||||||
final Conversation c = conversation;
|
final Conversation c = conversation;
|
||||||
final Runnable runnable = () -> {
|
final Runnable runnable = () -> {
|
||||||
if (loadMessagesFromDb) {
|
if (loadMessagesFromDb) {
|
||||||
c.addAll(0, databaseBackend.getMessages(c, Config.PAGE_SIZE), false);
|
List<Message> messages = databaseBackend.getMessages(c, Config.PAGE_SIZE);
|
||||||
|
restoreRepliesForMessages(c, messages);
|
||||||
|
c.addAll(0, messages, false);
|
||||||
updateConversationUi();
|
updateConversationUi();
|
||||||
c.messagesLoaded.set(true);
|
c.messagesLoaded.set(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1554,9 +1554,9 @@ public class ConversationFragment extends XmppFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpannableStringBuilder body = message.getBodyForDisplaying();
|
SpannableStringBuilder body = message.getBodyForReplyPreview();
|
||||||
if (message.isFileOrImage() || message.isOOb()) body.append(" 🖼️");
|
if (message.isFileOrImage() || message.isOOb()) body.append(" 🖼️");
|
||||||
messageListAdapter.handleTextQuotes(body, activity.isDarkTheme(), false, message);
|
messageListAdapter.handleTextQuotes(body, activity.isDarkTheme(), true, message);
|
||||||
binding.contextPreviewText.setText(body);
|
binding.contextPreviewText.setText(body);
|
||||||
binding.contextPreviewAuthor.setText(message.getAvatarName());
|
binding.contextPreviewAuthor.setText(message.getAvatarName());
|
||||||
binding.contextPreview.setVisibility(View.VISIBLE);
|
binding.contextPreview.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -37,6 +37,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
@ -462,7 +463,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
||||||
* Applies QuoteSpan to group of lines which starts with > or » characters.
|
* Applies QuoteSpan to group of lines which starts with > or » characters.
|
||||||
* Appends likebreaks and applies DividerSpan to them to show a padding between quote and text.
|
* Appends likebreaks and applies DividerSpan to them to show a padding between quote and text.
|
||||||
*/
|
*/
|
||||||
public boolean handleTextQuotes(SpannableStringBuilder body, boolean darkBackground, boolean highlightReply, Message message) {
|
public void handleTextQuotes(SpannableStringBuilder body, boolean darkBackground, boolean highlightReply, Message message) {
|
||||||
boolean startsWithQuote = false;
|
boolean startsWithQuote = false;
|
||||||
int quoteDepth = 0;
|
int quoteDepth = 0;
|
||||||
while (QuoteHelper.bodyContainsQuoteStart(body) && quoteDepth <= Config.QUOTE_MAX_DEPTH) {
|
while (QuoteHelper.bodyContainsQuoteStart(body) && quoteDepth <= Config.QUOTE_MAX_DEPTH) {
|
||||||
|
@ -546,7 +547,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
||||||
|
|
||||||
applyQuoteSpan(body, start, end, darkBackground, true, message);
|
applyQuoteSpan(body, start, end, darkBackground, true, message);
|
||||||
}
|
}
|
||||||
return startsWithQuote;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayTextMessage(final ViewHolder viewHolder, final Message message, boolean darkBackground, int type) {
|
private void displayTextMessage(final ViewHolder viewHolder, final Message message, boolean darkBackground, int type) {
|
||||||
|
@ -586,10 +586,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
||||||
int start = body.getSpanStart(quote);
|
int start = body.getSpanStart(quote);
|
||||||
int end = body.getSpanEnd(quote);
|
int end = body.getSpanEnd(quote);
|
||||||
body.removeSpan(quote);
|
body.removeSpan(quote);
|
||||||
applyQuoteSpan(body, start, end, darkBackground, message.getReply() != null, message);
|
applyQuoteSpan(body, start, end, darkBackground, message.getReplyMessage() != null, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean startsWithQuote = handleTextQuotes(body, darkBackground, message.getReply() != null, message);
|
handleTextQuotes(body, darkBackground, message.getReplyMessage() != null, message);
|
||||||
if (!message.isPrivateMessage()) {
|
if (!message.isPrivateMessage()) {
|
||||||
if (hasMeCommand) {
|
if (hasMeCommand) {
|
||||||
body.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(),
|
body.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(),
|
||||||
|
|
|
@ -508,6 +508,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
||||||
}
|
}
|
||||||
long size = parseLong(fileSize, 0);
|
long size = parseLong(fileSize, 0);
|
||||||
message.setBody(Long.toString(size));
|
message.setBody(Long.toString(size));
|
||||||
|
xmppConnectionService.restoreReplyForMessage(conversation, message);
|
||||||
conversation.add(message);
|
conversation.add(message);
|
||||||
jingleConnectionManager.updateConversationUi(true);
|
jingleConnectionManager.updateConversationUi(true);
|
||||||
this.file = this.xmppConnectionService.getFileBackend().getFile(message, false);
|
this.file = this.xmppConnectionService.getFileBackend().getFile(message, false);
|
||||||
|
|
Loading…
Reference in a new issue