Browse Source

make TopicViewModel an interface for loads (not finished)

pull/34/head
Thodoris1999 7 years ago
parent
commit
14f97d7ce3
  1. 2
      app/build.gradle
  2. 62
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/DeleteTask.java
  3. 77
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/EditTask.java
  4. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java
  5. 51
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditResult.java
  6. 79
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForEditTask.java
  7. 96
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReply.java
  8. 34
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/PrepareForReplyResult.java
  9. 74
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyTask.java
  10. 650
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  11. 125
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  12. 91
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicTask.java
  13. 221
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java

2
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'

62
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<String, Void, Boolean> {
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);
}
}

77
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<String, Void, Boolean> {
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);
}
}

4
app/src/main/java/gr/thmmy/mthmmy/activities/topic/GetQuoteTextTask.java

@ -1,4 +0,0 @@
package gr.thmmy.mthmmy.activities.topic;
public class GetQuoteTextTask {
}

51
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;
}
}

79
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<String, Void, PrepareForEditResult> {
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);
}
}

96
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<Integer, Void, PrepareForReplyResult> {
private PrepareForReplyCallbacks listener;
private OnPrepareForReplyFinished finishListener;
private String replyPageUrl;
private ArrayList<Post> postsList;
public PrepareForReply(PrepareForReplyCallbacks listener, OnPrepareForReplyFinished finishListener,
String replyPageUrl, ArrayList<Post> 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("<quote>") + 7, body.indexOf("</quote>")));
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);
}
}

34
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;
}
}

74
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<String, Void, Boolean> {
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);
}
}

650
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<Post> 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<String> 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<ArrayList<Integer>, 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<Integer>... 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("<quote>") + 7, body.indexOf("</quote>"));
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<String, Void, Boolean> {
@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<String, Void, Boolean> {
@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<Integer, Void, Boolean> {
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, Void, Boolean> {
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();
}
}
}

125
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<RecyclerView.ViewHolder> {
*/
private static int THUMBNAIL_SIZE;
private final Context context;
private String topicTitle;
private String baseUrl;
private final ArrayList<Integer> toQuoteList = new ArrayList<>();
private final List<Post> postsList;
@ -88,15 +89,11 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
* 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<RecyclerView.ViewHolder> {
* @param context the context of the {@link RecyclerView}
* @param postsList List of {@link Post} objects to use
*/
TopicAdapter(Context context, List<Post> postsList, String baseUrl,
TopicActivity.TopicTask topicTask) {
TopicAdapter(TopicActivity context, List<Post> 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<Integer> 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<RecyclerView.ViewHolder> {
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<RecyclerView.ViewHolder> {
@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<RecyclerView.ViewHolder> {
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<RecyclerView.ViewHolder> {
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<RecyclerView.ViewHolder> {
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<RecyclerView.ViewHolder> {
}
}
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<RecyclerView.ViewHolder> {
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<RecyclerView.ViewHolder> {
}
}
topicTask.execute(uri.toString());
viewModel.loadUrl(uri.toString());
}
Intent intent = new Intent(context, TopicActivity.class);
@ -866,12 +817,4 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return context.getResources().getString(R.string.fa_file);
}
public void disablePostEditing() {
postEditingDisabled = true;
}
public void enablePostEditing() {
postEditingDisabled = false;
}
}

91
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.</p>
*/
public class TopicTask extends AsyncTask<String, Void, TopicTaskResult> {
//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<Post> 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<Post> 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<String> 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<Post> lastPostsList) {
this.viewModel = viewModel;
public TopicTask(TopicTaskObserver topicTaskObserver, OnTopicTaskCompleted finishListener,
boolean reloadingPage, String baseUrl, int currentPageIndex, int pageCount,
String lastPageLoadAttemptedUrl,
ArrayList<Post> 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<String, Void, TopicTaskResult> {
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<String, Void, TopicTaskResult> {
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<String, Void, TopicTaskResult> {
} 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<String, Void, TopicTaskResult> {
"είναι προσβάσιμο από εσάς.)").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);
}

221
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<TopicTaskResult> topicTaskResultMutableLiveData;
//TODO: make variables for editing and replying state
public MutableLiveData<TopicTaskResult> 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> topicTaskResult = new MutableLiveData<>();
private MutableLiveData<PrepareForReplyResult> prepareForReplyResult = new MutableLiveData<>();
private MutableLiveData<PrepareForEditResult> 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<TopicTaskResult> getTopicTaskResult() {
return topicTaskResult;
}
public MutableLiveData<PrepareForReplyResult> getPrepareForReplyResult() {
return prepareForReplyResult;
}
public MutableLiveData<PrepareForEditResult> 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<Post> postsList, ArrayList<Integer> 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);
}
}

Loading…
Cancel
Save