diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/NewPostSeparator.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/NewPostSeparator.java
new file mode 100644
index 00000000..0c313f01
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/NewPostSeparator.java
@@ -0,0 +1,5 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+public class NewPostSeparator extends TopicRecyclerViewItem {
+ public static final int TYPE_NEW_MESSAGE_SEPARATOR = 3;
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
index 84f35817..0228e56a 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
@@ -80,7 +80,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
/**
* Holds a list of this topic's posts
*/
- private ArrayList postsList;
+ private ArrayList topicRecyclerviewItems;
//Reply related
private FloatingActionButton replyFAB;
//Topic's pages related
@@ -165,7 +165,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
progressBar = findViewById(R.id.progressBar);
emojiKeyboard = findViewById(R.id.emoji_keyboard);
- postsList = new ArrayList<>();
+ topicRecyclerviewItems = new ArrayList<>();
recyclerView = findViewById(R.id.topic_recycler_view);
recyclerView.setHasFixedSize(true);
@@ -174,7 +174,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
getApplicationContext(), topicPageUrl);
recyclerView.setLayoutManager(layoutManager);
- topicAdapter = new TopicAdapter(this, postsList);
+ topicAdapter = new TopicAdapter(this, topicRecyclerviewItems);
recyclerView.setAdapter(topicAdapter);
replyFAB = findViewById(R.id.topic_fab);
@@ -275,15 +275,15 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
}
return;
} else if (viewModel.isWritingReply()) {
- postsList.remove(postsList.size() - 1);
- topicAdapter.notifyItemRemoved(postsList.size());
+ topicRecyclerviewItems.remove(topicRecyclerviewItems.size() - 1);
+ topicAdapter.notifyItemRemoved(topicRecyclerviewItems.size());
topicAdapter.setBackButtonHidden();
viewModel.setWritingReply(false);
replyFAB.show();
bottomNavBar.setVisibility(View.VISIBLE);
return;
} else if (viewModel.isEditingPost()) {
- postsList.get(viewModel.getPostBeingEditedPosition()).setPostType(Post.TYPE_POST);
+ ((Post) topicRecyclerviewItems.get(viewModel.getPostBeingEditedPosition())).setPostType(Post.TYPE_POST);
topicAdapter.notifyItemChanged(viewModel.getPostBeingEditedPosition());
topicAdapter.setBackButtonHidden();
viewModel.setEditingPost(false);
@@ -533,7 +533,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
replyFAB.show();
bottomNavBar.setVisibility(View.VISIBLE);
viewModel.setWritingReply(false);
- if ((postsList.get(postsList.size() - 1).getPostNumber() + 1) % 15 == 0) {
+ if ((((Post) topicRecyclerviewItems.get(topicRecyclerviewItems.size() - 1)).getPostNumber() + 1) % 15 == 0) {
Timber.i("Reply was posted in new page. Switching to last page.");
viewModel.loadUrl(ParseHelpers.getBaseURL(viewModel.getTopicUrl()) + "." + 2147483647);
} else {
@@ -542,8 +542,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
} else {
Timber.w("Post reply unsuccessful");
Toast.makeText(getBaseContext(), "Post failed!", Toast.LENGTH_SHORT).show();
- recyclerView.getChildAt(postsList.size() - 1).setAlpha(1);
- recyclerView.getChildAt(postsList.size() - 1).setEnabled(true);
+ recyclerView.getChildAt(topicRecyclerviewItems.size() - 1).setAlpha(1);
+ recyclerView.getChildAt(topicRecyclerviewItems.size() - 1).setEnabled(true);
}
}
});
@@ -576,7 +576,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (result) {
Timber.i("Post edit successful");
- postsList.get(position).setPostType(Post.TYPE_POST);
+ ((Post) topicRecyclerviewItems.get(position)).setPostType(Post.TYPE_POST);
topicAdapter.notifyItemChanged(position);
replyFAB.show();
bottomNavBar.setVisibility(View.VISIBLE);
@@ -629,20 +629,25 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
viewModel.getPostsList().observe(this, postList -> {
if (postList == null) progressBar.setVisibility(ProgressBar.VISIBLE);
recyclerView.getRecycledViewPool().clear(); //Avoid inconsistency detected bug
- postsList.clear();
- postsList.addAll(postList);
+ topicRecyclerviewItems.clear();
+ topicRecyclerviewItems.addAll(postList);
topicAdapter.notifyDataSetChanged();
});
- /*viewModel.getFocusedPostIndex().observe(this, focusedPostIndex -> {
+ viewModel.getFocusedPostIndex().observe(this, focusedPostIndex -> {
if (focusedPostIndex == null) return;
- recyclerView.scrollToPosition(focusedPostIndex);
- });*/
+ if (viewModel.isFocusedPostLastSeenMessage() && focusedPostIndex != viewModel.postCount() - 1) {
+ topicRecyclerviewItems.add(focusedPostIndex, new NewPostSeparator());
+ topicAdapter.notifyItemInserted(focusedPostIndex);
+ }
+ //recyclerView.scrollToPosition(focusedPostIndex);
+ });
viewModel.getTopicTaskResultCode().observe(this, resultCode -> {
if (resultCode == null) return;
progressBar.setVisibility(ProgressBar.GONE);
switch (resultCode) {
case SUCCESS:
Timber.i("Successfully loaded topic with URL %s", viewModel.getTopicUrl());
+ Timber.i("load " + viewModel.isFocusedPostLastSeenMessage());
paginationEnabled(true);
break;
case NETWORK_ERROR:
@@ -688,9 +693,9 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
Timber.i("Prepare for reply successful");
//prepare for a reply
viewModel.setWritingReply(true);
- postsList.add(Post.newQuickReply());
- topicAdapter.notifyItemInserted(postsList.size());
- recyclerView.scrollToPosition(postsList.size() - 1);
+ topicRecyclerviewItems.add(Post.newQuickReply());
+ topicAdapter.notifyItemInserted(topicRecyclerviewItems.size());
+ recyclerView.scrollToPosition(topicRecyclerviewItems.size() - 1);
replyFAB.hide();
bottomNavBar.setVisibility(View.GONE);
} else {
@@ -703,7 +708,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (result != null && result.isSuccessful()) {
Timber.i("Prepare for edit successful");
viewModel.setEditingPost(true);
- postsList.get(result.getPosition()).setPostType(Post.TYPE_EDIT);
+ ((Post) topicRecyclerviewItems.get(result.getPosition())).setPostType(Post.TYPE_EDIT);
topicAdapter.notifyItemChanged(result.getPosition());
recyclerView.scrollToPosition(result.getPosition());
replyFAB.hide();
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
index 4c853526..11d780f6 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
@@ -35,7 +35,7 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso;
-import java.util.List;
+import java.util.ArrayList;
import java.util.Objects;
import gr.thmmy.mthmmy.R;
@@ -74,16 +74,16 @@ class TopicAdapter extends RecyclerView.Adapter {
private final Context context;
private final OnPostFocusChangeListener postFocusListener;
private final EmojiKeyboard.EmojiKeyboardOwner emojiKeyboardOwner;
- private final List postsList;
+ private final ArrayList topicRecyclerViewItems;
private TopicViewModel viewModel;
/**
* @param context the context of the {@link RecyclerView}
- * @param postsList List of {@link Post} objects to use
+ * @param topicRecyclerViewItems List of {@link Post} objects to use
*/
- TopicAdapter(TopicActivity context, List postsList) {
+ TopicAdapter(TopicActivity context, ArrayList topicRecyclerViewItems) {
this.context = context;
- this.postsList = postsList;
+ this.topicRecyclerViewItems = topicRecyclerViewItems;
this.postFocusListener = context;
this.emojiKeyboardOwner = context;
@@ -94,7 +94,9 @@ class TopicAdapter extends RecyclerView.Adapter {
@Override
public int getItemViewType(int position) {
- return postsList.get(position).getPostType();
+ if (topicRecyclerViewItems.get(position) instanceof NewPostSeparator)
+ return NewPostSeparator.TYPE_NEW_MESSAGE_SEPARATOR;
+ return ((Post) topicRecyclerViewItems.get(position)).getPostType();
}
@NonNull
@@ -130,6 +132,10 @@ class TopicAdapter extends RecyclerView.Adapter {
editPostEdittext.requestFocus();
return new EditMessageViewHolder(view);
+ } else if (viewType == NewPostSeparator.TYPE_NEW_MESSAGE_SEPARATOR) {
+ View view = LayoutInflater.from(parent.getContext()).
+ inflate(R.layout.activity_topic_new_message_separator, parent, false);
+ return new NewMessageSeparatorViewHolder(view);
} else {
throw new IllegalArgumentException("Unknown view type");
}
@@ -140,7 +146,7 @@ class TopicAdapter extends RecyclerView.Adapter {
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder currentHolder,
final int position) {
if (currentHolder instanceof PostViewHolder) {
- final Post currentPost = postsList.get(position);
+ final Post currentPost = (Post) topicRecyclerViewItems.get(position);
final PostViewHolder holder = (PostViewHolder) currentHolder;
//Post's WebView parameters
@@ -396,7 +402,7 @@ class TopicAdapter extends RecyclerView.Adapter {
editPostButton.setVisibility(View.GONE);
} else {
editPostButton.setOnClickListener(v -> {
- viewModel.prepareForEdit(position, postsList.get(position).getPostEditURL());
+ viewModel.prepareForEdit(position, ((Post) topicRecyclerViewItems.get(position)).getPostEditURL());
popUp.dismiss();
});
}
@@ -504,7 +510,7 @@ class TopicAdapter extends RecyclerView.Adapter {
.transform(new CircleTransform())
.into(holder.thumbnail);
holder.username.setText(getSessionManager().getUsername());
- holder.editSubject.setText(postsList.get(position).getSubject());
+ holder.editSubject.setText(((Post) topicRecyclerViewItems.get(position)).getSubject());
holder.editEditor.setEmojiKeyboardOwner(emojiKeyboardOwner);
InputConnection ic = holder.editEditor.getInputConnection();
@@ -542,7 +548,7 @@ class TopicAdapter extends RecyclerView.Adapter {
@Override
public int getItemCount() {
- return postsList.size();
+ return topicRecyclerViewItems.size();
}
/**
@@ -631,6 +637,12 @@ class TopicAdapter extends RecyclerView.Adapter {
}
}
+ static class NewMessageSeparatorViewHolder extends RecyclerView.ViewHolder {
+ NewMessageSeparatorViewHolder(View itemView) {
+ super(itemView);
+ }
+ }
+
/**
* This class is used to handle link clicks in WebViews. When link url is one that the app can
* handle internally, it does. Otherwise user is prompt to open the link in a browser.
@@ -674,8 +686,9 @@ class TopicAdapter extends RecyclerView.Adapter {
if (tmpUrlSbstr.contains("msg"))
tmpUrlSbstr = tmpUrlSbstr.substring(0, tmpUrlSbstr.indexOf("msg") - 1);
int testAgainst = Integer.parseInt(tmpUrlSbstr);
- for (int i = 0; i < postsList.size(); i++) {
- if (postsList.get(i).getPostIndex() == testAgainst) {
+ for (int i = 0; i < topicRecyclerViewItems.size(); i++) {
+ if (!(topicRecyclerViewItems.get(i) instanceof Post)) continue;
+ if (((Post) topicRecyclerViewItems.get(i)).getPostIndex() == testAgainst) {
//same page
Timber.e(Integer.toString(i));
postFocusListener.onPostFocusChange(i);
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicRecyclerViewItem.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicRecyclerViewItem.java
new file mode 100644
index 00000000..8c31c8bb
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicRecyclerViewItem.java
@@ -0,0 +1,4 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+public class TopicRecyclerViewItem {
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
index 7c5e5d1f..c2b53086 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
@@ -45,13 +45,17 @@ public class TopicTask extends AsyncTask {
//Finds the index of message focus if present
int postFocus = 0;
- {
- if (newPageUrl.contains("msg")) {
- String tmp = newPageUrl.substring(newPageUrl.indexOf("msg") + 3);
- if (tmp.contains(";"))
- postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf(";")));
- else if (tmp.contains("#"))
- postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf("#")));
+ boolean focusedPostLastSeenMessage = false;
+ if (newPageUrl.contains("msg")) {
+ String tmp = newPageUrl.substring(newPageUrl.indexOf("msg") + 3);
+ if (tmp.contains(";")) {
+ postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf(";")));
+ if (newPageUrl.contains("topicseen"))
+ focusedPostLastSeenMessage = true;
+ } else if (tmp.contains("#")) {
+ postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf("#")));
+ if (newPageUrl.contains("topicseen"))
+ focusedPostLastSeenMessage = true;
}
}
@@ -105,18 +109,18 @@ public class TopicTask extends AsyncTask {
}
}
return new TopicTaskResult(ResultCode.SUCCESS, topicTitle, replyPageUrl, newPostsList, loadedPageTopicId,
- currentPageIndex, pageCount, focusedPostIndex, topicTreeAndMods, topicViewers);
+ currentPageIndex, pageCount, focusedPostIndex, topicTreeAndMods, topicViewers, focusedPostLastSeenMessage);
} catch (IOException e) {
return new TopicTaskResult(ResultCode.NETWORK_ERROR, null, null, null,
- 0, 0, 0, 0, null, null);
+ 0, 0, 0, 0, null, null, false);
} catch (Exception e) {
if (isUnauthorized(topic)) {
return new TopicTaskResult(ResultCode.UNAUTHORIZED, null, null, null,
- 0, 0, 0, 0, null, null);
+ 0, 0, 0, 0, null, null, false);
} else {
Timber.e(e, "Topic parse failed");
return new TopicTaskResult(ResultCode.PARSING_ERROR, null, null, null,
- 0, 0, 0, 0, null, null);
+ 0, 0, 0, 0, null, null, false);
}
}
}
@@ -139,6 +143,7 @@ public class TopicTask extends AsyncTask {
public interface TopicTaskObserver {
void onTopicTaskStarted();
+
void onTopicTaskCancelled();
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java
index c713da1f..2e098c16 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java
@@ -36,11 +36,12 @@ public class TopicTaskResult {
//Topic's info related
private final String topicTreeAndMods;
private final String topicViewers;
+ private final boolean focusedPostLastSeenMessage;
public TopicTaskResult(TopicTask.ResultCode resultCode, String topicTitle,
String replyPageUrl, ArrayList newPostsList, int loadedPageTopicId,
int currentPageIndex, int pageCount, int focusedPostIndex, String topicTreeAndMods,
- String topicViewers) {
+ String topicViewers, boolean focusedPostLastSeenMessage) {
this.resultCode = resultCode;
this.topicTitle = topicTitle;
this.replyPageUrl = replyPageUrl;
@@ -51,6 +52,7 @@ public class TopicTaskResult {
this.focusedPostIndex = focusedPostIndex;
this.topicTreeAndMods = topicTreeAndMods;
this.topicViewers = topicViewers;
+ this.focusedPostLastSeenMessage = focusedPostLastSeenMessage;
}
public TopicTask.ResultCode getResultCode() {
@@ -92,4 +94,8 @@ public class TopicTaskResult {
public String getTopicViewers() {
return topicViewers;
}
+
+ public boolean isFocusedPostLastSeenMessage() {
+ return focusedPostLastSeenMessage;
+ }
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Post.java b/app/src/main/java/gr/thmmy/mthmmy/model/Post.java
index 078386dc..5a69e6a5 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/model/Post.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/model/Post.java
@@ -5,6 +5,8 @@ import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.Objects;
+import gr.thmmy.mthmmy.activities.topic.TopicRecyclerViewItem;
+
/**
* Class that defines a topic's post. All member variables are declared final (thus no setters are
* supplied). Class has two constructors and getter methods for all variables.
@@ -15,7 +17,7 @@ import java.util.Objects;
* gender, number of posts, personal text and number of start to be described in addition to
* previous fields.
*/
-public class Post {
+public class Post extends TopicRecyclerViewItem {
public static final int TYPE_POST = 0;
public static final int TYPE_QUICK_REPLY = 1;
public static final int TYPE_EDIT = 2;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
index 96cecf4a..fbc40ece 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
@@ -73,6 +73,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
private String topicUrl;
private int currentPageIndex;
private int pageCount;
+ private boolean focusedPostLastSeenMessage;
private MutableLiveData prepareForReplyResult = new MutableLiveData<>();
private MutableLiveData prepareForEditResult = new MutableLiveData<>();
@@ -187,6 +188,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
if (result.getResultCode() == TopicTask.ResultCode.SUCCESS) {
currentPageIndex = result.getCurrentPageIndex();
pageCount = result.getPageCount();
+ focusedPostLastSeenMessage = result.isFocusedPostLastSeenMessage();
topicTreeAndMods.setValue(result.getTopicTreeAndMods());
topicViewers.setValue(result.getTopicViewers());
pageTopicId.setValue(result.getLoadedPageTopicId());
@@ -392,4 +394,8 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
throw new NullPointerException("No page has been loaded yet!");
return postsList.getValue().size();
}
+
+ public boolean isFocusedPostLastSeenMessage() {
+ return focusedPostLastSeenMessage;
+ }
}
diff --git a/app/src/main/res/layout/activity_topic_new_message_separator.xml b/app/src/main/res/layout/activity_topic_new_message_separator.xml
new file mode 100644
index 00000000..b7e5507f
--- /dev/null
+++ b/app/src/main/res/layout/activity_topic_new_message_separator.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file