From 14f97d7ce3d3e78dbd2da7b0e201c10ca43c2e50 Mon Sep 17 00:00:00 2001
From: Thodoris1999
Date: Thu, 26 Jul 2018 12:51:17 +0300
Subject: [PATCH] make TopicViewModel an interface for loads (not finished)
---
app/build.gradle | 2 +-
.../mthmmy/activities/topic/DeleteTask.java | 62 ++
.../mthmmy/activities/topic/EditTask.java | 77 +++
.../activities/topic/GetQuoteTextTask.java | 4 -
.../topic/PrepareForEditResult.java | 51 ++
.../activities/topic/PrepareForEditTask.java | 79 +++
.../activities/topic/PrepareForReply.java | 96 +++
.../topic/PrepareForReplyResult.java | 34 +
.../mthmmy/activities/topic/ReplyTask.java | 74 ++
.../activities/topic/TopicActivity.java | 650 +++++-------------
.../mthmmy/activities/topic/TopicAdapter.java | 125 +---
.../mthmmy/activities/topic/TopicTask.java | 91 ++-
.../mthmmy/viewmodel/TopicViewModel.java | 221 +++++-
13 files changed, 939 insertions(+), 627 deletions(-)
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/DeleteTask.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/EditTask.java
delete mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditResult.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditTask.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReply.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReplyResult.java
create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyTask.java
diff --git a/app/build.gradle b/app/build.gradle
index 4e9bb2f4..dd59ec42 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -42,7 +42,7 @@ dependencies {
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.google.firebase:firebase-core:16.0.1'
- implementation 'com.google.firebase:firebase-messaging:17.0.0'
+ implementation 'com.google.firebase:firebase-messaging:17.1.0'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.4'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/DeleteTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/DeleteTask.java
new file mode 100644
index 00000000..7c74d17a
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/DeleteTask.java
@@ -0,0 +1,62 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.os.AsyncTask;
+
+import java.io.IOException;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import timber.log.Timber;
+
+import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
+
+public class DeleteTask extends AsyncTask {
+ private DeleteTaskCallbacks listener;
+
+ public DeleteTask(DeleteTaskCallbacks listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ listener.onDeleteTaskStarted();
+ }
+
+ @Override
+ protected Boolean doInBackground(String... args) {
+ Request delete = new Request.Builder()
+ .url(args[0])
+ .header("User-Agent",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
+ .build();
+
+ try {
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ client.newCall(delete).execute();
+ Response response = client.newCall(delete).execute();
+ //Response response = client.newCall(delete).execute();
+ switch (replyStatus(response)) {
+ case SUCCESSFUL:
+ return true;
+ default:
+ Timber.e("Something went wrong. Request string: %s", delete.toString());
+ return true;
+ }
+ } catch (IOException e) {
+ Timber.e(e, "Delete failed.");
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ listener.onDeleteTaskFinished(result);
+ }
+
+ public interface DeleteTaskCallbacks {
+ void onDeleteTaskStarted();
+ void onDeleteTaskFinished(boolean result);
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/EditTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/EditTask.java
new file mode 100644
index 00000000..4d4802b3
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/EditTask.java
@@ -0,0 +1,77 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.os.AsyncTask;
+
+import java.io.IOException;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import timber.log.Timber;
+
+import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
+
+public class EditTask extends AsyncTask {
+ private EditTaskCallbacks listener;
+ private int position;
+
+ public EditTask(EditTaskCallbacks listener, int position) {
+ this.listener = listener;
+ this.position = position;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ listener.onEditTaskStarted();
+ }
+
+ @Override
+ protected Boolean doInBackground(String... strings) {
+ RequestBody postBody = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("message", strings[1])
+ .addFormDataPart("num_replies", strings[2])
+ .addFormDataPart("seqnum", strings[3])
+ .addFormDataPart("sc", strings[4])
+ .addFormDataPart("subject", strings[5])
+ .addFormDataPart("topic", strings[6])
+ .build();
+ Request post = new Request.Builder()
+ .url(strings[0])
+ .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
+ .post(postBody)
+ .build();
+
+ try {
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ client.newCall(post).execute();
+ Response response = client.newCall(post).execute();
+ switch (replyStatus(response)) {
+ case SUCCESSFUL:
+ return true;
+ case NEW_REPLY_WHILE_POSTING:
+ //TODO this...
+ return true;
+ default:
+ Timber.e("Malformed post. Request string: %s", post.toString());
+ return true;
+ }
+ } catch (IOException e) {
+ Timber.e(e, "Edit failed.");
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ listener.onEditTaskFinished(result, position);
+ }
+
+ public interface EditTaskCallbacks {
+ void onEditTaskStarted();
+ void onEditTaskFinished(boolean result, int position);
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java
deleted file mode 100644
index 0b29087f..00000000
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package gr.thmmy.mthmmy.activities.topic;
-
-public class GetQuoteTextTask {
-}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditResult.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditResult.java
new file mode 100644
index 00000000..0c3f9dec
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditResult.java
@@ -0,0 +1,51 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+public class PrepareForEditResult {
+ private final String postText, commitEditUrl, numReplies, seqnum, sc, topic;
+ private int position;
+ private boolean successful;
+
+ public PrepareForEditResult(String postText, String commitEditUrl, String numReplies, String seqnum,
+ String sc, String topic, int position, boolean successful) {
+ this.postText = postText;
+ this.commitEditUrl = commitEditUrl;
+ this.numReplies = numReplies;
+ this.seqnum = seqnum;
+ this.sc = sc;
+ this.topic = topic;
+ this.position = position;
+ this.successful = successful;
+ }
+
+ public String getPostText() {
+ return postText;
+ }
+
+ public String getCommitEditUrl() {
+ return commitEditUrl;
+ }
+
+ public String getNumReplies() {
+ return numReplies;
+ }
+
+ public String getSeqnum() {
+ return seqnum;
+ }
+
+ public String getSc() {
+ return sc;
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public boolean isSuccessful() {
+ return successful;
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditTask.java
new file mode 100644
index 00000000..f1933cce
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditTask.java
@@ -0,0 +1,79 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.os.AsyncTask;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Selector;
+
+import java.io.IOException;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import timber.log.Timber;
+
+public class PrepareForEditTask extends AsyncTask {
+ private int position;
+ private String replyPageUrl;
+ private PrepareForEditCallbacks listener;
+ private OnPrepareEditFinished finishListener;
+
+ public PrepareForEditTask(PrepareForEditCallbacks listener, OnPrepareEditFinished finishListener, int position, String replyPageUrl) {
+ this.listener = listener;
+ this.finishListener = finishListener;
+ this.position = position;
+ this.replyPageUrl = replyPageUrl;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ listener.onPrepareEditStarted();
+ }
+
+ @Override
+ protected PrepareForEditResult doInBackground(String... strings) {
+ Document document;
+ String url = strings[0];
+ Request request = new Request.Builder()
+ .url(url + ";wap2")
+ .build();
+
+ try {
+ String postText, commitEditURL, numReplies, seqnum, sc, topic;
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ Response response = client.newCall(request).execute();
+ document = Jsoup.parse(response.body().string());
+
+ Element message = document.select("textarea").first();
+ postText = message.text();
+
+ commitEditURL = document.select("form").first().attr("action");
+ numReplies = replyPageUrl.substring(replyPageUrl.indexOf("num_replies=") + 12);
+ seqnum = document.select("input[name=seqnum]").first().attr("value");
+ sc = document.select("input[name=sc]").first().attr("value");
+ topic = document.select("input[name=topic]").first().attr("value");
+
+ return new PrepareForEditResult(postText, commitEditURL, numReplies, seqnum, sc, topic, position, true);
+ } catch (IOException | Selector.SelectorParseException e) {
+ Timber.e(e, "Prepare failed.");
+ return new PrepareForEditResult(null, null, null, null, null, null, position, false);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(PrepareForEditResult result) {
+ finishListener.onPrepareEditFinished(result, position);
+ }
+
+ public interface PrepareForEditCallbacks {
+ void onPrepareEditStarted();
+ void onPrepareEditCancelled();
+ }
+
+ public interface OnPrepareEditFinished {
+ void onPrepareEditFinished(PrepareForEditResult result, int position);
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReply.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReply.java
new file mode 100644
index 00000000..752692f5
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReply.java
@@ -0,0 +1,96 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.os.AsyncTask;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.select.Selector;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import gr.thmmy.mthmmy.model.Post;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import timber.log.Timber;
+
+public class PrepareForReply extends AsyncTask {
+ private PrepareForReplyCallbacks listener;
+ private OnPrepareForReplyFinished finishListener;
+ private String replyPageUrl;
+ private ArrayList postsList;
+
+ public PrepareForReply(PrepareForReplyCallbacks listener, OnPrepareForReplyFinished finishListener,
+ String replyPageUrl, ArrayList postsList) {
+ this.listener = listener;
+ this.finishListener = finishListener;
+ this.replyPageUrl = replyPageUrl;
+ this.postsList = postsList;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ listener.onPrepareForReplyStarted();
+ }
+
+ @Override
+ protected PrepareForReplyResult doInBackground(Integer... quoteList) {
+ String numReplies = null;
+ String seqnum = null;
+ String sc = null;
+ String topic = null;
+ StringBuilder buildedQuotes = new StringBuilder();
+
+ Document document;
+ Request request = new Request.Builder()
+ .url(replyPageUrl + ";wap2")
+ .build();
+
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ try {
+ Response response = client.newCall(request).execute();
+ document = Jsoup.parse(response.body().string());
+
+ numReplies = replyPageUrl.substring(replyPageUrl.indexOf("num_replies=") + 12);
+ seqnum = document.select("input[name=seqnum]").first().attr("value");
+ sc = document.select("input[name=sc]").first().attr("value");
+ topic = document.select("input[name=topic]").first().attr("value");
+ } catch (IOException | Selector.SelectorParseException e) {
+ Timber.e(e, "Prepare failed.");
+ }
+
+ for (Integer quotePosition : quoteList) {
+ request = new Request.Builder()
+ .url("https://www.thmmy.gr/smf/index.php?action=quotefast;quote=" +
+ postsList.get(quotePosition).getPostIndex() +
+ ";" + "sesc=" + sc + ";xml")
+ .build();
+
+ try {
+ Response response = client.newCall(request).execute();
+ String body = response.body().string();
+ buildedQuotes.append(body.substring(body.indexOf("") + 7, body.indexOf("
")));
+ buildedQuotes.append("\n\n");
+ } catch (IOException | Selector.SelectorParseException e) {
+ Timber.e(e, "Quote building failed.");
+ }
+ }
+ return new PrepareForReplyResult(numReplies, seqnum, sc, topic, buildedQuotes.toString());
+ }
+
+ @Override
+ protected void onPostExecute(PrepareForReplyResult result) {
+ finishListener.onPrepareForReplyFinished(result);
+ }
+
+ public interface PrepareForReplyCallbacks {
+ void onPrepareForReplyStarted();
+ void onPrepareForReplyCancelled();
+ }
+
+ public interface OnPrepareForReplyFinished {
+ void onPrepareForReplyFinished(PrepareForReplyResult result);
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReplyResult.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReplyResult.java
new file mode 100644
index 00000000..24364d49
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReplyResult.java
@@ -0,0 +1,34 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+public class PrepareForReplyResult {
+ private final String numReplies, seqnum, sc, topic, buildedQuotes;
+
+
+ public PrepareForReplyResult(String numReplies, String seqnum, String sc, String topic, String buildedQuotes) {
+ this.numReplies = numReplies;
+ this.seqnum = seqnum;
+ this.sc = sc;
+ this.topic = topic;
+ this.buildedQuotes = buildedQuotes;
+ }
+
+ public String getNumReplies() {
+ return numReplies;
+ }
+
+ public String getSeqnum() {
+ return seqnum;
+ }
+
+ public String getSc() {
+ return sc;
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public String getBuildedQuotes() {
+ return buildedQuotes;
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyTask.java
new file mode 100644
index 00000000..5ec23f2f
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyTask.java
@@ -0,0 +1,74 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.os.AsyncTask;
+
+import java.io.IOException;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import timber.log.Timber;
+
+import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
+
+public class ReplyTask extends AsyncTask {
+ private OnReplyTaskFinished listener;
+ private boolean includeAppSignature;
+
+ public ReplyTask(OnReplyTaskFinished listener, boolean includeAppSignature) {
+ this.listener = listener;
+ this.includeAppSignature = includeAppSignature;
+ }
+
+ @Override
+ protected Boolean doInBackground(String... args) {
+ final String sentFrommTHMMY = includeAppSignature
+ ? "\n[right][size=7pt][i]sent from [url=https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy]mTHMMY [/url][/i][/size][/right]"
+ : "";
+ RequestBody postBody = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("message", args[1] + sentFrommTHMMY)
+ .addFormDataPart("num_replies", args[2])
+ .addFormDataPart("seqnum", args[3])
+ .addFormDataPart("sc", args[4])
+ .addFormDataPart("subject", args[0])
+ .addFormDataPart("topic", args[5])
+ .build();
+ Request post = new Request.Builder()
+ .url("https://www.thmmy.gr/smf/index.php?action=post2")
+ .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
+ .post(postBody)
+ .build();
+
+ try {
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ client.newCall(post).execute();
+ Response response = client.newCall(post).execute();
+ switch (replyStatus(response)) {
+ case SUCCESSFUL:
+ return true;
+ case NEW_REPLY_WHILE_POSTING:
+ //TODO this...
+ return true;
+ default:
+ Timber.e("Malformed post. Request string: %s", post.toString());
+ return true;
+ }
+ } catch (IOException e) {
+ Timber.e(e, "Post failed.");
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ listener.onReplyTaskFinished(result);
+ }
+
+ public interface OnReplyTaskFinished {
+ void onReplyTaskFinished(boolean result);
+ }
+}
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 a1ff2822..f4cf139b 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
@@ -2,28 +2,19 @@ package gr.thmmy.mthmmy.activities.topic;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
-import android.arch.lifecycle.ViewModelProvider;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
-import android.support.v7.preference.PreferenceManager;
import android.support.v7.widget.RecyclerView;
-import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
-import android.text.style.URLSpan;
-import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -36,42 +27,20 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Selector;
-
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
import gr.thmmy.mthmmy.R;
-import gr.thmmy.mthmmy.activities.board.BoardActivity;
-import gr.thmmy.mthmmy.activities.profile.ProfileActivity;
-import gr.thmmy.mthmmy.activities.settings.SettingsActivity;
import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.CustomLinearLayoutManager;
import gr.thmmy.mthmmy.utils.HTMLUtils;
-import gr.thmmy.mthmmy.utils.parsing.ParseException;
-import gr.thmmy.mthmmy.utils.parsing.ParseHelpers;
import gr.thmmy.mthmmy.viewmodel.TopicViewModel;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
-import okhttp3.MultipartBody;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
import timber.log.Timber;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
-import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
-import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
-import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
-import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
-import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
/**
@@ -81,7 +50,9 @@ import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
* key {@link #BUNDLE_TOPIC_TITLE} for faster title rendering.
*/
@SuppressWarnings("unchecked")
-public class TopicActivity extends BaseActivity {
+public class TopicActivity extends BaseActivity implements TopicTask.TopicTaskObserver,
+ DeleteTask.DeleteTaskCallbacks, ReplyTask.OnReplyTaskFinished, PrepareForEditTask.PrepareForEditCallbacks,
+ EditTask.EditTaskCallbacks, PrepareForReply.PrepareForReplyCallbacks {
//Activity's variables
/**
* The key to use when putting topic's url String to {@link TopicActivity}'s Bundle.
@@ -91,76 +62,18 @@ public class TopicActivity extends BaseActivity {
* The key to use when putting topic's title String to {@link TopicActivity}'s Bundle.
*/
public static final String BUNDLE_TOPIC_TITLE = "TOPIC_TITLE";
- private static TopicTask topicTask;
private MaterialProgressBar progressBar;
private TextView toolbarTitle;
- /**
- * Holds this topic's base url. For example a topic with url similar to
- * "https://www.thmmy.gr/smf/index.php?topic=1.15;topicseen" or
- * "https://www.thmmy.gr/smf/index.php?topic=1.msg1#msg1"
- * has the base url "https://www.thmmy.gr/smf/index.php?topic=1"
- */
- private static String base_url = "";
- /**
- * Holds this topic's title. At first this gets the value of the topic title that came with
- * bundle and is rendered in the toolbar while parsing this topic. Later, after topic's parsing
- * is done, it gets the value of {@link #parsedTitle} if bundle title and parsed title differ.
- */
- private String topicTitle;
- /**
- * Holds this topic's title as parsed from the html source. If this (parsed) title is different
- * than the one that came with activity's bundle then the parsed title is preferred over the
- * bundle one and gets rendered in the toolbar.
- */
- private String parsedTitle;
- private String topicPageUrl;
private RecyclerView recyclerView;
- /**
- * Holds the url of this page
- */
- private String loadedPageUrl = "";
- /**
- * Holds the topicId of this page
- */
- private int loadedPageTopicId = -1;
- /**
- * Becomes true after user has posted in this topic and the page is being reloaded and false
- * when topic's reloading is done
- */
- private boolean reloadingPage = false;
//Posts related
private TopicAdapter topicAdapter;
/**
* Holds a list of this topic's posts
*/
private ArrayList postsList;
- /**
- * Holds the index of the post that has focus
- */
-
- /**
- * Holds the position in the {@link #postsList} of the post with focus
- */
- private static int postFocusPosition = 0;
//Reply related
private FloatingActionButton replyFAB;
- /**
- * Holds this topic's reply url
- */
- private String replyPageUrl = null;
//Topic's pages related
- /**
- * Holds current page's index (starting from 1, not 0)
- */
- private int thisPage = 1;
- /**
- * Holds this topic's number of pages
- */
- private int numberOfPages = 1;
- /**
- * Holds a list of this topic's pages urls
- */
- private final SparseArray pagesUrls = new SparseArray<>();
//Page select related
/**
* Used for handling bottom navigation bar's buttons long click user interactions
@@ -197,21 +110,22 @@ public class TopicActivity extends BaseActivity {
private ImageButton lastPage;
private TopicViewModel viewModel;
- //Topic's info related
- private SpannableStringBuilder topicTreeAndMods = new SpannableStringBuilder("Loading..."),
- topicViewers = new SpannableStringBuilder("Loading...");
-
- boolean includeAppSignaturePreference = true;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic);
+ viewModel = ViewModelProviders.of(this).get(TopicViewModel.class);
+ viewModel.setTopicTaskObserver(this);
+ viewModel.setDeleteTaskCallbacks(this);
+ viewModel.setReplyFinishListener(this);
+ viewModel.setPrepareForEditCallbacks(this);
+ viewModel.setEditTaskCallbacks(this);
+ viewModel.setPrepareForReplyCallbacks(this);
+
Bundle extras = getIntent().getExtras();
- topicTitle = extras.getString(BUNDLE_TOPIC_TITLE);
- String maybeTopicTitle = topicTitle;
- topicPageUrl = extras.getString(BUNDLE_TOPIC_URL);
+ String topicTitle = extras.getString(BUNDLE_TOPIC_TITLE);
+ String topicPageUrl = extras.getString(BUNDLE_TOPIC_URL);
ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(
Uri.parse(topicPageUrl));
if (!target.is(ThmmyPage.PageCategory.TOPIC)) {
@@ -222,10 +136,6 @@ public class TopicActivity extends BaseActivity {
topicPageUrl = ThmmyPage.sanitizeTopicUrl(topicPageUrl);
- if (sessionManager.isLoggedIn()) {
- SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- includeAppSignaturePreference = sharedPrefs.getBoolean(SettingsActivity.APP_SIGNATURE_ENABLE_KEY, true);
- }
thisPageBookmark = new Bookmark(topicTitle, ThmmyPage.getTopicId(topicPageUrl), true);
@@ -251,20 +161,11 @@ public class TopicActivity extends BaseActivity {
recyclerView = findViewById(R.id.topic_recycler_view);
recyclerView.setHasFixedSize(true);
- recyclerView.setOnTouchListener(
- new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- v.performClick();
- return topicTask != null && topicTask.getStatus() == AsyncTask.Status.RUNNING;
- }
- }
- );
//LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(
- getApplicationContext(), loadedPageUrl);
+ getApplicationContext(), topicPageUrl);
recyclerView.setLayoutManager(layoutManager);
- topicAdapter = new TopicAdapter(this, postsList, viewModel.getTopicTaskResultMutableLiveData().getValue().getBaseUrl(), topicTask);
+ topicAdapter = new TopicAdapter(this, postsList);
recyclerView.setAdapter(topicAdapter);
replyFAB = findViewById(R.id.topic_fab);
@@ -272,13 +173,9 @@ public class TopicActivity extends BaseActivity {
bottomNavBar = findViewById(R.id.bottom_navigation_bar);
if (!sessionManager.isLoggedIn()) replyFAB.hide();
else {
- replyFAB.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (sessionManager.isLoggedIn()) {
- PrepareForReply prepareForReply = new PrepareForReply();
- prepareForReply.execute(topicAdapter.getToQuoteList());
- }
+ replyFAB.setOnClickListener(view -> {
+ if (sessionManager.isLoggedIn()) {
+ viewModel.prepareForReply(postsList, topicAdapter.getToQuoteList());
}
});
}
@@ -294,14 +191,8 @@ public class TopicActivity extends BaseActivity {
initDecrementButton(previousPage, SMALL_STEP);
initIncrementButton(nextPage, SMALL_STEP);
initIncrementButton(lastPage, LARGE_STEP);
- paginationEnabled(false);
-
- //Gets posts
- //topicTask = new TopicTask();
- //topicTask.execute(topicPageUrl); //Attempt data parsing
- viewModel = ViewModelProviders.of(this).get(TopicViewModel.class);
- viewModel.getTopicTaskResultMutableLiveData().observe(this, topicTaskResult -> {
+ viewModel.getTopicTaskResult().observe(this, topicTaskResult -> {
if (topicTaskResult == null) {
hideControls();
} else {
@@ -320,19 +211,19 @@ public class TopicActivity extends BaseActivity {
}
postsList.addAll(topicTaskResult.getNewPostsList());
topicAdapter.notifyItemRangeInserted(0, postsList.size());
- topicAdapter.prepareForDelete(new TopicActivity.DeleteTask());
- topicAdapter.prepareForPrepareForEdit(new TopicActivity.PrepareForEdit());
- pageIndicator.setText(String.valueOf(thisPage) + "/" + String.valueOf(numberOfPages));
+ pageIndicator.setText(String.valueOf(topicTaskResult.getCurrentPageIndex()) + "/" +
+ String.valueOf(topicTaskResult.getPageCount()));
pageRequestValue = topicTaskResult.getCurrentPageIndex();
if (topicTaskResult.getCurrentPageIndex() == topicTaskResult.getPageCount()) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null)
- notificationManager.cancel(NEW_POST_TAG, loadedPageTopicId);
+ notificationManager.cancel(NEW_POST_TAG, topicTaskResult.getLoadedPageTopicId());
}
showControls();
+ break;
case NETWORK_ERROR:
Toast.makeText(getBaseContext(), "Network Error", Toast.LENGTH_SHORT).show();
break;
@@ -355,23 +246,41 @@ public class TopicActivity extends BaseActivity {
}
});
- viewModel.initialLoad(topicPageUrl);
+ viewModel.getPrepareForReplyResult().observe(this, prepareForReplyResult -> {
+ if (prepareForReplyResult != null) {
+ //prepare for a reply
+ viewModel.setWritingReply(true);
+ postsList.add(Post.newQuickReply());
+ topicAdapter.notifyItemInserted(postsList.size());
+ recyclerView.scrollToPosition(postsList.size() - 1);
+ showControls();
+ }
+ });
+ viewModel.getPrepareForEditResult().observe(this, result -> {
+ if (result != null && result.isSuccessful()) {
+ viewModel.setEditingPost(true);
+ postsList.get(result.getPosition()).setPostType(Post.TYPE_EDIT);
+ topicAdapter.notifyItemChanged(result.getPosition());
+ recyclerView.scrollToPosition(result.getPosition());
+ showControls();
+ }
+ });
+ viewModel.initialLoad(topicPageUrl);
}
public void hideControls() {
progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(false);
}
public void showControls() {
- progressBar.setVisibility(ProgressBar.INVISIBLE);
- if (replyPageUrl == null) {
+ progressBar.setVisibility(ProgressBar.GONE);
+ if (viewModel.getTopicTaskResult().getValue().getReplyPageUrl() == null) {
replyFAB.hide();
- topicAdapter.resetTopic(viewModel.getTopicTaskResultMutableLiveData().getValue().getBaseUrl(), new TopicTask(), false);
- } else topicAdapter.resetTopic(viewModel.getTopicTaskResultMutableLiveData().getValue().getBaseUrl(), new TopicTask(), true);
- paginationEnabled(true);
+ topicAdapter.resetTopic(false);
+ } else
+ topicAdapter.resetTopic(true);
if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true);
}
@@ -397,12 +306,12 @@ public class TopicActivity extends BaseActivity {
LinearLayout infoDialog = (LinearLayout) inflater.inflate(R.layout.dialog_topic_info
, null);
TextView treeAndMods = infoDialog.findViewById(R.id.topic_tree_and_mods);
- //treeAndMods.setText(new SpannableStringBuilder("Loading..."));
+ treeAndMods.setText(new SpannableStringBuilder("Loading..."));
treeAndMods.setMovementMethod(LinkMovementMethod.getInstance());
TextView usersViewing = infoDialog.findViewById(R.id.users_viewing);
- //usersViewing.setText(new SpannableStringBuilder("Loading..."));
+ usersViewing.setText(new SpannableStringBuilder("Loading..."));
usersViewing.setMovementMethod(LinkMovementMethod.getInstance());
- viewModel.getTopicTaskResultMutableLiveData().observe(this, topicTaskResult -> {
+ viewModel.getTopicTaskResult().observe(this, topicTaskResult -> {
if (topicTaskResult == null) {
usersViewing.setText(new SpannableStringBuilder("Loading..."));
treeAndMods.setText(new SpannableStringBuilder("Loading..."));
@@ -421,7 +330,7 @@ public class TopicActivity extends BaseActivity {
case R.id.menu_share:
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.setType("text/plain");
- sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, topicPageUrl);
+ sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, viewModel.getTopicUrl());
startActivity(Intent.createChooser(sendIntent, "Share via"));
return true; //invalidateOptionsMenu();
default:
@@ -452,19 +361,13 @@ public class TopicActivity extends BaseActivity {
super.onResume();
refreshTopicBookmark();
drawer.setSelection(-1);
-
- if (sessionManager.isLoggedIn()) {
- SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- includeAppSignaturePreference = sharedPrefs.getBoolean(SettingsActivity.APP_SIGNATURE_ENABLE_KEY, true);
- }
}
@Override
protected void onDestroy() {
super.onDestroy();
recyclerView.setAdapter(null);
- if (topicTask != null && topicTask.getStatus() != AsyncTask.Status.RUNNING)
- topicTask.cancel(true);
+ viewModel.stopLoading();
}
//--------------------------------------BOTTOM NAV BAR METHODS----------------------------------
@@ -527,26 +430,22 @@ public class TopicActivity extends BaseActivity {
@SuppressLint("ClickableViewAccessibility")
private void initIncrementButton(ImageButton increment, final int step) {
// Increment once for a click
- increment.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (!autoIncrement && step == LARGE_STEP) {
- changePage(numberOfPages - 1);
- } else if (!autoIncrement) {
- incrementPageRequestValue(step);
- changePage(pageRequestValue - 1);
- }
+ increment.setOnClickListener(v -> {
+ if (!autoIncrement && step == LARGE_STEP) {
+ viewModel.changePage(viewModel.getTopicTaskResult().getValue().getPageCount() - 1);
+ } else if (!autoIncrement) {
+ incrementPageRequestValue(step);
+ viewModel.changePage(pageRequestValue - 1);
}
});
// Auto increment for a long click
increment.setOnLongClickListener(
- new View.OnLongClickListener() {
- public boolean onLongClick(View arg0) {
- paginationDisable(arg0);
- autoIncrement = true;
- repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), INITIAL_DELAY);
- return false;
- }
+ arg0 -> {
+ paginationDisable(arg0);
+ autoIncrement = true;
+ repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), INITIAL_DELAY);
+ return false;
}
);
@@ -560,11 +459,11 @@ public class TopicActivity extends BaseActivity {
} else if (rect != null && event.getAction() == MotionEvent.ACTION_UP && autoIncrement) {
autoIncrement = false;
paginationEnabled(true);
- changePage(pageRequestValue - 1);
+ viewModel.changePage(pageRequestValue - 1);
} else if (rect != null && event.getAction() == MotionEvent.ACTION_MOVE) {
if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) {
autoIncrement = false;
- decrementPageRequestValue(pageRequestValue - thisPage);
+ decrementPageRequestValue(pageRequestValue - viewModel.getTopicTaskResult().getValue().getCurrentPageIndex());
paginationEnabled(true);
}
}
@@ -576,26 +475,22 @@ public class TopicActivity extends BaseActivity {
@SuppressLint("ClickableViewAccessibility")
private void initDecrementButton(ImageButton decrement, final int step) {
// Decrement once for a click
- decrement.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (!autoDecrement && step == LARGE_STEP) {
- changePage(0);
- } else if (!autoDecrement) {
- decrementPageRequestValue(step);
- changePage(pageRequestValue - 1);
- }
+ decrement.setOnClickListener(v -> {
+ if (!autoDecrement && step == LARGE_STEP) {
+ viewModel.changePage(0);
+ } else if (!autoDecrement) {
+ decrementPageRequestValue(step);
+ viewModel.changePage(pageRequestValue - 1);
}
});
// Auto decrement for a long click
decrement.setOnLongClickListener(
- new View.OnLongClickListener() {
- public boolean onLongClick(View arg0) {
- paginationDisable(arg0);
- autoDecrement = true;
- repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), INITIAL_DELAY);
- return false;
- }
+ arg0 -> {
+ paginationDisable(arg0);
+ autoDecrement = true;
+ repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), INITIAL_DELAY);
+ return false;
}
);
@@ -609,12 +504,12 @@ public class TopicActivity extends BaseActivity {
} else if (event.getAction() == MotionEvent.ACTION_UP && autoDecrement) {
autoDecrement = false;
paginationEnabled(true);
- changePage(pageRequestValue - 1);
+ viewModel.changePage(pageRequestValue - 1);
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (rect != null &&
!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) {
autoIncrement = false;
- incrementPageRequestValue(thisPage - pageRequestValue);
+ incrementPageRequestValue(viewModel.getTopicTaskResult().getValue().getCurrentPageIndex() - pageRequestValue);
paginationEnabled(true);
}
}
@@ -624,11 +519,11 @@ public class TopicActivity extends BaseActivity {
}
private void incrementPageRequestValue(int step) {
- if (pageRequestValue < numberOfPages - step) {
+ if (pageRequestValue < viewModel.getTopicTaskResult().getValue().getPageCount() - step) {
pageRequestValue = pageRequestValue + step;
} else
- pageRequestValue = numberOfPages;
- pageIndicator.setText(pageRequestValue + "/" + String.valueOf(numberOfPages));
+ pageRequestValue = viewModel.getTopicTaskResult().getValue().getPageCount();
+ pageIndicator.setText(pageRequestValue + "/" + String.valueOf(viewModel.getTopicTaskResult().getValue().getPageCount()));
}
private void decrementPageRequestValue(int step) {
@@ -636,346 +531,107 @@ public class TopicActivity extends BaseActivity {
pageRequestValue = pageRequestValue - step;
else
pageRequestValue = 1;
- pageIndicator.setText(pageRequestValue + "/" + String.valueOf(numberOfPages));
- }
-
- private void changePage(int pageRequested) {
- if (pageRequested != thisPage - 1) {
- if (topicTask != null && topicTask.getStatus() != AsyncTask.Status.RUNNING)
- topicTask.cancel(true);
-
- topicTask = new TopicTask();
- topicTask.execute(pagesUrls.get(pageRequested)); //Attempt data parsing
-
- }
+ pageIndicator.setText(pageRequestValue + "/" + String.valueOf(viewModel.getTopicTaskResult().getValue().getPageCount()));
}
//------------------------------------BOTTOM NAV BAR METHODS END------------------------------------
- class PrepareForReply extends AsyncTask, Void, Boolean> {
- String numReplies, seqnum, sc, topic, buildedQuotes = "";
-
- @Override
- protected void onPreExecute() {
- changePage(numberOfPages - 1);
- progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
- replyFAB.setEnabled(false);
- replyFAB.hide();
- bottomNavBar.setVisibility(View.GONE);
- }
-
- @Override
- protected Boolean doInBackground(ArrayList... quoteList) {
- Document document;
- Request request = new Request.Builder()
- .url(replyPageUrl + ";wap2")
- .build();
-
- try {
- Response response = client.newCall(request).execute();
- document = Jsoup.parse(response.body().string());
-
- numReplies = replyPageUrl.substring(replyPageUrl.indexOf("num_replies=") + 12);
- seqnum = document.select("input[name=seqnum]").first().attr("value");
- sc = document.select("input[name=sc]").first().attr("value");
- topic = document.select("input[name=topic]").first().attr("value");
- } catch (IOException | Selector.SelectorParseException e) {
- Timber.e(e, "Prepare failed.");
- return false;
- }
-
- for (Integer quotePosition : quoteList[0]) {
- request = new Request.Builder()
- .url("https://www.thmmy.gr/smf/index.php?action=quotefast;quote=" +
- postsList.get(quotePosition).getPostIndex() +
- ";" + "sesc=" + sc + ";xml")
- .build();
-
- try {
- Response response = client.newCall(request).execute();
- String body = response.body().string();
- buildedQuotes += body.substring(body.indexOf("") + 7, body.indexOf("
"));
- buildedQuotes += "\n\n";
- } catch (IOException | Selector.SelectorParseException e) {
- Timber.e(e, "Quote building failed.");
- return false;
- }
- }
- return true;
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- postsList.add(Post.newQuickReply());
- topicAdapter.notifyItemInserted(postsList.size());
- topicAdapter.prepareForReply(new ReplyTask(), topicTitle, numReplies, seqnum, sc,
- topic, buildedQuotes);
- recyclerView.scrollToPosition(postsList.size() - 1);
- progressBar.setVisibility(ProgressBar.GONE);
- }
+ @Override
+ public void onTopicTaskStarted() {
+ hideControls();
}
- class ReplyTask extends AsyncTask {
-
- @Override
- protected void onPreExecute() {
- progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
- replyFAB.setEnabled(false);
- }
-
- @Override
- protected Boolean doInBackground(String... args) {
- final String sentFrommTHMMY = includeAppSignaturePreference
- ? "\n[right][size=7pt][i]sent from [url=https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy]mTHMMY [/url][/i][/size][/right]"
- : "";
- RequestBody postBody = new MultipartBody.Builder()
- .setType(MultipartBody.FORM)
- .addFormDataPart("message", args[1] + sentFrommTHMMY)
- .addFormDataPart("num_replies", args[2])
- .addFormDataPart("seqnum", args[3])
- .addFormDataPart("sc", args[4])
- .addFormDataPart("subject", args[0])
- .addFormDataPart("topic", args[5])
- .build();
- Request post = new Request.Builder()
- .url("https://www.thmmy.gr/smf/index.php?action=post2")
- .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
- .post(postBody)
- .build();
-
- try {
- client.newCall(post).execute();
- Response response = client.newCall(post).execute();
- switch (replyStatus(response)) {
- case SUCCESSFUL:
- return true;
- case NEW_REPLY_WHILE_POSTING:
- //TODO this...
- return true;
- default:
- Timber.e("Malformed post. Request string: %s", post.toString());
- return true;
- }
- } catch (IOException e) {
- Timber.e(e, "Post failed.");
- return false;
- }
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- View view = getCurrentFocus();
- if (view != null) {
- InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
- }
-
- postsList.remove(postsList.size() - 1);
- topicAdapter.notifyItemRemoved(postsList.size());
-
- progressBar.setVisibility(ProgressBar.GONE);
- replyFAB.setVisibility(View.VISIBLE);
- bottomNavBar.setVisibility(View.VISIBLE);
-
- if (!result)
- Toast.makeText(TopicActivity.this, "Post failed!", Toast.LENGTH_SHORT).show();
- paginationEnabled(true);
- replyFAB.setEnabled(true);
-
- if (result) {
- topicTask = new TopicTask();
- if ((postsList.get(postsList.size() - 1).getPostNumber() + 1) % 15 == 0)
- topicTask.execute(viewModel.getTopicTaskResultMutableLiveData().getValue().getBaseUrl() + "." + 2147483647);
- else {
- reloadingPage = true;
- topicTask.execute(loadedPageUrl);
- }
- }
- }
+ @Override
+ public void onTopicTaskCancelled() {
+ showControls();
}
- class DeleteTask extends AsyncTask {
-
- @Override
- protected void onPreExecute() {
- progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
- replyFAB.setEnabled(false);
- }
-
- @Override
- protected Boolean doInBackground(String... args) {
- Request delete = new Request.Builder()
- .url(args[0])
- .header("User-Agent",
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
- .build();
-
- try {
- client.newCall(delete).execute();
- Response response = client.newCall(delete).execute();
- //Response response = client.newCall(delete).execute();
- switch (replyStatus(response)) {
- case SUCCESSFUL:
- return true;
- default:
- Timber.e("Something went wrong. Request string: %s", delete.toString());
- return true;
- }
- } catch (IOException e) {
- Timber.e(e, "Delete failed.");
- return false;
- }
+ @Override
+ public void onReplyTaskFinished(boolean success) {
+ View view = getCurrentFocus();
+ if (view != null) {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
- @Override
- protected void onPostExecute(Boolean result) {
- progressBar.setVisibility(ProgressBar.GONE);
- replyFAB.setVisibility(View.VISIBLE);
- bottomNavBar.setVisibility(View.VISIBLE);
+ postsList.remove(postsList.size() - 1);
+ topicAdapter.notifyItemRemoved(postsList.size());
- if (!result)
- Toast.makeText(TopicActivity.this, "Post deleted!", Toast.LENGTH_SHORT).show();
- paginationEnabled(true);
- replyFAB.setEnabled(true);
+ showControls();
+ viewModel.setWritingReply(false);
- if (result) {
- topicTask = new TopicTask();
- reloadingPage = true;
- topicTask.execute(loadedPageUrl);
+ if (success) {
+ if ((postsList.get(postsList.size() - 1).getPostNumber() + 1) % 15 == 0) {
+ viewModel.loadUrl(viewModel.getBaseUrl() + "." + 2147483647);
+ } else {
+ viewModel.reloadPage();
}
+ } else {
+ Toast.makeText(TopicActivity.this, "Post failed!", Toast.LENGTH_SHORT).show();
}
- }
-
- class PrepareForEdit extends AsyncTask {
- int position;
- String commitEditURL, numReplies, seqnum, sc, topic, postText = "";
- @Override
- protected void onPreExecute() {
- progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
- replyFAB.setEnabled(false);
- replyFAB.hide();
- bottomNavBar.setVisibility(View.GONE);
- topicAdapter.disablePostEditing();
- }
+ }
- @Override
- protected Boolean doInBackground(Integer... positions) {
- Document document;
- position = positions[0];
- String url = postsList.get(position).getPostEditURL();
- Request request = new Request.Builder()
- .url(url + ";wap2")
- .build();
+ @Override
+ public void onPrepareForReplyStarted() {
+ hideControls();
+ }
- try {
- Response response = client.newCall(request).execute();
- document = Jsoup.parse(response.body().string());
+ @Override
+ public void onPrepareForReplyCancelled() {
+ showControls();
+ }
- Element message = document.select("textarea").first();
- postText = message.text();
+ @Override
+ public void onDeleteTaskStarted() {
+ hideControls();
+ }
- commitEditURL = document.select("form").first().attr("action");
- numReplies = replyPageUrl.substring(replyPageUrl.indexOf("num_replies=") + 12);
- seqnum = document.select("input[name=seqnum]").first().attr("value");
- sc = document.select("input[name=sc]").first().attr("value");
- topic = document.select("input[name=topic]").first().attr("value");
+ @Override
+ public void onDeleteTaskFinished(boolean result) {
+ showControls();
- return true;
- } catch (IOException | Selector.SelectorParseException e) {
- Timber.e(e, "Prepare failed.");
- return false;
- }
+ if (result) {
+ viewModel.reloadPage();
+ } else {
+ Toast.makeText(TopicActivity.this, "Post deleted!", Toast.LENGTH_SHORT).show();
}
+ }
-
- @Override
- protected void onPostExecute(Boolean result) {
- postsList.get(position).setPostType(Post.TYPE_EDIT);
- topicAdapter.notifyItemChanged(position);
- topicAdapter.prepareForEdit(new EditTask(), commitEditURL, numReplies, seqnum, sc, topic, postText);
- recyclerView.scrollToPosition(position);
- progressBar.setVisibility(ProgressBar.GONE);
- }
+ @Override
+ public void onPrepareEditStarted() {
+ hideControls();
}
- public class EditTask extends AsyncTask {
- EditTaskDTO dto;
+ @Override
+ public void onPrepareEditCancelled() {
+ showControls();
+ }
- @Override
- protected void onPreExecute() {
- progressBar.setVisibility(ProgressBar.VISIBLE);
- paginationEnabled(false);
- replyFAB.setEnabled(false);
- }
+ @Override
+ public void onEditTaskStarted() {
+ hideControls();
+ }
- @Override
- protected Boolean doInBackground(EditTaskDTO... editTaskDTOS) {
- dto = editTaskDTOS[0];
- RequestBody postBody = new MultipartBody.Builder()
- .setType(MultipartBody.FORM)
- .addFormDataPart("message", dto.getMessage())
- .addFormDataPart("num_replies", dto.getNumReplies())
- .addFormDataPart("seqnum", dto.getSeqnum())
- .addFormDataPart("sc", dto.getSc())
- .addFormDataPart("subject", dto.getSubject())
- .addFormDataPart("topic", dto.getTopic())
- .build();
- Request post = new Request.Builder()
- .url(dto.getUrl())
- .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
- .post(postBody)
- .build();
-
- try {
- client.newCall(post).execute();
- Response response = client.newCall(post).execute();
- switch (replyStatus(response)) {
- case SUCCESSFUL:
- return true;
- case NEW_REPLY_WHILE_POSTING:
- //TODO this...
- return true;
- default:
- Timber.e("Malformed post. Request string: %s", post.toString());
- return true;
- }
- } catch (IOException e) {
- Timber.e(e, "Edit failed.");
- return false;
- }
+ @Override
+ public void onEditTaskFinished(boolean result, int position) {
+ View view = getCurrentFocus();
+ if (view != null) {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
- @Override
- protected void onPostExecute(Boolean result) {
- View view = getCurrentFocus();
- if (view != null) {
- InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
- }
+ postsList.get(position).setPostType(Post.TYPE_POST);
+ topicAdapter.notifyItemChanged(position);
+ viewModel.setEditingPost(false);
- postsList.get(dto.getPosition()).setPostType(Post.TYPE_POST);
- topicAdapter.notifyItemChanged(dto.getPosition());
+ showControls();
- progressBar.setVisibility(ProgressBar.GONE);
- replyFAB.setVisibility(View.VISIBLE);
- bottomNavBar.setVisibility(View.VISIBLE);
-
- if (!result)
- Toast.makeText(TopicActivity.this, "Edit failed!", Toast.LENGTH_SHORT).show();
- paginationEnabled(true);
- replyFAB.setEnabled(true);
- topicAdapter.enablePostEditing();
-
- if (result) {
- topicTask = new TopicTask();
- reloadingPage = true;
- topicTask.execute(loadedPageUrl);
- }
+ if (result) {
+ viewModel.setEditingPost(false);
+ viewModel.reloadPage();
+ } else {
+ Toast.makeText(TopicActivity.this, "Edit failed!", Toast.LENGTH_SHORT).show();
}
}
}
\ No newline at end of file
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 df252fc2..89f1ed25 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
@@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.activities.topic;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
+import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -47,6 +48,7 @@ import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyFile;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.CircleTransform;
+import gr.thmmy.mthmmy.viewmodel.TopicViewModel;
import timber.log.Timber;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -69,7 +71,6 @@ class TopicAdapter extends RecyclerView.Adapter {
*/
private static int THUMBNAIL_SIZE;
private final Context context;
- private String topicTitle;
private String baseUrl;
private final ArrayList toQuoteList = new ArrayList<>();
private final List postsList;
@@ -88,15 +89,11 @@ class TopicAdapter extends RecyclerView.Adapter {
* Index of state indicator in the boolean array. If true quote button for this post is checked.
*/
private static final int isQuoteButtonChecked = 1;
- private TopicActivity.TopicTask topicTask;
- private TopicActivity.ReplyTask replyTask;
- private TopicActivity.DeleteTask deleteTask;
- private TopicActivity.PrepareForEdit prepareForEditTask;
- private TopicActivity.EditTask editTask;
+ private TopicViewModel viewModel;
private final String[] replyDataHolder = new String[2];
private final int replySubject = 0, replyText = 1;
- private String commitEditURL, numReplies, seqnum, sc, topic, buildedQuotes, postText;
+ private String commitEditURL, buildedQuotes, postText;
private boolean canReply = false;
private boolean postEditingDisabled = false;
@@ -104,54 +101,23 @@ class TopicAdapter extends RecyclerView.Adapter {
* @param context the context of the {@link RecyclerView}
* @param postsList List of {@link Post} objects to use
*/
- TopicAdapter(Context context, List postsList, String baseUrl,
- TopicActivity.TopicTask topicTask) {
+ TopicAdapter(TopicActivity context, List postsList) {
this.context = context;
this.postsList = postsList;
- this.baseUrl = baseUrl;
+
+ viewModel = ViewModelProviders.of(context).get(TopicViewModel.class);
THUMBNAIL_SIZE = (int) context.getResources().getDimension(R.dimen.thumbnail_size);
for (int i = 0; i < postsList.size(); ++i) {
//Initializes properties, array's values will be false by default
viewProperties.add(new boolean[3]);
}
- this.topicTask = topicTask;
}
ArrayList getToQuoteList() {
return toQuoteList;
}
- void prepareForReply(TopicActivity.ReplyTask replyTask, String topicTitle, String numReplies,
- String seqnum, String sc, String topic, String buildedQuotes) {
- this.replyTask = replyTask;
- this.topicTitle = topicTitle;
- this.numReplies = numReplies;
- this.seqnum = seqnum;
- this.sc = sc;
- this.topic = topic;
- this.buildedQuotes = buildedQuotes;
- }
-
- void prepareForDelete(TopicActivity.DeleteTask deleteTask) {
- this.deleteTask = deleteTask;
- }
-
- void prepareForPrepareForEdit(TopicActivity.PrepareForEdit prepareForEditTask) {
- this.prepareForEditTask = prepareForEditTask;
- }
-
- void prepareForEdit(TopicActivity.EditTask editTask, String commitEditURL, String numReplies, String seqnum, String sc,
- String topic, String postText) {
- this.commitEditURL = commitEditURL;
- this.editTask = editTask;
- this.numReplies = numReplies;
- this.seqnum = seqnum;
- this.sc = sc;
- this.topic = topic;
- this.postText = postText;
- }
-
@Override
public int getItemViewType(int position) {
return postsList.get(position).getPostType();
@@ -170,22 +136,14 @@ class TopicAdapter extends RecyclerView.Adapter {
final EditText quickReplyText = view.findViewById(R.id.quick_reply_text);
quickReplyText.setFocusableInTouchMode(true);
- quickReplyText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- quickReplyText.post(new Runnable() {
- @Override
- public void run() {
- InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(quickReplyText, InputMethodManager.SHOW_IMPLICIT);
- }
- });
- }
- });
+ quickReplyText.setOnFocusChangeListener((v, hasFocus) -> quickReplyText.post(() -> {
+ InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(quickReplyText, InputMethodManager.SHOW_IMPLICIT);
+ }));
quickReplyText.requestFocus();
//Default post subject
- replyDataHolder[replySubject] = "Re: " + topicTitle;
+ replyDataHolder[replySubject] = "Re: " + viewModel.getTopicTitle();
//Build quotes
if (!Objects.equals(buildedQuotes, ""))
replyDataHolder[replyText] = buildedQuotes;
@@ -483,7 +441,7 @@ class TopicAdapter extends RecyclerView.Adapter {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
- deleteTask.execute(currentPost.getPostDeleteURL());
+ viewModel.deletePost(currentPost.getPostDeleteURL());
}
})
.setNegativeButton(android.R.string.no, null).show();
@@ -494,15 +452,11 @@ class TopicAdapter extends RecyclerView.Adapter {
final TextView editPostButton = popUpContent.findViewById(R.id.edit_post);
- if (postEditingDisabled || currentPost.getPostEditURL() == null || currentPost.getPostEditURL().equals("")) {
+ if (viewModel.isEditingPost() || currentPost.getPostEditURL() == null || currentPost.getPostEditURL().equals("")) {
editPostButton.setVisibility(View.GONE);
} else {
- editPostButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- prepareForEditTask.execute(position);
- }
- });
+ editPostButton.setOnClickListener(v -> viewModel.prepareForEdit(position,
+ postsList.get(position).getPostEditURL()));
}
//Displays the popup
@@ -565,11 +519,12 @@ class TopicAdapter extends RecyclerView.Adapter {
if (holder.quickReplySubject.getText().toString().isEmpty()) return;
if (holder.quickReply.getText().toString().isEmpty()) return;
holder.submitButton.setEnabled(false);
- replyTask.execute(holder.quickReplySubject.getText().toString(),
- holder.quickReply.getText().toString(), numReplies, seqnum, sc, topic);
+
+ viewModel.postReply(context, holder.quickReplySubject.getText().toString(),
+ holder.quickReply.getText().toString());
holder.quickReplySubject.getText().clear();
- holder.quickReplySubject.setText("Re: " + topicTitle);
+ holder.quickReplySubject.setText("Re: " + viewModel.getTopicTitle());
holder.quickReply.getText().clear();
holder.submitButton.setEnabled(true);
}
@@ -599,19 +554,16 @@ class TopicAdapter extends RecyclerView.Adapter {
holder.editSubject.setText(postsList.get(position).getSubject());
holder.editMessage.setText(postText);
- holder.submitButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (holder.editSubject.getText().toString().isEmpty()) return;
- if (holder.editMessage.getText().toString().isEmpty()) return;
- holder.submitButton.setEnabled(false);
- editTask.execute(new EditTaskDTO(position, commitEditURL, holder.editSubject.getText().toString(),
- holder.editMessage.getText().toString(), numReplies, seqnum, sc, topic));
-
- holder.editSubject.getText().clear();
- holder.editSubject.setText(postsList.get(position).getSubject());
- holder.submitButton.setEnabled(true);
- }
+ holder.submitButton.setOnClickListener(view -> {
+ if (holder.editSubject.getText().toString().isEmpty()) return;
+ if (holder.editMessage.getText().toString().isEmpty()) return;
+ holder.submitButton.setEnabled(false);
+
+ viewModel.editPost(position, holder.editSubject.getText().toString(), holder.editMessage.getText().toString());
+
+ holder.editSubject.getText().clear();
+ holder.editSubject.setText(postsList.get(position).getSubject());
+ holder.submitButton.setEnabled(true);
});
if (backPressHidden) {
@@ -621,9 +573,7 @@ class TopicAdapter extends RecyclerView.Adapter {
}
}
- void resetTopic(String baseUrl, TopicActivity.TopicTask topicTask, boolean canReply) {
- this.baseUrl = baseUrl;
- this.topicTask = topicTask;
+ void resetTopic(boolean canReply) {
this.canReply = canReply;
viewProperties.clear();
for (int i = 0; i < postsList.size(); ++i) {
@@ -753,10 +703,11 @@ class TopicAdapter extends RecyclerView.Adapter {
final String uriString = uri.toString();
ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(uri);
+ viewModel.stopLoading();
if (target.is(ThmmyPage.PageCategory.TOPIC)) {
//This url points to a topic
//Checks if this is the current topic
- if (Objects.equals(uriString.substring(0, uriString.lastIndexOf(".")), baseUrl)) {
+ if (Objects.equals(uriString.substring(0, uriString.lastIndexOf(".")), viewModel.getBaseUrl())) {
//Gets uri's targeted message's index number
String msgIndexReq = uriString.substring(uriString.indexOf("msg") + 3);
if (msgIndexReq.contains("#"))
@@ -772,7 +723,7 @@ class TopicAdapter extends RecyclerView.Adapter {
}
}
- topicTask.execute(uri.toString());
+ viewModel.loadUrl(uri.toString());
}
Intent intent = new Intent(context, TopicActivity.class);
@@ -866,12 +817,4 @@ class TopicAdapter extends RecyclerView.Adapter {
return context.getResources().getString(R.string.fa_file);
}
-
- public void disablePostEditing() {
- postEditingDisabled = true;
- }
-
- public void enablePostEditing() {
- postEditingDisabled = false;
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicTask.java
index 6c654475..74f2c23a 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicTask.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicTask.java
@@ -16,7 +16,6 @@ import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
import gr.thmmy.mthmmy.utils.parsing.ParseHelpers;
-import gr.thmmy.mthmmy.viewmodel.TopicViewModel;
import okhttp3.Request;
import okhttp3.Response;
import timber.log.Timber;
@@ -28,25 +27,71 @@ import timber.log.Timber;
* parameter.
*/
public class TopicTask extends AsyncTask {
- //input data
- private TopicViewModel viewModel;
+ //----------------------------input data-----------------------------
+ private TopicTaskObserver topicTaskObserver;
+ private OnTopicTaskCompleted finishListener;
+ /**
+ * Becomes true when a page is being reloaded
+ */
private boolean reloadingPage;
private ArrayList lastPostsList;
- //output data
+ //-----------------------------output data----------------------------
private ResultCode resultCode;
- private String topicTitle, replyPageUrl, topicTreeAndMods, topicViewers;
+ /**
+ * Holds this topic's title. At first this gets the value of the topic title that came with
+ * bundle and is rendered in the toolbar while parsing this topic. Later, if a different topic
+ * title is parsed from the html source, it gets updated.
+ */
+ private String topicTitle;
+ /**
+ * This topic's reply url
+ */
+ private String replyPageUrl;
+ //Topic's info related
+ private String topicTreeAndMods;
+ private String topicViewers;
+
private ArrayList newPostsList;
+ /**
+ * The topicId of the loaded page
+ */
private int loadedPageTopicId = -1;
+ /**
+ * The index of the post that has focus
+ */
private int focusedPostIndex = 0;
+ /**
+ * A list of the requested topic's pages urls
+ */
private SparseArray pagesUrls = new SparseArray<>();
- //(possibly) update data
- private int currentPageIndex, pageCount;
- private String baseUrl, lastPageLoadAttemptedUrl;
+ //-------------------------------------(possibly) update data------------------------------
+ /**
+ * Holds current page's index (starting from 1, not 0)
+ */
+ private int currentPageIndex;
+ /**
+ * Holds the requested topic's number of pages
+ */
+ private int pageCount;
+ /**
+ * Holds this topic's base url. For example a topic with url similar to
+ * "https://www.thmmy.gr/smf/index.php?topic=1.15;topicseen" or
+ * "https://www.thmmy.gr/smf/index.php?topic=1.msg1#msg1"
+ * has the base url "https://www.thmmy.gr/smf/index.php?topic=1"
+ */
+ private String baseUrl;
+ /**
+ * The url of the last page that was attempted to be loaded
+ */
+ private String lastPageLoadAttemptedUrl;
//consecutive load constructor
- public TopicTask(boolean reloadingPage, String baseUrl, int currentPageIndex, int pageCount,
- String lastPageLoadAttemptedUrl, ArrayList lastPostsList) {
- this.viewModel = viewModel;
+ public TopicTask(TopicTaskObserver topicTaskObserver, OnTopicTaskCompleted finishListener,
+ boolean reloadingPage, String baseUrl, int currentPageIndex, int pageCount,
+ String lastPageLoadAttemptedUrl,
+ ArrayList lastPostsList) {
+ this.topicTaskObserver = topicTaskObserver;
+ this.finishListener = finishListener;
this.reloadingPage = reloadingPage;
this.baseUrl = baseUrl;
this.currentPageIndex = currentPageIndex;
@@ -55,9 +100,10 @@ public class TopicTask extends AsyncTask {
this.lastPostsList = lastPostsList;
}
- //first load constructor
- public TopicTask() {
- this.viewModel = viewModel;
+ // first load or reload constructor
+ public TopicTask(TopicTaskObserver topicTaskObserver, OnTopicTaskCompleted finishListener) {
+ this.topicTaskObserver = topicTaskObserver;
+ this.finishListener = finishListener;
this.reloadingPage = false;
this.baseUrl = "";
this.currentPageIndex = 1;
@@ -66,6 +112,11 @@ public class TopicTask extends AsyncTask {
this.lastPostsList = null;
}
+ @Override
+ protected void onPreExecute() {
+ topicTaskObserver.onTopicTaskStarted();
+ }
+
@Override
protected TopicTaskResult doInBackground(String... strings) {
Document document = null;
@@ -100,8 +151,8 @@ public class TopicTask extends AsyncTask {
} else if ((Objects.equals(newPageUrl, baseUrl) && currentPageIndex == 1) ||
Integer.parseInt(newPageUrl.substring(baseUrl.length() + 1)) / 15 + 1 ==currentPageIndex)
resultCode = ResultCode.SAME_PAGE;
+
} else if (!Objects.equals(lastPageLoadAttemptedUrl, "")) topicTitle = null;
- if (reloadingPage) reloadingPage = !reloadingPage;
lastPageLoadAttemptedUrl = newPageUrl;
if (strings[0].substring(0, strings[0].lastIndexOf(".")).contains("topic="))
@@ -203,10 +254,20 @@ public class TopicTask extends AsyncTask {
"είναι προσβάσιμο από εσάς.)").size() > 0;
}
+ @Override
+ protected void onPostExecute(TopicTaskResult topicTaskResult) {
+ finishListener.onTopicTaskCompleted(topicTaskResult);
+ }
+
public enum ResultCode {
SUCCESS, NETWORK_ERROR, PARSING_ERROR, OTHER_ERROR, SAME_PAGE, UNAUTHORIZED
}
+ public interface TopicTaskObserver {
+ void onTopicTaskStarted();
+ void onTopicTaskCancelled();
+ }
+
public interface OnTopicTaskCompleted {
void onTopicTaskCompleted(TopicTaskResult result);
}
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 8286b3fd..3f48c240 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
@@ -1,40 +1,223 @@
package gr.thmmy.mthmmy.viewmodel;
-import android.app.NotificationManager;
import android.arch.lifecycle.MutableLiveData;
import android.content.Context;
-import android.view.View;
-import android.widget.ProgressBar;
-import android.widget.Toast;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
-import java.util.Objects;
+import java.util.ArrayList;
-import gr.thmmy.mthmmy.activities.topic.TopicActivity;
+import gr.thmmy.mthmmy.activities.settings.SettingsActivity;
+import gr.thmmy.mthmmy.activities.topic.DeleteTask;
+import gr.thmmy.mthmmy.activities.topic.EditTask;
+import gr.thmmy.mthmmy.activities.topic.PrepareForReply;
+import gr.thmmy.mthmmy.activities.topic.PrepareForReplyResult;
+import gr.thmmy.mthmmy.activities.topic.PrepareForEditResult;
+import gr.thmmy.mthmmy.activities.topic.PrepareForEditTask;
+import gr.thmmy.mthmmy.activities.topic.ReplyTask;
import gr.thmmy.mthmmy.activities.topic.TopicTask;
import gr.thmmy.mthmmy.activities.topic.TopicTaskResult;
-import gr.thmmy.mthmmy.model.Bookmark;
-import timber.log.Timber;
+import gr.thmmy.mthmmy.base.BaseActivity;
+import gr.thmmy.mthmmy.model.Post;
+import gr.thmmy.mthmmy.session.SessionManager;
-import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
+public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTaskCompleted,
+ PrepareForReply.OnPrepareForReplyFinished, PrepareForEditTask.OnPrepareEditFinished {
-public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTaskCompleted {
- private MutableLiveData topicTaskResultMutableLiveData;
+ //TODO: make variables for editing and replying state
- public MutableLiveData getTopicTaskResultMutableLiveData() {
- if (topicTaskResultMutableLiveData == null) {
- topicTaskResultMutableLiveData = new MutableLiveData<>();
- //load topic data
+ private boolean editingPost = false;
+ private boolean writingReply = false;
+
+ private TopicTask currentTopicTask;
+ private PrepareForEditTask currentPrepareForEditTask;
+ private PrepareForReply currentPrepareForReplyTask;
+
+ private TopicTask.TopicTaskObserver topicTaskObserver;
+ private DeleteTask.DeleteTaskCallbacks deleteTaskCallbacks;
+ private ReplyTask.OnReplyTaskFinished replyFinishListener;
+ private PrepareForEditTask.PrepareForEditCallbacks prepareForEditCallbacks;
+ private EditTask.EditTaskCallbacks editTaskCallbacks;
+ private PrepareForReply.PrepareForReplyCallbacks prepareForReplyCallbacks;
+
+ private MutableLiveData topicTaskResult = new MutableLiveData<>();
+ private MutableLiveData prepareForReplyResult = new MutableLiveData<>();
+ private MutableLiveData prepareForEditResult = new MutableLiveData<>();
+
+ public void setTopicTaskObserver(TopicTask.TopicTaskObserver topicTaskObserver) {
+ this.topicTaskObserver = topicTaskObserver;
+ }
+
+ public void setDeleteTaskCallbacks(DeleteTask.DeleteTaskCallbacks deleteTaskCallbacks) {
+ this.deleteTaskCallbacks = deleteTaskCallbacks;
+ }
+
+ public void setReplyFinishListener(ReplyTask.OnReplyTaskFinished replyFinishListener) {
+ this.replyFinishListener = replyFinishListener;
+ }
+
+ public void setPrepareForEditCallbacks(PrepareForEditTask.PrepareForEditCallbacks prepareForEditCallbacks) {
+ this.prepareForEditCallbacks = prepareForEditCallbacks;
+ }
+
+ public void setEditTaskCallbacks(EditTask.EditTaskCallbacks editTaskCallbacks) {
+ this.editTaskCallbacks = editTaskCallbacks;
+ }
+
+ public void setPrepareForReplyCallbacks(PrepareForReply.PrepareForReplyCallbacks prepareForReplyCallbacks) {
+ this.prepareForReplyCallbacks = prepareForReplyCallbacks;
+ }
+
+ public MutableLiveData getTopicTaskResult() {
+ return topicTaskResult;
+ }
+
+ public MutableLiveData getPrepareForReplyResult() {
+ return prepareForReplyResult;
+ }
+
+ public MutableLiveData getPrepareForEditResult() {
+ return prepareForEditResult;
+ }
+
+ public void setEditingPost(boolean editingPost) {
+ this.editingPost = editingPost;
+ }
+
+ public boolean isEditingPost() {
+ return editingPost;
+ }
+
+ public void setWritingReply(boolean writingReply) {
+ this.writingReply = writingReply;
+ }
+
+ public String getBaseUrl() {
+ if (topicTaskResult.getValue() != null) {
+ return topicTaskResult.getValue().getBaseUrl();
+ } else {
+ return "";
+ }
+ }
+
+ public String getTopicUrl() {
+ if (topicTaskResult.getValue() != null) {
+ return topicTaskResult.getValue().getLastPageLoadAttemptedUrl();
+ } else {
+ throw new NullPointerException("Topic task has not finished yet!");
+ }
+ }
+
+ public String getTopicTitle() {
+ if (topicTaskResult.getValue() != null) {
+ return topicTaskResult.getValue().getTopicTitle();
+ } else {
+ throw new NullPointerException("Topic task has not finished yet!");
}
- return topicTaskResultMutableLiveData;
}
public void initialLoad(String pageUrl) {
- new TopicTask().execute(pageUrl);
- //load posts
+ currentTopicTask = new TopicTask(topicTaskObserver, this);
+ currentTopicTask.execute(pageUrl);
+ }
+
+ public void loadUrl(String pageUrl) {
+ stopLoading();
+ currentTopicTask = new TopicTask(topicTaskObserver, this);
+ currentTopicTask.execute(pageUrl);
+ }
+
+ public void reloadPage() {
+ stopLoading();
+ currentTopicTask = new TopicTask(topicTaskObserver, this);
+ currentTopicTask.execute(topicTaskResult.getValue().getLastPageLoadAttemptedUrl());
+ }
+
+ public void changePage(int pageRequested) {
+ if (pageRequested != topicTaskResult.getValue().getCurrentPageIndex() - 1) {
+ stopLoading();
+ currentTopicTask = new TopicTask(topicTaskObserver, this);
+ currentTopicTask.execute(topicTaskResult.getValue().getPagesUrls().get(pageRequested));
+ }
+ }
+
+ public void prepareForReply(ArrayList postsList, ArrayList toQuoteList) {
+ if (topicTaskResult.getValue() == null)
+ throw new NullPointerException("Topic task has not finished yet!");
+ stopLoading();
+ changePage(topicTaskResult.getValue().getPageCount() - 1);
+ currentPrepareForReplyTask = new PrepareForReply(prepareForReplyCallbacks, this,
+ topicTaskResult.getValue().getReplyPageUrl(), postsList);
+ currentPrepareForReplyTask.execute(toQuoteList.toArray(new Integer[0]));
+ }
+
+ public void postReply(Context context, String subject, String reply) {
+ if (prepareForReplyResult.getValue() == null) {
+ throw new NullPointerException("Reply preparation was not found!");
+ }
+ PrepareForReplyResult replyForm = prepareForReplyResult.getValue();
+ boolean includeAppSignature = true;
+ SessionManager sessionManager = BaseActivity.getSessionManager();
+ if (sessionManager.isLoggedIn()) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ includeAppSignature = prefs.getBoolean(SettingsActivity.APP_SIGNATURE_ENABLE_KEY, true);
+ }
+ new ReplyTask(replyFinishListener, includeAppSignature).execute(subject, reply,
+ replyForm.getNumReplies(), replyForm.getSeqnum(), replyForm.getSc(), replyForm.getTopic());
+ }
+
+ public void deletePost(String postDeleteUrl) {
+ new DeleteTask(deleteTaskCallbacks).execute(postDeleteUrl);
+ }
+
+ public void prepareForEdit(int position, String postEditURL) {
+ if (topicTaskResult.getValue() == null)
+ throw new NullPointerException("Topic task has not finished yet!");
+ currentPrepareForEditTask = new PrepareForEditTask(prepareForEditCallbacks, this, position,
+ topicTaskResult.getValue().getReplyPageUrl());
+ currentPrepareForEditTask.execute(postEditURL);
+ }
+
+ public void editPost(int position, String subject, String message) {
+ if (prepareForEditResult.getValue() == null)
+ throw new NullPointerException("Edit preparation was not found!");
+ PrepareForEditResult editResult = prepareForEditResult.getValue();
+ new EditTask(editTaskCallbacks, position).execute(editResult.getCommitEditUrl(), message,
+ editResult.getNumReplies(), editResult.getSeqnum(), editResult.getSc(), subject, editResult.getTopic());
+ }
+
+ /**
+ * cancel tasks that change the ui
+ */
+ public void stopLoading() {
+ if (currentTopicTask != null && currentTopicTask.getStatus() == AsyncTask.Status.RUNNING) {
+ currentTopicTask.cancel(true);
+ topicTaskObserver.onTopicTaskCancelled();
+ }
+ if (currentPrepareForEditTask != null && currentPrepareForEditTask.getStatus() == AsyncTask.Status.RUNNING) {
+ currentPrepareForEditTask.cancel(true);
+ prepareForEditCallbacks.onPrepareEditCancelled();
+ }
+ if (currentPrepareForReplyTask != null && currentPrepareForReplyTask.getStatus() == AsyncTask.Status.RUNNING) {
+ currentPrepareForReplyTask.cancel(true);
+ prepareForReplyCallbacks.onPrepareForReplyCancelled();
+ }
+ // no need to cancel reply, edit and delete task for navigation
}
@Override
public void onTopicTaskCompleted(TopicTaskResult result) {
- topicTaskResultMutableLiveData.setValue(result);
+ topicTaskResult.setValue(result);
+ }
+
+ @Override
+ public void onPrepareForReplyFinished(PrepareForReplyResult result) {
+ prepareForReplyResult.setValue(result);
+ }
+
+ @Override
+ public void onPrepareEditFinished(PrepareForEditResult result, int position) {
+ prepareForEditResult.setValue(result);
}
}