From 4fdb0d92fe854126ad5201d56752716b9ab581b2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 4 Feb 2016 14:39:16 +0100 Subject: prevent previoulsly cleared messages from reloading. fixes #1110 --- .../siacs/conversations/entities/Conversation.java | 12 +++++++ .../eu/siacs/conversations/entities/Message.java | 8 +++++ .../services/MessageArchiveService.java | 17 ++++----- .../services/XmppConnectionService.java | 4 +++ .../conversations/ui/ConversationActivity.java | 6 ++++ .../conversations/ui/ConversationFragment.java | 10 ++++-- .../conversations/ui/adapter/MessageAdapter.java | 42 ++++++++++++++++++---- src/main/res/layout/message_status.xml | 9 +++++ src/main/res/values/strings.xml | 1 + 9 files changed, 92 insertions(+), 17 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index f2c08b9a..cb472b87 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -286,6 +286,14 @@ public class Conversation extends AbstractEntity implements Blockable { return this.mFirstMamReference; } + public void setLastClearHistory(long time) { + setAttribute("last_clear_history",String.valueOf(time)); + } + + public long getLastClearHistory() { + return getLongAttribute("last_clear_history", 0); + } + public interface OnMessageFound { void onMessageFound(final Message message); } @@ -720,6 +728,10 @@ public class Conversation extends AbstractEntity implements Blockable { } public long getLastMessageTransmitted() { + long last_clear = getLastClearHistory(); + if (last_clear != 0) { + return last_clear; + } synchronized (this.messages) { for(int i = this.messages.size() - 1; i >= 0; --i) { Message message = this.messages.get(i); diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index f3d891e8..f37ae427 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -178,6 +178,14 @@ public class Message extends AbstractEntity { return message; } + public static Message createLoadMoreMessage(Conversation conversation) { + final Message message = new Message(); + message.setType(Message.TYPE_STATUS); + message.setConversation(conversation); + message.setBody("LOAD_MORE"); + return message; + } + @Override public ContentValues getContentValues() { ContentValues values = new ContentValues(); diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java index a225760f..165c7c2a 100644 --- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java @@ -24,13 +24,13 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private final XmppConnectionService mXmppConnectionService; - private final HashSet queries = new HashSet(); - private final ArrayList pendingQueries = new ArrayList(); + private final HashSet queries = new HashSet<>(); + private final ArrayList pendingQueries = new ArrayList<>(); public enum PagingOrder { NORMAL, REVERSE - }; + } public MessageArchiveService(final XmppConnectionService service) { this.mXmppConnectionService = service; @@ -137,7 +137,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { synchronized (MessageArchiveService.this.queries) { MessageArchiveService.this.queries.remove(query); if (query.hasCallback()) { - query.callback(); + query.callback(false); } } } else if (packet.getType() != IqPacket.TYPE.RESULT) { @@ -169,7 +169,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } if (query.hasCallback()) { - query.callback(); + query.callback(done); } else { this.mXmppConnectionService.updateConversationUi(); } @@ -329,10 +329,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.callback = callback; } - public void callback() { + public void callback(boolean done) { if (this.callback != null) { this.callback.onMoreMessagesLoaded(messageCount,conversation); - if (messageCount == 0) { + if (done) { this.callback.informUser(R.string.no_more_history_on_server); } } @@ -375,7 +375,8 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { public String toString() { StringBuilder builder = new StringBuilder(); if (this.muc()) { - builder.append("to="+this.getWith().toString()); + builder.append("to="); + builder.append(this.getWith().toString()); } else { builder.append("with="); if (this.getWith() == null) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 73f17e3b..0973036c 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1215,6 +1215,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) { if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) { return; + } else if (timestamp == 0) { + callback.onMoreMessagesLoaded(0, conversation); + return; } Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp)); Runnable runnable = new Runnable() { @@ -2911,6 +2914,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void clearConversationHistory(final Conversation conversation) { conversation.clearMessages(); conversation.setHasMessagesLeftOnServer(false); //avoid messages getting loaded through mam + conversation.setLastClearHistory(System.currentTimeMillis()); Runnable runnable = new Runnable() { @Override public void run() { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 2461c39d..97774650 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1602,4 +1602,10 @@ public class ConversationActivity extends XmppActivity public boolean highlightSelectedConversations() { return !isConversationsOverviewHideable() || this.conversationWasSelectedByKeyboard; } + + public void setMessagesLoaded() { + if (mConversationFragment != null) { + mConversationFragment.setMessagesLoaded(); + } + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index af6f5d6f..42e442ed 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -40,12 +40,9 @@ import net.java.otr4j.session.SessionStatus; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.NoSuchElementException; -import java.util.concurrent.ConcurrentLinkedQueue; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; @@ -318,6 +315,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private ConversationActivity activity; private Message selectedMessage; + public void setMessagesLoaded() { + this.messagesLoaded = true; + } + private void sendMessage() { final String body = mEditMessage.getText().toString(); if (body.length() == 0 || this.conversation == null) { @@ -1008,6 +1009,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa protected void updateStatusMessages() { synchronized (this.messageList) { + if (conversation.getLastClearHistory() != 0) { + this.messageList.add(0, Message.createLoadMoreMessage(conversation)); + } if (conversation.getMode() == Conversation.MODE_SINGLE) { ChatState state = conversation.getIncomingChatState(); if (state == ChatState.COMPOSING) { 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 a9234e1a..fc2bd2ab 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -428,6 +428,19 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.image.setOnLongClickListener(openContextMenu); } + private void loadMoreMessages(Conversation conversation) { + conversation.setLastClearHistory(0); + conversation.setHasMessagesLeftOnServer(true); + conversation.setFirstMamReference(null); + long timestamp = conversation.getLastMessageTransmitted(); + if (timestamp == 0) { + timestamp = System.currentTimeMillis(); + } + activity.setMessagesLoaded(); + activity.xmppConnectionService.getMessageArchiveService().query(conversation, 0, timestamp); + Toast.makeText(activity, R.string.fetching_history_from_server,Toast.LENGTH_LONG).show(); + } + @Override public View getView(int position, View view, ViewGroup parent) { final Message message = getItem(position); @@ -484,6 +497,7 @@ public class MessageAdapter extends ArrayAdapter { view = activity.getLayoutInflater().inflate(R.layout.message_status, parent, false); viewHolder.contact_picture = (ImageView) view.findViewById(R.id.message_photo); viewHolder.status_message = (TextView) view.findViewById(R.id.status_message); + viewHolder.load_more_messages = (Button) view.findViewById(R.id.load_more_messages); break; default: viewHolder = null; @@ -500,16 +514,31 @@ public class MessageAdapter extends ArrayAdapter { boolean darkBackground = (type == RECEIVED && (!isInValidSession || !mUseWhiteBackground)); if (type == STATUS) { - if (conversation.getMode() == Conversation.MODE_SINGLE) { - viewHolder.contact_picture.setImageBitmap(activity - .avatarService().get(conversation.getContact(), - activity.getPixel(32))); - viewHolder.contact_picture.setAlpha(0.5f); + if ("LOAD_MORE".equals(message.getBody())) { + viewHolder.status_message.setVisibility(View.GONE); + viewHolder.contact_picture.setVisibility(View.GONE); + viewHolder.load_more_messages.setVisibility(View.VISIBLE); + viewHolder.load_more_messages.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + loadMoreMessages(message.getConversation()); + } + }); + } else { + viewHolder.status_message.setVisibility(View.VISIBLE); + viewHolder.contact_picture.setVisibility(View.VISIBLE); + viewHolder.load_more_messages.setVisibility(View.GONE); + if (conversation.getMode() == Conversation.MODE_SINGLE) { + viewHolder.contact_picture.setImageBitmap(activity + .avatarService().get(conversation.getContact(), + activity.getPixel(32))); + viewHolder.contact_picture.setAlpha(0.5f); + } viewHolder.status_message.setText(message.getBody()); } return view; } else { - loadAvatar(message,viewHolder.contact_picture); + loadAvatar(message, viewHolder.contact_picture); } viewHolder.contact_picture @@ -671,6 +700,7 @@ public class MessageAdapter extends ArrayAdapter { protected ImageView contact_picture; protected TextView status_message; protected TextView encryption; + public Button load_more_messages; } class BitmapWorkerTask extends AsyncTask { diff --git a/src/main/res/layout/message_status.xml b/src/main/res/layout/message_status.xml index ad2579fa..93a80d84 100644 --- a/src/main/res/layout/message_status.xml +++ b/src/main/res/layout/message_status.xml @@ -9,6 +9,15 @@ android:paddingRight="8dp" android:paddingTop="5dp"> +