Browse Source

UnreadFragment improvements

pull/68/head
Ezerous 5 years ago
parent
commit
56ba2440f8
No known key found for this signature in database GPG Key ID: 262B2954BBA319E3
  1. 227
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
  2. 96
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
  3. 18
      app/src/main/java/gr/thmmy/mthmmy/session/ValidateSessionTask.java
  4. 8
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParser.java
  5. 3
      app/src/main/res/layout/fragment_unread.xml

227
app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java

@ -1,4 +1,3 @@
package gr.thmmy.mthmmy.activities.main.unread; package gr.thmmy.mthmmy.activities.main.unread;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -23,20 +22,20 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.base.BaseFragment;
import gr.thmmy.mthmmy.model.TopicSummary; import gr.thmmy.mthmmy.model.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager; import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.session.ValidateSessionTask;
import gr.thmmy.mthmmy.utils.NetworkResultCodes; import gr.thmmy.mthmmy.utils.NetworkResultCodes;
import gr.thmmy.mthmmy.utils.parsing.NewParseTask; import gr.thmmy.mthmmy.utils.parsing.NewParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException; import gr.thmmy.mthmmy.utils.parsing.ParseException;
import gr.thmmy.mthmmy.views.CustomRecyclerView; import gr.thmmy.mthmmy.views.CustomRecyclerView;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
@ -60,12 +59,13 @@ public class UnreadFragment extends BaseFragment {
private UnreadAdapter unreadAdapter; private UnreadAdapter unreadAdapter;
private List<TopicSummary> topicSummaries; private List<TopicSummary> topicSummaries;
private String markAsReadUrl = ""; private String markAsReadUrl;
private int numberOfPages = 0; private int numberOfPages = 0;
private int loadedPages = 0; private int loadedPages = 0;
private UnreadTask unreadTask; private UnreadTask unreadTask;
private MarkReadTask markReadTask; private MarkReadTask markReadTask;
private ValidateSessionTask validateSessionTask;
// Required empty public constructor // Required empty public constructor
public UnreadFragment() {} public UnreadFragment() {}
@ -89,18 +89,22 @@ public class UnreadFragment extends BaseFragment {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
topicSummaries = new ArrayList<>(); topicSummaries = new ArrayList<>();
markAsReadUrl = BaseApplication.getInstance().getSessionManager().getMarkAllAsReadLink();
if(markAsReadUrl==null){
Timber.i("MarkAsRead URL is null.");
startValidateSessionTask();
}
} }
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if (topicSummaries.isEmpty()) { if (topicSummaries.isEmpty()){
unreadTask = new UnreadTask(this::onUnreadTaskStarted, this::onUnreadTaskFinished); unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null; assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString()); unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString());
} }
markReadTask = new MarkReadTask(); markReadTask = new MarkReadTask(this::onMarkReadTaskStarted, this::onMarkReadTaskFinished);
Timber.d("onActivityCreated");
} }
@ -139,15 +143,7 @@ public class UnreadFragment extends BaseFragment {
swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.primary); swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.primary);
swipeRefreshLayout.setColorSchemeResources(R.color.accent); swipeRefreshLayout.setColorSchemeResources(R.color.accent);
swipeRefreshLayout.setOnRefreshListener( swipeRefreshLayout.setOnRefreshListener(
() -> { this::startUnreadTask
if (!unreadTask.isRunning()) {
numberOfPages = 0;
loadedPages = 0;
unreadTask = new UnreadTask(this::onUnreadTaskStarted, this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString());
}
}
); );
} }
@ -157,17 +153,18 @@ public class UnreadFragment extends BaseFragment {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (unreadTask!=null){ cancelUnreadTaskIfRunning();
if (markReadTask!=null){
try{ try{
if(unreadTask.isRunning()) if(markReadTask.isRunning())
unreadTask.cancel(true); markReadTask.cancel(true);
} // Yes, it happens even though we checked } // Yes, it happens even though we checked
catch (NullPointerException ignored){ } catch (NullPointerException ignored){ }
} }
if (markReadTask!=null){ if (validateSessionTask!=null){
try{ try{
if(markReadTask.isRunning()) if(validateSessionTask.isRunning())
markReadTask.cancel(true); validateSessionTask.cancel(true);
} // Yes, it happens even though we checked } // Yes, it happens even though we checked
catch (NullPointerException ignored){ } catch (NullPointerException ignored){ }
} }
@ -175,15 +172,42 @@ public class UnreadFragment extends BaseFragment {
topicSummaries.clear(); topicSummaries.clear();
} }
private void startUnreadTask(){
if (unreadTask!=null) {
try{
if(!unreadTask.isRunning()){
numberOfPages = 0;
loadedPages = 0;
unreadTask = new UnreadTask(UnreadFragment.this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, UnreadFragment.this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString());
}
}
catch (NullPointerException ignored){ }
}
}
private void startValidateSessionTask(){
validateSessionTask = new ValidateSessionTask();
validateSessionTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void cancelUnreadTaskIfRunning(){
if (unreadTask!=null){
try{
if(unreadTask.isRunning())
unreadTask.cancel(true);
} // Yes, it happens even though we checked
catch (NullPointerException ignored){ }
}
}
public interface UnreadFragmentInteractionListener extends FragmentInteractionListener { public interface UnreadFragmentInteractionListener extends FragmentInteractionListener {
void onUnreadFragmentInteraction(TopicSummary topicSummary); void onUnreadFragmentInteraction(TopicSummary topicSummary);
} }
private void showMarkAsReadFAB() { private void showMarkAsReadFAB() {
markAsReadFAB.setOnClickListener(v -> { markAsReadFAB.setOnClickListener(v -> showMarkAsReadConfirmationDialog());
if (!markReadTask.isRunning() && !unreadTask.isRunning())
showMarkAsReadConfirmationDialog();
});
markAsReadFAB.show(); markAsReadFAB.show();
markAsReadFAB.setTag(true); markAsReadFAB.setTag(true);
} }
@ -199,27 +223,36 @@ public class UnreadFragment extends BaseFragment {
builder.setTitle("Mark all as read"); builder.setTitle("Mark all as read");
builder.setMessage("Are you sure that you want to mark ALL topics as read?"); builder.setMessage("Are you sure that you want to mark ALL topics as read?");
builder.setPositiveButton("Yep", (dialogInterface, i) -> { builder.setPositiveButton("Yep", (dialogInterface, i) -> {
markReadTask = new MarkReadTask(); if (!markReadTask.isRunning() && markAsReadUrl!=null){
markReadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, markAsReadUrl); markReadTask = new MarkReadTask(this::onMarkReadTaskStarted, this::onMarkReadTaskFinished);
markReadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, markAsReadUrl);
}
}); });
builder.setNegativeButton("Nope", (dialogInterface, i) -> {}); builder.setNegativeButton("Nope", (dialogInterface, i) -> {});
builder.create().show(); builder.create().show();
} }
//---------------------------------------ASYNC TASK----------------------------------- private void hideProgressUI(){
progressBar.setVisibility(ProgressBar.INVISIBLE);
swipeRefreshLayout.setRefreshing(false);
}
//---------------------------------------UNREAD TASK-----------------------------------
private void onUnreadTaskStarted() { private void onUnreadTaskStarted() {
progressBar.setVisibility(ProgressBar.VISIBLE); progressBar.setVisibility(ProgressBar.VISIBLE);
} }
private void onUnreadTaskFinished(int resultCode, UnreadTaskData unreadTaskData) { private void onUnreadTaskCancelled() {
swipeRefreshLayout.setRefreshing(false);
}
private void onUnreadTaskFinished(int resultCode, ArrayList<TopicSummary> fetchedUnread) {
if (resultCode == NetworkResultCodes.SUCCESSFUL) { if (resultCode == NetworkResultCodes.SUCCESSFUL) {
ArrayList<TopicSummary> fetchedUnread = unreadTaskData.getTopicSummaries();
if(!fetchedUnread.isEmpty()){ if(!fetchedUnread.isEmpty()){
if(loadedPages==0) if(loadedPages==0)
topicSummaries.clear(); topicSummaries.clear();
topicSummaries.addAll(fetchedUnread); topicSummaries.addAll(fetchedUnread);
markAsReadUrl = unreadTaskData.getMarkAsReadUrl();
noUnreadTopicsTextView.setVisibility(View.INVISIBLE); noUnreadTopicsTextView.setVisibility(View.INVISIBLE);
showMarkAsReadFAB(); showMarkAsReadFAB();
} }
@ -231,18 +264,15 @@ public class UnreadFragment extends BaseFragment {
unreadAdapter.notifyDataSetChanged(); unreadAdapter.notifyDataSetChanged();
loadedPages++; loadedPages++;
if (loadedPages < numberOfPages) { if (loadedPages < numberOfPages) {
unreadTask = new UnreadTask(this::onUnreadTaskStarted, this::onUnreadTaskFinished); unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null; assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString() + ";start=" + loadedPages * 20); unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString() + ";start=" + loadedPages * 20);
} }
else { else
progressBar.setVisibility(ProgressBar.INVISIBLE); hideProgressUI();
swipeRefreshLayout.setRefreshing(false);
}
} }
else{ else{
progressBar.setVisibility(ProgressBar.INVISIBLE); hideProgressUI();
swipeRefreshLayout.setRefreshing(false);
if (resultCode == NetworkResultCodes.NETWORK_ERROR) if (resultCode == NetworkResultCodes.NETWORK_ERROR)
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
else else
@ -251,16 +281,15 @@ public class UnreadFragment extends BaseFragment {
} }
} }
private class UnreadTask extends NewParseTask<UnreadTaskData> { private class UnreadTask extends NewParseTask<ArrayList<TopicSummary>> {
UnreadTask(OnTaskStartedListener onTaskStartedListener, OnNetworkTaskFinishedListener<UnreadTaskData> onParseTaskFinishedListener) { UnreadTask(OnTaskStartedListener onTaskStartedListener, OnTaskCancelledListener onTaskCancelledListener, OnNetworkTaskFinishedListener<ArrayList<TopicSummary>> onParseTaskFinishedListener) {
super(onTaskStartedListener, onParseTaskFinishedListener); super(onTaskStartedListener, onTaskCancelledListener, onParseTaskFinishedListener);
} }
@Override @Override
protected UnreadTaskData parse(Document document, Response response) throws ParseException { protected ArrayList<TopicSummary> parse(Document document, Response response) throws ParseException {
Elements unread = document.select("table.bordercolor[cellspacing=1] tr:not(.titlebg)"); Elements unread = document.select("table.bordercolor[cellspacing=1] tr:not(.titlebg)");
ArrayList<TopicSummary> fetchedTopicSummaries = new ArrayList<>(); ArrayList<TopicSummary> fetchedTopicSummaries = new ArrayList<>();
String markAsReadUrl="";
if (!unread.isEmpty()) { if (!unread.isEmpty()) {
for (Element row : unread) { for (Element row : unread) {
Elements information = row.select("td"); Elements information = row.select("td");
@ -278,12 +307,9 @@ public class UnreadFragment extends BaseFragment {
} }
Element topBar = document.select("table:not(.bordercolor):not(#bodyarea):has(td.middletext)").first(); Element topBar = document.select("table:not(.bordercolor):not(#bodyarea):has(td.middletext)").first();
Element pagesElement = null, markRead = null; Element pagesElement = null;
if (topBar != null) { if (topBar != null)
pagesElement = topBar.select("td.middletext").first(); pagesElement = topBar.select("td.middletext").first();
markRead = document.select("table:not(.bordercolor):not([width])").select("a")
.first();
}
if (numberOfPages == 0 && pagesElement != null) { if (numberOfPages == 0 && pagesElement != null) {
Elements pages = pagesElement.select("a"); Elements pages = pagesElement.select("a");
@ -293,91 +319,60 @@ public class UnreadFragment extends BaseFragment {
numberOfPages = 1; numberOfPages = 1;
} }
if (markRead != null && loadedPages == numberOfPages - 1) return fetchedTopicSummaries;
markAsReadUrl = markRead.attr("href");
return new UnreadTaskData(fetchedTopicSummaries, markAsReadUrl);
} }
return new ArrayList<>();
return new UnreadTaskData(new ArrayList<>(), markAsReadUrl);
} }
@Override @Override
protected int getResultCode(Response response, UnreadTaskData data) { protected int getResultCode(Response response, ArrayList<TopicSummary> topicSummaries) {
return NetworkResultCodes.SUCCESSFUL; return NetworkResultCodes.SUCCESSFUL;
} }
} }
private class UnreadTaskData { //---------------------------------------MARKREAD TASK------------------------------------------
ArrayList<TopicSummary> topicSummaries; private void onMarkReadTaskStarted() {
String markAsReadUrl; cancelUnreadTaskIfRunning();
progressBar.setVisibility(ProgressBar.VISIBLE);
UnreadTaskData(ArrayList<TopicSummary> topicSummaries, String markAsReadUrl){ }
this.topicSummaries = topicSummaries;
this.markAsReadUrl = markAsReadUrl;
}
ArrayList<TopicSummary> getTopicSummaries() { private void onMarkReadTaskFinished(int resultCode, Boolean isSessionVerified) {
return topicSummaries; hideProgressUI();
if (resultCode == NetworkResultCodes.SUCCESSFUL) {
if (!isSessionVerified){
Toast.makeText(getContext(), "Session verification failed", Toast.LENGTH_SHORT).show();
startValidateSessionTask();
}
else
startUnreadTask();
} }
else{
String getMarkAsReadUrl() { hideProgressUI();
return markAsReadUrl; if (resultCode == NetworkResultCodes.NETWORK_ERROR)
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
else
Toast.makeText(getContext(), "Unexpected error," +
" please contact the developers with the details", Toast.LENGTH_LONG).show();
} }
} }
private class MarkReadTask extends AsyncTask<String, Void, Integer> { private class MarkReadTask extends NewParseTask<Boolean> {
private static final int SUCCESS = 0; MarkReadTask(OnTaskStartedListener onTaskStartedListener, OnNetworkTaskFinishedListener<Boolean> onParseTaskFinishedListener) {
private static final int NETWORK_ERROR = 1; super(onTaskStartedListener, onParseTaskFinishedListener);
private static final int OTHER_ERROR = 2;
@Override
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);
} }
@Override @Override
protected Integer doInBackground(String... strings) { protected Boolean parse(Document document, Response response) throws ParseException {
Request request = new Request.Builder() Elements sessionVerificationFailed = document.select("td:containsOwn(Session " +
.url(strings[0]) "verification failed. Please try logging out and back in again, and then try " +
.build(); "again.), td:containsOwn(Η επαλήθευση συνόδου απέτυχε. Παρακαλούμε κάντε " +
try { "αποσύνδεση, επανασύνδεση και ξαναδοκιμάστε.)");
client.newCall(request).execute(); return sessionVerificationFailed.isEmpty();
return SUCCESS;
} catch (IOException e) {
Timber.i(e, "IO Exception");
return NETWORK_ERROR;
} catch (Exception e) {
Timber.e(e, "Exception");
return OTHER_ERROR;
}
} }
@Override @Override
protected void onPostExecute(Integer result) { protected int getResultCode(Response response, Boolean isSessionVerified) {
progressBar.setVisibility(ProgressBar.GONE); return NetworkResultCodes.SUCCESSFUL;
if (result == NETWORK_ERROR) {
Toast.makeText(getContext()
, "Task was unsuccessful!\n Please check your internet conneciton.",
Toast.LENGTH_LONG).show();
} else if (result == OTHER_ERROR) {
Toast.makeText(getContext()
, "Fatal error!\n Task aborted...", Toast.LENGTH_LONG).show();
} else {
if (!unreadTask.isRunning()) {
numberOfPages = 0;
loadedPages = 0;
unreadTask = new UnreadTask(UnreadFragment.this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString());
}
}
}
//TODO: Maybe extend this task and use isRunning() from ExternalAsyncTask instead (?)
public boolean isRunning(){
return getStatus() == AsyncTask.Status.RUNNING;
} }
} }
} }

96
app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

@ -39,6 +39,8 @@ public class SessionManager {
private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2"); private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2");
public static final HttpUrl unreadUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=unread;all;start=0;theme=4"); public static final HttpUrl unreadUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=unread;all;start=0;theme=4");
public static final HttpUrl shoutboxUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=tpmod;sa=shoutbox;theme=4"); public static final HttpUrl shoutboxUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=tpmod;sa=shoutbox;theme=4");
private static final String baseLogoutLink = "https://www.thmmy.gr/smf/index.php?action=logout;sesc=";
private static final String baseMarkAllAsReadLink = "https://www.thmmy.gr/smf/index.php?action=markasread;sa=all;sesc=";
private static final String guestName = "Guest"; private static final String guestName = "Guest";
//Response Codes //Response Codes
@ -63,7 +65,9 @@ public class SessionManager {
private static final String USER_ID = "UserID"; private static final String USER_ID = "UserID";
private static final String AVATAR_LINK = "AvatarLink"; private static final String AVATAR_LINK = "AvatarLink";
private static final String HAS_AVATAR = "HasAvatar"; private static final String HAS_AVATAR = "HasAvatar";
private static final String SESC = "Sesc";
private static final String LOGOUT_LINK = "LogoutLink"; private static final String LOGOUT_LINK = "LogoutLink";
private static final String MARK_ALL_AS_READ_LINK = "MarkAllAsReadLink";
private static final String LOGGED_IN = "LoggedIn"; private static final String LOGGED_IN = "LoggedIn";
private static final String LOGIN_SCREEN_AS_DEFAULT = "LoginScreenAsDefault"; private static final String LOGIN_SCREEN_AS_DEFAULT = "LoginScreenAsDefault";
@ -84,7 +88,7 @@ public class SessionManager {
* Always call it in a separate thread. * Always call it in a separate thread.
*/ */
public int login(String... strings) { public int login(String... strings) {
Timber.i("Logging in..."); Timber.d("Logging in...");
//Build the login request for each case //Build the login request for each case
Request request; Request request;
@ -114,8 +118,7 @@ public class SessionManager {
Response response = client.newCall(request).execute(); Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string()); Document document = Jsoup.parse(response.body().string());
if (validateRetrievedCookies()) if (validateRetrievedCookies()) {
{
Timber.i("Login successful!"); Timber.i("Login successful!");
setPersistentCookieSession(); //Store cookies setPersistentCookieSession(); //Store cookies
@ -129,7 +132,10 @@ public class SessionManager {
if (avatar != null) if (avatar != null)
editor.putString(AVATAR_LINK, avatar); editor.putString(AVATAR_LINK, avatar);
editor.putBoolean(HAS_AVATAR, avatar != null); editor.putBoolean(HAS_AVATAR, avatar != null);
editor.putString(LOGOUT_LINK, extractLogoutLink(document)); String sesc = extractSesc(document);
editor.putString(SESC, sesc);
editor.putString(LOGOUT_LINK, generateLogoutLink(sesc));
editor.putString(MARK_ALL_AS_READ_LINK, generateMarkAllAsReadLink(sesc));
editor.apply(); editor.apply();
return SUCCESS; return SUCCESS;
@ -181,10 +187,10 @@ public class SessionManager {
* Always call it in a separate thread in a way that won't hinder performance (e.g. after * Always call it in a separate thread in a way that won't hinder performance (e.g. after
* fragments' data are retrieved). * fragments' data are retrieved).
*/ */
public void validateSession() { void validateSession() {
Timber.i("Validating session..."); Timber.e("Validating session...");
if (isLoggedIn()) { if (isLoggedIn()) {
Timber.e("Refreshing session...");
int loginResult = login(); int loginResult = login();
if (loginResult != FAILURE) if (loginResult != FAILURE)
return; return;
@ -204,18 +210,15 @@ public class SessionManager {
setLoginScreenAsDefault(false); setLoginScreenAsDefault(false);
} }
/** /**
* Logout function. Always call it in a separate thread. * Logout function. Always call it in a separate thread.
*/ */
public int logout() { public int logout() {
Timber.i("Logging out..."); Timber.i("Logging out...");
Request request = new Request.Builder()
.url(sharedPrefs.getString(LOGOUT_LINK, "LogoutLink"))
.build();
try { try {
Request request = new Request.Builder()
.url(getLogoutLink())
.build();
//Make request & handle response //Make request & handle response
Response response = client.newCall(request).execute(); Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string()); Document document = Jsoup.parse(response.body().string());
@ -258,14 +261,31 @@ public class SessionManager {
public Cookie getThmmyCookie() { public Cookie getThmmyCookie() {
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl); List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl);
for(Cookie cookie: cookieList) for(Cookie cookie: cookieList) {
{
if(cookie.name().equals("THMMYgrC00ki3")) if(cookie.name().equals("THMMYgrC00ki3"))
return cookie; return cookie;
} }
return null; return null;
} }
public String getMarkAllAsReadLink() {
String markAsReadLink = sharedPrefs.getString(MARK_ALL_AS_READ_LINK, null);
if(markAsReadLink == null){ //For older versions, extract it from logout link (otherwise user would have to login again)
String sesc = extractSescFromLogoutLink(getLogoutLink());
if(sesc!=null) {
setSesc(sesc);
markAsReadLink = generateMarkAllAsReadLink(sesc);
setMarkAsReadLink(markAsReadLink);
return markAsReadLink;
}
}
return markAsReadLink; // Warning: it can be null
}
private String getLogoutLink() {
return sharedPrefs.getString(LOGOUT_LINK, null);
}
public boolean hasAvatar() { public boolean hasAvatar() {
return sharedPrefs.getBoolean(HAS_AVATAR, false); return sharedPrefs.getBoolean(HAS_AVATAR, false);
} }
@ -280,6 +300,21 @@ public class SessionManager {
//--------------------------------------GETTERS END--------------------------------------------- //--------------------------------------GETTERS END---------------------------------------------
//---------------------------------------SETTERS------------------------------------------------
private void setSesc(String sesc){
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(SESC, sesc);
editor.apply();
}
private void setMarkAsReadLink(String markAllAsReadLink){
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(MARK_ALL_AS_READ_LINK, markAllAsReadLink);
editor.apply();
}
//--------------------------------------SETTERS END---------------------------------------------
//------------------------------------OTHER FUNCTIONS------------------------------------------- //------------------------------------OTHER FUNCTIONS-------------------------------------------
private boolean validateRetrievedCookies() { private boolean validateRetrievedCookies() {
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl); List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl);
@ -353,7 +388,6 @@ public class SessionManager {
return "User"; //return a default username return "User"; //return a default username
} }
@NonNull
private int extractUserId(@NonNull Document doc) { private int extractUserId(@NonNull Document doc) {
try{ try{
Elements elements = doc.select("a:containsOwn(Εμφάνιση των μηνυμάτων σας), a:containsOwn(Show own posts)"); Elements elements = doc.select("a:containsOwn(Εμφάνιση των μηνυμάτων σας), a:containsOwn(Show own posts)");
@ -383,17 +417,33 @@ public class SessionManager {
return null; return null;
} }
@NonNull private String extractSesc(@NonNull Document doc) {
private String extractLogoutLink(@NonNull Document doc) {
Elements logoutLink = doc.select("a[href^=https://www.thmmy.gr/smf/index.php?action=logout;sesc=]"); Elements logoutLink = doc.select("a[href^=https://www.thmmy.gr/smf/index.php?action=logout;sesc=]");
if (!logoutLink.isEmpty()) { if (!logoutLink.isEmpty()) {
String link = logoutLink.first().attr("href"); String link = logoutLink.first().attr("href");
if (link != null && !link.isEmpty()) return extractSescFromLogoutLink(link);
return link; }
Timber.e(new ParseException("Parsing failed(extractSesc)"),"ParseException");
return null;
}
private String extractSescFromLogoutLink(String logoutLink){
if (logoutLink != null){
Pattern pattern = Pattern.compile(".+;sesc=(\\w+)");
Matcher matcher = pattern.matcher(logoutLink);
if (matcher.find())
return matcher.group(1);
} }
Timber.e(new ParseException("Parsing failed(logoutLink extraction)"),"ParseException"); Timber.e(new ParseException("Parsing failed(extractSescFromLogoutLink)"),"ParseException");
return "https://www.thmmy.gr/smf/index.php?action=logout"; //return a default link return null;
}
private String generateLogoutLink(String sesc){
return baseLogoutLink + sesc;
}
private String generateMarkAllAsReadLink(String sesc){
return baseMarkAllAsReadLink + sesc;
} }
//----------------------------------OTHER FUNCTIONS END----------------------------------------- //----------------------------------OTHER FUNCTIONS END-----------------------------------------

18
app/src/main/java/gr/thmmy/mthmmy/session/ValidateSessionTask.java

@ -0,0 +1,18 @@
package gr.thmmy.mthmmy.session;
import android.os.AsyncTask;
import gr.thmmy.mthmmy.base.BaseApplication;
public class ValidateSessionTask extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
BaseApplication.getInstance().getSessionManager().validateSession();
return null;
}
public boolean isRunning(){
return getStatus() == AsyncTask.Status.RUNNING;
}
}

8
app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParser.java

@ -42,7 +42,7 @@ public class ThmmyDateTimeParser {
private ThmmyDateTimeParser(){} private ThmmyDateTimeParser(){}
public static String convertToTimestamp(String thmmyDateTime){ public static String convertToTimestamp(String thmmyDateTime){
Timber.d("Will attempt to convert %s to timestamp.", thmmyDateTime); Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime);
String originalDateTime = thmmyDateTime; String originalDateTime = thmmyDateTime;
DateTimeZone dtz = getDtz(); DateTimeZone dtz = getDtz();
@ -67,12 +67,12 @@ public class ThmmyDateTimeParser {
dateTime=formatter.withZone(dtz).withLocale(englishLocale).parseDateTime(thmmyDateTime); dateTime=formatter.withZone(dtz).withLocale(englishLocale).parseDateTime(thmmyDateTime);
} }
catch (IllegalArgumentException e1){ catch (IllegalArgumentException e1){
Timber.d("Parsing DateTime %s using English Locale failed.", thmmyDateTime); Timber.v("Parsing DateTime %s using English Locale failed.", thmmyDateTime);
try{ try{
DateFormatSymbols dfs = DateTimeUtils.getDateFormatSymbols(greekLocale); DateFormatSymbols dfs = DateTimeUtils.getDateFormatSymbols(greekLocale);
thmmyDateTime = thmmyDateTime.replace("am",dfs.getAmPmStrings()[0]); thmmyDateTime = thmmyDateTime.replace("am",dfs.getAmPmStrings()[0]);
thmmyDateTime = thmmyDateTime.replace("pm",dfs.getAmPmStrings()[1]); thmmyDateTime = thmmyDateTime.replace("pm",dfs.getAmPmStrings()[1]);
Timber.d("Attempting to parse DateTime %s using Greek Locale...", thmmyDateTime); Timber.v("Attempting to parse DateTime %s using Greek Locale...", thmmyDateTime);
dateTime=formatter.withZone(dtz).withLocale(greekLocale).parseDateTime(thmmyDateTime); dateTime=formatter.withZone(dtz).withLocale(greekLocale).parseDateTime(thmmyDateTime);
} }
catch (IllegalArgumentException e2){ catch (IllegalArgumentException e2){
@ -82,7 +82,7 @@ public class ThmmyDateTimeParser {
} }
} }
String timestamp = Long.toString(dateTime.getMillis()); String timestamp = Long.toString(dateTime.getMillis());
Timber.d("DateTime %s was converted to %s, or %s", originalDateTime, timestamp, dateTime.toString()); Timber.v("DateTime %s was converted to %s, or %s", originalDateTime, timestamp, dateTime.toString());
return timestamp; return timestamp;
} }

3
app/src/main/res/layout/fragment_unread.xml

@ -37,7 +37,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:visibility="invisible"
android:text="@string/no_unread_topics" android:text="@string/no_unread_topics"
android:textColor="@color/primary_text" android:textColor="@color/accent"
android:textSize="@dimen/medium_text"
app:layout_anchor="@+id/relativeLayout" app:layout_anchor="@+id/relativeLayout"
app:layout_anchorGravity="center" /> app:layout_anchorGravity="center" />

Loading…
Cancel
Save